blob: 163355dd39ecbc23524f3c7195ff95af53d06fa3 [file] [log] [blame]
Mike Dodd8cfa7022010-11-17 11:12:26 -08001/**
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
25class opd_header;
26class 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 */
33class profile_t : noncopyable {
34public:
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
96private:
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.
149namespace 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
161class profile_t::const_iterator
162{
163 typedef ordered_samples_t::const_iterator iterator_t;
164public:
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
182private:
183 iterator_t it;
184 u64 start_offset;
185};
186
187#endif /* !PROFILE_H */