diff options
Diffstat (limited to 'addr2line/addr2line.c')
-rw-r--r-- | addr2line/addr2line.c | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/addr2line/addr2line.c b/addr2line/addr2line.c index cfdcc745f9fb..9863fcdc634a 100644 --- a/addr2line/addr2line.c +++ b/addr2line/addr2line.c @@ -39,7 +39,7 @@ #include "_elftc.h" -ELFTC_VCSID("$Id: addr2line.c 3197 2015-05-12 21:01:31Z emaste $"); +ELFTC_VCSID("$Id: addr2line.c 3249 2015-10-04 08:11:30Z kaiwang27 $"); static struct option longopts[] = { {"target" , required_argument, NULL, 'b'}, @@ -61,7 +61,7 @@ Usage: %s [options] hexaddress...\n\ Map program addresses to source file names and line numbers.\n\n\ Options:\n\ -b TGT | --target=TGT (Accepted but ignored).\n\ - -e EXE | --exec=EXE Use program \"EXE\" to translate addresses.\n\ + -e EXE | --exe=EXE Use program \"EXE\" to translate addresses.\n\ -f | --functions Display function names.\n\ -j NAME | --section=NAME Values are offsets into section \"NAME\".\n\ -s | --basename Only show the base name for each file name.\n\ @@ -123,8 +123,7 @@ handle_high_pc(Dwarf_Die die, Dwarf_Unsigned lopc, Dwarf_Unsigned *hipc) } static void -search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, - const char **rlt_func) +search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, char **rlt_func) { Dwarf_Die ret_die, spec_die; Dwarf_Error de; @@ -133,10 +132,11 @@ search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, Dwarf_Off ref; Dwarf_Attribute sub_at, spec_at; char *func0; + const char *func1; int ret; if (*rlt_func != NULL) - return; + goto done; if (dwarf_tag(die, &tag, &de)) { warnx("dwarf_tag: %s", dwarf_errmsg(de)); @@ -153,16 +153,19 @@ search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, /* Found it! */ - *rlt_func = unknown; + if ((*rlt_func = strdup(unknown)) == NULL) + err(EXIT_FAILURE, "strdup"); ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); if (ret == DW_DLV_ERROR) - return; + goto done; if (ret == DW_DLV_OK) { - if (dwarf_formstring(sub_at, &func0, &de)) - *rlt_func = unknown; - else - *rlt_func = func0; - return; + if (dwarf_formstring(sub_at, &func0, &de) == + DW_DLV_OK) { + free(*rlt_func); + if ((*rlt_func = strdup(func0)) == NULL) + err(EXIT_FAILURE, "strdup"); + } + goto done; } /* @@ -171,15 +174,19 @@ search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, * referenced by DW_AT_specification. */ if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) - return; + goto done; if (dwarf_global_formref(spec_at, &ref, &de)) - return; + goto done; if (dwarf_offdie(dbg, ref, &spec_die, &de)) - return; - if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de)) - *rlt_func = unknown; + goto done; + if (dwarf_attrval_string(spec_die, DW_AT_name, &func1, &de) == + DW_DLV_OK) { + free(*rlt_func); + if ((*rlt_func = strdup(func1)) == NULL) + err(EXIT_FAILURE, "strdup"); + } - return; + goto done; } cont_search: @@ -197,19 +204,22 @@ cont_search: errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_func(dbg, ret_die, addr, rlt_func); + +done: + dwarf_dealloc(dbg, die, DW_DLA_DIE); } static void translate(Dwarf_Debug dbg, const char* addrstr) { - Dwarf_Die die; + Dwarf_Die die, ret_die; Dwarf_Line *lbuf; Dwarf_Error de; Dwarf_Half tag; Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; Dwarf_Signed lcount; Dwarf_Addr lineaddr, plineaddr; - const char *funcname; + char *funcname; char *file, *file0, *pfile; char demangled[1024]; int i, ret; @@ -218,23 +228,29 @@ translate(Dwarf_Debug dbg, const char* addrstr) addr += section_base; lineno = 0; file = unknown; + lbuf = NULL; + lcount = 0; while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { die = NULL; - while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { + while (dwarf_siblingof(dbg, die, &ret_die, &de) == DW_DLV_OK) { + if (die != NULL) + dwarf_dealloc(dbg, die, DW_DLA_DIE); + die = ret_die; if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); - goto out; + goto next_cu; } + /* XXX: What about DW_TAG_partial_unit? */ if (tag == DW_TAG_compile_unit) break; } - if (die == NULL) { + if (ret_die == NULL) { warnx("could not find DW_TAG_compile_unit die"); - goto out; + goto next_cu; } if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { @@ -243,12 +259,18 @@ translate(Dwarf_Debug dbg, const char* addrstr) * this CU. */ if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) - continue; + goto next_cu; if (addr < lopc || addr >= hipc) - continue; + goto next_cu; } - if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) { + switch (dwarf_srclines(die, &lbuf, &lcount, &de)) { + case DW_DLV_OK: + break; + case DW_DLV_NO_ENTRY: + /* If a CU lacks debug info, just skip it. */ + goto next_cu; + default: warnx("dwarf_srclines: %s", dwarf_errmsg(de)); goto out; } @@ -283,25 +305,37 @@ translate(Dwarf_Debug dbg, const char* addrstr) plineno = lineno; pfile = file; } + next_cu: + if (die != NULL) { + dwarf_dealloc(dbg, die, DW_DLA_DIE); + die = NULL; + } } out: funcname = NULL; - if (ret == DW_DLV_OK && func) + if (ret == DW_DLV_OK && func) { search_func(dbg, die, addr, &funcname); + die = NULL; + } if (func) { if (funcname == NULL) - funcname = unknown; + if ((funcname = strdup(unknown)) == NULL) + err(EXIT_FAILURE, "strdup"); if (demangle && !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) printf("%s\n", demangled); else printf("%s\n", funcname); + free(funcname); } (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); + if (die != NULL) + dwarf_dealloc(dbg, die, DW_DLA_DIE); + /* * Reset internal CU pointer, so we will start from the first CU * next round. |