Home | History | Annotate | Download | only in libpp
      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