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 "dwarf-regs.h" 13 #include "strbuf.h" 14 #include "string2.h" 15 16 /** 17 * cu_find_realpath - Find the realpath of the target file 18 * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit) 19 * @fname: The tail filename of the target file 20 * 21 * Find the real(long) path of @fname in @cu_die. 22 */ 23 const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) 24 { 25 Dwarf_Files *files; 26 size_t nfiles, i; 27 const char *src = NULL; 28 int ret; 29 30 if (!fname) 31 return NULL; 32 33 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles); 34 if (ret != 0) 35 return NULL; 36 37 for (i = 0; i < nfiles; i++) { 38 src = dwarf_filesrc(files, i, NULL, NULL); 39 if (strtailcmp(src, fname) == 0) 40 break; 41 } 42 if (i == nfiles) 43 return NULL; 44 return src; 45 } 46 47 /** 48 * cu_get_comp_dir - Get the path of compilation directory 49 * @cu_die: a CU DIE 50 * 51 * Get the path of compilation directory of given @cu_die. 52 * Since this depends on DW_AT_comp_dir, older gcc will not 53 * embedded it. In that case, this returns NULL. 54 */ 55 const char *cu_get_comp_dir(Dwarf_Die *cu_die) 56 { 57 Dwarf_Attribute attr; 58 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL) 59 return NULL; 60 return dwarf_formstring(&attr); 61 } 62 63 /* Unlike dwarf_getsrc_die(), cu_getsrc_die() only returns statement line */ 64 static Dwarf_Line *cu_getsrc_die(Dwarf_Die *cu_die, Dwarf_Addr addr) 65 { 66 Dwarf_Addr laddr; 67 Dwarf_Lines *lines; 68 Dwarf_Line *line; 69 size_t nlines, l, u, n; 70 bool flag; 71 72 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0 || 73 nlines == 0) 74 return NULL; 75 76 /* Lines are sorted by address, use binary search */ 77 l = 0; u = nlines - 1; 78 while (l < u) { 79 n = u - (u - l) / 2; 80 line = dwarf_onesrcline(lines, n); 81 if (!line || dwarf_lineaddr(line, &laddr) != 0) 82 return NULL; 83 if (addr < laddr) 84 u = n - 1; 85 else 86 l = n; 87 } 88 /* Going backward to find the lowest line */ 89 do { 90 line = dwarf_onesrcline(lines, --l); 91 if (!line || dwarf_lineaddr(line, &laddr) != 0) 92 return NULL; 93 } while (laddr == addr); 94 l++; 95 /* Going forward to find the statement line */ 96 do { 97 line = dwarf_onesrcline(lines, l++); 98 if (!line || dwarf_lineaddr(line, &laddr) != 0 || 99 dwarf_linebeginstatement(line, &flag) != 0) 100 return NULL; 101 if (laddr > addr) 102 return NULL; 103 } while (!flag); 104 105 return line; 106 } 107 108 /** 109 * cu_find_lineinfo - Get a line number and file name for given address 110 * @cu_die: a CU DIE 111 * @addr: An address 112 * @fname: a pointer which returns the file name string 113 * @lineno: a pointer which returns the line number 114 * 115 * Find a line number and file name for @addr in @cu_die. 116 */ 117 int cu_find_lineinfo(Dwarf_Die *cu_die, Dwarf_Addr addr, 118 const char **fname, int *lineno) 119 { 120 Dwarf_Line *line; 121 Dwarf_Die die_mem; 122 Dwarf_Addr faddr; 123 124 if (die_find_realfunc(cu_die, addr, &die_mem) 125 && die_entrypc(&die_mem, &faddr) == 0 && 126 faddr == addr) { 127 *fname = die_get_decl_file(&die_mem); 128 dwarf_decl_line(&die_mem, lineno); 129 goto out; 130 } 131 132 line = cu_getsrc_die(cu_die, addr); 133 if (line && dwarf_lineno(line, lineno) == 0) { 134 *fname = dwarf_linesrc(line, NULL, NULL); 135 if (!*fname) 136 /* line number is useless without filename */ 137 *lineno = 0; 138 } 139 140 out: 141 return (*lineno && *fname) ? *lineno : -ENOENT; 142 } 143 144 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data); 145 146 /** 147 * cu_walk_functions_at - Walk on function DIEs at given address 148 * @cu_die: A CU DIE 149 * @addr: An address 150 * @callback: A callback which called with found DIEs 151 * @data: A user data 152 * 153 * Walk on function DIEs at given @addr in @cu_die. Passed DIEs 154 * should be subprogram or inlined-subroutines. 155 */ 156 int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, 157 int (*callback)(Dwarf_Die *, void *), void *data) 158 { 159 Dwarf_Die die_mem; 160 Dwarf_Die *sc_die; 161 int ret = -ENOENT; 162 163 /* Inlined function could be recursive. Trace it until fail */ 164 for (sc_die = die_find_realfunc(cu_die, addr, &die_mem); 165 sc_die != NULL; 166 sc_die = die_find_child(sc_die, __die_find_inline_cb, &addr, 167 &die_mem)) { 168 ret = callback(sc_die, data); 169 if (ret) 170 break; 171 } 172 173 return ret; 174 175 } 176 177 /** 178 * die_get_linkage_name - Get the linkage name of the object 179 * @dw_die: A DIE of the object 180 * 181 * Get the linkage name attribute of given @dw_die. 182 * For C++ binary, the linkage name will be the mangled symbol. 183 */ 184 const char *die_get_linkage_name(Dwarf_Die *dw_die) 185 { 186 Dwarf_Attribute attr; 187 188 if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL) 189 return NULL; 190 return dwarf_formstring(&attr); 191 } 192 193 /** 194 * die_compare_name - Compare diename and tname 195 * @dw_die: a DIE 196 * @tname: a string of target name 197 * 198 * Compare the name of @dw_die and @tname. Return false if @dw_die has no name. 199 */ 200 bool die_compare_name(Dwarf_Die *dw_die, const char *tname) 201 { 202 const char *name; 203 204 name = dwarf_diename(dw_die); 205 return name ? (strcmp(tname, name) == 0) : false; 206 } 207 208 /** 209 * die_match_name - Match diename/linkage name and glob 210 * @dw_die: a DIE 211 * @glob: a string of target glob pattern 212 * 213 * Glob matching the name of @dw_die and @glob. Return false if matching fail. 214 * This also match linkage name. 215 */ 216 bool die_match_name(Dwarf_Die *dw_die, const char *glob) 217 { 218 const char *name; 219 220 name = dwarf_diename(dw_die); 221 if (name && strglobmatch(name, glob)) 222 return true; 223 /* fall back to check linkage name */ 224 name = die_get_linkage_name(dw_die); 225 if (name && strglobmatch(name, glob)) 226 return true; 227 228 return false; 229 } 230 231 /** 232 * die_get_call_lineno - Get callsite line number of inline-function instance 233 * @in_die: a DIE of an inlined function instance 234 * 235 * Get call-site line number of @in_die. This means from where the inline 236 * function is called. 237 */ 238 int die_get_call_lineno(Dwarf_Die *in_die) 239 { 240 Dwarf_Attribute attr; 241 Dwarf_Word ret; 242 243 if (!dwarf_attr(in_die, DW_AT_call_line, &attr)) 244 return -ENOENT; 245 246 dwarf_formudata(&attr, &ret); 247 return (int)ret; 248 } 249 250 /** 251 * die_get_type - Get type DIE 252 * @vr_die: a DIE of a variable 253 * @die_mem: where to store a type DIE 254 * 255 * Get a DIE of the type of given variable (@vr_die), and store 256 * it to die_mem. Return NULL if fails to get a type DIE. 257 */ 258 Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) 259 { 260 Dwarf_Attribute attr; 261 262 if (dwarf_attr_integrate(vr_die, DW_AT_type, &attr) && 263 dwarf_formref_die(&attr, die_mem)) 264 return die_mem; 265 else 266 return NULL; 267 } 268 269 /* Get a type die, but skip qualifiers */ 270 static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) 271 { 272 int tag; 273 274 do { 275 vr_die = die_get_type(vr_die, die_mem); 276 if (!vr_die) 277 break; 278 tag = dwarf_tag(vr_die); 279 } while (tag == DW_TAG_const_type || 280 tag == DW_TAG_restrict_type || 281 tag == DW_TAG_volatile_type || 282 tag == DW_TAG_shared_type); 283 284 return vr_die; 285 } 286 287 /** 288 * die_get_real_type - Get a type die, but skip qualifiers and typedef 289 * @vr_die: a DIE of a variable 290 * @die_mem: where to store a type DIE 291 * 292 * Get a DIE of the type of given variable (@vr_die), and store 293 * it to die_mem. Return NULL if fails to get a type DIE. 294 * If the type is qualifiers (e.g. const) or typedef, this skips it 295 * and tries to find real type (structure or basic types, e.g. int). 296 */ 297 Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) 298 { 299 do { 300 vr_die = __die_get_real_type(vr_die, die_mem); 301 } while (vr_die && dwarf_tag(vr_die) == DW_TAG_typedef); 302 303 return vr_die; 304 } 305 306 /* Get attribute and translate it as a udata */ 307 static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name, 308 Dwarf_Word *result) 309 { 310 Dwarf_Attribute attr; 311 312 if (dwarf_attr_integrate(tp_die, attr_name, &attr) == NULL || 313 dwarf_formudata(&attr, result) != 0) 314 return -ENOENT; 315 316 return 0; 317 } 318 319 /** 320 * die_is_signed_type - Check whether a type DIE is signed or not 321 * @tp_die: a DIE of a type 322 * 323 * Get the encoding of @tp_die and return true if the encoding 324 * is signed. 325 */ 326 bool die_is_signed_type(Dwarf_Die *tp_die) 327 { 328 Dwarf_Word ret; 329 330 if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret)) 331 return false; 332 333 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || 334 ret == DW_ATE_signed_fixed); 335 } 336 337 /** 338 * die_is_func_def - Ensure that this DIE is a subprogram and definition 339 * @dw_die: a DIE 340 * 341 * Ensure that this DIE is a subprogram and NOT a declaration. This 342 * returns true if @dw_die is a function definition. 343 **/ 344 bool die_is_func_def(Dwarf_Die *dw_die) 345 { 346 Dwarf_Attribute attr; 347 Dwarf_Addr addr = 0; 348 349 if (dwarf_tag(dw_die) != DW_TAG_subprogram) 350 return false; 351 352 if (dwarf_attr(dw_die, DW_AT_declaration, &attr)) 353 return false; 354 355 /* 356 * DW_AT_declaration can be lost from function declaration 357 * by gcc's bug #97060. 358 * So we need to check this subprogram DIE has DW_AT_inline 359 * or an entry address. 360 */ 361 if (!dwarf_attr(dw_die, DW_AT_inline, &attr) && 362 die_entrypc(dw_die, &addr) < 0) 363 return false; 364 365 return true; 366 } 367 368 /** 369 * die_entrypc - Returns entry PC (the lowest address) of a DIE 370 * @dw_die: a DIE 371 * @addr: where to store entry PC 372 * 373 * Since dwarf_entrypc() does not return entry PC if the DIE has only address 374 * range, we have to use this to retrieve the lowest address from the address 375 * range attribute. 376 */ 377 int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr) 378 { 379 Dwarf_Addr base, end; 380 Dwarf_Attribute attr; 381 382 if (!addr) 383 return -EINVAL; 384 385 if (dwarf_entrypc(dw_die, addr) == 0) 386 return 0; 387 388 /* 389 * Since the dwarf_ranges() will return 0 if there is no 390 * DW_AT_ranges attribute, we should check it first. 391 */ 392 if (!dwarf_attr(dw_die, DW_AT_ranges, &attr)) 393 return -ENOENT; 394 395 return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0; 396 } 397 398 /** 399 * die_is_func_instance - Ensure that this DIE is an instance of a subprogram 400 * @dw_die: a DIE 401 * 402 * Ensure that this DIE is an instance (which has an entry address). 403 * This returns true if @dw_die is a function instance. If not, the @dw_die 404 * must be a prototype. You can use die_walk_instances() to find actual 405 * instances. 406 **/ 407 bool die_is_func_instance(Dwarf_Die *dw_die) 408 { 409 Dwarf_Addr tmp; 410 Dwarf_Attribute attr_mem; 411 int tag = dwarf_tag(dw_die); 412 413 if (tag != DW_TAG_subprogram && 414 tag != DW_TAG_inlined_subroutine) 415 return false; 416 417 return dwarf_entrypc(dw_die, &tmp) == 0 || 418 dwarf_attr(dw_die, DW_AT_ranges, &attr_mem) != NULL; 419 } 420 421 /** 422 * die_get_data_member_location - Get the data-member offset 423 * @mb_die: a DIE of a member of a data structure 424 * @offs: The offset of the member in the data structure 425 * 426 * Get the offset of @mb_die in the data structure including @mb_die, and 427 * stores result offset to @offs. If any error occurs this returns errno. 428 */ 429 int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) 430 { 431 Dwarf_Attribute attr; 432 Dwarf_Op *expr; 433 size_t nexpr; 434 int ret; 435 436 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL) 437 return -ENOENT; 438 439 if (dwarf_formudata(&attr, offs) != 0) { 440 /* DW_AT_data_member_location should be DW_OP_plus_uconst */ 441 ret = dwarf_getlocation(&attr, &expr, &nexpr); 442 if (ret < 0 || nexpr == 0) 443 return -ENOENT; 444 445 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) { 446 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n", 447 expr[0].atom, nexpr); 448 return -ENOTSUP; 449 } 450 *offs = (Dwarf_Word)expr[0].number; 451 } 452 return 0; 453 } 454 455 /* Get the call file index number in CU DIE */ 456 static int die_get_call_fileno(Dwarf_Die *in_die) 457 { 458 Dwarf_Word idx; 459 460 if (die_get_attr_udata(in_die, DW_AT_call_file, &idx) == 0) 461 return (int)idx; 462 else 463 return -ENOENT; 464 } 465 466 /* Get the declared file index number in CU DIE */ 467 static int die_get_decl_fileno(Dwarf_Die *pdie) 468 { 469 Dwarf_Word idx; 470 471 if (die_get_attr_udata(pdie, DW_AT_decl_file, &idx) == 0) 472 return (int)idx; 473 else 474 return -ENOENT; 475 } 476 477 /* Return the file name by index */ 478 static const char *die_get_file_name(Dwarf_Die *dw_die, int idx) 479 { 480 Dwarf_Die cu_die; 481 Dwarf_Files *files; 482 Dwarf_Attribute attr_mem; 483 484 if (idx < 0 || !dwarf_attr_integrate(dw_die, DW_AT_decl_file, &attr_mem) || 485 !dwarf_cu_die(attr_mem.cu, &cu_die, NULL, NULL, NULL, NULL, NULL, NULL) || 486 dwarf_getsrcfiles(&cu_die, &files, NULL) != 0) 487 return NULL; 488 489 return dwarf_filesrc(files, idx, NULL, NULL); 490 } 491 492 /** 493 * die_get_call_file - Get callsite file name of inlined function instance 494 * @in_die: a DIE of an inlined function instance 495 * 496 * Get call-site file name of @in_die. This means from which file the inline 497 * function is called. 498 */ 499 const char *die_get_call_file(Dwarf_Die *in_die) 500 { 501 return die_get_file_name(in_die, die_get_call_fileno(in_die)); 502 } 503 504 /** 505 * die_get_decl_file - Find the declared file name of this DIE 506 * @dw_die: a DIE for something declared. 507 * 508 * Get declared file name of @dw_die. 509 * NOTE: Since some version of clang DWARF5 implementation incorrectly uses 510 * file index 0 for DW_AT_decl_file, die_get_decl_file() will return NULL for 511 * such cases. Use this function instead. 512 */ 513 const char *die_get_decl_file(Dwarf_Die *dw_die) 514 { 515 return die_get_file_name(dw_die, die_get_decl_fileno(dw_die)); 516 } 517 518 /** 519 * die_find_child - Generic DIE search function in DIE tree 520 * @rt_die: a root DIE 521 * @callback: a callback function 522 * @data: a user data passed to the callback function 523 * @die_mem: a buffer for result DIE 524 * 525 * Trace DIE tree from @rt_die and call @callback for each child DIE. 526 * If @callback returns DIE_FIND_CB_END, this stores the DIE into 527 * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE, 528 * this continues to trace the tree. Optionally, @callback can return 529 * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only 530 * the children and trace only the siblings respectively. 531 * Returns NULL if @callback can't find any appropriate DIE. 532 */ 533 Dwarf_Die *die_find_child(Dwarf_Die *rt_die, 534 int (*callback)(Dwarf_Die *, void *), 535 void *data, Dwarf_Die *die_mem) 536 { 537 Dwarf_Die child_die; 538 int ret; 539 540 ret = dwarf_child(rt_die, die_mem); 541 if (ret != 0) 542 return NULL; 543 544 do { 545 ret = callback(die_mem, data); 546 if (ret == DIE_FIND_CB_END) 547 return die_mem; 548 549 if ((ret & DIE_FIND_CB_CHILD) && 550 die_find_child(die_mem, callback, data, &child_die)) { 551 memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); 552 return die_mem; 553 } 554 } while ((ret & DIE_FIND_CB_SIBLING) && 555 dwarf_siblingof(die_mem, die_mem) == 0); 556 557 return NULL; 558 } 559 560 struct __addr_die_search_param { 561 Dwarf_Addr addr; 562 Dwarf_Die *die_mem; 563 }; 564 565 static int __die_search_func_tail_cb(Dwarf_Die *fn_die, void *data) 566 { 567 struct __addr_die_search_param *ad = data; 568 Dwarf_Addr addr = 0; 569 570 if (dwarf_tag(fn_die) == DW_TAG_subprogram && 571 !dwarf_highpc(fn_die, &addr) && 572 addr == ad->addr) { 573 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die)); 574 return DWARF_CB_ABORT; 575 } 576 return DWARF_CB_OK; 577 } 578 579 /** 580 * die_find_tailfunc - Search for a non-inlined function with tail call at 581 * given address 582 * @cu_die: a CU DIE which including @addr 583 * @addr: target address 584 * @die_mem: a buffer for result DIE 585 * 586 * Search for a non-inlined function DIE with tail call at @addr. Stores the 587 * DIE to @die_mem and returns it if found. Returns NULL if failed. 588 */ 589 Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, 590 Dwarf_Die *die_mem) 591 { 592 struct __addr_die_search_param ad; 593 ad.addr = addr; 594 ad.die_mem = die_mem; 595 /* dwarf_getscopes can't find subprogram. */ 596 if (!dwarf_getfuncs(cu_die, __die_search_func_tail_cb, &ad, 0)) 597 return NULL; 598 else 599 return die_mem; 600 } 601 602 /* die_find callback for non-inlined function search */ 603 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data) 604 { 605 struct __addr_die_search_param *ad = data; 606 607 /* 608 * Since a declaration entry doesn't has given pc, this always returns 609 * function definition entry. 610 */ 611 if (dwarf_tag(fn_die) == DW_TAG_subprogram && 612 dwarf_haspc(fn_die, ad->addr)) { 613 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die)); 614 return DWARF_CB_ABORT; 615 } 616 return DWARF_CB_OK; 617 } 618 619 /** 620 * die_find_realfunc - Search a non-inlined function at given address 621 * @cu_die: a CU DIE which including @addr 622 * @addr: target address 623 * @die_mem: a buffer for result DIE 624 * 625 * Search a non-inlined function DIE which includes @addr. Stores the 626 * DIE to @die_mem and returns it if found. Returns NULL if failed. 627 */ 628 Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, 629 Dwarf_Die *die_mem) 630 { 631 struct __addr_die_search_param ad; 632 ad.addr = addr; 633 ad.die_mem = die_mem; 634 /* dwarf_getscopes can't find subprogram. */ 635 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0)) 636 return NULL; 637 else 638 return die_mem; 639 } 640 641 /* die_find callback for inline function search */ 642 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) 643 { 644 Dwarf_Addr *addr = data; 645 646 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && 647 dwarf_haspc(die_mem, *addr)) 648 return DIE_FIND_CB_END; 649 650 return DIE_FIND_CB_CONTINUE; 651 } 652 653 /** 654 * die_find_top_inlinefunc - Search the top inlined function at given address 655 * @sp_die: a subprogram DIE which including @addr 656 * @addr: target address 657 * @die_mem: a buffer for result DIE 658 * 659 * Search an inlined function DIE which includes @addr. Stores the 660 * DIE to @die_mem and returns it if found. Returns NULL if failed. 661 * Even if several inlined functions are expanded recursively, this 662 * doesn't trace it down, and returns the topmost one. 663 */ 664 Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 665 Dwarf_Die *die_mem) 666 { 667 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); 668 } 669 670 /** 671 * die_find_inlinefunc - Search an inlined function at given address 672 * @sp_die: a subprogram DIE which including @addr 673 * @addr: target address 674 * @die_mem: a buffer for result DIE 675 * 676 * Search an inlined function DIE which includes @addr. Stores the 677 * DIE to @die_mem and returns it if found. Returns NULL if failed. 678 * If several inlined functions are expanded recursively, this trace 679 * it down and returns deepest one. 680 */ 681 Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 682 Dwarf_Die *die_mem) 683 { 684 Dwarf_Die tmp_die; 685 686 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die); 687 if (!sp_die) 688 return NULL; 689 690 /* Inlined function could be recursive. Trace it until fail */ 691 while (sp_die) { 692 memcpy(die_mem, sp_die, sizeof(Dwarf_Die)); 693 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, 694 &tmp_die); 695 } 696 697 return die_mem; 698 } 699 700 static int __die_find_func_rettype_cb(Dwarf_Die *die_mem, void *data) 701 { 702 const char *func_name; 703 704 if (dwarf_tag(die_mem) != DW_TAG_subprogram) 705 return DIE_FIND_CB_SIBLING; 706 707 func_name = dwarf_diename(die_mem); 708 if (func_name && !strcmp(func_name, data)) 709 return DIE_FIND_CB_END; 710 711 return DIE_FIND_CB_SIBLING; 712 } 713 714 /** 715 * die_find_func_rettype - Search a return type of function 716 * @cu_die: a CU DIE 717 * @name: target function name 718 * @die_mem: a buffer for result DIE 719 * 720 * Search a non-inlined function which matches to @name and stores the 721 * return type of the function to @die_mem and returns it if found. 722 * Returns NULL if failed. Note that it doesn't needs to find a 723 * definition of the function, so it doesn't match with address. 724 * Most likely, it can find a declaration at the top level. Thus the 725 * callback function continues to sibling entries only. 726 */ 727 Dwarf_Die *die_find_func_rettype(Dwarf_Die *cu_die, const char *name, 728 Dwarf_Die *die_mem) 729 { 730 Dwarf_Die tmp_die; 731 732 cu_die = die_find_child(cu_die, __die_find_func_rettype_cb, 733 (void *)name, &tmp_die); 734 if (!cu_die) 735 return NULL; 736 737 if (die_get_real_type(&tmp_die, die_mem) == NULL) 738 return NULL; 739 740 return die_mem; 741 } 742 743 struct __instance_walk_param { 744 void *addr; 745 int (*callback)(Dwarf_Die *, void *); 746 void *data; 747 int retval; 748 }; 749 750 static int __die_walk_instances_cb(Dwarf_Die *inst, void *data) 751 { 752 struct __instance_walk_param *iwp = data; 753 Dwarf_Attribute attr_mem; 754 Dwarf_Die origin_mem; 755 Dwarf_Attribute *attr; 756 Dwarf_Die *origin; 757 int tmp; 758 759 if (!die_is_func_instance(inst)) 760 return DIE_FIND_CB_CONTINUE; 761 762 attr = dwarf_attr(inst, DW_AT_abstract_origin, &attr_mem); 763 if (attr == NULL) 764 return DIE_FIND_CB_CONTINUE; 765 766 origin = dwarf_formref_die(attr, &origin_mem); 767 if (origin == NULL || origin->addr != iwp->addr) 768 return DIE_FIND_CB_CONTINUE; 769 770 /* Ignore redundant instances */ 771 if (dwarf_tag(inst) == DW_TAG_inlined_subroutine) { 772 dwarf_decl_line(origin, &tmp); 773 if (die_get_call_lineno(inst) == tmp) { 774 tmp = die_get_decl_fileno(origin); 775 if (die_get_call_fileno(inst) == tmp) 776 return DIE_FIND_CB_CONTINUE; 777 } 778 } 779 780 iwp->retval = iwp->callback(inst, iwp->data); 781 782 return (iwp->retval) ? DIE_FIND_CB_END : DIE_FIND_CB_CONTINUE; 783 } 784 785 /** 786 * die_walk_instances - Walk on instances of given DIE 787 * @or_die: an abstract original DIE 788 * @callback: a callback function which is called with instance DIE 789 * @data: user data 790 * 791 * Walk on the instances of give @in_die. @in_die must be an inlined function 792 * declaration. This returns the return value of @callback if it returns 793 * non-zero value, or -ENOENT if there is no instance. 794 */ 795 int die_walk_instances(Dwarf_Die *or_die, int (*callback)(Dwarf_Die *, void *), 796 void *data) 797 { 798 Dwarf_Die cu_die; 799 Dwarf_Die die_mem; 800 struct __instance_walk_param iwp = { 801 .addr = or_die->addr, 802 .callback = callback, 803 .data = data, 804 .retval = -ENOENT, 805 }; 806 807 if (dwarf_diecu(or_die, &cu_die, NULL, NULL) == NULL) 808 return -ENOENT; 809 810 die_find_child(&cu_die, __die_walk_instances_cb, &iwp, &die_mem); 811 812 return iwp.retval; 813 } 814 815 /* Line walker internal parameters */ 816 struct __line_walk_param { 817 bool recursive; 818 line_walk_callback_t callback; 819 void *data; 820 int retval; 821 }; 822 823 static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data) 824 { 825 struct __line_walk_param *lw = data; 826 Dwarf_Addr addr = 0; 827 const char *fname; 828 int lineno; 829 830 if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) { 831 fname = die_get_call_file(in_die); 832 lineno = die_get_call_lineno(in_die); 833 if (fname && lineno > 0 && die_entrypc(in_die, &addr) == 0) { 834 lw->retval = lw->callback(fname, lineno, addr, lw->data); 835 if (lw->retval != 0) 836 return DIE_FIND_CB_END; 837 } 838 if (!lw->recursive) 839 return DIE_FIND_CB_SIBLING; 840 } 841 842 if (addr) { 843 fname = die_get_decl_file(in_die); 844 if (fname && dwarf_decl_line(in_die, &lineno) == 0) { 845 lw->retval = lw->callback(fname, lineno, addr, lw->data); 846 if (lw->retval != 0) 847 return DIE_FIND_CB_END; 848 } 849 } 850 851 /* Continue to search nested inlined function call-sites */ 852 return DIE_FIND_CB_CONTINUE; 853 } 854 855 /* Walk on lines of blocks included in given DIE */ 856 static int __die_walk_funclines(Dwarf_Die *sp_die, bool recursive, 857 line_walk_callback_t callback, void *data) 858 { 859 struct __line_walk_param lw = { 860 .recursive = recursive, 861 .callback = callback, 862 .data = data, 863 .retval = 0, 864 }; 865 Dwarf_Die die_mem; 866 Dwarf_Addr addr; 867 const char *fname; 868 int lineno; 869 870 /* Handle function declaration line */ 871 fname = die_get_decl_file(sp_die); 872 if (fname && dwarf_decl_line(sp_die, &lineno) == 0 && 873 die_entrypc(sp_die, &addr) == 0) { 874 lw.retval = callback(fname, lineno, addr, data); 875 if (lw.retval != 0) 876 goto done; 877 } 878 die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem); 879 done: 880 return lw.retval; 881 } 882 883 static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data) 884 { 885 struct __line_walk_param *lw = data; 886 887 /* 888 * Since inlined function can include another inlined function in 889 * the same file, we need to walk in it recursively. 890 */ 891 lw->retval = __die_walk_funclines(sp_die, true, lw->callback, lw->data); 892 if (lw->retval != 0) 893 return DWARF_CB_ABORT; 894 895 return DWARF_CB_OK; 896 } 897 898 /** 899 * die_walk_lines - Walk on lines inside given DIE 900 * @rt_die: a root DIE (CU, subprogram or inlined_subroutine) 901 * @callback: callback routine 902 * @data: user data 903 * 904 * Walk on all lines inside given @rt_die and call @callback on each line. 905 * If the @rt_die is a function, walk only on the lines inside the function, 906 * otherwise @rt_die must be a CU DIE. 907 * Note that this walks not only dwarf line list, but also function entries 908 * and inline call-site. 909 */ 910 int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data) 911 { 912 Dwarf_Lines *lines; 913 Dwarf_Line *line; 914 Dwarf_Addr addr; 915 const char *fname, *decf = NULL, *inf = NULL; 916 int lineno, ret = 0; 917 int decl = 0, inl; 918 Dwarf_Die die_mem, *cu_die; 919 size_t nlines, i; 920 bool flag; 921 922 /* Get the CU die */ 923 if (dwarf_tag(rt_die) != DW_TAG_compile_unit) { 924 cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL); 925 dwarf_decl_line(rt_die, &decl); 926 decf = die_get_decl_file(rt_die); 927 if (!decf) { 928 pr_debug2("Failed to get the declared file name of %s\n", 929 dwarf_diename(rt_die)); 930 return -EINVAL; 931 } 932 } else 933 cu_die = rt_die; 934 if (!cu_die) { 935 pr_debug2("Failed to get CU from given DIE.\n"); 936 return -EINVAL; 937 } 938 939 /* Get lines list in the CU */ 940 if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) { 941 pr_debug2("Failed to get source lines on this CU.\n"); 942 return -ENOENT; 943 } 944 pr_debug2("Get %zd lines from this CU\n", nlines); 945 946 /* Walk on the lines on lines list */ 947 for (i = 0; i < nlines; i++) { 948 line = dwarf_onesrcline(lines, i); 949 if (line == NULL || 950 dwarf_lineno(line, &lineno) != 0 || 951 dwarf_lineaddr(line, &addr) != 0) { 952 pr_debug2("Failed to get line info. " 953 "Possible error in debuginfo.\n"); 954 continue; 955 } 956 /* Skip end-of-sequence */ 957 if (dwarf_lineendsequence(line, &flag) != 0 || flag) 958 continue; 959 /* Skip Non statement line-info */ 960 if (dwarf_linebeginstatement(line, &flag) != 0 || !flag) 961 continue; 962 /* Filter lines based on address */ 963 if (rt_die != cu_die) { 964 /* 965 * Address filtering 966 * The line is included in given function, and 967 * no inline block includes it. 968 */ 969 if (!dwarf_haspc(rt_die, addr)) 970 continue; 971 972 if (die_find_inlinefunc(rt_die, addr, &die_mem)) { 973 /* Call-site check */ 974 inf = die_get_call_file(&die_mem); 975 if ((inf && !strcmp(inf, decf)) && 976 die_get_call_lineno(&die_mem) == lineno) 977 goto found; 978 979 dwarf_decl_line(&die_mem, &inl); 980 if (inl != decl || 981 decf != die_get_decl_file(&die_mem)) 982 continue; 983 } 984 } 985 found: 986 /* Get source line */ 987 fname = dwarf_linesrc(line, NULL, NULL); 988 989 ret = callback(fname, lineno, addr, data); 990 if (ret != 0) 991 return ret; 992 } 993 994 /* 995 * Dwarf lines doesn't include function declarations and inlined 996 * subroutines. We have to check functions list or given function. 997 */ 998 if (rt_die != cu_die) 999 /* 1000 * Don't need walk inlined functions recursively, because 1001 * inner inlined functions don't have the lines of the 1002 * specified function. 1003 */ 1004 ret = __die_walk_funclines(rt_die, false, callback, data); 1005 else { 1006 struct __line_walk_param param = { 1007 .callback = callback, 1008 .data = data, 1009 .retval = 0, 1010 }; 1011 dwarf_getfuncs(cu_die, __die_walk_culines_cb, ¶m, 0); 1012 ret = param.retval; 1013 } 1014 1015 return ret; 1016 } 1017 1018 struct __find_variable_param { 1019 const char *name; 1020 Dwarf_Addr addr; 1021 }; 1022 1023 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) 1024 { 1025 struct __find_variable_param *fvp = data; 1026 Dwarf_Attribute attr; 1027 int tag; 1028 1029 tag = dwarf_tag(die_mem); 1030 if ((tag == DW_TAG_formal_parameter || 1031 tag == DW_TAG_variable) && 1032 die_compare_name(die_mem, fvp->name) && 1033 /* 1034 * Does the DIE have location information or const value 1035 * or external instance? 1036 */ 1037 (dwarf_attr(die_mem, DW_AT_external, &attr) || 1038 dwarf_attr(die_mem, DW_AT_location, &attr) || 1039 dwarf_attr(die_mem, DW_AT_const_value, &attr))) 1040 return DIE_FIND_CB_END; 1041 if (dwarf_haspc(die_mem, fvp->addr)) 1042 return DIE_FIND_CB_CONTINUE; 1043 else 1044 return DIE_FIND_CB_SIBLING; 1045 } 1046 1047 /** 1048 * die_find_variable_at - Find a given name variable at given address 1049 * @sp_die: a function DIE 1050 * @name: variable name 1051 * @addr: address 1052 * @die_mem: a buffer for result DIE 1053 * 1054 * Find a variable DIE called @name at @addr in @sp_die. 1055 */ 1056 Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name, 1057 Dwarf_Addr addr, Dwarf_Die *die_mem) 1058 { 1059 struct __find_variable_param fvp = { .name = name, .addr = addr}; 1060 1061 return die_find_child(sp_die, __die_find_variable_cb, (void *)&fvp, 1062 die_mem); 1063 } 1064 1065 static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) 1066 { 1067 const char *name = data; 1068 1069 if (dwarf_tag(die_mem) == DW_TAG_member) { 1070 if (die_compare_name(die_mem, name)) 1071 return DIE_FIND_CB_END; 1072 else if (!dwarf_diename(die_mem)) { /* Unnamed structure */ 1073 Dwarf_Die type_die, tmp_die; 1074 if (die_get_type(die_mem, &type_die) && 1075 die_find_member(&type_die, name, &tmp_die)) 1076 return DIE_FIND_CB_END; 1077 } 1078 } 1079 return DIE_FIND_CB_SIBLING; 1080 } 1081 1082 /** 1083 * die_find_member - Find a given name member in a data structure 1084 * @st_die: a data structure type DIE 1085 * @name: member name 1086 * @die_mem: a buffer for result DIE 1087 * 1088 * Find a member DIE called @name in @st_die. 1089 */ 1090 Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, 1091 Dwarf_Die *die_mem) 1092 { 1093 return die_find_child(st_die, __die_find_member_cb, (void *)name, 1094 die_mem); 1095 } 1096 1097 /** 1098 * die_get_typename_from_type - Get the name of given type DIE 1099 * @type_die: a type DIE 1100 * @buf: a strbuf for result type name 1101 * 1102 * Get the name of @type_die and stores it to @buf. Return 0 if succeeded. 1103 * and Return -ENOENT if failed to find type name. 1104 * Note that the result will stores typedef name if possible, and stores 1105 * "*(function_type)" if the type is a function pointer. 1106 */ 1107 int die_get_typename_from_type(Dwarf_Die *type_die, struct strbuf *buf) 1108 { 1109 int tag, ret; 1110 const char *tmp = ""; 1111 1112 tag = dwarf_tag(type_die); 1113 if (tag == DW_TAG_pointer_type) 1114 tmp = "*"; 1115 else if (tag == DW_TAG_array_type) 1116 tmp = "[]"; 1117 else if (tag == DW_TAG_subroutine_type) { 1118 /* Function pointer */ 1119 return strbuf_add(buf, "(function_type)", 15); 1120 } else { 1121 const char *name = dwarf_diename(type_die); 1122 1123 if (tag == DW_TAG_union_type) 1124 tmp = "union "; 1125 else if (tag == DW_TAG_structure_type) 1126 tmp = "struct "; 1127 else if (tag == DW_TAG_enumeration_type) 1128 tmp = "enum "; 1129 else if (name == NULL) 1130 return -ENOENT; 1131 /* Write a base name */ 1132 return strbuf_addf(buf, "%s%s", tmp, name ?: ""); 1133 } 1134 ret = die_get_typename(type_die, buf); 1135 if (ret < 0) { 1136 /* void pointer has no type attribute */ 1137 if (tag == DW_TAG_pointer_type && ret == -ENOENT) 1138 return strbuf_addf(buf, "void*"); 1139 1140 return ret; 1141 } 1142 return strbuf_addstr(buf, tmp); 1143 } 1144 1145 /** 1146 * die_get_typename - Get the name of given variable DIE 1147 * @vr_die: a variable DIE 1148 * @buf: a strbuf for result type name 1149 * 1150 * Get the name of @vr_die and stores it to @buf. Return 0 if succeeded. 1151 * and Return -ENOENT if failed to find type name. 1152 * Note that the result will stores typedef name if possible, and stores 1153 * "*(function_type)" if the type is a function pointer. 1154 */ 1155 int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) 1156 { 1157 Dwarf_Die type; 1158 1159 if (__die_get_real_type(vr_die, &type) == NULL) 1160 return -ENOENT; 1161 1162 return die_get_typename_from_type(&type, buf); 1163 } 1164 1165 /** 1166 * die_get_varname - Get the name and type of given variable DIE 1167 * @vr_die: a variable DIE 1168 * @buf: a strbuf for type and variable name 1169 * 1170 * Get the name and type of @vr_die and stores it in @buf as "type\tname". 1171 */ 1172 int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) 1173 { 1174 int ret; 1175 1176 ret = die_get_typename(vr_die, buf); 1177 if (ret < 0) { 1178 pr_debug("Failed to get type, make it unknown.\n"); 1179 ret = strbuf_add(buf, "(unknown_type)", 14); 1180 } 1181 1182 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); 1183 } 1184 1185 #if defined(HAVE_DWARF_GETLOCATIONS_SUPPORT) || defined(HAVE_DWARF_CFI_SUPPORT) 1186 static int reg_from_dwarf_op(Dwarf_Op *op) 1187 { 1188 switch (op->atom) { 1189 case DW_OP_reg0 ... DW_OP_reg31: 1190 return op->atom - DW_OP_reg0; 1191 case DW_OP_breg0 ... DW_OP_breg31: 1192 return op->atom - DW_OP_breg0; 1193 case DW_OP_regx: 1194 case DW_OP_bregx: 1195 return op->number; 1196 case DW_OP_fbreg: 1197 return DWARF_REG_FB; 1198 default: 1199 break; 1200 } 1201 return -1; 1202 } 1203 1204 static int offset_from_dwarf_op(Dwarf_Op *op) 1205 { 1206 switch (op->atom) { 1207 case DW_OP_reg0 ... DW_OP_reg31: 1208 case DW_OP_regx: 1209 return 0; 1210 case DW_OP_breg0 ... DW_OP_breg31: 1211 case DW_OP_fbreg: 1212 return op->number; 1213 case DW_OP_bregx: 1214 return op->number2; 1215 default: 1216 break; 1217 } 1218 return -1; 1219 } 1220 1221 static bool check_allowed_ops(Dwarf_Op *ops, size_t nops) 1222 { 1223 /* The first op is checked separately */ 1224 ops++; 1225 nops--; 1226 1227 /* 1228 * It needs to make sure if the location expression matches to the given 1229 * register and offset exactly. Thus it rejects any complex expressions 1230 * and only allows a few of selected operators that doesn't change the 1231 * location. 1232 */ 1233 while (nops) { 1234 switch (ops->atom) { 1235 case DW_OP_stack_value: 1236 case DW_OP_deref_size: 1237 case DW_OP_deref: 1238 case DW_OP_piece: 1239 break; 1240 default: 1241 return false; 1242 } 1243 ops++; 1244 nops--; 1245 } 1246 return true; 1247 } 1248 #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT || HAVE_DWARF_CFI_SUPPORT */ 1249 1250 #ifdef HAVE_DWARF_GETLOCATIONS_SUPPORT 1251 /** 1252 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE 1253 * @sp_die: a subprogram DIE 1254 * @vr_die: a variable DIE 1255 * @buf: a strbuf for variable byte offset range 1256 * 1257 * Get the innermost scope range of @vr_die and stores it in @buf as 1258 * "@<function_name+[NN-NN,NN-NN]>". 1259 */ 1260 static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die, 1261 struct strbuf *buf) 1262 { 1263 Dwarf_Die *scopes; 1264 int count; 1265 size_t offset = 0; 1266 Dwarf_Addr base; 1267 Dwarf_Addr start, end; 1268 Dwarf_Addr entry; 1269 int ret; 1270 bool first = true; 1271 const char *name; 1272 1273 ret = die_entrypc(sp_die, &entry); 1274 if (ret) 1275 return ret; 1276 1277 name = dwarf_diename(sp_die); 1278 if (!name) 1279 return -ENOENT; 1280 1281 count = dwarf_getscopes_die(vr_die, &scopes); 1282 1283 /* (*SCOPES)[1] is the DIE for the scope containing that scope */ 1284 if (count <= 1) { 1285 ret = -EINVAL; 1286 goto out; 1287 } 1288 1289 while ((offset = dwarf_ranges(&scopes[1], offset, &base, 1290 &start, &end)) > 0) { 1291 start -= entry; 1292 end -= entry; 1293 1294 if (first) { 1295 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, 1296 name, start, end); 1297 first = false; 1298 } else { 1299 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, 1300 start, end); 1301 } 1302 if (ret < 0) 1303 goto out; 1304 } 1305 1306 if (!first) 1307 ret = strbuf_add(buf, "]>", 2); 1308 1309 out: 1310 free(scopes); 1311 return ret; 1312 } 1313 1314 /** 1315 * die_get_var_range - Get byte offset range of given variable DIE 1316 * @sp_die: a subprogram DIE 1317 * @vr_die: a variable DIE 1318 * @buf: a strbuf for type and variable name and byte offset range 1319 * 1320 * Get the byte offset range of @vr_die and stores it in @buf as 1321 * "@<function_name+[NN-NN,NN-NN]>". 1322 */ 1323 int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) 1324 { 1325 int ret = 0; 1326 Dwarf_Addr base; 1327 Dwarf_Addr start, end; 1328 Dwarf_Addr entry; 1329 Dwarf_Op *op; 1330 size_t nops; 1331 size_t offset = 0; 1332 Dwarf_Attribute attr; 1333 bool first = true; 1334 const char *name; 1335 1336 ret = die_entrypc(sp_die, &entry); 1337 if (ret) 1338 return ret; 1339 1340 name = dwarf_diename(sp_die); 1341 if (!name) 1342 return -ENOENT; 1343 1344 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) 1345 return -EINVAL; 1346 1347 while ((offset = dwarf_getlocations(&attr, offset, &base, 1348 &start, &end, &op, &nops)) > 0) { 1349 if (start == 0) { 1350 /* Single Location Descriptions */ 1351 ret = die_get_var_innermost_scope(sp_die, vr_die, buf); 1352 goto out; 1353 } 1354 1355 /* Location Lists */ 1356 start -= entry; 1357 end -= entry; 1358 if (first) { 1359 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64, 1360 name, start, end); 1361 first = false; 1362 } else { 1363 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64, 1364 start, end); 1365 } 1366 if (ret < 0) 1367 goto out; 1368 } 1369 1370 if (!first) 1371 ret = strbuf_add(buf, "]>", 2); 1372 out: 1373 return ret; 1374 } 1375 1376 /* Interval parameters for __die_find_var_reg_cb() */ 1377 struct find_var_data { 1378 /* Target instruction address */ 1379 Dwarf_Addr pc; 1380 /* Target memory address (for global data) */ 1381 Dwarf_Addr addr; 1382 /* Target register */ 1383 unsigned reg; 1384 /* Access offset, set for global data */ 1385 int offset; 1386 /* True if the current register is the frame base */ 1387 bool is_fbreg; 1388 }; 1389 1390 /* Max number of registers DW_OP_regN supports */ 1391 #define DWARF_OP_DIRECT_REGS 32 1392 1393 static bool match_var_offset(Dwarf_Die *die_mem, struct find_var_data *data, 1394 u64 addr_offset, u64 addr_type, bool is_pointer) 1395 { 1396 Dwarf_Die type_die; 1397 Dwarf_Word size; 1398 1399 if (addr_offset == addr_type) { 1400 /* Update offset relative to the start of the variable */ 1401 data->offset = 0; 1402 return true; 1403 } 1404 1405 if (addr_offset < addr_type) 1406 return false; 1407 1408 if (die_get_real_type(die_mem, &type_die) == NULL) 1409 return false; 1410 1411 if (is_pointer && dwarf_tag(&type_die) == DW_TAG_pointer_type) { 1412 /* Get the target type of the pointer */ 1413 if (die_get_real_type(&type_die, &type_die) == NULL) 1414 return false; 1415 } 1416 1417 if (dwarf_aggregate_size(&type_die, &size) < 0) 1418 return false; 1419 1420 if (addr_offset >= addr_type + size) 1421 return false; 1422 1423 /* Update offset relative to the start of the variable */ 1424 data->offset = addr_offset - addr_type; 1425 return true; 1426 } 1427 1428 /* Only checks direct child DIEs in the given scope. */ 1429 static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg) 1430 { 1431 struct find_var_data *data = arg; 1432 int tag = dwarf_tag(die_mem); 1433 ptrdiff_t off = 0; 1434 Dwarf_Attribute attr; 1435 Dwarf_Addr base, start, end; 1436 Dwarf_Op *ops; 1437 size_t nops; 1438 1439 if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter) 1440 return DIE_FIND_CB_SIBLING; 1441 1442 if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) 1443 return DIE_FIND_CB_SIBLING; 1444 1445 while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) { 1446 /* Assuming the location list is sorted by address */ 1447 if (end <= data->pc) 1448 continue; 1449 if (start > data->pc) 1450 break; 1451 1452 /* Local variables accessed using frame base register */ 1453 if (data->is_fbreg && ops->atom == DW_OP_fbreg && 1454 check_allowed_ops(ops, nops) && 1455 match_var_offset(die_mem, data, data->offset, ops->number, 1456 /*is_pointer=*/false)) 1457 return DIE_FIND_CB_END; 1458 1459 /* Only match with a simple case */ 1460 if (data->reg < DWARF_OP_DIRECT_REGS) { 1461 /* pointer variables saved in a register 0 to 31 */ 1462 if (ops->atom == (DW_OP_reg0 + data->reg) && 1463 check_allowed_ops(ops, nops) && 1464 match_var_offset(die_mem, data, data->offset, 0, 1465 /*is_pointer=*/true)) 1466 return DIE_FIND_CB_END; 1467 1468 /* Local variables accessed by a register + offset */ 1469 if (ops->atom == (DW_OP_breg0 + data->reg) && 1470 check_allowed_ops(ops, nops) && 1471 match_var_offset(die_mem, data, data->offset, ops->number, 1472 /*is_pointer=*/false)) 1473 return DIE_FIND_CB_END; 1474 } else { 1475 /* pointer variables saved in a register 32 or above */ 1476 if (ops->atom == DW_OP_regx && ops->number == data->reg && 1477 check_allowed_ops(ops, nops) && 1478 match_var_offset(die_mem, data, data->offset, 0, 1479 /*is_pointer=*/true)) 1480 return DIE_FIND_CB_END; 1481 1482 /* Local variables accessed by a register + offset */ 1483 if (ops->atom == DW_OP_bregx && data->reg == ops->number && 1484 check_allowed_ops(ops, nops) && 1485 match_var_offset(die_mem, data, data->offset, ops->number2, 1486 /*is_poitner=*/false)) 1487 return DIE_FIND_CB_END; 1488 } 1489 } 1490 return DIE_FIND_CB_SIBLING; 1491 } 1492 1493 /** 1494 * die_find_variable_by_reg - Find a variable saved in a register 1495 * @sc_die: a scope DIE 1496 * @pc: the program address to find 1497 * @reg: the register number to find 1498 * @poffset: pointer to offset, will be updated for fbreg case 1499 * @is_fbreg: boolean value if the current register is the frame base 1500 * @die_mem: a buffer to save the resulting DIE 1501 * 1502 * Find the variable DIE accessed by the given register. It'll update the @offset 1503 * when the variable is in the stack. 1504 */ 1505 Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg, 1506 int *poffset, bool is_fbreg, 1507 Dwarf_Die *die_mem) 1508 { 1509 struct find_var_data data = { 1510 .pc = pc, 1511 .reg = reg, 1512 .offset = *poffset, 1513 .is_fbreg = is_fbreg, 1514 }; 1515 Dwarf_Die *result; 1516 1517 result = die_find_child(sc_die, __die_find_var_reg_cb, &data, die_mem); 1518 if (result) 1519 *poffset = data.offset; 1520 return result; 1521 } 1522 1523 /* Only checks direct child DIEs in the given scope */ 1524 static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg) 1525 { 1526 struct find_var_data *data = arg; 1527 int tag = dwarf_tag(die_mem); 1528 ptrdiff_t off = 0; 1529 Dwarf_Attribute attr; 1530 Dwarf_Addr base, start, end; 1531 Dwarf_Op *ops; 1532 size_t nops; 1533 1534 if (tag != DW_TAG_variable) 1535 return DIE_FIND_CB_SIBLING; 1536 1537 if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) 1538 return DIE_FIND_CB_SIBLING; 1539 1540 while ((off = dwarf_getlocations(&attr, off, &base, &start, &end, &ops, &nops)) > 0) { 1541 if (ops->atom != DW_OP_addr) 1542 continue; 1543 1544 if (check_allowed_ops(ops, nops) && 1545 match_var_offset(die_mem, data, data->addr, ops->number, 1546 /*is_pointer=*/false)) 1547 return DIE_FIND_CB_END; 1548 } 1549 return DIE_FIND_CB_SIBLING; 1550 } 1551 1552 /** 1553 * die_find_variable_by_addr - Find variable located at given address 1554 * @sc_die: a scope DIE 1555 * @addr: the data address to find 1556 * @die_mem: a buffer to save the resulting DIE 1557 * @offset: the offset in the resulting type 1558 * 1559 * Find the variable DIE located at the given address (in PC-relative mode). 1560 * This is usually for global variables. 1561 */ 1562 Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr addr, 1563 Dwarf_Die *die_mem, int *offset) 1564 { 1565 struct find_var_data data = { 1566 .addr = addr, 1567 }; 1568 Dwarf_Die *result; 1569 1570 result = die_find_child(sc_die, __die_find_var_addr_cb, &data, die_mem); 1571 if (result) 1572 *offset = data.offset; 1573 return result; 1574 } 1575 1576 static int __die_collect_vars_cb(Dwarf_Die *die_mem, void *arg) 1577 { 1578 struct die_var_type **var_types = arg; 1579 Dwarf_Die type_die; 1580 int tag = dwarf_tag(die_mem); 1581 Dwarf_Attribute attr; 1582 Dwarf_Addr base, start, end; 1583 Dwarf_Op *ops; 1584 size_t nops; 1585 struct die_var_type *vt; 1586 1587 if (tag != DW_TAG_variable && tag != DW_TAG_formal_parameter) 1588 return DIE_FIND_CB_SIBLING; 1589 1590 if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) 1591 return DIE_FIND_CB_SIBLING; 1592 1593 /* 1594 * Only collect the first location as it can reconstruct the 1595 * remaining state by following the instructions. 1596 * start = 0 means it covers the whole range. 1597 */ 1598 if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0) 1599 return DIE_FIND_CB_SIBLING; 1600 1601 if (!check_allowed_ops(ops, nops)) 1602 return DIE_FIND_CB_SIBLING; 1603 1604 if (die_get_real_type(die_mem, &type_die) == NULL) 1605 return DIE_FIND_CB_SIBLING; 1606 1607 vt = malloc(sizeof(*vt)); 1608 if (vt == NULL) 1609 return DIE_FIND_CB_END; 1610 1611 vt->die_off = dwarf_dieoffset(&type_die); 1612 vt->addr = start; 1613 vt->reg = reg_from_dwarf_op(ops); 1614 vt->offset = offset_from_dwarf_op(ops); 1615 vt->next = *var_types; 1616 *var_types = vt; 1617 1618 return DIE_FIND_CB_SIBLING; 1619 } 1620 1621 /** 1622 * die_collect_vars - Save all variables and parameters 1623 * @sc_die: a scope DIE 1624 * @var_types: a pointer to save the resulting list 1625 * 1626 * Save all variables and parameters in the @sc_die and save them to @var_types. 1627 * The @var_types is a singly-linked list containing type and location info. 1628 * Actual type can be retrieved using dwarf_offdie() with 'die_off' later. 1629 * 1630 * Callers should free @var_types. 1631 */ 1632 void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types) 1633 { 1634 Dwarf_Die die_mem; 1635 1636 die_find_child(sc_die, __die_collect_vars_cb, (void *)var_types, &die_mem); 1637 } 1638 1639 static int __die_collect_global_vars_cb(Dwarf_Die *die_mem, void *arg) 1640 { 1641 struct die_var_type **var_types = arg; 1642 Dwarf_Die type_die; 1643 int tag = dwarf_tag(die_mem); 1644 Dwarf_Attribute attr; 1645 Dwarf_Addr base, start, end; 1646 Dwarf_Op *ops; 1647 size_t nops; 1648 struct die_var_type *vt; 1649 1650 if (tag != DW_TAG_variable) 1651 return DIE_FIND_CB_SIBLING; 1652 1653 if (dwarf_attr(die_mem, DW_AT_location, &attr) == NULL) 1654 return DIE_FIND_CB_SIBLING; 1655 1656 /* Only collect the location with an absolute address. */ 1657 if (dwarf_getlocations(&attr, 0, &base, &start, &end, &ops, &nops) <= 0) 1658 return DIE_FIND_CB_SIBLING; 1659 1660 if (ops->atom != DW_OP_addr) 1661 return DIE_FIND_CB_SIBLING; 1662 1663 if (!check_allowed_ops(ops, nops)) 1664 return DIE_FIND_CB_SIBLING; 1665 1666 if (die_get_real_type(die_mem, &type_die) == NULL) 1667 return DIE_FIND_CB_SIBLING; 1668 1669 vt = malloc(sizeof(*vt)); 1670 if (vt == NULL) 1671 return DIE_FIND_CB_END; 1672 1673 vt->die_off = dwarf_dieoffset(&type_die); 1674 vt->addr = ops->number; 1675 vt->reg = -1; 1676 vt->offset = 0; 1677 vt->next = *var_types; 1678 *var_types = vt; 1679 1680 return DIE_FIND_CB_SIBLING; 1681 } 1682 1683 /** 1684 * die_collect_global_vars - Save all global variables 1685 * @cu_die: a CU DIE 1686 * @var_types: a pointer to save the resulting list 1687 * 1688 * Save all global variables in the @cu_die and save them to @var_types. 1689 * The @var_types is a singly-linked list containing type and location info. 1690 * Actual type can be retrieved using dwarf_offdie() with 'die_off' later. 1691 * 1692 * Callers should free @var_types. 1693 */ 1694 void die_collect_global_vars(Dwarf_Die *cu_die, struct die_var_type **var_types) 1695 { 1696 Dwarf_Die die_mem; 1697 1698 die_find_child(cu_die, __die_collect_global_vars_cb, (void *)var_types, &die_mem); 1699 } 1700 #endif /* HAVE_DWARF_GETLOCATIONS_SUPPORT */ 1701 1702 #ifdef HAVE_DWARF_CFI_SUPPORT 1703 /** 1704 * die_get_cfa - Get frame base information 1705 * @dwarf: a Dwarf info 1706 * @pc: program address 1707 * @preg: pointer for saved register 1708 * @poffset: pointer for saved offset 1709 * 1710 * This function gets register and offset for CFA (Canonical Frame Address) 1711 * by searching the CIE/FDE info. The CFA usually points to the start address 1712 * of the current stack frame and local variables can be located using an offset 1713 * from the CFA. The @preg and @poffset will be updated if it returns 0. 1714 */ 1715 int die_get_cfa(Dwarf *dwarf, u64 pc, int *preg, int *poffset) 1716 { 1717 Dwarf_CFI *cfi; 1718 Dwarf_Frame *frame = NULL; 1719 Dwarf_Op *ops = NULL; 1720 size_t nops; 1721 1722 cfi = dwarf_getcfi(dwarf); 1723 if (cfi == NULL) 1724 return -1; 1725 1726 if (!dwarf_cfi_addrframe(cfi, pc, &frame) && 1727 !dwarf_frame_cfa(frame, &ops, &nops) && 1728 check_allowed_ops(ops, nops)) { 1729 *preg = reg_from_dwarf_op(ops); 1730 *poffset = offset_from_dwarf_op(ops); 1731 return 0; 1732 } 1733 return -1; 1734 } 1735 #endif /* HAVE_DWARF_CFI_SUPPORT */ 1736 1737 /* 1738 * die_has_loclist - Check if DW_AT_location of @vr_die is a location list 1739 * @vr_die: a variable DIE 1740 */ 1741 static bool die_has_loclist(Dwarf_Die *vr_die) 1742 { 1743 Dwarf_Attribute loc; 1744 int tag = dwarf_tag(vr_die); 1745 1746 if (tag != DW_TAG_formal_parameter && 1747 tag != DW_TAG_variable) 1748 return false; 1749 1750 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) && 1751 dwarf_whatform(&loc) == DW_FORM_sec_offset); 1752 } 1753 1754 /* 1755 * die_is_optimized_target - Check if target program is compiled with 1756 * optimization 1757 * @cu_die: a CU DIE 1758 * 1759 * For any object in given CU whose DW_AT_location is a location list, 1760 * target program is compiled with optimization. This is applicable to 1761 * clang as well. 1762 */ 1763 bool die_is_optimized_target(Dwarf_Die *cu_die) 1764 { 1765 Dwarf_Die tmp_die; 1766 1767 if (die_has_loclist(cu_die)) 1768 return true; 1769 1770 if (!dwarf_child(cu_die, &tmp_die) && 1771 die_is_optimized_target(&tmp_die)) 1772 return true; 1773 1774 if (!dwarf_siblingof(cu_die, &tmp_die) && 1775 die_is_optimized_target(&tmp_die)) 1776 return true; 1777 1778 return false; 1779 } 1780 1781 /* 1782 * die_search_idx - Search index of given line address 1783 * @lines: Line records of single CU 1784 * @nr_lines: Number of @lines 1785 * @addr: address we are looking for 1786 * @idx: index to be set by this function (return value) 1787 * 1788 * Search for @addr by looping over every lines of CU. If address 1789 * matches, set index of that line in @idx. Note that single source 1790 * line can have multiple line records. i.e. single source line can 1791 * have multiple index. 1792 */ 1793 static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines, 1794 Dwarf_Addr addr, unsigned long *idx) 1795 { 1796 unsigned long i; 1797 Dwarf_Addr tmp; 1798 1799 for (i = 0; i < nr_lines; i++) { 1800 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp)) 1801 return false; 1802 1803 if (tmp == addr) { 1804 *idx = i; 1805 return true; 1806 } 1807 } 1808 return false; 1809 } 1810 1811 /* 1812 * die_get_postprologue_addr - Search next address after function prologue 1813 * @entrypc_idx: entrypc index 1814 * @lines: Line records of single CU 1815 * @nr_lines: Number of @lines 1816 * @hignpc: high PC address of function 1817 * @postprologue_addr: Next address after function prologue (return value) 1818 * 1819 * Look for prologue-end marker. If there is no explicit marker, return 1820 * address of next line record or next source line. 1821 */ 1822 static bool die_get_postprologue_addr(unsigned long entrypc_idx, 1823 Dwarf_Lines *lines, 1824 unsigned long nr_lines, 1825 Dwarf_Addr highpc, 1826 Dwarf_Addr *postprologue_addr) 1827 { 1828 unsigned long i; 1829 int entrypc_lno, lno; 1830 Dwarf_Line *line; 1831 Dwarf_Addr addr; 1832 bool p_end; 1833 1834 /* entrypc_lno is actual source line number */ 1835 line = dwarf_onesrcline(lines, entrypc_idx); 1836 if (dwarf_lineno(line, &entrypc_lno)) 1837 return false; 1838 1839 for (i = entrypc_idx; i < nr_lines; i++) { 1840 line = dwarf_onesrcline(lines, i); 1841 1842 if (dwarf_lineaddr(line, &addr) || 1843 dwarf_lineno(line, &lno) || 1844 dwarf_lineprologueend(line, &p_end)) 1845 return false; 1846 1847 /* highpc is exclusive. [entrypc,highpc) */ 1848 if (addr >= highpc) 1849 break; 1850 1851 /* clang supports prologue-end marker */ 1852 if (p_end) 1853 break; 1854 1855 /* Actual next line in source */ 1856 if (lno != entrypc_lno) 1857 break; 1858 1859 /* 1860 * Single source line can have multiple line records. 1861 * For Example, 1862 * void foo() { printf("hello\n"); } 1863 * contains two line records. One points to declaration and 1864 * other points to printf() line. Variable 'lno' won't get 1865 * incremented in this case but 'i' will. 1866 */ 1867 if (i != entrypc_idx) 1868 break; 1869 } 1870 1871 dwarf_lineaddr(line, postprologue_addr); 1872 if (*postprologue_addr >= highpc) 1873 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1), 1874 postprologue_addr); 1875 1876 return true; 1877 } 1878 1879 /* 1880 * die_skip_prologue - Use next address after prologue as probe location 1881 * @sp_die: a subprogram DIE 1882 * @cu_die: a CU DIE 1883 * @entrypc: entrypc of the function 1884 * 1885 * Function prologue prepares stack and registers before executing function 1886 * logic. When target program is compiled without optimization, function 1887 * parameter information is only valid after prologue. When we probe entrypc 1888 * of the function, and try to record function parameter, it contains 1889 * garbage value. 1890 */ 1891 void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die, 1892 Dwarf_Addr *entrypc) 1893 { 1894 size_t nr_lines = 0; 1895 unsigned long entrypc_idx = 0; 1896 Dwarf_Lines *lines = NULL; 1897 Dwarf_Addr postprologue_addr; 1898 Dwarf_Addr highpc; 1899 1900 if (dwarf_highpc(sp_die, &highpc)) 1901 return; 1902 1903 if (dwarf_getsrclines(cu_die, &lines, &nr_lines)) 1904 return; 1905 1906 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx)) 1907 return; 1908 1909 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines, 1910 highpc, &postprologue_addr)) 1911 return; 1912 1913 *entrypc = postprologue_addr; 1914 } 1915 1916 /* Internal parameters for __die_find_scope_cb() */ 1917 struct find_scope_data { 1918 /* Target instruction address */ 1919 Dwarf_Addr pc; 1920 /* Number of scopes found [output] */ 1921 int nr; 1922 /* Array of scopes found, 0 for the outermost one. [output] */ 1923 Dwarf_Die *scopes; 1924 }; 1925 1926 static int __die_find_scope_cb(Dwarf_Die *die_mem, void *arg) 1927 { 1928 struct find_scope_data *data = arg; 1929 1930 if (dwarf_haspc(die_mem, data->pc)) { 1931 Dwarf_Die *tmp; 1932 1933 tmp = realloc(data->scopes, (data->nr + 1) * sizeof(*tmp)); 1934 if (tmp == NULL) 1935 return DIE_FIND_CB_END; 1936 1937 memcpy(tmp + data->nr, die_mem, sizeof(*die_mem)); 1938 data->scopes = tmp; 1939 data->nr++; 1940 return DIE_FIND_CB_CHILD; 1941 } 1942 return DIE_FIND_CB_SIBLING; 1943 } 1944 1945 /** 1946 * die_get_scopes - Return a list of scopes including the address 1947 * @cu_die: a compile unit DIE 1948 * @pc: the address to find 1949 * @scopes: the array of DIEs for scopes (result) 1950 * 1951 * This function does the same as the dwarf_getscopes() but doesn't follow 1952 * the origins of inlined functions. It returns the number of scopes saved 1953 * in the @scopes argument. The outer scope will be saved first (index 0) and 1954 * the last one is the innermost scope at the @pc. 1955 */ 1956 int die_get_scopes(Dwarf_Die *cu_die, Dwarf_Addr pc, Dwarf_Die **scopes) 1957 { 1958 struct find_scope_data data = { 1959 .pc = pc, 1960 }; 1961 Dwarf_Die die_mem; 1962 1963 die_find_child(cu_die, __die_find_scope_cb, &data, &die_mem); 1964 1965 *scopes = data.scopes; 1966 return data.nr; 1967 } 1968 1969 static int __die_find_member_offset_cb(Dwarf_Die *die_mem, void *arg) 1970 { 1971 Dwarf_Die type_die; 1972 Dwarf_Word size, loc; 1973 Dwarf_Word offset = (long)arg; 1974 int tag = dwarf_tag(die_mem); 1975 1976 if (tag != DW_TAG_member) 1977 return DIE_FIND_CB_SIBLING; 1978 1979 /* Unions might not have location */ 1980 if (die_get_data_member_location(die_mem, &loc) < 0) { 1981 Dwarf_Attribute attr; 1982 1983 if (dwarf_attr_integrate(die_mem, DW_AT_data_bit_offset, &attr) && 1984 dwarf_formudata(&attr, &loc) == 0) 1985 loc /= 8; 1986 else 1987 loc = 0; 1988 } 1989 1990 if (offset == loc) 1991 return DIE_FIND_CB_END; 1992 1993 if (die_get_real_type(die_mem, &type_die) == NULL) { 1994 // TODO: add a pr_debug_dtp() later for this unlikely failure 1995 return DIE_FIND_CB_SIBLING; 1996 } 1997 1998 if (dwarf_aggregate_size(&type_die, &size) < 0) 1999 size = 0; 2000 2001 if (loc < offset && offset < (loc + size)) 2002 return DIE_FIND_CB_END; 2003 2004 return DIE_FIND_CB_SIBLING; 2005 } 2006 2007 /** 2008 * die_get_member_type - Return type info of struct member 2009 * @type_die: a type DIE 2010 * @offset: offset in the type 2011 * @die_mem: a buffer to save the resulting DIE 2012 * 2013 * This function returns a type of a member in @type_die where it's located at 2014 * @offset if it's a struct. For now, it just returns the first matching 2015 * member in a union. For other types, it'd return the given type directly 2016 * if it's within the size of the type or NULL otherwise. 2017 */ 2018 Dwarf_Die *die_get_member_type(Dwarf_Die *type_die, int offset, 2019 Dwarf_Die *die_mem) 2020 { 2021 Dwarf_Die *member; 2022 Dwarf_Die mb_type; 2023 int tag; 2024 2025 tag = dwarf_tag(type_die); 2026 /* If it's not a compound type, return the type directly */ 2027 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { 2028 Dwarf_Word size; 2029 2030 if (dwarf_aggregate_size(type_die, &size) < 0) 2031 size = 0; 2032 2033 if ((unsigned)offset >= size) 2034 return NULL; 2035 2036 *die_mem = *type_die; 2037 return die_mem; 2038 } 2039 2040 mb_type = *type_die; 2041 /* TODO: Handle union types better? */ 2042 while (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) { 2043 member = die_find_child(&mb_type, __die_find_member_offset_cb, 2044 (void *)(long)offset, die_mem); 2045 if (member == NULL) 2046 return NULL; 2047 2048 if (die_get_real_type(member, &mb_type) == NULL) 2049 return NULL; 2050 2051 tag = dwarf_tag(&mb_type); 2052 2053 if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type) { 2054 Dwarf_Word loc; 2055 2056 /* Update offset for the start of the member struct */ 2057 if (die_get_data_member_location(member, &loc) == 0) 2058 offset -= loc; 2059 } 2060 } 2061 *die_mem = mb_type; 2062 return die_mem; 2063 } 2064 2065 /** 2066 * die_deref_ptr_type - Return type info for pointer access 2067 * @ptr_die: a pointer type DIE 2068 * @offset: access offset for the pointer 2069 * @die_mem: a buffer to save the resulting DIE 2070 * 2071 * This function follows the pointer in @ptr_die with given @offset 2072 * and saves the resulting type in @die_mem. If the pointer points 2073 * a struct type, actual member at the offset would be returned. 2074 */ 2075 Dwarf_Die *die_deref_ptr_type(Dwarf_Die *ptr_die, int offset, 2076 Dwarf_Die *die_mem) 2077 { 2078 Dwarf_Die type_die; 2079 2080 if (dwarf_tag(ptr_die) != DW_TAG_pointer_type) 2081 return NULL; 2082 2083 if (die_get_real_type(ptr_die, &type_die) == NULL) 2084 return NULL; 2085 2086 return die_get_member_type(&type_die, offset, die_mem); 2087 } 2088
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.