2088 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * dwarf-aux.c : libdw auxiliary interfaces4 */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 file18 * @cu_die: A DIE(dwarf information entry) of CU(compilation Unit)19 * @fname: The tail filename of the target file20 *21 * Find the real(long) path of @fname in @cu_die.22 */23const 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 directory49 * @cu_die: a CU DIE50 *51 * Get the path of compilation directory of given @cu_die.52 * Since this depends on DW_AT_comp_dir, older gcc will not53 * embedded it. In that case, this returns NULL.54 */55const 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 */64static 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 else86 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 address110 * @cu_die: a CU DIE111 * @addr: An address112 * @fname: a pointer which returns the file name string113 * @lineno: a pointer which returns the line number114 *115 * Find a line number and file name for @addr in @cu_die.116 */117int 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 140out:141 return (*lineno && *fname) ? *lineno : -ENOENT;142}143 144static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);145 146/**147 * cu_walk_functions_at - Walk on function DIEs at given address148 * @cu_die: A CU DIE149 * @addr: An address150 * @callback: A callback which called with found DIEs151 * @data: A user data152 *153 * Walk on function DIEs at given @addr in @cu_die. Passed DIEs154 * should be subprogram or inlined-subroutines.155 */156int 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 object179 * @dw_die: A DIE of the object180 *181 * Get the linkage name attribute of given @dw_die.182 * For C++ binary, the linkage name will be the mangled symbol.183 */184const 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 tname195 * @dw_die: a DIE196 * @tname: a string of target name197 *198 * Compare the name of @dw_die and @tname. Return false if @dw_die has no name.199 */200bool 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 glob210 * @dw_die: a DIE211 * @glob: a string of target glob pattern212 *213 * Glob matching the name of @dw_die and @glob. Return false if matching fail.214 * This also match linkage name.215 */216bool 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 instance233 * @in_die: a DIE of an inlined function instance234 *235 * Get call-site line number of @in_die. This means from where the inline236 * function is called.237 */238int 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 DIE252 * @vr_die: a DIE of a variable253 * @die_mem: where to store a type DIE254 *255 * Get a DIE of the type of given variable (@vr_die), and store256 * it to die_mem. Return NULL if fails to get a type DIE.257 */258Dwarf_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 else266 return NULL;267}268 269/* Get a type die, but skip qualifiers */270Dwarf_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 typedef289 * @vr_die: a DIE of a variable290 * @die_mem: where to store a type DIE291 *292 * Get a DIE of the type of given variable (@vr_die), and store293 * 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 it295 * and tries to find real type (structure or basic types, e.g. int).296 */297Dwarf_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 */307static 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 not321 * @tp_die: a DIE of a type322 *323 * Get the encoding of @tp_die and return true if the encoding324 * is signed.325 */326bool 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 definition339 * @dw_die: a DIE340 *341 * Ensure that this DIE is a subprogram and NOT a declaration. This342 * returns true if @dw_die is a function definition.343 **/344bool 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 declaration357 * by gcc's bug #97060.358 * So we need to check this subprogram DIE has DW_AT_inline359 * 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 DIE370 * @dw_die: a DIE371 * @addr: where to store entry PC372 *373 * Since dwarf_entrypc() does not return entry PC if the DIE has only address374 * range, we have to use this to retrieve the lowest address from the address375 * range attribute.376 */377int 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 no390 * 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 subprogram400 * @dw_die: a DIE401 *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_die404 * must be a prototype. You can use die_walk_instances() to find actual405 * instances.406 **/407bool 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 offset423 * @mb_die: a DIE of a member of a data structure424 * @offs: The offset of the member in the data structure425 *426 * Get the offset of @mb_die in the data structure including @mb_die, and427 * stores result offset to @offs. If any error occurs this returns errno.428 */429int 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 */456static 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 else463 return -ENOENT;464}465 466/* Get the declared file index number in CU DIE */467static 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 else474 return -ENOENT;475}476 477/* Return the file name by index */478static 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 instance494 * @in_die: a DIE of an inlined function instance495 *496 * Get call-site file name of @in_die. This means from which file the inline497 * function is called.498 */499const 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 DIE506 * @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 uses510 * file index 0 for DW_AT_decl_file, die_get_decl_file() will return NULL for511 * such cases. Use this function instead.512 */513const 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 tree520 * @rt_die: a root DIE521 * @callback: a callback function522 * @data: a user data passed to the callback function523 * @die_mem: a buffer for result DIE524 *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 into527 * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE,528 * this continues to trace the tree. Optionally, @callback can return529 * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only530 * the children and trace only the siblings respectively.531 * Returns NULL if @callback can't find any appropriate DIE.532 */533Dwarf_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 560struct __addr_die_search_param {561 Dwarf_Addr addr;562 Dwarf_Die *die_mem;563};564 565static 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 at581 * given address582 * @cu_die: a CU DIE which including @addr583 * @addr: target address584 * @die_mem: a buffer for result DIE585 *586 * Search for a non-inlined function DIE with tail call at @addr. Stores the587 * DIE to @die_mem and returns it if found. Returns NULL if failed.588 */589Dwarf_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 else599 return die_mem;600}601 602/* die_find callback for non-inlined function search */603static 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 returns609 * 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 address621 * @cu_die: a CU DIE which including @addr622 * @addr: target address623 * @die_mem: a buffer for result DIE624 *625 * Search a non-inlined function DIE which includes @addr. Stores the626 * DIE to @die_mem and returns it if found. Returns NULL if failed.627 */628Dwarf_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 else638 return die_mem;639}640 641/* die_find callback for inline function search */642static 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 address655 * @sp_die: a subprogram DIE which including @addr656 * @addr: target address657 * @die_mem: a buffer for result DIE658 *659 * Search an inlined function DIE which includes @addr. Stores the660 * DIE to @die_mem and returns it if found. Returns NULL if failed.661 * Even if several inlined functions are expanded recursively, this662 * doesn't trace it down, and returns the topmost one.663 */664Dwarf_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 address672 * @sp_die: a subprogram DIE which including @addr673 * @addr: target address674 * @die_mem: a buffer for result DIE675 *676 * Search an inlined function DIE which includes @addr. Stores the677 * DIE to @die_mem and returns it if found. Returns NULL if failed.678 * If several inlined functions are expanded recursively, this trace679 * it down and returns deepest one.680 */681Dwarf_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 700static 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 function716 * @cu_die: a CU DIE717 * @name: target function name718 * @die_mem: a buffer for result DIE719 *720 * Search a non-inlined function which matches to @name and stores the721 * 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 a723 * definition of the function, so it doesn't match with address.724 * Most likely, it can find a declaration at the top level. Thus the725 * callback function continues to sibling entries only.726 */727Dwarf_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 743struct __instance_walk_param {744 void *addr;745 int (*callback)(Dwarf_Die *, void *);746 void *data;747 int retval;748};749 750static 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 DIE787 * @or_die: an abstract original DIE788 * @callback: a callback function which is called with instance DIE789 * @data: user data790 *791 * Walk on the instances of give @in_die. @in_die must be an inlined function792 * declaration. This returns the return value of @callback if it returns793 * non-zero value, or -ENOENT if there is no instance.794 */795int 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 */816struct __line_walk_param {817 bool recursive;818 line_walk_callback_t callback;819 void *data;820 int retval;821};822 823static 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 */856static 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);879done:880 return lw.retval;881}882 883static 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 in889 * 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 DIE900 * @rt_die: a root DIE (CU, subprogram or inlined_subroutine)901 * @callback: callback routine902 * @data: user data903 *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 entries908 * and inline call-site.909 */910int 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 } else933 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 filtering966 * The line is included in given function, and967 * 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 }985found: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 inlined996 * 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, because1001 * inner inlined functions don't have the lines of the1002 * 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 1018struct __find_variable_param {1019 const char *name;1020 Dwarf_Addr addr;1021};1022 1023static 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 value1035 * 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 else1044 return DIE_FIND_CB_SIBLING;1045}1046 1047/**1048 * die_find_variable_at - Find a given name variable at given address1049 * @sp_die: a function DIE1050 * @name: variable name1051 * @addr: address1052 * @die_mem: a buffer for result DIE1053 *1054 * Find a variable DIE called @name at @addr in @sp_die.1055 */1056Dwarf_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 1065static 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 structure1084 * @st_die: a data structure type DIE1085 * @name: member name1086 * @die_mem: a buffer for result DIE1087 *1088 * Find a member DIE called @name in @st_die.1089 */1090Dwarf_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 DIE1099 * @type_die: a type DIE1100 * @buf: a strbuf for result type name1101 *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 stores1105 * "*(function_type)" if the type is a function pointer.1106 */1107int 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 DIE1147 * @vr_die: a variable DIE1148 * @buf: a strbuf for result type name1149 *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 stores1153 * "*(function_type)" if the type is a function pointer.1154 */1155int 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 DIE1167 * @vr_die: a variable DIE1168 * @buf: a strbuf for type and variable name1169 *1170 * Get the name and type of @vr_die and stores it in @buf as "type\tname".1171 */1172int 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)1186static 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 1204static 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 1221static 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 given1229 * register and offset exactly. Thus it rejects any complex expressions1230 * and only allows a few of selected operators that doesn't change the1231 * 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_SUPPORT1251/**1252 * die_get_var_innermost_scope - Get innermost scope range of given variable DIE1253 * @sp_die: a subprogram DIE1254 * @vr_die: a variable DIE1255 * @buf: a strbuf for variable byte offset range1256 *1257 * Get the innermost scope range of @vr_die and stores it in @buf as1258 * "@<function_name+[NN-NN,NN-NN]>".1259 */1260static 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 1309out:1310 free(scopes);1311 return ret;1312}1313 1314/**1315 * die_get_var_range - Get byte offset range of given variable DIE1316 * @sp_die: a subprogram DIE1317 * @vr_die: a variable DIE1318 * @buf: a strbuf for type and variable name and byte offset range1319 *1320 * Get the byte offset range of @vr_die and stores it in @buf as1321 * "@<function_name+[NN-NN,NN-NN]>".1322 */1323int 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);1372out:1373 return ret;1374}1375 1376/* Interval parameters for __die_find_var_reg_cb() */1377struct 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 321392 1393static 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. */1429static 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 register1495 * @sc_die: a scope DIE1496 * @pc: the program address to find1497 * @reg: the register number to find1498 * @poffset: pointer to offset, will be updated for fbreg case1499 * @is_fbreg: boolean value if the current register is the frame base1500 * @die_mem: a buffer to save the resulting DIE1501 *1502 * Find the variable DIE accessed by the given register. It'll update the @offset1503 * when the variable is in the stack.1504 */1505Dwarf_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 */1524static 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 address1554 * @sc_die: a scope DIE1555 * @addr: the data address to find1556 * @die_mem: a buffer to save the resulting DIE1557 * @offset: the offset in the resulting type1558 *1559 * Find the variable DIE located at the given address (in PC-relative mode).1560 * This is usually for global variables.1561 */1562Dwarf_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 1576static 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 the1595 * 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 parameters1623 * @sc_die: a scope DIE1624 * @var_types: a pointer to save the resulting list1625 *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 */1632void 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 1639static 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 variables1685 * @cu_die: a CU DIE1686 * @var_types: a pointer to save the resulting list1687 *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 */1694void 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_SUPPORT1703/**1704 * die_get_cfa - Get frame base information1705 * @dwarf: a Dwarf info1706 * @pc: program address1707 * @preg: pointer for saved register1708 * @poffset: pointer for saved offset1709 *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 address1712 * of the current stack frame and local variables can be located using an offset1713 * from the CFA. The @preg and @poffset will be updated if it returns 0.1714 */1715int 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 list1739 * @vr_die: a variable DIE1740 */1741static 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 with1756 * optimization1757 * @cu_die: a CU DIE1758 *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 to1761 * clang as well.1762 */1763bool 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 address1783 * @lines: Line records of single CU1784 * @nr_lines: Number of @lines1785 * @addr: address we are looking for1786 * @idx: index to be set by this function (return value)1787 *1788 * Search for @addr by looping over every lines of CU. If address1789 * matches, set index of that line in @idx. Note that single source1790 * line can have multiple line records. i.e. single source line can1791 * have multiple index.1792 */1793static 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 prologue1813 * @entrypc_idx: entrypc index1814 * @lines: Line records of single CU1815 * @nr_lines: Number of @lines1816 * @hignpc: high PC address of function1817 * @postprologue_addr: Next address after function prologue (return value)1818 *1819 * Look for prologue-end marker. If there is no explicit marker, return1820 * address of next line record or next source line.1821 */1822static 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 and1864 * other points to printf() line. Variable 'lno' won't get1865 * 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 location1881 * @sp_die: a subprogram DIE1882 * @cu_die: a CU DIE1883 * @entrypc: entrypc of the function1884 *1885 * Function prologue prepares stack and registers before executing function1886 * logic. When target program is compiled without optimization, function1887 * parameter information is only valid after prologue. When we probe entrypc1888 * of the function, and try to record function parameter, it contains1889 * garbage value.1890 */1891void 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() */1917struct 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 1926static 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 address1947 * @cu_die: a compile unit DIE1948 * @pc: the address to find1949 * @scopes: the array of DIEs for scopes (result)1950 *1951 * This function does the same as the dwarf_getscopes() but doesn't follow1952 * the origins of inlined functions. It returns the number of scopes saved1953 * in the @scopes argument. The outer scope will be saved first (index 0) and1954 * the last one is the innermost scope at the @pc.1955 */1956int 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 1969static 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 else1987 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 failure1995 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 member2009 * @type_die: a type DIE2010 * @offset: offset in the type2011 * @die_mem: a buffer to save the resulting DIE2012 *2013 * This function returns a type of a member in @type_die where it's located at2014 * @offset if it's a struct. For now, it just returns the first matching2015 * member in a union. For other types, it'd return the given type directly2016 * if it's within the size of the type or NULL otherwise.2017 */2018Dwarf_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 access2067 * @ptr_die: a pointer type DIE2068 * @offset: access offset for the pointer2069 * @die_mem: a buffer to save the resulting DIE2070 *2071 * This function follows the pointer in @ptr_die with given @offset2072 * and saves the resulting type in @die_mem. If the pointer points2073 * a struct type, actual member at the offset would be returned.2074 */2075Dwarf_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