9
9
10
10
#include "util/util.h"
11
11
12
+ #include "util/util.h"
12
13
#include "util/color.h"
13
14
#include <linux/list.h>
14
15
#include "util/cache.h"
18
19
#include "perf.h"
19
20
#include "util/debug.h"
20
21
22
+ #include "util/annotate.h"
21
23
#include "util/event.h"
22
24
#include "util/parse-options.h"
23
25
#include "util/parse-events.h"
@@ -55,7 +57,18 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
55
57
if (he == NULL )
56
58
return - ENOMEM ;
57
59
58
- return hist_entry__inc_addr_samples (he , al -> addr );
60
+ if (he -> ms .sym != NULL ) {
61
+ /*
62
+ * All aggregated on the first sym_hist.
63
+ */
64
+ struct annotation * notes = symbol__annotation (he -> ms .sym );
65
+ if (notes -> histograms == NULL && symbol__alloc_hist (he -> ms .sym , 1 ) < 0 )
66
+ return - ENOMEM ;
67
+
68
+ return hist_entry__inc_addr_samples (he , 0 , al -> addr );
69
+ }
70
+
71
+ return 0 ;
59
72
}
60
73
61
74
static int process_sample_event (union perf_event * event ,
@@ -79,245 +92,10 @@ static int process_sample_event(union perf_event *event,
79
92
return 0 ;
80
93
}
81
94
82
- static int objdump_line__print (struct objdump_line * self ,
83
- struct list_head * head ,
84
- struct hist_entry * he , u64 len )
85
- {
86
- struct symbol * sym = he -> ms .sym ;
87
- static const char * prev_line ;
88
- static const char * prev_color ;
89
-
90
- if (self -> offset != -1 ) {
91
- const char * path = NULL ;
92
- unsigned int hits = 0 ;
93
- double percent = 0.0 ;
94
- const char * color ;
95
- struct sym_priv * priv = symbol__priv (sym );
96
- struct sym_ext * sym_ext = priv -> ext ;
97
- struct sym_hist * h = priv -> hist ;
98
- s64 offset = self -> offset ;
99
- struct objdump_line * next = objdump__get_next_ip_line (head , self );
100
-
101
- while (offset < (s64 )len &&
102
- (next == NULL || offset < next -> offset )) {
103
- if (sym_ext ) {
104
- if (path == NULL )
105
- path = sym_ext [offset ].path ;
106
- percent += sym_ext [offset ].percent ;
107
- } else
108
- hits += h -> ip [offset ];
109
-
110
- ++ offset ;
111
- }
112
-
113
- if (sym_ext == NULL && h -> sum )
114
- percent = 100.0 * hits / h -> sum ;
115
-
116
- color = get_percent_color (percent );
117
-
118
- /*
119
- * Also color the filename and line if needed, with
120
- * the same color than the percentage. Don't print it
121
- * twice for close colored ip with the same filename:line
122
- */
123
- if (path ) {
124
- if (!prev_line || strcmp (prev_line , path )
125
- || color != prev_color ) {
126
- color_fprintf (stdout , color , " %s" , path );
127
- prev_line = path ;
128
- prev_color = color ;
129
- }
130
- }
131
-
132
- color_fprintf (stdout , color , " %7.2f" , percent );
133
- printf (" : " );
134
- color_fprintf (stdout , PERF_COLOR_BLUE , "%s\n" , self -> line );
135
- } else {
136
- if (!* self -> line )
137
- printf (" :\n" );
138
- else
139
- printf (" : %s\n" , self -> line );
140
- }
141
-
142
- return 0 ;
143
- }
144
-
145
- static struct rb_root root_sym_ext ;
146
-
147
- static void insert_source_line (struct sym_ext * sym_ext )
148
- {
149
- struct sym_ext * iter ;
150
- struct rb_node * * p = & root_sym_ext .rb_node ;
151
- struct rb_node * parent = NULL ;
152
-
153
- while (* p != NULL ) {
154
- parent = * p ;
155
- iter = rb_entry (parent , struct sym_ext , node );
156
-
157
- if (sym_ext -> percent > iter -> percent )
158
- p = & (* p )-> rb_left ;
159
- else
160
- p = & (* p )-> rb_right ;
161
- }
162
-
163
- rb_link_node (& sym_ext -> node , parent , p );
164
- rb_insert_color (& sym_ext -> node , & root_sym_ext );
165
- }
166
-
167
- static void free_source_line (struct hist_entry * he , int len )
168
- {
169
- struct sym_priv * priv = symbol__priv (he -> ms .sym );
170
- struct sym_ext * sym_ext = priv -> ext ;
171
- int i ;
172
-
173
- if (!sym_ext )
174
- return ;
175
-
176
- for (i = 0 ; i < len ; i ++ )
177
- free (sym_ext [i ].path );
178
- free (sym_ext );
179
-
180
- priv -> ext = NULL ;
181
- root_sym_ext = RB_ROOT ;
182
- }
183
-
184
- /* Get the filename:line for the colored entries */
185
- static void
186
- get_source_line (struct hist_entry * he , int len , const char * filename )
187
- {
188
- struct symbol * sym = he -> ms .sym ;
189
- u64 start ;
190
- int i ;
191
- char cmd [PATH_MAX * 2 ];
192
- struct sym_ext * sym_ext ;
193
- struct sym_priv * priv = symbol__priv (sym );
194
- struct sym_hist * h = priv -> hist ;
195
-
196
- if (!h -> sum )
197
- return ;
198
-
199
- sym_ext = priv -> ext = calloc (len , sizeof (struct sym_ext ));
200
- if (!priv -> ext )
201
- return ;
202
-
203
- start = he -> ms .map -> unmap_ip (he -> ms .map , sym -> start );
204
-
205
- for (i = 0 ; i < len ; i ++ ) {
206
- char * path = NULL ;
207
- size_t line_len ;
208
- u64 offset ;
209
- FILE * fp ;
210
-
211
- sym_ext [i ].percent = 100.0 * h -> ip [i ] / h -> sum ;
212
- if (sym_ext [i ].percent <= 0.5 )
213
- continue ;
214
-
215
- offset = start + i ;
216
- sprintf (cmd , "addr2line -e %s %016" PRIx64 , filename , offset );
217
- fp = popen (cmd , "r" );
218
- if (!fp )
219
- continue ;
220
-
221
- if (getline (& path , & line_len , fp ) < 0 || !line_len )
222
- goto next ;
223
-
224
- sym_ext [i ].path = malloc (sizeof (char ) * line_len + 1 );
225
- if (!sym_ext [i ].path )
226
- goto next ;
227
-
228
- strcpy (sym_ext [i ].path , path );
229
- insert_source_line (& sym_ext [i ]);
230
-
231
- next :
232
- pclose (fp );
233
- }
234
- }
235
-
236
- static void print_summary (const char * filename )
95
+ static int hist_entry__tty_annotate (struct hist_entry * he , int evidx )
237
96
{
238
- struct sym_ext * sym_ext ;
239
- struct rb_node * node ;
240
-
241
- printf ("\nSorted summary for file %s\n" , filename );
242
- printf ("----------------------------------------------\n\n" );
243
-
244
- if (RB_EMPTY_ROOT (& root_sym_ext )) {
245
- printf (" Nothing higher than %1.1f%%\n" , MIN_GREEN );
246
- return ;
247
- }
248
-
249
- node = rb_first (& root_sym_ext );
250
- while (node ) {
251
- double percent ;
252
- const char * color ;
253
- char * path ;
254
-
255
- sym_ext = rb_entry (node , struct sym_ext , node );
256
- percent = sym_ext -> percent ;
257
- color = get_percent_color (percent );
258
- path = sym_ext -> path ;
259
-
260
- color_fprintf (stdout , color , " %7.2f %s" , percent , path );
261
- node = rb_next (node );
262
- }
263
- }
264
-
265
- static void hist_entry__print_hits (struct hist_entry * self )
266
- {
267
- struct symbol * sym = self -> ms .sym ;
268
- struct sym_priv * priv = symbol__priv (sym );
269
- struct sym_hist * h = priv -> hist ;
270
- u64 len = sym -> end - sym -> start , offset ;
271
-
272
- for (offset = 0 ; offset < len ; ++ offset )
273
- if (h -> ip [offset ] != 0 )
274
- printf ("%*" PRIx64 ": %" PRIu64 "\n" , BITS_PER_LONG / 2 ,
275
- sym -> start + offset , h -> ip [offset ]);
276
- printf ("%*s: %" PRIu64 "\n" , BITS_PER_LONG / 2 , "h->sum" , h -> sum );
277
- }
278
-
279
- static int hist_entry__tty_annotate (struct hist_entry * he )
280
- {
281
- struct map * map = he -> ms .map ;
282
- struct dso * dso = map -> dso ;
283
- struct symbol * sym = he -> ms .sym ;
284
- const char * filename = dso -> long_name , * d_filename ;
285
- u64 len ;
286
- LIST_HEAD (head );
287
- struct objdump_line * pos , * n ;
288
-
289
- if (hist_entry__annotate (he , & head , 0 ) < 0 )
290
- return -1 ;
291
-
292
- if (full_paths )
293
- d_filename = filename ;
294
- else
295
- d_filename = basename (filename );
296
-
297
- len = sym -> end - sym -> start ;
298
-
299
- if (print_line ) {
300
- get_source_line (he , len , filename );
301
- print_summary (filename );
302
- }
303
-
304
- printf ("\n\n------------------------------------------------\n" );
305
- printf (" Percent | Source code & Disassembly of %s\n" , d_filename );
306
- printf ("------------------------------------------------\n" );
307
-
308
- if (verbose )
309
- hist_entry__print_hits (he );
310
-
311
- list_for_each_entry_safe (pos , n , & head , node ) {
312
- objdump_line__print (pos , & head , he , len );
313
- list_del (& pos -> node );
314
- objdump_line__free (pos );
315
- }
316
-
317
- if (print_line )
318
- free_source_line (he , len );
319
-
320
- return 0 ;
97
+ return symbol__tty_annotate (he -> ms .sym , he -> ms .map , evidx ,
98
+ print_line , full_paths , 0 , 0 );
321
99
}
322
100
323
101
static void hists__find_annotations (struct hists * self )
@@ -327,13 +105,13 @@ static void hists__find_annotations(struct hists *self)
327
105
328
106
while (nd ) {
329
107
struct hist_entry * he = rb_entry (nd , struct hist_entry , rb_node );
330
- struct sym_priv * priv ;
108
+ struct annotation * notes ;
331
109
332
110
if (he -> ms .sym == NULL || he -> ms .map -> dso -> annotate_warned )
333
111
goto find_next ;
334
112
335
- priv = symbol__priv (he -> ms .sym );
336
- if (priv -> hist == NULL ) {
113
+ notes = symbol__annotation (he -> ms .sym );
114
+ if (notes -> histograms == NULL ) {
337
115
find_next :
338
116
if (key == KEY_LEFT )
339
117
nd = rb_prev (nd );
@@ -343,7 +121,8 @@ static void hists__find_annotations(struct hists *self)
343
121
}
344
122
345
123
if (use_browser > 0 ) {
346
- key = hist_entry__tui_annotate (he );
124
+ /* For now all is aggregated on the first */
125
+ key = hist_entry__tui_annotate (he , 0 );
347
126
switch (key ) {
348
127
case KEY_RIGHT :
349
128
next = rb_next (nd );
@@ -358,15 +137,16 @@ static void hists__find_annotations(struct hists *self)
358
137
if (next != NULL )
359
138
nd = next ;
360
139
} else {
361
- hist_entry__tty_annotate (he );
140
+ /* For now all is aggregated on the first */
141
+ hist_entry__tty_annotate (he , 0 );
362
142
nd = rb_next (nd );
363
143
/*
364
144
* Since we have a hist_entry per IP for the same
365
- * symbol, free he->ms.sym->hist to signal we already
145
+ * symbol, free he->ms.sym->histogram to signal we already
366
146
* processed this symbol.
367
147
*/
368
- free (priv -> hist );
369
- priv -> hist = NULL ;
148
+ free (notes -> histograms );
149
+ notes -> histograms = NULL ;
370
150
}
371
151
}
372
152
}
@@ -454,7 +234,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
454
234
455
235
setup_browser (true);
456
236
457
- symbol_conf .priv_size = sizeof (struct sym_priv );
237
+ symbol_conf .priv_size = sizeof (struct annotation );
458
238
symbol_conf .try_vmlinux_path = true;
459
239
460
240
if (symbol__init () < 0 )
0 commit comments