7
7
#include "util/dso.h"
8
8
#include "util/util.h"
9
9
#include "util/debug.h"
10
+ #include "util/callchain.h"
10
11
11
12
#include "symbol.h"
12
13
@@ -30,6 +31,34 @@ static const char *dso__name(struct dso *dso)
30
31
return dso_name ;
31
32
}
32
33
34
+ static int inline_list__append (char * filename , char * funcname , int line_nr ,
35
+ struct inline_node * node , struct dso * dso )
36
+ {
37
+ struct inline_list * ilist ;
38
+ char * demangled ;
39
+
40
+ ilist = zalloc (sizeof (* ilist ));
41
+ if (ilist == NULL )
42
+ return -1 ;
43
+
44
+ ilist -> filename = filename ;
45
+ ilist -> line_nr = line_nr ;
46
+
47
+ if (dso != NULL ) {
48
+ demangled = dso__demangle_sym (dso , 0 , funcname );
49
+ if (demangled == NULL ) {
50
+ ilist -> funcname = funcname ;
51
+ } else {
52
+ ilist -> funcname = demangled ;
53
+ free (funcname );
54
+ }
55
+ }
56
+
57
+ list_add_tail (& ilist -> list , & node -> val );
58
+
59
+ return 0 ;
60
+ }
61
+
33
62
#ifdef HAVE_LIBBFD_SUPPORT
34
63
35
64
/*
@@ -169,9 +198,17 @@ static void addr2line_cleanup(struct a2l_data *a2l)
169
198
170
199
#define MAX_INLINE_NEST 1024
171
200
201
+ static void inline_list__reverse (struct inline_node * node )
202
+ {
203
+ struct inline_list * ilist , * n ;
204
+
205
+ list_for_each_entry_safe_reverse (ilist , n , & node -> val , list )
206
+ list_move_tail (& ilist -> list , & node -> val );
207
+ }
208
+
172
209
static int addr2line (const char * dso_name , u64 addr ,
173
210
char * * file , unsigned int * line , struct dso * dso ,
174
- bool unwind_inlines )
211
+ bool unwind_inlines , struct inline_node * node )
175
212
{
176
213
int ret = 0 ;
177
214
struct a2l_data * a2l = dso -> a2l ;
@@ -196,8 +233,21 @@ static int addr2line(const char *dso_name, u64 addr,
196
233
197
234
while (bfd_find_inliner_info (a2l -> abfd , & a2l -> filename ,
198
235
& a2l -> funcname , & a2l -> line ) &&
199
- cnt ++ < MAX_INLINE_NEST )
200
- ;
236
+ cnt ++ < MAX_INLINE_NEST ) {
237
+
238
+ if (node != NULL ) {
239
+ if (inline_list__append (strdup (a2l -> filename ),
240
+ strdup (a2l -> funcname ),
241
+ a2l -> line , node ,
242
+ dso ) != 0 )
243
+ return 0 ;
244
+ }
245
+ }
246
+
247
+ if ((node != NULL ) &&
248
+ (callchain_param .order != ORDER_CALLEE )) {
249
+ inline_list__reverse (node );
250
+ }
201
251
}
202
252
203
253
if (a2l -> found && a2l -> filename ) {
@@ -223,6 +273,35 @@ void dso__free_a2l(struct dso *dso)
223
273
dso -> a2l = NULL ;
224
274
}
225
275
276
+ static struct inline_node * addr2inlines (const char * dso_name , u64 addr ,
277
+ struct dso * dso )
278
+ {
279
+ char * file = NULL ;
280
+ unsigned int line = 0 ;
281
+ struct inline_node * node ;
282
+
283
+ node = zalloc (sizeof (* node ));
284
+ if (node == NULL ) {
285
+ perror ("not enough memory for the inline node" );
286
+ return NULL ;
287
+ }
288
+
289
+ INIT_LIST_HEAD (& node -> val );
290
+ node -> addr = addr ;
291
+
292
+ if (!addr2line (dso_name , addr , & file , & line , dso , TRUE, node ))
293
+ goto out_free_inline_node ;
294
+
295
+ if (list_empty (& node -> val ))
296
+ goto out_free_inline_node ;
297
+
298
+ return node ;
299
+
300
+ out_free_inline_node :
301
+ inline_node__delete (node );
302
+ return NULL ;
303
+ }
304
+
226
305
#else /* HAVE_LIBBFD_SUPPORT */
227
306
228
307
static int filename_split (char * filename , unsigned int * line_nr )
@@ -249,7 +328,8 @@ static int filename_split(char *filename, unsigned int *line_nr)
249
328
static int addr2line (const char * dso_name , u64 addr ,
250
329
char * * file , unsigned int * line_nr ,
251
330
struct dso * dso __maybe_unused ,
252
- bool unwind_inlines __maybe_unused )
331
+ bool unwind_inlines __maybe_unused ,
332
+ struct inline_node * node __maybe_unused )
253
333
{
254
334
FILE * fp ;
255
335
char cmd [PATH_MAX ];
@@ -288,6 +368,58 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
288
368
{
289
369
}
290
370
371
+ static struct inline_node * addr2inlines (const char * dso_name , u64 addr ,
372
+ struct dso * dso __maybe_unused )
373
+ {
374
+ FILE * fp ;
375
+ char cmd [PATH_MAX ];
376
+ struct inline_node * node ;
377
+ char * filename = NULL ;
378
+ size_t len ;
379
+ unsigned int line_nr = 0 ;
380
+
381
+ scnprintf (cmd , sizeof (cmd ), "addr2line -e %s -i %016" PRIx64 ,
382
+ dso_name , addr );
383
+
384
+ fp = popen (cmd , "r" );
385
+ if (fp == NULL ) {
386
+ pr_err ("popen failed for %s\n" , dso_name );
387
+ return NULL ;
388
+ }
389
+
390
+ node = zalloc (sizeof (* node ));
391
+ if (node == NULL ) {
392
+ perror ("not enough memory for the inline node" );
393
+ goto out ;
394
+ }
395
+
396
+ INIT_LIST_HEAD (& node -> val );
397
+ node -> addr = addr ;
398
+
399
+ while (getline (& filename , & len , fp ) != -1 ) {
400
+ if (filename_split (filename , & line_nr ) != 1 ) {
401
+ free (filename );
402
+ goto out ;
403
+ }
404
+
405
+ if (inline_list__append (filename , NULL , line_nr , node ,
406
+ NULL ) != 0 )
407
+ goto out ;
408
+
409
+ filename = NULL ;
410
+ }
411
+
412
+ out :
413
+ pclose (fp );
414
+
415
+ if (list_empty (& node -> val )) {
416
+ inline_node__delete (node );
417
+ return NULL ;
418
+ }
419
+
420
+ return node ;
421
+ }
422
+
291
423
#endif /* HAVE_LIBBFD_SUPPORT */
292
424
293
425
/*
@@ -311,7 +443,7 @@ char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
311
443
if (dso_name == NULL )
312
444
goto out ;
313
445
314
- if (!addr2line (dso_name , addr , & file , & line , dso , unwind_inlines ))
446
+ if (!addr2line (dso_name , addr , & file , & line , dso , unwind_inlines , NULL ))
315
447
goto out ;
316
448
317
449
if (asprintf (& srcline , "%s:%u" ,
@@ -351,3 +483,28 @@ char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
351
483
{
352
484
return __get_srcline (dso , addr , sym , show_sym , false);
353
485
}
486
+
487
+ struct inline_node * dso__parse_addr_inlines (struct dso * dso , u64 addr )
488
+ {
489
+ const char * dso_name ;
490
+
491
+ dso_name = dso__name (dso );
492
+ if (dso_name == NULL )
493
+ return NULL ;
494
+
495
+ return addr2inlines (dso_name , addr , dso );
496
+ }
497
+
498
+ void inline_node__delete (struct inline_node * node )
499
+ {
500
+ struct inline_list * ilist , * tmp ;
501
+
502
+ list_for_each_entry_safe (ilist , tmp , & node -> val , list ) {
503
+ list_del_init (& ilist -> list );
504
+ zfree (& ilist -> filename );
505
+ zfree (& ilist -> funcname );
506
+ free (ilist );
507
+ }
508
+
509
+ free (node );
510
+ }
0 commit comments