root/tools/perf/util/dwarf-aux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cu_find_realpath
  2. cu_get_comp_dir
  3. cu_find_lineinfo
  4. cu_walk_functions_at
  5. die_get_linkage_name
  6. die_compare_name
  7. die_match_name
  8. die_get_call_lineno
  9. die_get_type
  10. __die_get_real_type
  11. die_get_real_type
  12. die_get_attr_udata
  13. die_get_attr_sdata
  14. die_is_signed_type
  15. die_is_func_def
  16. die_entrypc
  17. die_is_func_instance
  18. die_get_data_member_location
  19. die_get_call_fileno
  20. die_get_decl_fileno
  21. die_get_call_file
  22. die_find_child
  23. __die_search_func_tail_cb
  24. die_find_tailfunc
  25. __die_search_func_cb
  26. die_find_realfunc
  27. __die_find_inline_cb
  28. die_find_top_inlinefunc
  29. die_find_inlinefunc
  30. __die_walk_instances_cb
  31. die_walk_instances
  32. __die_walk_funclines_cb
  33. __die_walk_funclines
  34. __die_walk_culines_cb
  35. die_walk_lines
  36. __die_find_variable_cb
  37. die_find_variable_at
  38. __die_find_member_cb
  39. die_find_member
  40. die_get_typename
  41. die_get_varname
  42. die_get_var_innermost_scope
  43. die_get_var_range
  44. die_get_var_range
  45. die_has_loclist
  46. die_is_optimized_target
  47. die_search_idx
  48. die_get_postprologue_addr
  49. die_skip_prologue

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * dwarf-aux.c : libdw auxiliary interfaces
   4  */
   5 
   6 #include <errno.h>
   7 #include <inttypes.h>
   8 #include <stdbool.h>
   9 #include <stdlib.h>
  10 #include "debug.h"
  11 #include "dwarf-aux.h"
  12 #include "strbuf.h"
  13 #include "string2.h"
  14 
  15 /**
  16  * cu_find_realpath - Find the realpath of the target file
  17  * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)
  18  * @fname:  The tail filename of the target file
  19  *
  20  * Find the real(long) path of @fname in @cu_die.
  21  */
  22 const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname)
  23 {
  24         Dwarf_Files *files;
  25         size_t nfiles, i;
  26         const char *src = NULL;
  27         int ret;
  28 
  29         if (!fname)
  30                 return NULL;
  31 
  32         ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
  33         if (ret != 0)
  34                 return NULL;
  35 
  36         for (i = 0; i < nfiles; i++) {
  37                 src = dwarf_filesrc(files, i, NULL, NULL);
  38                 if (strtailcmp(src, fname) == 0)
  39                         break;
  40         }
  41         if (i == nfiles)
  42                 return NULL;
  43         return src;
  44 }
  45 
  46 /**
  47  * cu_get_comp_dir - Get the path of compilation directory
  48  * @cu_die: a CU DIE
  49  *
  50  * Get the path of compilation directory of given @cu_die.
  51  * Since this depends on DW_AT_comp_dir, older gcc will not
  52  * embedded it. In that case, this returns NULL.
  53  */
  54 const char *cu_get_comp_dir(Dwarf_Die *cu_die)
  55 {
  56         Dwarf_Attribute attr;
  57         if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL)
  58                 return NULL;
  59         return dwarf_formstring(&attr);
  60 }
  61 
  62 /**
  63  * cu_find_lineinfo - Get a line number and file name for given address
  64  * @cu_die: a CU DIE
  65  * @addr: An address
  66  * @fname: a pointer which returns the file name string
  67  * @lineno: a pointer which returns the line number
  68  *
  69  * Find a line number and file name for @addr in @cu_die.
  70  */
  71 int cu_find_lineinfo(Dwarf_Die *cu_die, unsigned long addr,
  72                     const char **fname, int *lineno)
  73 {
  74         Dwarf_Line *line;
  75         Dwarf_Addr laddr;
  76 
  77         line = dwarf_getsrc_die(cu_die, (Dwarf_Addr)addr);
  78         if (line && dwarf_lineaddr(line, &laddr) == 0 &&
  79             addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
  80                 *fname = dwarf_linesrc(line, NULL, NULL);
  81                 if (!*fname)
  82                         /* line number is useless without filename */
  83                         *lineno = 0;
  84         }
  85 
  86         return *lineno ?: -ENOENT;
  87 }
  88 
  89 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
  90 
  91 /**
  92  * cu_walk_functions_at - Walk on function DIEs at given address
  93  * @cu_die: A CU DIE
  94  * @addr: An address
  95  * @callback: A callback which called with found DIEs
  96  * @data: A user data
  97  *
  98  * Walk on function DIEs at given @addr in @cu_die. Passed DIEs
  99  * should be subprogram or inlined-subroutines.
 100  */
 101 int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
 102                     int (*callback)(Dwarf_Die *, void *), void *data)
 103 {
 104         Dwarf_Die die_mem;
 105         Dwarf_Die *sc_die;
 106         int ret = -ENOENT;
 107 
 108         /* Inlined function could be recursive. Trace it until fail */
 109         for (sc_die = die_find_realfunc(cu_die, addr, &die_mem);
 110              sc_die != NULL;
 111              sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr,
 112                                      &die_mem)) {
 113                 ret = callback(sc_die, data);
 114                 if (ret)
 115                         break;
 116         }
 117 
 118         return ret;
 119 
 120 }
 121 
 122 /**
 123  * die_get_linkage_name - Get the linkage name of the object
 124  * @dw_die: A DIE of the object
 125  *
 126  * Get the linkage name attiribute of given @dw_die.
 127  * For C++ binary, the linkage name will be the mangled symbol.
 128  */
 129 const char *die_get_linkage_name(Dwarf_Die *dw_die)
 130 {
 131         Dwarf_Attribute attr;
 132 
 133         if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
 134                 return NULL;
 135         return dwarf_formstring(&attr);
 136 }
 137 
 138 /**
 139  * die_compare_name - Compare diename and tname
 140  * @dw_die: a DIE
 141  * @tname: a string of target name
 142  *
 143  * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.
 144  */
 145 bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
 146 {
 147         const char *name;
 148 
 149         name = dwarf_diename(dw_die);
 150         return name ? (strcmp(tname, name) == 0) : false;
 151 }
 152 
 153 /**
 154  * die_match_name - Match diename/linkage name and glob
 155  * @dw_die: a DIE
 156  * @glob: a string of target glob pattern
 157  *
 158  * Glob matching the name of @dw_die and @glob. Return false if matching fail.
 159  * This also match linkage name.
 160  */
 161 bool die_match_name(Dwarf_Die *dw_die, const char *glob)
 162 {
 163         const char *name;
 164 
 165         name = dwarf_diename(dw_die);
 166         if (name && strglobmatch(name, glob))
 167                 return true;
 168         /* fall back to check linkage name */
 169         name = die_get_linkage_name(dw_die);
 170         if (name && strglobmatch(name, glob))
 171                 return true;
 172 
 173         return false;
 174 }
 175 
 176 /**
 177  * die_get_call_lineno - Get callsite line number of inline-function instance
 178  * @in_die: a DIE of an inlined function instance
 179  *
 180  * Get call-site line number of @in_die. This means from where the inline
 181  * function is called.
 182  */
 183 int die_get_call_lineno(Dwarf_Die *in_die)
 184 {
 185         Dwarf_Attribute attr;
 186         Dwarf_Word ret;
 187 
 188         if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
 189                 return -ENOENT;
 190 
 191         dwarf_formudata(&attr, &ret);
 192         return (int)ret;
 193 }
 194 
 195 /**
 196  * die_get_type - Get type DIE
 197  * @vr_die: a DIE of a variable
 198  * @die_mem: where to store a type DIE
 199  *
 200  * Get a DIE of the type of given variable (@vr_die), and store
 201  * it to die_mem. Return NULL if fails to get a type DIE.
 202  */
 203 Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
 204 {
 205         Dwarf_Attribute attr;
 206 
 207         if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) &&
 208             dwarf_formref_die(&attr, die_mem))
 209                 return die_mem;
 210         else
 211                 return NULL;
 212 }
 213 
 214 /* Get a type die, but skip qualifiers */
 215 static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
 216 {
 217         int tag;
 218 
 219         do {
 220                 vr_die = die_get_type(vr_die, die_mem);
 221                 if (!vr_die)
 222                         break;
 223                 tag = dwarf_tag(vr_die);
 224         } while (tag == DW_TAG_const_type ||
 225                  tag == DW_TAG_restrict_type ||
 226                  tag == DW_TAG_volatile_type ||
 227                  tag == DW_TAG_shared_type);
 228 
 229         return vr_die;
 230 }
 231 
 232 /**
 233  * die_get_real_type - Get a type die, but skip qualifiers and typedef
 234  * @vr_die: a DIE of a variable
 235  * @die_mem: where to store a type DIE
 236  *
 237  * Get a DIE of the type of given variable (@vr_die), and store
 238  * it to die_mem. Return NULL if fails to get a type DIE.
 239  * If the type is qualifiers (e.g. const) or typedef, this skips it
 240  * and tries to find real type (structure or basic types, e.g. int).
 241  */
 242 Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
 243 {
 244         do {
 245                 vr_die = __die_get_real_type(vr_die, die_mem);
 246         } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef);
 247 
 248         return vr_die;
 249 }
 250 
 251 /* Get attribute and translate it as a udata */
 252 static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
 253                               Dwarf_Word *result)
 254 {
 255         Dwarf_Attribute attr;
 256 
 257         if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
 258             dwarf_formudata(&attr, result) != 0)
 259                 return -ENOENT;
 260 
 261         return 0;
 262 }
 263 
 264 /* Get attribute and translate it as a sdata */
 265 static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name,
 266                               Dwarf_Sword *result)
 267 {
 268         Dwarf_Attribute attr;
 269 
 270         if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
 271             dwarf_formsdata(&attr, result) != 0)
 272                 return -ENOENT;
 273 
 274         return 0;
 275 }
 276 
 277 /**
 278  * die_is_signed_type - Check whether a type DIE is signed or not
 279  * @tp_die: a DIE of a type
 280  *
 281  * Get the encoding of @tp_die and return true if the encoding
 282  * is signed.
 283  */
 284 bool die_is_signed_type(Dwarf_Die *tp_die)
 285 {
 286         Dwarf_Word ret;
 287 
 288         if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
 289                 return false;
 290 
 291         return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
 292                 ret == DW_ATE_signed_fixed);
 293 }
 294 
 295 /**
 296  * die_is_func_def - Ensure that this DIE is a subprogram and definition
 297  * @dw_die: a DIE
 298  *
 299  * Ensure that this DIE is a subprogram and NOT a declaration. This
 300  * returns true if @dw_die is a function definition.
 301  **/
 302 bool die_is_func_def(Dwarf_Die *dw_die)
 303 {
 304         Dwarf_Attribute attr;
 305 
 306         return (dwarf_tag(dw_die) == DW_TAG_subprogram &&
 307                 dwarf_attr(dw_die, DW_AT_declaration, &attr) == NULL);
 308 }
 309 
 310 /**
 311  * die_entrypc - Returns entry PC (the lowest address) of a DIE
 312  * @dw_die: a DIE
 313  * @addr: where to store entry PC
 314  *
 315  * Since dwarf_entrypc() does not return entry PC if the DIE has only address
 316  * range, we have to use this to retrieve the lowest address from the address
 317  * range attribute.
 318  */
 319 int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr)
 320 {
 321         Dwarf_Addr base, end;
 322 
 323         if (!addr)
 324                 return -EINVAL;
 325 
 326         if (dwarf_entrypc(dw_die, addr) == 0)
 327                 return 0;
 328 
 329         return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0;
 330 }
 331 
 332 /**
 333  * die_is_func_instance - Ensure that this DIE is an instance of a subprogram
 334  * @dw_die: a DIE
 335  *
 336  * Ensure that this DIE is an instance (which has an entry address).
 337  * This returns true if @dw_die is a function instance. If not, the @dw_die
 338  * must be a prototype. You can use die_walk_instances() to find actual
 339  * instances.
 340  **/
 341 bool die_is_func_instance(Dwarf_Die *dw_die)
 342 {
 343         Dwarf_Addr tmp;
 344         Dwarf_Attribute attr_mem;
 345         int tag = dwarf_tag(dw_die);
 346 
 347         if (tag != DW_TAG_subprogram &&
 348             tag != DW_TAG_inlined_subroutine)
 349                 return false;
 350 
 351         return dwarf_entrypc(dw_die, &tmp) == 0 ||
 352                 dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL;
 353 }
 354 
 355 /**
 356  * die_get_data_member_location - Get the data-member offset
 357  * @mb_die: a DIE of a member of a data structure
 358  * @offs: The offset of the member in the data structure
 359  *
 360  * Get the offset of @mb_die in the data structure including @mb_die, and
 361  * stores result offset to @offs. If any error occurs this returns errno.
 362  */
 363 int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs)
 364 {
 365         Dwarf_Attribute attr;
 366         Dwarf_Op *expr;
 367         size_t nexpr;
 368         int ret;
 369 
 370         if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL)
 371                 return -ENOENT;
 372 
 373         if (dwarf_formudata(&attr, offs) != 0) {
 374                 /* DW_AT_data_member_location should be DW_OP_plus_uconst */
 375                 ret = dwarf_getlocation(&attr, &expr, &nexpr);
 376                 if (ret < 0 || nexpr == 0)
 377                         return -ENOENT;
 378 
 379                 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) {
 380                         pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n",
 381                                  expr[0].atom, nexpr);
 382                         return -ENOTSUP;
 383                 }
 384                 *offs = (Dwarf_Word)expr[0].number;
 385         }
 386         return 0;
 387 }
 388 
 389 /* Get the call file index number in CU DIE */
 390 static int die_get_call_fileno(Dwarf_Die *in_die)
 391 {
 392         Dwarf_Sword idx;
 393 
 394         if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0)
 395                 return (int)idx;
 396         else
 397                 return -ENOENT;
 398 }
 399 
 400 /* Get the declared file index number in CU DIE */
 401 static int die_get_decl_fileno(Dwarf_Die *pdie)
 402 {
 403         Dwarf_Sword idx;
 404 
 405         if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0)
 406                 return (int)idx;
 407         else
 408                 return -ENOENT;
 409 }
 410 
 411 /**
 412  * die_get_call_file - Get callsite file name of inlined function instance
 413  * @in_die: a DIE of an inlined function instance
 414  *
 415  * Get call-site file name of @in_die. This means from which file the inline
 416  * function is called.
 417  */
 418 const char *die_get_call_file(Dwarf_Die *in_die)
 419 {
 420         Dwarf_Die cu_die;
 421         Dwarf_Files *files;
 422         int idx;
 423 
 424         idx = die_get_call_fileno(in_die);
 425         if (idx < 0 || !dwarf_diecu(in_die, &cu_die, NULL, NULL) ||
 426             dwarf_getsrcfiles(&cu_die, &files, NULL) != 0)
 427                 return NULL;
 428 
 429         return dwarf_filesrc(files, idx, NULL, NULL);
 430 }
 431 
 432 
 433 /**
 434  * die_find_child - Generic DIE search function in DIE tree
 435  * @rt_die: a root DIE
 436  * @callback: a callback function
 437  * @data: a user data passed to the callback function
 438  * @die_mem: a buffer for result DIE
 439  *
 440  * Trace DIE tree from @rt_die and call @callback for each child DIE.
 441  * If @callback returns DIE_FIND_CB_END, this stores the DIE into
 442  * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,
 443  * this continues to trace the tree. Optionally, @callback can return
 444  * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only
 445  * the children and trace only the siblings respectively.
 446  * Returns NULL if @callback can't find any appropriate DIE.
 447  */
 448 Dwarf_Die *die_find_child(Dwarf_Die *rt_die,
 449                           int (*callback)(Dwarf_Die *, void *),
 450                           void *data, Dwarf_Die *die_mem)
 451 {
 452         Dwarf_Die child_die;
 453         int ret;
 454 
 455         ret = dwarf_child(rt_die, die_mem);
 456         if (ret != 0)
 457                 return NULL;
 458 
 459         do {
 460                 ret = callback(die_mem, data);
 461                 if (ret == DIE_FIND_CB_END)
 462                         return die_mem;
 463 
 464                 if ((ret & DIE_FIND_CB_CHILD) &&
 465                     die_find_child(die_mem, callback, data, &child_die)) {
 466                         memcpy(die_mem, &child_die, sizeof(Dwarf_Die));
 467                         return die_mem;
 468                 }
 469         } while ((ret & DIE_FIND_CB_SIBLING) &&
 470                  dwarf_siblingof(die_mem, die_mem) == 0);
 471 
 472         return NULL;
 473 }
 474 
 475 struct __addr_die_search_param {
 476         Dwarf_Addr      addr;
 477         Dwarf_Die       *die_mem;
 478 };
 479 
 480 static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data)
 481 {
 482         struct __addr_die_search_param *ad = data;
 483         Dwarf_Addr addr = 0;
 484 
 485         if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
 486             !dwarf_highpc(fn_die, &addr) &&
 487             addr == ad->addr) {
 488                 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
 489                 return DWARF_CB_ABORT;
 490         }
 491         return DWARF_CB_OK;
 492 }
 493 
 494 /**
 495  * die_find_tailfunc - Search for a non-inlined function with tail call at
 496  * given address
 497  * @cu_die: a CU DIE which including @addr
 498  * @addr: target address
 499  * @die_mem: a buffer for result DIE
 500  *
 501  * Search for a non-inlined function DIE with tail call at @addr. Stores the
 502  * DIE to @die_mem and returns it if found. Returns NULL if failed.
 503  */
 504 Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
 505                                     Dwarf_Die *die_mem)
 506 {
 507         struct __addr_die_search_param ad;
 508         ad.addr = addr;
 509         ad.die_mem = die_mem;
 510         /* dwarf_getscopes can't find subprogram. */
 511         if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0))
 512                 return NULL;
 513         else
 514                 return die_mem;
 515 }
 516 
 517 /* die_find callback for non-inlined function search */
 518 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
 519 {
 520         struct __addr_die_search_param *ad = data;
 521 
 522         /*
 523          * Since a declaration entry doesn't has given pc, this always returns
 524          * function definition entry.
 525          */
 526         if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
 527             dwarf_haspc(fn_die, ad->addr)) {
 528                 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
 529                 return DWARF_CB_ABORT;
 530         }
 531         return DWARF_CB_OK;
 532 }
 533 
 534 /**
 535  * die_find_realfunc - Search a non-inlined function at given address
 536  * @cu_die: a CU DIE which including @addr
 537  * @addr: target address
 538  * @die_mem: a buffer for result DIE
 539  *
 540  * Search a non-inlined function DIE which includes @addr. Stores the
 541  * DIE to @die_mem and returns it if found. Returns NULL if failed.
 542  */
 543 Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr,
 544                                     Dwarf_Die *die_mem)
 545 {
 546         struct __addr_die_search_param ad;
 547         ad.addr = addr;
 548         ad.die_mem = die_mem;
 549         /* dwarf_getscopes can't find subprogram. */
 550         if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
 551                 return NULL;
 552         else
 553                 return die_mem;
 554 }
 555 
 556 /* die_find callback for inline function search */
 557 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
 558 {
 559         Dwarf_Addr *addr = data;
 560 
 561         if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine &&
 562             dwarf_haspc(die_mem, *addr))
 563                 return DIE_FIND_CB_END;
 564 
 565         return DIE_FIND_CB_CONTINUE;
 566 }
 567 
 568 /**
 569  * die_find_top_inlinefunc - Search the top inlined function at given address
 570  * @sp_die: a subprogram DIE which including @addr
 571  * @addr: target address
 572  * @die_mem: a buffer for result DIE
 573  *
 574  * Search an inlined function DIE which includes @addr. Stores the
 575  * DIE to @die_mem and returns it if found. Returns NULL if failed.
 576  * Even if several inlined functions are expanded recursively, this
 577  * doesn't trace it down, and returns the topmost one.
 578  */
 579 Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
 580                                    Dwarf_Die *die_mem)
 581 {
 582         return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
 583 }
 584 
 585 /**
 586  * die_find_inlinefunc - Search an inlined function at given address
 587  * @sp_die: a subprogram DIE which including @addr
 588  * @addr: target address
 589  * @die_mem: a buffer for result DIE
 590  *
 591  * Search an inlined function DIE which includes @addr. Stores the
 592  * DIE to @die_mem and returns it if found. Returns NULL if failed.
 593  * If several inlined functions are expanded recursively, this trace
 594  * it down and returns deepest one.
 595  */
 596 Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
 597                                Dwarf_Die *die_mem)
 598 {
 599         Dwarf_Die tmp_die;
 600 
 601         sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
 602         if (!sp_die)
 603                 return NULL;
 604 
 605         /* Inlined function could be recursive. Trace it until fail */
 606         while (sp_die) {
 607                 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
 608                 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
 609                                         &tmp_die);
 610         }
 611 
 612         return die_mem;
 613 }
 614 
 615 struct __instance_walk_param {
 616         void    *addr;
 617         int     (*callback)(Dwarf_Die *, void *);
 618         void    *data;
 619         int     retval;
 620 };
 621 
 622 static int __die_walk_instances_cb(Dwarf_Die *inst, void *data)
 623 {
 624         struct __instance_walk_param *iwp = data;
 625         Dwarf_Attribute attr_mem;
 626         Dwarf_Die origin_mem;
 627         Dwarf_Attribute *attr;
 628         Dwarf_Die *origin;
 629         int tmp;
 630 
 631         if (!die_is_func_instance(inst))
 632                 return DIE_FIND_CB_CONTINUE;
 633 
 634         attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem);
 635         if (attr == NULL)
 636                 return DIE_FIND_CB_CONTINUE;
 637 
 638         origin = dwarf_formref_die(attr, &origin_mem);
 639         if (origin == NULL || origin->addr != iwp->addr)
 640                 return DIE_FIND_CB_CONTINUE;
 641 
 642         /* Ignore redundant instances */
 643         if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) {
 644                 dwarf_decl_line(origin, &tmp);
 645                 if (die_get_call_lineno(inst) == tmp) {
 646                         tmp = die_get_decl_fileno(origin);
 647                         if (die_get_call_fileno(inst) == tmp)
 648                                 return DIE_FIND_CB_CONTINUE;
 649                 }
 650         }
 651 
 652         iwp->retval = iwp->callback(inst, iwp->data);
 653 
 654         return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE;
 655 }
 656 
 657 /**
 658  * die_walk_instances - Walk on instances of given DIE
 659  * @or_die: an abstract original DIE
 660  * @callback: a callback function which is called with instance DIE
 661  * @data: user data
 662  *
 663  * Walk on the instances of give @in_die. @in_die must be an inlined function
 664  * declartion. This returns the return value of @callback if it returns
 665  * non-zero value, or -ENOENT if there is no instance.
 666  */
 667 int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *),
 668                        void *data)
 669 {
 670         Dwarf_Die cu_die;
 671         Dwarf_Die die_mem;
 672         struct __instance_walk_param iwp = {
 673                 .addr = or_die->addr,
 674                 .callback = callback,
 675                 .data = data,
 676                 .retval = -ENOENT,
 677         };
 678 
 679         if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL)
 680                 return -ENOENT;
 681 
 682         die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem);
 683 
 684         return iwp.retval;
 685 }
 686 
 687 /* Line walker internal parameters */
 688 struct __line_walk_param {
 689         bool recursive;
 690         line_walk_callback_t callback;
 691         void *data;
 692         int retval;
 693 };
 694 
 695 static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
 696 {
 697         struct __line_walk_param *lw = data;
 698         Dwarf_Addr addr = 0;
 699         const char *fname;
 700         int lineno;
 701 
 702         if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
 703                 fname = die_get_call_file(in_die);
 704                 lineno = die_get_call_lineno(in_die);
 705                 if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) {
 706                         lw->retval = lw->callback(fname, lineno, addr, lw->data);
 707                         if (lw->retval != 0)
 708                                 return DIE_FIND_CB_END;
 709                 }
 710                 if (!lw->recursive)
 711                         return DIE_FIND_CB_SIBLING;
 712         }
 713 
 714         if (addr) {
 715                 fname = dwarf_decl_file(in_die);
 716                 if (fname && dwarf_decl_line(in_die, &lineno) == 0) {
 717                         lw->retval = lw->callback(fname, lineno, addr, lw->data);
 718                         if (lw->retval != 0)
 719                                 return DIE_FIND_CB_END;
 720                 }
 721         }
 722 
 723         /* Continue to search nested inlined function call-sites */
 724         return DIE_FIND_CB_CONTINUE;
 725 }
 726 
 727 /* Walk on lines of blocks included in given DIE */
 728 static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive,
 729                                 line_walk_callback_t callback, void *data)
 730 {
 731         struct __line_walk_param lw = {
 732                 .recursive = recursive,
 733                 .callback = callback,
 734                 .data = data,
 735                 .retval = 0,
 736         };
 737         Dwarf_Die die_mem;
 738         Dwarf_Addr addr;
 739         const char *fname;
 740         int lineno;
 741 
 742         /* Handle function declaration line */
 743         fname = dwarf_decl_file(sp_die);
 744         if (fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
 745             die_entrypc(sp_die, &addr) == 0) {
 746                 lw.retval = callback(fname, lineno, addr, data);
 747                 if (lw.retval != 0)
 748                         goto done;
 749         }
 750         die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
 751 done:
 752         return lw.retval;
 753 }
 754 
 755 static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
 756 {
 757         struct __line_walk_param *lw = data;
 758 
 759         /*
 760          * Since inlined function can include another inlined function in
 761          * the same file, we need to walk in it recursively.
 762          */
 763         lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data);
 764         if (lw->retval != 0)
 765                 return DWARF_CB_ABORT;
 766 
 767         return DWARF_CB_OK;
 768 }
 769 
 770 /**
 771  * die_walk_lines - Walk on lines inside given DIE
 772  * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)
 773  * @callback: callback routine
 774  * @data: user data
 775  *
 776  * Walk on all lines inside given @rt_die and call @callback on each line.
 777  * If the @rt_die is a function, walk only on the lines inside the function,
 778  * otherwise @rt_die must be a CU DIE.
 779  * Note that this walks not only dwarf line list, but also function entries
 780  * and inline call-site.
 781  */
 782 int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
 783 {
 784         Dwarf_Lines *lines;
 785         Dwarf_Line *line;
 786         Dwarf_Addr addr;
 787         const char *fname, *decf = NULL, *inf = NULL;
 788         int lineno, ret = 0;
 789         int decl = 0, inl;
 790         Dwarf_Die die_mem, *cu_die;
 791         size_t nlines, i;
 792         bool flag;
 793 
 794         /* Get the CU die */
 795         if (dwarf_tag(rt_die) != DW_TAG_compile_unit) {
 796                 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
 797                 dwarf_decl_line(rt_die, &decl);
 798                 decf = dwarf_decl_file(rt_die);
 799         } else
 800                 cu_die = rt_die;
 801         if (!cu_die) {
 802                 pr_debug2("Failed to get CU from given DIE.\n");
 803                 return -EINVAL;
 804         }
 805 
 806         /* Get lines list in the CU */
 807         if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
 808                 pr_debug2("Failed to get source lines on this CU.\n");
 809                 return -ENOENT;
 810         }
 811         pr_debug2("Get %zd lines from this CU\n", nlines);
 812 
 813         /* Walk on the lines on lines list */
 814         for (i = 0; i < nlines; i++) {
 815                 line = dwarf_onesrcline(lines, i);
 816                 if (line == NULL ||
 817                     dwarf_lineno(line, &lineno) != 0 ||
 818                     dwarf_lineaddr(line, &addr) != 0) {
 819                         pr_debug2("Failed to get line info. "
 820                                   "Possible error in debuginfo.\n");
 821                         continue;
 822                 }
 823                 /* Skip end-of-sequence */
 824                 if (dwarf_lineendsequence(line, &flag) != 0 || flag)
 825                         continue;
 826                 /* Skip Non statement line-info */
 827                 if (dwarf_linebeginstatement(line, &flag) != 0 || !flag)
 828                         continue;
 829                 /* Filter lines based on address */
 830                 if (rt_die != cu_die) {
 831                         /*
 832                          * Address filtering
 833                          * The line is included in given function, and
 834                          * no inline block includes it.
 835                          */
 836                         if (!dwarf_haspc(rt_die, addr))
 837                                 continue;
 838 
 839                         if (die_find_inlinefunc(rt_die, addr, &die_mem)) {
 840                                 /* Call-site check */
 841                                 inf = die_get_call_file(&die_mem);
 842                                 if ((inf && !strcmp(inf, decf)) &&
 843                                     die_get_call_lineno(&die_mem) == lineno)
 844                                         goto found;
 845 
 846                                 dwarf_decl_line(&die_mem, &inl);
 847                                 if (inl != decl ||
 848                                     decf != dwarf_decl_file(&die_mem))
 849                                         continue;
 850                         }
 851                 }
 852 found:
 853                 /* Get source line */
 854                 fname = dwarf_linesrc(line, NULL, NULL);
 855 
 856                 ret = callback(fname, lineno, addr, data);
 857                 if (ret != 0)
 858                         return ret;
 859         }
 860 
 861         /*
 862          * Dwarf lines doesn't include function declarations and inlined
 863          * subroutines. We have to check functions list or given function.
 864          */
 865         if (rt_die != cu_die)
 866                 /*
 867                  * Don't need walk inlined functions recursively, because
 868                  * inner inlined functions don't have the lines of the
 869                  * specified function.
 870                  */
 871                 ret = __die_walk_funclines(rt_die, false, callback, data);
 872         else {
 873                 struct __line_walk_param param = {
 874                         .callback = callback,
 875                         .data = data,
 876                         .retval = 0,
 877                 };
 878                 dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
 879                 ret = param.retval;
 880         }
 881 
 882         return ret;
 883 }
 884 
 885 struct __find_variable_param {
 886         const char *name;
 887         Dwarf_Addr addr;
 888 };
 889 
 890 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data)
 891 {
 892         struct __find_variable_param *fvp = data;
 893         Dwarf_Attribute attr;
 894         int tag;
 895 
 896         tag = dwarf_tag(die_mem);
 897         if ((tag == DW_TAG_formal_parameter ||
 898              tag == DW_TAG_variable) &&
 899             die_compare_name(die_mem, fvp->name) &&
 900         /* Does the DIE have location information or external instance? */
 901             (dwarf_attr(die_mem, DW_AT_external, &attr) ||
 902              dwarf_attr(die_mem, DW_AT_location, &attr)))
 903                 return DIE_FIND_CB_END;
 904         if (dwarf_haspc(die_mem, fvp->addr))
 905                 return DIE_FIND_CB_CONTINUE;
 906         else
 907                 return DIE_FIND_CB_SIBLING;
 908 }
 909 
 910 /**
 911  * die_find_variable_at - Find a given name variable at given address
 912  * @sp_die: a function DIE
 913  * @name: variable name
 914  * @addr: address
 915  * @die_mem: a buffer for result DIE
 916  *
 917  * Find a variable DIE called @name at @addr in @sp_die.
 918  */
 919 Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name,
 920                                 Dwarf_Addr addr, Dwarf_Die *die_mem)
 921 {
 922         struct __find_variable_param fvp = { .name = name, .addr = addr};
 923 
 924         return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp,
 925                               die_mem);
 926 }
 927 
 928 static int __die_find_member_cb(Dwarf_Die *die_mem, void *data)
 929 {
 930         const char *name = data;
 931 
 932         if (dwarf_tag(die_mem) == DW_TAG_member) {
 933                 if (die_compare_name(die_mem, name))
 934                         return DIE_FIND_CB_END;
 935                 else if (!dwarf_diename(die_mem)) {     /* Unnamed structure */
 936                         Dwarf_Die type_die, tmp_die;
 937                         if (die_get_type(die_mem, &type_die) &&
 938                             die_find_member(&type_die, name, &tmp_die))
 939                                 return DIE_FIND_CB_END;
 940                 }
 941         }
 942         return DIE_FIND_CB_SIBLING;
 943 }
 944 
 945 /**
 946  * die_find_member - Find a given name member in a data structure
 947  * @st_die: a data structure type DIE
 948  * @name: member name
 949  * @die_mem: a buffer for result DIE
 950  *
 951  * Find a member DIE called @name in @st_die.
 952  */
 953 Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name,
 954                            Dwarf_Die *die_mem)
 955 {
 956         return die_find_child(st_die, __die_find_member_cb, (void *)name,
 957                               die_mem);
 958 }
 959 
 960 /**
 961  * die_get_typename - Get the name of given variable DIE
 962  * @vr_die: a variable DIE
 963  * @buf: a strbuf for result type name
 964  *
 965  * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded.
 966  * and Return -ENOENT if failed to find type name.
 967  * Note that the result will stores typedef name if possible, and stores
 968  * "*(function_type)" if the type is a function pointer.
 969  */
 970 int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
 971 {
 972         Dwarf_Die type;
 973         int tag, ret;
 974         const char *tmp = "";
 975 
 976         if (__die_get_real_type(vr_die, &type) == NULL)
 977                 return -ENOENT;
 978 
 979         tag = dwarf_tag(&type);
 980         if (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)
 981                 tmp = "*";
 982         else if (tag == DW_TAG_subroutine_type) {
 983                 /* Function pointer */
 984                 return strbuf_add(buf, "(function_type)", 15);
 985         } else {
 986                 if (!dwarf_diename(&type))
 987                         return -ENOENT;
 988                 if (tag == DW_TAG_union_type)
 989                         tmp = "union ";
 990                 else if (tag == DW_TAG_structure_type)
 991                         tmp = "struct ";
 992                 else if (tag == DW_TAG_enumeration_type)
 993                         tmp = "enum ";
 994                 /* Write a base name */
 995                 return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
 996         }
 997         ret = die_get_typename(&type, buf);
 998         return ret ? ret : strbuf_addstr(buf, tmp);
 999 }
