• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
empty()41 	bool empty() const { return !file_header.get(); }
42 
43 	/// return the header of the last opened samples file
get_header()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