1 /** 2 * @file profile.h 3 * Encapsulation for samples files over all profile classes 4 * belonging to the same binary image 5 * 6 * @remark Copyright 2002 OProfile authors 7 * @remark Read the file COPYING 8 * 9 * @author Philippe Elie 10 * @author John Levon 11 */ 12 13 #ifndef PROFILE_H 14 #define PROFILE_H 15 16 #include <string> 17 #include <map> 18 #include <iterator> 19 20 #include "odb.h" 21 #include "op_types.h" 22 #include "utility.h" 23 #include "populate_for_spu.h" 24 25 class opd_header; 26 class op_bfd; 27 28 /** 29 * Class containing a single sample file contents. 30 * i.e. set of count values for VMA offsets for 31 * a particular binary. 32 */ 33 class profile_t : noncopyable { 34 public: 35 /** 36 * profile_t - construct an empty profile_t object 37 */ 38 profile_t(); 39 40 /// return true if no sample file has been loaded 41 bool empty() const { return !file_header.get(); } 42 43 /// return the header of the last opened samples file 44 opd_header const & get_header() const { 45 return *file_header; 46 } 47 48 /** 49 * count samples count w/o recording them 50 * @param filename sample filename 51 * 52 * convenience interface for raw access to sample count w/o recording 53 * them. It's placed here so all access to samples files go through 54 * profile_t static or non static member. 55 */ 56 static count_type sample_count(std::string const & filename); 57 58 /** 59 * Indicate if given sample file is from a Cell Broadband Engine 60 * SPU profile 61 * @param filename sample filename 62 * 63 * Convenience interface put here so all access to samples files 64 * go through profile_t static or non static member. 65 */ 66 static enum profile_type is_spu_sample_file(std::string const & filename); 67 68 /** 69 * cumulate sample file to our container of samples 70 * @param filename sample file name 71 * 72 * store samples for one sample file, sample file header is sanitized. 73 * 74 * all error are fatal 75 */ 76 void add_sample_file(std::string const & filename); 77 78 /// Set an appropriate start offset, see comments below. 79 void set_offset(op_bfd const & abfd); 80 81 class const_iterator; 82 typedef std::pair<const_iterator, const_iterator> iterator_pair; 83 84 /** 85 * @param start start offset 86 * @param end end offset 87 * 88 * return an iterator pair to [start, end) range 89 */ 90 iterator_pair 91 samples_range(odb_key_t start, odb_key_t end) const; 92 93 /// return a pair of iterator for all samples 94 iterator_pair samples_range() const; 95 96 private: 97 /// helper for sample_count() and add_sample_file(). All error launch 98 /// an exception. 99 static void 100 open_sample_file(std::string const & filename, odb_t &); 101 102 /// copy of the samples file header 103 scoped_ptr<opd_header> file_header; 104 105 /// storage type for samples sorted by eip 106 typedef std::map<odb_key_t, count_type> ordered_samples_t; 107 108 /** 109 * Samples are stored in hash table, iterating over hash table don't 110 * provide any ordering, the above count() interface rely on samples 111 * ordered by eip. This map is only a temporary storage where samples 112 * are ordered by eip. 113 */ 114 ordered_samples_t ordered_samples; 115 116 /** 117 * For certain profiles, such as kernel/modules, and anon 118 * regions with a matching binary, this value is non-zero, 119 * and represents the file offset of the relevant section. 120 * 121 * For kernel profiles, this is done because we use the information 122 * provided in /proc/ksyms, which only gives the mapped position of 123 * .text, and the symbol _text from vmlinux. This value is used to fix 124 * up the sample offsets for kernel code as a result of this difference 125 * 126 * In user-space samples, the sample offset is from the start of the 127 * mapped file, as seen in /proc/pid/maps. This is fine for 128 * mappings of permanent files, but with anon mappings, we need 129 * to adjust the key values to be a file offset against the 130 * *binary* (if there is one). This can obviously be different. 131 * So we pass our anon mapping start VMA to op_bfd, which looks 132 * for a section with that VMA, then returns the section's 133 * filepos. So all is good. 134 * 135 * Finally, note that for cg we can't use this inside the 136 * profile_t, as we're storing two offsets in the key value. So 137 * we do it later in that case. 138 * 139 * Phew. 140 */ 141 u64 start_offset; 142 }; 143 144 145 // It will be easier to derive profile_t::const_iterator from 146 // std::iterator<std::input_iterator_tag, unsigned int> but this doesn't 147 // work for gcc <= 2.95 so we provide the neccessary typedef in the hard way. 148 // See ISO C++ 17.4.3.1 1 and 14.7.3 9. 149 namespace std { 150 template <> 151 struct iterator_traits<profile_t::const_iterator> { 152 typedef ptrdiff_t difference_type; 153 typedef count_type value_type; 154 typedef count_type * pointer; 155 typedef count_type & reference; 156 typedef input_iterator_tag iterator_category; 157 }; 158 } 159 160 161 class profile_t::const_iterator 162 { 163 typedef ordered_samples_t::const_iterator iterator_t; 164 public: 165 const_iterator() : start_offset(0) {} 166 const_iterator(iterator_t it_, u64 start_offset_) 167 : it(it_), start_offset(start_offset_) {} 168 169 count_type operator*() const { return it->second; } 170 const_iterator & operator++() { ++it; return *this; } 171 172 odb_key_t vma() const { return it->first + start_offset; } 173 count_type count() const { return **this; } 174 175 bool operator!=(const_iterator const & rhs) const { 176 return it != rhs.it; 177 } 178 bool operator==(const_iterator const & rhs) const { 179 return it == rhs.it; 180 } 181 182 private: 183 iterator_t it; 184 u64 start_offset; 185 }; 186 187 #endif /* !PROFILE_H */ 188