1000 
1001 /**
1002  * die_get_varname - Get the name and type of given variable DIE
1003  * @vr_die: a variable DIE
1004  * @buf: a strbuf for type and variable name
1005  *
1006  * Get the name and type of @vr_die and stores it in @buf as "type\tname".
1007  */
1008 int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf)
1009 {
1010         int ret;
1011 
1012         ret = die_get_typename(vr_die, buf);
1013         if (ret < 0) {
1014                 pr_debug("Failed to get type, make it unknown.\n");
1015                 ret = strbuf_add(buf, " (unknown_type)", 14);
1016         }
1017 
1018         return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
1019 }
1020 
1021 #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT
1022 /**
1023  * die_get_var_innermost_scope - Get innermost scope range of given variable DIE
1024  * @sp_die: a subprogram DIE
1025  * @vr_die: a variable DIE
1026  * @buf: a strbuf for variable byte offset range
1027  *
1028  * Get the innermost scope range of @vr_die and stores it in @buf as
1029  * "@<function_name+[NN-NN,NN-NN]>".
1030  */
1031 static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
1032                                 struct strbuf *buf)
1033 {
1034         Dwarf_Die *scopes;
1035         int count;
1036         size_t offset = 0;
1037         Dwarf_Addr base;
1038         Dwarf_Addr start, end;
1039         Dwarf_Addr entry;
1040         int ret;
1041         bool first = true;
1042         const char *name;
1043 
1044         ret = die_entrypc(sp_die, &entry);
1045         if (ret)
1046                 return ret;
1047 
1048         name = dwarf_diename(sp_die);
1049         if (!name)
1050                 return -ENOENT;
1051 
1052         count = dwarf_getscopes_die(vr_die, &scopes);
1053 
1054         /* (*SCOPES)[1] is the DIE for the scope containing that scope */
1055         if (count <= 1) {
1056                 ret = -EINVAL;
1057                 goto out;
1058         }
1059 
1060         while ((offset = dwarf_ranges(&scopes[1], offset, &base,
1061                                         &start, &end)) > 0) {
1062                 start -= entry;
1063                 end -= entry;
1064 
1065                 if (first) {
1066                         ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1067                                           name, start, end);
1068                         first = false;
1069                 } else {
1070                         ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1071                                           start, end);
1072                 }
1073                 if (ret < 0)
1074                         goto out;
1075         }
1076 
1077         if (!first)
1078                 ret = strbuf_add(buf, "]>", 2);
1079 
1080 out:
1081         free(scopes);
1082         return ret;
1083 }
1084 
1085 /**
1086  * die_get_var_range - Get byte offset range of given variable DIE
1087  * @sp_die: a subprogram DIE
1088  * @vr_die: a variable DIE
1089  * @buf: a strbuf for type and variable name and byte offset range
1090  *
1091  * Get the byte offset range of @vr_die and stores it in @buf as
1092  * "@<function_name+[NN-NN,NN-NN]>".
1093  */
1094 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf)
1095 {
1096         int ret = 0;
1097         Dwarf_Addr base;
1098         Dwarf_Addr start, end;
1099         Dwarf_Addr entry;
1100         Dwarf_Op *op;
1101         size_t nops;
1102         size_t offset = 0;
1103         Dwarf_Attribute attr;
1104         bool first = true;
1105         const char *name;
1106 
1107         ret = die_entrypc(sp_die, &entry);
1108         if (ret)
1109                 return ret;
1110 
1111         name = dwarf_diename(sp_die);
1112         if (!name)
1113                 return -ENOENT;
1114 
1115         if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1116                 return -EINVAL;
1117 
1118         while ((offset = dwarf_getlocations(&attr, offset, &base,
1119                                         &start, &end, &op, &nops)) > 0) {
1120                 if (start == 0) {
1121                         /* Single Location Descriptions */
1122                         ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1123                         goto out;
1124                 }
1125 
1126                 /* Location Lists */
1127                 start -= entry;
1128                 end -= entry;
1129                 if (first) {
1130                         ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1131                                           name, start, end);
1132                         first = false;
1133                 } else {
1134                         ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1135                                           start, end);
1136                 }
1137                 if (ret < 0)
1138                         goto out;
1139         }
1140 
1141         if (!first)
1142                 ret = strbuf_add(buf, "]>", 2);
1143 out:
1144         return ret;
1145 }
1146 #else
1147 int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1148                       Dwarf_Die *vr_die __maybe_unused,
1149                       struct strbuf *buf __maybe_unused)
1150 {
1151         return -ENOTSUP;
1152 }
1153 #endif
1154 
1155 /*
1156  * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
1157  * @vr_die: a variable DIE
1158  */
1159 static bool die_has_loclist(Dwarf_Die *vr_die)
1160 {
1161         Dwarf_Attribute loc;
1162         int tag = dwarf_tag(vr_die);
1163 
1164         if (tag != DW_TAG_formal_parameter &&
1165             tag != DW_TAG_variable)
1166                 return false;
1167 
1168         return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1169                 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1170 }
1171 
1172 /*
1173  * die_is_optimized_target - Check if target program is compiled with
1174  * optimization
1175  * @cu_die: a CU DIE
1176  *
1177  * For any object in given CU whose DW_AT_location is a location list,
1178  * target program is compiled with optimization. This is applicable to
1179  * clang as well.
1180  */
1181 bool die_is_optimized_target(Dwarf_Die *cu_die)
1182 {
1183         Dwarf_Die tmp_die;
1184 
1185         if (die_has_loclist(cu_die))
1186                 return true;
1187 
1188         if (!dwarf_child(cu_die, &tmp_die) &&
1189             die_is_optimized_target(&tmp_die))
1190                 return true;
1191 
1192         if (!dwarf_siblingof(cu_die, &tmp_die) &&
1193             die_is_optimized_target(&tmp_die))
1194                 return true;
1195 
1196         return false;
1197 }
1198 
1199 /*
1200  * die_search_idx - Search index of given line address
1201  * @lines: Line records of single CU
1202  * @nr_lines: Number of @lines
1203  * @addr: address we are looking for
1204  * @idx: index to be set by this function (return value)
1205  *
1206  * Search for @addr by looping over every lines of CU. If address
1207  * matches, set index of that line in @idx. Note that single source
1208  * line can have multiple line records. i.e. single source line can
1209  * have multiple index.
1210  */
1211 static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1212                            Dwarf_Addr addr, unsigned long *idx)
1213 {
1214         unsigned long i;
1215         Dwarf_Addr tmp;
1216 
1217         for (i = 0; i < nr_lines; i++) {
1218                 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1219                         return false;
1220 
1221                 if (tmp == addr) {
1222                         *idx = i;
1223                         return true;
1224                 }
1225         }
1226         return false;
1227 }
1228 
1229 /*
1230  * die_get_postprologue_addr - Search next address after function prologue
1231  * @entrypc_idx: entrypc index
1232  * @lines: Line records of single CU
1233  * @nr_lines: Number of @lines
1234  * @hignpc: high PC address of function
1235  * @postprologue_addr: Next address after function prologue (return value)
1236  *
1237  * Look for prologue-end marker. If there is no explicit marker, return
1238  * address of next line record or next source line.
1239  */
1240 static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1241                                       Dwarf_Lines *lines,
1242                                       unsigned long nr_lines,
1243                                       Dwarf_Addr highpc,
1244                                       Dwarf_Addr *postprologue_addr)
1245 {
1246         unsigned long i;
1247         int entrypc_lno, lno;
1248         Dwarf_Line *line;
1249         Dwarf_Addr addr;
1250         bool p_end;
1251 
1252         /* entrypc_lno is actual source line number */
1253         line = dwarf_onesrcline(lines, entrypc_idx);
1254         if (dwarf_lineno(line, &entrypc_lno))
1255                 return false;
1256 
1257         for (i = entrypc_idx; i < nr_lines; i++) {
1258                 line = dwarf_onesrcline(lines, i);
1259 
1260                 if (dwarf_lineaddr(line, &addr) ||
1261                     dwarf_lineno(line, &lno)    ||
1262                     dwarf_lineprologueend(line, &p_end))
1263                         return false;
1264 
1265                 /* highpc is exclusive. [entrypc,highpc) */
1266                 if (addr >= highpc)
1267                         break;
1268 
1269                 /* clang supports prologue-end marker */
1270                 if (p_end)
1271                         break;
1272 
1273                 /* Actual next line in source */
1274                 if (lno != entrypc_lno)
1275                         break;
1276 
1277                 /*
1278                  * Single source line can have multiple line records.
1279                  * For Example,
1280                  *     void foo() { printf("hello\n"); }
1281                  * contains two line records. One points to declaration and
1282                  * other points to printf() line. Variable 'lno' won't get
1283                  * incremented in this case but 'i' will.
1284                  */
1285                 if (i != entrypc_idx)
1286                         break;
1287         }
1288 
1289         dwarf_lineaddr(line, postprologue_addr);
1290         if (*postprologue_addr >= highpc)
1291                 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1292                                postprologue_addr);
1293 
1294         return true;
1295 }
1296 
1297 /*
1298  * die_skip_prologue - Use next address after prologue as probe location
1299  * @sp_die: a subprogram DIE
1300  * @cu_die: a CU DIE
1301  * @entrypc: entrypc of the function
1302  *
1303  * Function prologue prepares stack and registers before executing function
1304  * logic. When target program is compiled without optimization, function
1305  * parameter information is only valid after prologue. When we probe entrypc
1306  * of the function, and try to record function parameter, it contains
1307  * garbage value.
1308  */
1309 void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1310                        Dwarf_Addr *entrypc)
1311 {
1312         size_t nr_lines = 0;
1313         unsigned long entrypc_idx = 0;
1314         Dwarf_Lines *lines = NULL;
1315         Dwarf_Addr postprologue_addr;
1316         Dwarf_Addr highpc;
1317 
1318         if (dwarf_highpc(sp_die, &highpc))
1319                 return;
1320 
1321         if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1322                 return;
1323 
1324         if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1325                 return;
1326 
1327         if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1328                                        highpc, &postprologue_addr))
1329                 return;
1330 
1331         *entrypc = postprologue_addr;
1332 }

/* [<][>][^][v][top][bottom][index][help] */