static char * demangle(char *name, int strict, size_t *pos) { static char dem[STRBUFSZ]; char nb[STRBUFSZ]; size_t p, t; if (stripus && *name == '_') { strncpy(nb, name + 1, sizeof(nb) - 1); t = 1; } else { strncpy(nb, name, sizeof(nb) - 1); t = 0; } nb[sizeof(nb) - 1] = '\0'; p = strlen(nb); if (p == 0) return NULL; while (elftc_demangle(nb, dem, sizeof(dem), (unsigned) format) < 0) { if (!strict && p > 1) { nb[--p] = '\0'; continue; } else return (NULL); } if (pos != NULL) *pos = t ? p + 1 : p; return (dem); }
static char * demangle(char *name) { static char dem[STRBUFSZ]; if (stripus && *name == '_') name++; if (strlen(name) == 0) return (NULL); if (elftc_demangle(name, dem, sizeof(dem), (unsigned) format) < 0) return (NULL); return (dem); }
static void translate(Dwarf_Debug dbg, const char* addrstr) { 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; char *funcname; char *file, *file0, *pfile; char demangled[1024]; int i, ret; addr = strtoull(addrstr, NULL, 16); addr += section_base; lineno = 0; file = unknown; die = NULL; 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, &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 next_cu; } /* XXX: What about DW_TAG_partial_unit? */ if (tag == DW_TAG_compile_unit) break; } if (ret_die == NULL) { warnx("could not find DW_TAG_compile_unit die"); goto next_cu; } if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { /* * Check if the address falls into the PC range of * this CU. */ if (handle_high_pc(die, lopc, &hipc) != DW_DLV_OK) goto next_cu; if (addr < lopc || addr >= hipc) goto next_cu; } 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; } plineaddr = ~0ULL; plineno = 0; pfile = unknown; for (i = 0; i < lcount; i++) { if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { warnx("dwarf_lineaddr: %s", dwarf_errmsg(de)); goto out; } if (dwarf_lineno(lbuf[i], &lineno, &de)) { warnx("dwarf_lineno: %s", dwarf_errmsg(de)); goto out; } if (dwarf_linesrc(lbuf[i], &file0, &de)) { warnx("dwarf_linesrc: %s", dwarf_errmsg(de)); } else file = file0; if (addr == lineaddr) goto out; else if (addr < lineaddr && addr > plineaddr) { lineno = plineno; file = pfile; goto out; } plineaddr = lineaddr; 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) { search_func(dbg, die, addr, &funcname); die = NULL; } if (func) { if (funcname == NULL) 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. */ while (ret != DW_DLV_NO_ENTRY) { if (ret == DW_DLV_ERROR) errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", dwarf_errmsg(de)); ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, &de); } }