• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file profile_container.cpp
3  * profile file container
4  *
5  * @remark Copyright 2002 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author Philippe Elie
9  * @author John Levon
10  */
11 
12 #include <set>
13 #include <vector>
14 #include <string>
15 #include <iostream>
16 #include <sstream>
17 #include <algorithm>
18 #include <numeric>
19 
20 #include "symbol.h"
21 #include "op_header.h"
22 #include "profile.h"
23 #include "symbol_functors.h"
24 #include "profile_container.h"
25 #include "sample_container.h"
26 #include "symbol_container.h"
27 #include "populate_for_spu.h"
28 
29 using namespace std;
30 
31 namespace {
32 
33 struct filename_by_samples {
filename_by_samples__anond6d3f82e0111::filename_by_samples34 	filename_by_samples(debug_name_id id, double percent_)
35 		: filename(id), percent(percent_)
36 		{}
37 
operator <__anond6d3f82e0111::filename_by_samples38 	bool operator<(filename_by_samples const & lhs) const {
39 		if (percent != lhs.percent)
40 			return percent < lhs.percent;
41 		return filename < lhs.filename;
42 	}
43 
44 	debug_name_id filename;
45 	// ratio of samples which belongs to this filename.
46 	double percent;
47 };
48 
49 }  // anon namespace
50 
51 
profile_container(bool debug_info_,bool need_details_,extra_images const & extra_)52 profile_container::profile_container(bool debug_info_, bool need_details_,
53 				     extra_images const & extra_)
54 	:
55 	symbols(new symbol_container),
56 	samples(new sample_container),
57 	debug_info(debug_info_),
58 	need_details(need_details_),
59 	extra_found_images(extra_)
60 {
61 }
62 
63 
~profile_container()64 profile_container::~profile_container()
65 {
66 }
67 
68 
69 // Post condition:
70 //  the symbols/samples are sorted by increasing vma.
71 //  the range of sample_entry inside each symbol entry are valid
72 //  the samples_by_file_loc member var is correctly setup.
add(profile_t const & profile,op_bfd const & abfd,string const & app_name,size_t pclass)73 void profile_container::add(profile_t const & profile,
74                             op_bfd const & abfd, string const & app_name,
75                             size_t pclass)
76 {
77 	string const image_name = abfd.get_filename();
78 	opd_header header = profile.get_header();
79 
80 	for (symbol_index_t i = 0; i < abfd.syms.size(); ++i) {
81 
82 		unsigned long long start = 0, end = 0;
83 		symbol_entry symb_entry;
84 
85 		abfd.get_symbol_range(i, start, end);
86 
87 		profile_t::iterator_pair p_it =
88 			profile.samples_range(start, end);
89 		count_type count = accumulate(p_it.first, p_it.second, 0ull);
90 
91 		// skip entries with no samples
92 		if (count == 0)
93 			continue;
94 
95 		symb_entry.sample.counts[pclass] = count;
96 		total_count[pclass] += count;
97 
98 		symb_entry.size = end - start;
99 
100 		symb_entry.name = symbol_names.create(abfd.syms[i].name());
101 		symb_entry.sym_index = i;
102 
103 		symb_entry.sample.file_loc.linenr = 0;
104 		if (debug_info) {
105 			string filename;
106 			if (abfd.get_linenr(i, start, filename,
107 				symb_entry.sample.file_loc.linenr)) {
108 				symb_entry.sample.file_loc.filename =
109 					debug_names.create(filename);
110 			}
111 		}
112 
113 		symb_entry.image_name = image_names.create(image_name);
114 		symb_entry.app_name = image_names.create(app_name);
115 
116 		symb_entry.sample.vma = abfd.syms[i].vma();
117 		if ((header.spu_profile == cell_spu_profile) &&
118 		    header.embedded_offset) {
119 			symb_entry.spu_offset = header.embedded_offset;
120 			symb_entry.embedding_filename =
121 				image_names.create(abfd.get_embedding_filename());
122 		} else {
123 			symb_entry.spu_offset = 0;
124 		}
125 		symbol_entry const * symbol = symbols->insert(symb_entry);
126 
127 		if (need_details)
128 			add_samples(abfd, i, p_it, symbol, pclass, start);
129 	}
130 }
131 
132 
133 void
add_samples(op_bfd const & abfd,symbol_index_t sym_index,profile_t::iterator_pair const & p_it,symbol_entry const * symbol,size_t pclass,unsigned long start)134 profile_container::add_samples(op_bfd const & abfd, symbol_index_t sym_index,
135                                profile_t::iterator_pair const & p_it,
136                                symbol_entry const * symbol, size_t pclass,
137 			       unsigned long start)
138 {
139 	bfd_vma base_vma = abfd.syms[sym_index].vma();
140 
141 	profile_t::const_iterator it;
142 	for (it = p_it.first; it != p_it.second ; ++it) {
143 		sample_entry sample;
144 
145 		sample.counts[pclass] = it.count();
146 
147 		sample.file_loc.linenr = 0;
148 		if (debug_info) {
149 			string filename;
150 			if (abfd.get_linenr(sym_index, it.vma(), filename,
151 					sample.file_loc.linenr)) {
152 				sample.file_loc.filename =
153 					debug_names.create(filename);
154 			}
155 		}
156 
157 		sample.vma = (it.vma() - start) + base_vma;
158 
159 		samples->insert(symbol, sample);
160 	}
161 }
162 
163 
164 symbol_collection const
select_symbols(symbol_choice & choice) const165 profile_container::select_symbols(symbol_choice & choice) const
166 {
167 	symbol_collection result;
168 
169 	double const threshold = choice.threshold / 100.0;
170 
171 	symbol_container::symbols_t::iterator it = symbols->begin();
172 	symbol_container::symbols_t::iterator const end = symbols->end();
173 
174 	for (; it != end; ++it) {
175 		if (choice.match_image
176 		    && (image_names.name(it->image_name) != choice.image_name))
177 			continue;
178 
179 		double const percent =
180 			op_ratio(it->sample.counts[0], total_count[0]);
181 
182 		if (percent >= threshold) {
183 			result.push_back(&*it);
184 
185 			choice.hints = it->output_hint(choice.hints);
186 		}
187 	}
188 
189 	return result;
190 }
191 
192 
193 vector<debug_name_id> const
select_filename(double threshold) const194 profile_container::select_filename(double threshold) const
195 {
196 	set<debug_name_id> filename_set;
197 
198 	threshold /= 100.0;
199 
200 	// Trying to iterate on symbols to create the set of filenames which
201 	// contain sample does not work: a symbol can contain samples and this
202 	// symbol is in a source file that contain zero sample because only
203 	// inline function in this source file contains samples.
204 	sample_container::samples_iterator sit = samples->begin();
205 	sample_container::samples_iterator const send = samples->end();
206 
207 	for (; sit != send; ++sit) {
208 		debug_name_id name_id = sit->second.file_loc.filename;
209 		if (name_id.set())
210 			filename_set.insert(name_id);
211 	}
212 
213 	// Give a sort order on filename for the selected pclass.
214 	vector<filename_by_samples> file_by_samples;
215 
216 	set<debug_name_id>::const_iterator it = filename_set.begin();
217 	set<debug_name_id>::const_iterator const end = filename_set.end();
218 	for (; it != end; ++it) {
219 		// FIXME: is samples_count() the right interface now ?
220 		count_array_t counts = samples_count(*it);
221 
222 		double const ratio = op_ratio(counts[0], total_count[0]);
223 		filename_by_samples const f(*it, ratio);
224 
225 		file_by_samples.push_back(f);
226 	}
227 
228 	// now sort the file_by_samples entry.
229 	sort(file_by_samples.begin(), file_by_samples.end());
230 
231 	// 2.91.66 doesn't like const_reverse_iterator in this context
232 	vector<filename_by_samples>::reverse_iterator cit
233 		= file_by_samples.rbegin();
234 	vector<filename_by_samples>::reverse_iterator const cend
235 		= file_by_samples.rend();
236 
237 	vector<debug_name_id> result;
238 	for (; cit != cend; ++cit) {
239 		if (cit->percent >= threshold)
240 			result.push_back(cit->filename);
241 	}
242 
243 	return result;
244 }
245 
246 
samples_count() const247 count_array_t profile_container::samples_count() const
248 {
249 	return total_count;
250 }
251 
252 
253 // Rest here are delegated to our private implementation.
254 
255 symbol_entry const *
find_symbol(string const & image_name,bfd_vma vma) const256 profile_container::find_symbol(string const & image_name, bfd_vma vma) const
257 {
258 	return symbols->find_by_vma(image_name, vma);
259 }
260 
261 
262 symbol_collection const
find_symbol(debug_name_id filename,size_t linenr) const263 profile_container::find_symbol(debug_name_id filename, size_t linenr) const
264 {
265 	return symbols->find(filename, linenr);
266 }
267 
268 
269 symbol_collection const
select_symbols(debug_name_id filename) const270 profile_container::select_symbols(debug_name_id filename) const
271 {
272 	return symbols->find(filename);
273 }
274 
275 sample_entry const *
find_sample(symbol_entry const * symbol,bfd_vma vma) const276 profile_container::find_sample(symbol_entry const * symbol, bfd_vma vma) const
277 {
278 	return samples->find_by_vma(symbol, vma);
279 }
280 
281 
samples_count(debug_name_id filename_id) const282 count_array_t profile_container::samples_count(debug_name_id filename_id) const
283 {
284 	return samples->accumulate_samples(filename_id);
285 }
286 
287 
samples_count(debug_name_id filename,size_t linenr) const288 count_array_t profile_container::samples_count(debug_name_id filename,
289 				    size_t linenr) const
290 {
291 	return samples->accumulate_samples(filename, linenr);
292 }
293 
294 
295 sample_container::samples_iterator
begin(symbol_entry const * symbol) const296 profile_container::begin(symbol_entry const * symbol) const
297 {
298 	return samples->begin(symbol);
299 }
300 
301 
302 sample_container::samples_iterator
end(symbol_entry const * symbol) const303 profile_container::end(symbol_entry const * symbol) const
304 {
305 	return samples->end(symbol);
306 }
307 
308 
begin() const309 sample_container::samples_iterator profile_container::begin() const
310 {
311 	return samples->begin();
312 }
313 
314 
end() const315 sample_container::samples_iterator profile_container::end() const
316 {
317 	return samples->end();
318 }
319 
find(symbol_entry const & symbol) const320 symbol_entry const * profile_container::find(symbol_entry const & symbol) const
321 {
322 	return symbols->find(symbol);
323 }
324 
begin_symbol() const325 symbol_container::symbols_t::iterator profile_container::begin_symbol() const
326 {
327 	return symbols->begin();
328 }
329 
end_symbol() const330 symbol_container::symbols_t::iterator profile_container::end_symbol() const
331 {
332 	return symbols->end();
333 }
334