void close_dwarf_executable (void) { int dwStatus = -1; Elf *elfHandle = NULL; mpiPi_msg_debug ("enter close_dwarf_executable\n"); assert (dwHandle != NULL); assert (dwFd != -1); dwStatus = dwarf_get_elf (dwHandle, &elfHandle, &dw_err); if (dwStatus != DW_DLV_OK) { mpiPi_msg_debug ("dwarf_get_elf failed; ignoring : %s\n", dwarf_errmsg(dw_err)); } dwStatus = dwarf_finish (dwHandle, &dw_err); if (dwStatus != DW_DLV_OK) { mpiPi_msg_debug ("dwarf_finish failed; ignoring : %s\n", dwarf_errmsg(dw_err)); } dwHandle = NULL; close (dwFd); dwFd = -1; AddrToSourceMap_Destroy (); FunctionMap_Destroy (); }
static void _dwarf_die_offset(Dwarf_Die die) { Dwarf_Off rel_off, die_off, cu_off, cu_len; Dwarf_Error de; if (dwarf_die_CU_offset(die, &rel_off, &de) != DW_DLV_OK) { tet_printf("dwarf_die_CU_offset failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; } TS_CHECK_INT(rel_off); if (dwarf_die_CU_offset_range(die, &cu_off, &cu_len, &de) != DW_DLV_OK) { tet_printf("dwarf_die_CU_offset_range failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; } TS_CHECK_INT(cu_off); TS_CHECK_INT(cu_len); if (dwarf_dieoffset(die, &die_off, &de) != DW_DLV_OK) { tet_printf("dwarf_dieoffset failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; } TS_CHECK_INT(die_off); }
void CUsHolder::clean(void) throw() { Dwarf_Error err = NULL; int ret = 0; for(size_t idx = 0; idx < size(); ++idx) { dwarf_dealloc(m_dbg, (*this)[idx], DW_DLA_DIE); (*this)[idx] = NULL; } ret = dwarf_finish(m_dbg, &err); if(ret != DW_DLV_OK) { MSG("libdwarf cleanup failed: %s\n", dwarf_errmsg(err)); } clear(); m_dbg = NULL; if(m_fd != -1) { close(m_fd), m_fd = -1; } }
static void tp_dwarf_die_offset_given_cu(void) { Dwarf_Debug dbg; Dwarf_Error de; Dwarf_Off cu_offset, cu_dieoff; Dwarf_Unsigned cu_next_offset; int fd; result = TET_UNRESOLVED; TS_DWARF_INIT(dbg, fd, de); cu_offset = 0; TS_DWARF_CU_FOREACH(dbg, cu_next_offset, de) { if (dwarf_get_cu_die_offset_given_cu_header_offset(dbg, cu_offset, &cu_dieoff, &de) != DW_DLV_OK) { tet_printf("dwarf_get_cu_die_offset_given_cu_header" "_offset failed: %s", dwarf_errmsg(de)); result = TET_FAIL; goto done; } TS_CHECK_INT(cu_dieoff); cu_offset = cu_next_offset; } if (result == TET_UNRESOLVED) result = TET_PASS; done: TS_DWARF_FINISH(dbg, de); TS_RESULT(result); }
int main (int argc, char *argv[]) { assert (argc >= 3); const char *name = argv[1]; ptrdiff_t cuoff = strtol (argv[2], NULL, 0); bool new_style = argc > 3; int fd = open (name, O_RDONLY); Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem); for (ptrdiff_t off = new_style ? DWARF_GETMACROS_START : 0; (off = dwarf_getmacros (cudie, mac, dbg, off)); ) if (off == -1) { puts (dwarf_errmsg (dwarf_errno ())); break; } dwarf_end (dbg); return 0; }
static void print_detail (int result, const Dwarf_Op *ops, size_t nops, Dwarf_Addr bias) { if (result < 0) printf ("indeterminate (%s)\n", dwarf_errmsg (-1)); else if (nops == 0) printf ("%s\n", result == 0 ? "same_value" : "undefined"); else { printf ("%s expression:", result == 0 ? "location" : "value"); for (size_t i = 0; i < nops; ++i) { printf (" %#x", ops[i].atom); if (ops[i].number2 == 0) { if (ops[i].atom == DW_OP_addr) printf ("(%#" PRIx64 ")", ops[i].number + bias); else if (ops[i].number != 0) printf ("(%" PRId64 ")", ops[i].number); } else printf ("(%" PRId64 ",%" PRId64 ")", ops[i].number, ops[i].number2); } puts (""); } }
/* * Use the DWARF expression for the Call-frame-address and determine * if return address is in LR and if a new frame was allocated. */ static int check_return_reg(int ra_regno, Dwarf_Frame *frame) { Dwarf_Op ops_mem[2]; Dwarf_Op dummy; Dwarf_Op *ops = &dummy; size_t nops; int result; result = dwarf_frame_register(frame, ra_regno, ops_mem, &ops, &nops); if (result < 0) { pr_debug("dwarf_frame_register() %s\n", dwarf_errmsg(-1)); return -1; } /* * Check if return address is on the stack. If return address * is in a register (typically R0), it is yet to be saved on * the stack. */ if ((nops != 0 || ops != NULL) && !(nops == 1 && ops[0].atom == DW_OP_regx && ops[0].number2 == 0 && ops[0].offset == 0)) return 0; /* * Return address is in LR. Check if a frame was allocated * but not-yet used. */ result = dwarf_frame_cfa(frame, &ops, &nops); if (result < 0) { pr_debug("dwarf_frame_cfa() returns %d, %s\n", result, dwarf_errmsg(-1)); return -1; } /* * If call frame address is in r1, no new frame was allocated. */ if (nops == 1 && ops[0].atom == DW_OP_bregx && ops[0].number == 1 && ops[0].number2 == 0) return 1; /* * A new frame was allocated but has not yet been used. */ return 2; }
static void _dwarf_srcfiles(Dwarf_Die die) { Dwarf_Half tag; Dwarf_Error de; Dwarf_Signed srccount; char **srcfiles; int r_srcfiles, i; if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { tet_printf("dwarf_tag failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; return; } r_srcfiles = dwarf_srcfiles(die, &srcfiles, &srccount, &de); TS_CHECK_INT(r_srcfiles); if (r_srcfiles == DW_DLV_ERROR) { tet_printf("dwarf_srcfiles should not fail but still failed:", " %s", dwarf_errmsg(de)); return; } if (r_srcfiles != DW_DLV_OK) return; if (dwarf_srcfiles(die, &srcfiles, &srccount, &de) != DW_DLV_OK) { tet_printf("dwarf_srcfiles failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; return; } TS_CHECK_INT(srccount); for (i = 0; i < srccount; i++) { if (srcfiles[i] == NULL) { tet_printf("dwarf_srcfiles returned NULL pointer" " srcfiles[%d]\n", i); result = TET_FAIL; } else TS_CHECK_STRING(srcfiles[i]); } }
static void include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token) { while ((token = dwarf_getmacros_off (dbg, macoff, mac, dbg, token)) != 0) if (token == -1) { puts (dwarf_errmsg (dwarf_errno ())); break; } }
static int handle_function (Dwarf_Die *func, void *arg) { struct args *a = arg; const char *name = dwarf_diename (func); char **argv = a->argv; if (argv[0] != NULL) { bool match; do match = fnmatch (*argv, name, 0) == 0; while (!match && *++argv); if (!match) return 0; } if (dwarf_func_inline (func)) return 0; Dwarf_Addr entrypc; if (dwarf_entrypc (func, &entrypc) != 0) error (EXIT_FAILURE, 0, "dwarf_entrypc: %s: %s", dwarf_diename (func), dwarf_errmsg (-1)); entrypc += a->dwbias; printf ("%-16s %#.16" PRIx64, dwarf_diename (func), entrypc); Dwarf_Addr *bkpts = NULL; int result = dwarf_entry_breakpoints (func, &bkpts); if (result <= 0) printf ("\t%s\n", dwarf_errmsg (-1)); else { for (int i = 0; i < result; ++i) printf (" %#.16" PRIx64 "%s", bkpts[i] + a->dwbias, i == result - 1 ? "\n" : ""); free (bkpts); } return 0; }
int type_of(Dwarf_Debug dbg, Dwarf_Die *die, Dwarf_Die *type_die, Dwarf_Error *err) { Dwarf_Attribute type; Dwarf_Off ref_off = 0; if (type_off(die, &ref_off, err) != DW_DLV_OK) { fprintf(stderr, "Error in getting type offset: %s\n", dwarf_errmsg(*err)); return -1; } int status; if ((status = dwarf_offdie(dbg, ref_off, type_die, err)) != DW_DLV_OK) { fprintf(stderr, "Error %d in getting die at offset: %s\n", status, dwarf_errmsg(*err)); return status; } return DW_DLV_OK; }
static void record_line_error(const char *where, Dwarf_Error err) { char tmp_buff[500]; if (check_lines && checking_this_compiler()) { snprintf(tmp_buff, sizeof(tmp_buff), "Error getting line details calling %s dwarf error is %s", where,dwarf_errmsg(err)); DWARF_CHECK_ERROR(lines_result,tmp_buff); } }
static int chkerr2(int ret, Dwarf_Error *err) { if (ret == DW_DLV_ERROR) { if (err != NULL) { rb_raise(rd_eError, "%s", dwarf_errmsg(*err)); } else { rb_raise(rd_eError, "Unknown Error"); } } return ret == DW_DLV_OK; }
static void tp_dwarf_ranges(void) { Dwarf_Debug dbg; Dwarf_Ranges *ranges; Dwarf_Signed range_cnt; Dwarf_Unsigned byte_cnt; Dwarf_Off off; Dwarf_Error de; int fd, r_ranges, i; result = TET_UNRESOLVED; TS_DWARF_INIT(dbg, fd, de); off = 0; for (;;) { tet_printf("check ranges at offset(%ju):\n", (uintmax_t) off); r_ranges = dwarf_get_ranges_a(dbg, off, NULL, &ranges, &range_cnt, &byte_cnt, &de); if (r_ranges != DW_DLV_OK) break; TS_CHECK_INT(range_cnt); TS_CHECK_UINT(byte_cnt); off += byte_cnt; for (i = 0; i < range_cnt; i++) { tet_printf("check range %d:\n", i); TS_CHECK_INT(ranges[i].dwr_type); TS_CHECK_UINT(ranges[i].dwr_addr1); TS_CHECK_UINT(ranges[i].dwr_addr2); } } /* * SGI libdwarf return DW_DLV_ERROR when provided offset is out of * range, instead of DW_DLV_NO_ENTRY as stated in the SGI libdwarf * documentation. elftoolchain libdwarf follows the SGI libdwarf * documentation. */ #if 0 if (r_ranges == DW_DLV_ERROR) { tet_printf("dwarf_get_ranges failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; } #endif if (result == TET_UNRESOLVED) result = TET_PASS; done: TS_DWARF_FINISH(dbg, de); TS_RESULT(result); }
static Dwarf_Off die_attr_ref(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name) { Dwarf_Off off; if (dwarf_attrval_unsigned(die, name, &off, &dw->dw_err) != DWARF_E_NONE) { terminate("die %llu: failed to get ref: %s\n", die_off(dw, die), dwarf_errmsg(&dw->dw_err)); } return (off); }
static Dwarf_Half die_tag(dwarf_t *dw, Dwarf_Die die) { Dwarf_Half tag; if (dwarf_tag(die, &tag, &dw->dw_err) == DW_DLV_OK) return (tag); terminate("die %llu: failed to get tag for type: %s\n", die_off(dw, die), dwarf_errmsg(dw->dw_err)); /*NOTREACHED*/ return (0); }
int type_off(Dwarf_Die *die, Dwarf_Off *ref_off, Dwarf_Error *err) { Dwarf_Attribute type; int status; if ((status = dwarf_attr(*die, DW_AT_type, &type, err)) != DW_DLV_OK) { if (status == DW_DLV_NO_ENTRY) { fprintf(stderr, "No type information associated with die\n"); } else { fprintf(stderr, "Error %d in getting type attribute: %s\n", status, dwarf_errmsg(*err)); } return status; } if ((status = dwarf_global_formref(type, ref_off, err)) != DW_DLV_OK) { fprintf(stderr, "Error %d in getting type offset: %s\n", status, dwarf_errmsg(*err)); return status; } return DW_DLV_OK; }
static Dwarf_Half die_attr_form(dwarf_t *dw, Dwarf_Attribute attr) { Dwarf_Half form; if (dwarf_whatform(attr, &form, &dw->dw_err) == DW_DLV_OK) return (form); terminate("failed to get attribute form for type: %s\n", dwarf_errmsg(dw->dw_err)); /*NOTREACHED*/ return (0); }
static void HandleFunctionDIE (Dwarf_Debug dwHandle, Dwarf_Die currChildDIE) { char *funcName = NULL; Dwarf_Addr lowAddress = 0; Dwarf_Addr highAddress = 0; int dwDieNameRet, dwDieLowAddrRet, dwDieHighAddrRet; dwDieNameRet = dwarf_diename (currChildDIE, &funcName, &dw_err); if (dwDieNameRet != DW_DLV_OK) mpiPi_msg_debug("Failed to get DIE name : %s\n", dwarf_errmsg(dw_err)); dwDieLowAddrRet = dwarf_lowpc (currChildDIE, &lowAddress, &dw_err); if (dwDieLowAddrRet != DW_DLV_OK) mpiPi_msg_debug("Failed to get low PC : %s\n", dwarf_errmsg(dw_err)); dwDieHighAddrRet = dwarf_highpc (currChildDIE, &highAddress, &dw_err); if (dwDieHighAddrRet != DW_DLV_OK) mpiPi_msg_debug("Failed to get high PC : %s\n", dwarf_errmsg(dw_err)); if ((dwDieNameRet == DW_DLV_OK) && (dwDieLowAddrRet == DW_DLV_OK) && (dwDieHighAddrRet == DW_DLV_OK)) { FunctionMap_Add (funcName, lowAddress, highAddress); } if ((dwDieNameRet == DW_DLV_OK) && (funcName != NULL)) { dwarf_dealloc (dwHandle, funcName, DW_DLA_STRING); } }
static Dwarf_Off die_off(dwarf_t *dw, Dwarf_Die die) { Dwarf_Off off; if (dwarf_dieoffset(die, &off, &dw->dw_err) == DW_DLV_OK) return (off); terminate("failed to get offset for die: %s\n", dwarf_errmsg(dw->dw_err)); /*NOTREACHED*/ return (0); }
/* * Handle DWARF 4 'offset from' DW_AT_high_pc. Although we don't * fully support DWARF 4, some compilers (like FreeBSD Clang 3.5.1) * generate DW_AT_high_pc as an offset from DW_AT_low_pc. * * "If the value of the DW_AT_high_pc is of class address, it is the * relocated address of the first location past the last instruction * associated with the entity; if it is of class constant, the value * is an unsigned integer offset which when added to the low PC gives * the address of the first location past the last instruction * associated with the entity." * * DWARF4 spec, section 2.17.2. */ static int handle_high_pc(Dwarf_Die die, Dwarf_Unsigned lopc, Dwarf_Unsigned *hipc) { Dwarf_Error de; Dwarf_Half form; Dwarf_Attribute at; int ret; ret = dwarf_attr(die, DW_AT_high_pc, &at, &de); if (ret == DW_DLV_ERROR) { warnx("dwarf_attr failed: %s", dwarf_errmsg(de)); return (ret); } ret = dwarf_whatform(at, &form, &de); if (ret == DW_DLV_ERROR) { warnx("dwarf_whatform failed: %s", dwarf_errmsg(de)); return (ret); } if (dwarf_get_form_class(2, 0, 0, form) == DW_FORM_CLASS_CONSTANT) *hipc += lopc; return (DW_DLV_OK); }
static int die_bool(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, Dwarf_Bool *valp, int req) { *valp = 0; if (dwarf_attrval_flag(die, name, valp, &dw->dw_err) != DWARF_E_NONE) { if (req) terminate("die %llu: failed to get flag: %s\n", die_off(dw, die), dwarf_errmsg(&dw->dw_err)); return (0); } return (1); }
static void tp_dwarf_die_offset_sanity(void) { Dwarf_Debug dbg; Dwarf_Die die; Dwarf_Error de; Dwarf_Off rel_off, die_off, cu_off, cu_len; Dwarf_Unsigned cu_next_offset; int fd; result = TET_UNRESOLVED; TS_DWARF_INIT(dbg, fd, de); TS_DWARF_CU_FOREACH(dbg, cu_next_offset, de) { if (dwarf_siblingof(dbg, NULL, &die, &de) == DW_DLV_ERROR) { tet_printf("dwarf_siblingof failed: %s\n", dwarf_errmsg(de)); result = TET_FAIL; goto done; } if (dwarf_die_CU_offset(NULL, &rel_off, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_die_CU_offset didn't return" " DW_DLV_ERROR when called with NULL arguments"); result = TET_FAIL; goto done; } if (dwarf_die_CU_offset_range(NULL, &cu_off, &cu_len, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_die_CU_offset_range didn't return" " DW_DLV_ERROR when called with NULL arguments"); result = TET_FAIL; goto done; } if (dwarf_dieoffset(NULL, &die_off, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_dieoffset didn't return DW_DLV_ERROR" " when called with NULL arguments"); result = TET_FAIL; goto done; } } if (result == TET_UNRESOLVED) result = TET_PASS; done: TS_DWARF_FINISH(dbg, de); TS_RESULT(result); }
int main (int argc, char *argv[]) { int cnt; for (cnt = 1; cnt < argc; ++cnt) { Dwarf_Off offset = 0; size_t len; int fd = open (argv[cnt], O_RDONLY); if (fd == -1) { printf ("cannot open '%s': %m\n", argv[cnt]); return 1; } Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); if (dbg == NULL) { printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1)); close (fd); return 1; } /* Try to use NULL Dwarf object. */ const char *str = dwarf_getstring (NULL, offset, &len); assert (str == NULL); /* Use insane offset. */ str = dwarf_getstring (dbg, ~0UL, &len); assert (str == NULL); /* Now do some real work. */ for (int i = 0; i < 100; ++i) { str = dwarf_getstring (dbg, offset, &len); puts (str); /* Advance. */ offset += len + 1; } close (fd); } return 0; }
static Dwarf_Die die_child(dwarf_t *dw, Dwarf_Die die) { Dwarf_Die child; int rc; if ((rc = dwarf_child(die, &child, &dw->dw_err)) == DW_DLV_OK) return (child); else if (rc == DW_DLV_NO_ENTRY) return (NULL); terminate("die %llu: failed to find type child: %s\n", die_off(dw, die), dwarf_errmsg(dw->dw_err)); /*NOTREACHED*/ return (NULL); }
static Dwarf_Die die_sibling(dwarf_t *dw, Dwarf_Die die) { Dwarf_Die sib; int rc; if ((rc = dwarf_siblingof(dw->dw_dw, die, &sib, &dw->dw_err)) == DW_DLV_OK) return (sib); else if (rc == DW_DLV_NO_ENTRY) return (NULL); terminate("die %llu: failed to find type sibling: %s\n", die_off(dw, die), dwarf_errmsg(dw->dw_err)); /*NOTREACHED*/ return (NULL); }
static void chkerr1(int ret, Dwarf_Error *err, VALUE obj) { VALUE exc = Qnil; switch (ret) { case DW_DLV_NO_ENTRY: exc = rb_exc_new_cstr(rd_eError, "No Entry"); case DW_DLV_ERROR: if (err != NULL) { exc = rb_exc_new_cstr(rd_eError, dwarf_errmsg(*err)); } else { exc = rb_exc_new_cstr(rd_eError, "Unknown Error"); } } if (!NIL_P(exc)) { rb_iv_set(exc, "@obj", obj); rb_exc_raise(exc); } }
static int die_string(dwarf_t *dw, Dwarf_Die die, Dwarf_Half name, char **strp, int req) { const char *str = NULL; if (dwarf_attrval_string(die, name, &str, &dw->dw_err) != DWARF_E_NONE || str == NULL) { if (req) terminate("die %llu: failed to get string: %s\n", die_off(dw, die), dwarf_errmsg(&dw->dw_err)); else *strp = NULL; return (0); } else *strp = xstrdup(str); return (1); }
static int handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi, GElf_Addr pc, struct stuff *stuff) { int result = dwarf_cfi_addrframe (cfi, pc - stuff->bias, &stuff->frame); if (result != 0) { error (0, 0, "dwarf_addrframe (%s): %s", which, dwfl_errmsg (-1)); return 1; } Dwarf_Addr start = pc; Dwarf_Addr end = pc; bool signalp; int ra_regno = dwarf_frame_info (stuff->frame, &start, &end, &signalp); if (ra_regno >= 0) { start += stuff->bias; end += stuff->bias; } printf ("%s has %#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n", which, pc, start, end); if (ra_regno < 0) printf ("\treturn address register unavailable (%s)\n", dwarf_errmsg (0)); else printf ("\treturn address in reg%u%s\n", ra_regno, signalp ? " (signal frame)" : ""); Dwarf_Op *cfa_ops; size_t cfa_nops; result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops); printf ("\tCFA "); print_detail (result, cfa_ops, cfa_nops, stuff->bias); (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc), &print_register, stuff); return 0; }
static void tp_dwarf_get_address_size(void) { Dwarf_Debug dbg; Dwarf_Error de; Dwarf_Half addr_size; int fd, result; dbg = NULL; result = TET_UNRESOLVED; if (dwarf_get_address_size(NULL, &addr_size, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_get_adderss_size NULL 'dbg' test failed"); result = TET_FAIL; goto done; } TS_DWARF_INIT(dbg, fd, de); if (dwarf_get_address_size(dbg, NULL, &de) != DW_DLV_ERROR) { tet_infoline("dwarf_get_adderss_size NULL 'addr_size' test " "failed"); result = TET_FAIL; goto done; } if (dwarf_get_address_size(dbg, &addr_size, &de) != DW_DLV_OK) { tet_printf("dwarf_get_address_size failed: %s", dwarf_errmsg(de)); result = TET_FAIL; goto done; } TS_CHECK_UINT(addr_size); if (result == TET_UNRESOLVED) result = TET_PASS; done: TS_DWARF_FINISH(dbg, de); TS_RESULT(result); }