aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/dwarf-aux.c91
-rw-r--r--tools/perf/util/dwarf-aux.h3
2 files changed, 82 insertions, 12 deletions
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index d35b454f98b8..d9b8ad098498 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -198,6 +198,19 @@ static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
198 return 0; 198 return 0;
199} 199}
200 200
201/* Get attribute and translate it as a sdata */
202static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
203 Dwarf_Sword *result)
204{
205 Dwarf_Attribute attr;
206
207 if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
208 dwarf_formsdata(&attr, result) != 0)
209 return -ENOENT;
210
211 return 0;
212}
213
201/** 214/**
202 * die_is_signed_type - Check whether a type DIE is signed or not 215 * die_is_signed_type - Check whether a type DIE is signed or not
203 * @tp_die: a DIE of a type 216 * @tp_die: a DIE of a type
@@ -250,6 +263,39 @@ int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
250 return 0; 263 return 0;
251} 264}
252 265
266/* Get the call file index number in CU DIE */
267static int die_get_call_fileno(Dwarf_Die *in_die)
268{
269 Dwarf_Sword idx;
270
271 if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
272 return (int)idx;
273 else
274 return -ENOENT;
275}
276
277/**
278 * die_get_call_file - Get callsite file name of inlined function instance
279 * @in_die: a DIE of an inlined function instance
280 *
281 * Get call-site file name of @in_die. This means from which file the inline
282 * function is called.
283 */
284const char *die_get_call_file(Dwarf_Die *in_die)
285{
286 Dwarf_Die cu_die;
287 Dwarf_Files *files;
288 int idx;
289
290 idx = die_get_call_fileno(in_die);
291 if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
292 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
293 return NULL;
294
295 return dwarf_filesrc(files, idx, NULL, NULL);
296}
297
298
253/** 299/**
254 * die_find_child - Generic DIE search function in DIE tree 300 * die_find_child - Generic DIE search function in DIE tree
255 * @rt_die: a root DIE 301 * @rt_die: a root DIE
@@ -376,7 +422,7 @@ Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
376 422
377/* Line walker internal parameters */ 423/* Line walker internal parameters */
378struct __line_walk_param { 424struct __line_walk_param {
379 const char *fname; 425 bool recursive;
380 line_walk_callback_t callback; 426 line_walk_callback_t callback;
381 void *data; 427 void *data;
382 int retval; 428 int retval;
@@ -385,39 +431,56 @@ struct __line_walk_param {
385static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) 431static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
386{ 432{
387 struct __line_walk_param *lw = data; 433 struct __line_walk_param *lw = data;
388 Dwarf_Addr addr; 434 Dwarf_Addr addr = 0;
435 const char *fname;
389 int lineno; 436 int lineno;
390 437
391 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { 438 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
439 fname = die_get_call_file(in_die);
392 lineno = die_get_call_lineno(in_die); 440 lineno = die_get_call_lineno(in_die);
393 if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) { 441 if (fname && lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
394 lw->retval = lw->callback(lw->fname, lineno, addr, 442 lw->retval = lw->callback(fname, lineno, addr, lw->data);
395 lw->data);
396 if (lw->retval != 0) 443 if (lw->retval != 0)
397 return DIE_FIND_CB_END; 444 return DIE_FIND_CB_END;
398 } 445 }
399 } 446 }
400 return DIE_FIND_CB_SIBLING; 447 if (!lw->recursive)
448 /* Don't need to search recursively */
449 return DIE_FIND_CB_SIBLING;
450
451 if (addr) {
452 fname = dwarf_decl_file(in_die);
453 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
454 lw->retval = lw->callback(fname, lineno, addr, lw->data);
455 if (lw->retval != 0)
456 return DIE_FIND_CB_END;
457 }
458 }
459
460 /* Continue to search nested inlined function call-sites */
461 return DIE_FIND_CB_CONTINUE;
401} 462}
402 463
403/* Walk on lines of blocks included in given DIE */ 464/* Walk on lines of blocks included in given DIE */
404static int __die_walk_funclines(Dwarf_Die *sp_die, 465static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
405 line_walk_callback_t callback, void *data) 466 line_walk_callback_t callback, void *data)
406{ 467{
407 struct __line_walk_param lw = { 468 struct __line_walk_param lw = {
469 .recursive = recursive,
408 .callback = callback, 470 .callback = callback,
409 .data = data, 471 .data = data,
410 .retval = 0, 472 .retval = 0,
411 }; 473 };
412 Dwarf_Die die_mem; 474 Dwarf_Die die_mem;
413 Dwarf_Addr addr; 475 Dwarf_Addr addr;
476 const char *fname;
414 int lineno; 477 int lineno;
415 478
416 /* Handle function declaration line */ 479 /* Handle function declaration line */
417 lw.fname = dwarf_decl_file(sp_die); 480 fname = dwarf_decl_file(sp_die);
418 if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 && 481 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
419 dwarf_entrypc(sp_die, &addr) == 0) { 482 dwarf_entrypc(sp_die, &addr) == 0) {
420 lw.retval = callback(lw.fname, lineno, addr, data); 483 lw.retval = callback(fname, lineno, addr, data);
421 if (lw.retval != 0) 484 if (lw.retval != 0)
422 goto done; 485 goto done;
423 } 486 }
@@ -430,7 +493,7 @@ static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
430{ 493{
431 struct __line_walk_param *lw = data; 494 struct __line_walk_param *lw = data;
432 495
433 lw->retval = __die_walk_funclines(sp_die, lw->callback, lw->data); 496 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
434 if (lw->retval != 0) 497 if (lw->retval != 0)
435 return DWARF_CB_ABORT; 498 return DWARF_CB_ABORT;
436 499
@@ -509,7 +572,11 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
509 * subroutines. We have to check functions list or given function. 572 * subroutines. We have to check functions list or given function.
510 */ 573 */
511 if (rt_die != cu_die) 574 if (rt_die != cu_die)
512 ret = __die_walk_funclines(rt_die, callback, data); 575 /*
576 * Don't need walk functions recursively, because nested
577 * inlined functions don't have lines of the specified DIE.
578 */
579 ret = __die_walk_funclines(rt_die, false, callback, data);
513 else { 580 else {
514 struct __line_walk_param param = { 581 struct __line_walk_param param = {
515 .callback = callback, 582 .callback = callback,
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index bc3b21167e70..c8e491bc133f 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -40,6 +40,9 @@ extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);
40/* Get callsite line number of inline-function instance */ 40/* Get callsite line number of inline-function instance */
41extern int die_get_call_lineno(Dwarf_Die *in_die); 41extern int die_get_call_lineno(Dwarf_Die *in_die);
42 42
43/* Get callsite file name of inlined function instance */
44extern const char *die_get_call_file(Dwarf_Die *in_die);
45
43/* Get type die */ 46/* Get type die */
44extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); 47extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
45 48