20
20
21
21
#include "perf.h"
22
22
23
+ #include "util/annotate.h"
23
24
#include "util/cache.h"
24
25
#include "util/color.h"
25
26
#include "util/evlist.h"
@@ -140,10 +141,7 @@ static int parse_source(struct sym_entry *syme)
140
141
struct symbol * sym ;
141
142
struct sym_entry_source * source ;
142
143
struct map * map ;
143
- FILE * file ;
144
- char command [PATH_MAX * 2 ];
145
- const char * path ;
146
- u64 len ;
144
+ int err = -1 ;
147
145
148
146
if (!syme )
149
147
return -1 ;
@@ -162,197 +160,80 @@ static int parse_source(struct sym_entry *syme)
162
160
if (syme -> src == NULL )
163
161
return -1 ;
164
162
pthread_mutex_init (& syme -> src -> lock , NULL );
163
+ INIT_LIST_HEAD (& syme -> src -> head );
165
164
}
166
165
167
166
source = syme -> src ;
168
167
169
- if (source -> lines ) {
168
+ if (symbol__annotation ( sym ) -> histograms != NULL ) {
170
169
pthread_mutex_lock (& source -> lock );
171
170
goto out_assign ;
172
171
}
173
- path = map -> dso -> long_name ;
174
-
175
- len = sym -> end - sym -> start ;
176
-
177
- sprintf (command ,
178
- "objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s" ,
179
- BITS_PER_LONG / 4 , map__rip_2objdump (map , sym -> start ),
180
- BITS_PER_LONG / 4 , map__rip_2objdump (map , sym -> end ), path );
181
-
182
- file = popen (command , "r" );
183
- if (!file )
184
- return -1 ;
185
172
186
173
pthread_mutex_lock (& source -> lock );
187
- source -> lines_tail = & source -> lines ;
188
- while (!feof (file )) {
189
- struct source_line * src ;
190
- size_t dummy = 0 ;
191
- char * c , * sep ;
192
-
193
- src = malloc (sizeof (struct source_line ));
194
- assert (src != NULL );
195
- memset (src , 0 , sizeof (struct source_line ));
196
-
197
- if (getline (& src -> line , & dummy , file ) < 0 )
198
- break ;
199
- if (!src -> line )
200
- break ;
201
-
202
- c = strchr (src -> line , '\n' );
203
- if (c )
204
- * c = 0 ;
205
174
206
- src -> next = NULL ;
207
- * source -> lines_tail = src ;
208
- source -> lines_tail = & src -> next ;
209
-
210
- src -> eip = strtoull (src -> line , & sep , 16 );
211
- if (* sep == ':' )
212
- src -> eip = map__objdump_2ip (map , src -> eip );
213
- else /* this line has no ip info (e.g. source line) */
214
- src -> eip = 0 ;
175
+ if (symbol__alloc_hist (sym , top .evlist -> nr_entries ) < 0 ) {
176
+ pr_err ("Not enough memory for annotating '%s' symbol!\n" ,
177
+ sym -> name );
178
+ goto out_unlock ;
215
179
}
216
- pclose (file );
180
+
181
+ err = symbol__annotate (sym , syme -> map , & source -> head , 0 );
182
+ if (err == 0 ) {
217
183
out_assign :
218
184
sym_filter_entry = syme ;
185
+ }
186
+ out_unlock :
219
187
pthread_mutex_unlock (& source -> lock );
220
- return 0 ;
188
+ return err ;
221
189
}
222
190
223
191
static void __zero_source_counters (struct sym_entry * syme )
224
192
{
225
- int i ;
226
- struct source_line * line ;
227
-
228
- line = syme -> src -> lines ;
229
- while (line ) {
230
- for (i = 0 ; i < top .evlist -> nr_entries ; i ++ )
231
- line -> count [i ] = 0 ;
232
- line = line -> next ;
233
- }
193
+ struct symbol * sym = sym_entry__symbol (syme );
194
+ symbol__annotate_zero_histograms (sym );
234
195
}
235
196
236
197
static void record_precise_ip (struct sym_entry * syme , int counter , u64 ip )
237
198
{
238
- struct source_line * line ;
239
-
240
199
if (syme != sym_filter_entry )
241
200
return ;
242
201
243
202
if (pthread_mutex_trylock (& syme -> src -> lock ))
244
203
return ;
245
204
246
- if (syme -> src == NULL || syme -> src -> source == NULL )
247
- goto out_unlock ;
248
-
249
- for (line = syme -> src -> lines ; line ; line = line -> next ) {
250
- /* skip lines without IP info */
251
- if (line -> eip == 0 )
252
- continue ;
253
- if (line -> eip == ip ) {
254
- line -> count [counter ]++ ;
255
- break ;
256
- }
257
- if (line -> eip > ip )
258
- break ;
259
- }
260
- out_unlock :
261
- pthread_mutex_unlock (& syme -> src -> lock );
262
- }
263
-
264
- #define PATTERN_LEN (BITS_PER_LONG / 4 + 2)
205
+ ip = syme -> map -> map_ip (syme -> map , ip );
206
+ symbol__inc_addr_samples (sym_entry__symbol (syme ), syme -> map , counter , ip );
265
207
266
- static void lookup_sym_source (struct sym_entry * syme )
267
- {
268
- struct symbol * symbol = sym_entry__symbol (syme );
269
- struct source_line * line ;
270
- char pattern [PATTERN_LEN + 1 ];
271
-
272
- sprintf (pattern , "%0*" PRIx64 " <" , BITS_PER_LONG / 4 ,
273
- map__rip_2objdump (syme -> map , symbol -> start ));
274
-
275
- pthread_mutex_lock (& syme -> src -> lock );
276
- for (line = syme -> src -> lines ; line ; line = line -> next ) {
277
- if (memcmp (line -> line , pattern , PATTERN_LEN ) == 0 ) {
278
- syme -> src -> source = line ;
279
- break ;
280
- }
281
- }
282
208
pthread_mutex_unlock (& syme -> src -> lock );
283
209
}
284
210
285
- static void show_lines (struct source_line * queue , int count , int total )
286
- {
287
- int i ;
288
- struct source_line * line ;
289
-
290
- line = queue ;
291
- for (i = 0 ; i < count ; i ++ ) {
292
- float pcnt = 100.0 * (float )line -> count [top .sym_counter ]/(float )total ;
293
-
294
- printf ("%8li %4.1f%%\t%s\n" , line -> count [top .sym_counter ], pcnt , line -> line );
295
- line = line -> next ;
296
- }
297
- }
298
-
299
- #define TRACE_COUNT 3
300
-
301
211
static void show_details (struct sym_entry * syme )
302
212
{
303
213
struct symbol * symbol ;
304
- struct source_line * line ;
305
- struct source_line * line_queue = NULL ;
306
- int displayed = 0 ;
307
- int line_queue_count = 0 , total = 0 , more = 0 ;
214
+ int more ;
308
215
309
216
if (!syme )
310
217
return ;
311
218
312
- if (!syme -> src -> source )
313
- lookup_sym_source (syme );
314
-
315
- if (!syme -> src -> source )
219
+ symbol = sym_entry__symbol (syme );
220
+ if (!syme -> src || symbol__annotation (symbol )-> histograms == NULL )
316
221
return ;
317
222
318
- symbol = sym_entry__symbol (syme );
319
223
printf ("Showing %s for %s\n" , event_name (top .sym_evsel ), symbol -> name );
320
224
printf (" Events Pcnt (>=%d%%)\n" , sym_pcnt_filter );
321
225
322
226
pthread_mutex_lock (& syme -> src -> lock );
323
- line = syme -> src -> source ;
324
- while (line ) {
325
- total += line -> count [top .sym_counter ];
326
- line = line -> next ;
327
- }
328
-
329
- line = syme -> src -> source ;
330
- while (line ) {
331
- float pcnt = 0.0 ;
332
-
333
- if (!line_queue_count )
334
- line_queue = line ;
335
- line_queue_count ++ ;
336
-
337
- if (line -> count [top .sym_counter ])
338
- pcnt = 100.0 * line -> count [top .sym_counter ] / (float )total ;
339
- if (pcnt >= (float )sym_pcnt_filter ) {
340
- if (displayed <= top .print_entries )
341
- show_lines (line_queue , line_queue_count , total );
342
- else more ++ ;
343
- displayed += line_queue_count ;
344
- line_queue_count = 0 ;
345
- line_queue = NULL ;
346
- } else if (line_queue_count > TRACE_COUNT ) {
347
- line_queue = line_queue -> next ;
348
- line_queue_count -- ;
349
- }
350
-
351
- line -> count [top .sym_counter ] = top .zero ? 0 : line -> count [top .sym_counter ] * 7 / 8 ;
352
- line = line -> next ;
353
- }
227
+ more = symbol__annotate_printf (symbol , syme -> map , & syme -> src -> head ,
228
+ top .sym_evsel -> idx , 0 , sym_pcnt_filter ,
229
+ top .print_entries );
230
+ if (top .zero )
231
+ symbol__annotate_zero_histogram (symbol , top .sym_evsel -> idx );
232
+ else
233
+ symbol__annotate_decay_histogram (symbol , & syme -> src -> head ,
234
+ top .sym_evsel -> idx );
354
235
pthread_mutex_unlock (& syme -> src -> lock );
355
- if (more )
236
+ if (more != 0 )
356
237
printf ("%d lines not displayed, maybe increase display entries [e]\n" , more );
357
238
}
358
239
@@ -1172,7 +1053,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1172
1053
1173
1054
top .sym_evsel = list_entry (top .evlist -> entries .next , struct perf_evsel , node );
1174
1055
1175
- symbol_conf .priv_size = (sizeof (struct sym_entry ) +
1056
+ symbol_conf .priv_size = (sizeof (struct sym_entry ) + sizeof ( struct annotation ) +
1176
1057
(top .evlist -> nr_entries + 1 ) * sizeof (unsigned long ));
1177
1058
1178
1059
symbol_conf .try_vmlinux_path = (symbol_conf .vmlinux_name == NULL );
0 commit comments