int libdwLookupLocation(LibdwSession *session, Location *frame, StgPtr pc) { Dwarf_Addr addr = (Dwarf_Addr) (uintptr_t) pc; // Find the module containing PC Dwfl_Module *mod = dwfl_addrmodule(session->dwfl, addr); if (mod == NULL) return 1; dwfl_module_info(mod, NULL, NULL, NULL, NULL, NULL, &frame->object_file, NULL); // Find function name frame->function = dwfl_module_addrname(mod, addr); // Try looking up source location Dwfl_Line *line = dwfl_module_getsrc(mod, addr); if (line != NULL) { Dwarf_Addr addr; int lineno, colno; /* libdwfl owns the source_file buffer, don't free it */ frame->source_file = dwfl_lineinfo(line, &addr, &lineno, &colno, NULL, NULL); frame->lineno = lineno; frame->colno = colno; } if (line == NULL || frame->source_file == NULL) { frame->source_file = NULL; frame->lineno = 0; frame->colno = 0; } return 0; }
/* Prints information about one frame of a thread. Called by dwfl_getthread_frames in output_right. Returns 1 when done (max number of frames reached). Returns -1 on error. Returns 0 on success (if there are more frames in the thread, call us again). */ static int frame_callback (Dwfl_Frame *state, void *arg) { Dwarf_Addr pc; bool isactivation; int *frames = (int *) arg; if (!dwfl_frame_pc(state, &pc, &isactivation)) return -1; if (!isactivation) pc--; Dwfl *dwfl = dwfl_thread_dwfl(dwfl_frame_thread(state)); Dwfl_Module *mod = dwfl_addrmodule(dwfl, pc); const char *modname = NULL; const char *symname = NULL; GElf_Off off = 0; if (mod != NULL) { GElf_Sym sym; modname = dwfl_module_info(mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL); symname = dwfl_module_addrinfo(mod, pc, &off, &sym, NULL, NULL, NULL); } /* This mimics the output produced by libunwind below. */ fprintf(options.output, " > %s(%s+0x%" PRIx64 ") [%" PRIx64 "]\n", modname, symname, off, pc); /* See if we can extract the source line too and print it on the next line if we can find it. */ if (mod != NULL) { Dwfl_Line *l = dwfl_module_getsrc(mod, pc); if (l != NULL) { int line, col; line = col = -1; const char *src = dwfl_lineinfo(l, NULL, &line, &col, NULL, NULL); if (src != NULL) { fprintf(options.output, "\t%s", src); if (line > 0) { fprintf(options.output, ":%d", line); if (col > 0) fprintf(options.output, ":%d", col); } fprintf(options.output, "\n"); } } } /* Max number of frames to print reached? */ if ((*frames)-- == 0) return 1; return 0; }
static void paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line) { const char *src; int lineno, linecol; if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol, NULL, NULL)) != NULL) { if (linecol != 0) printf ("%s%#" PRIx64 " (%s:%d:%d)", prefix, addr, src, lineno, linecol); else printf ("%s%#" PRIx64 " (%s:%d)", prefix, addr, src, lineno); } else printf ("%s%#" PRIx64, prefix, addr); }
int main (int argc, char *argv[]) { int cnt; Dwfl *dwfl = NULL; (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &cnt, &dwfl); assert (dwfl != NULL); Dwarf_Die *cu = NULL; Dwarf_Addr bias; do { cu = dwfl_nextcu (dwfl, cu, &bias); if (cu != NULL) { Dwfl_Module *mod = dwfl_cumodule (cu); const char *modname = (dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL) ?: "<unknown>"); const char *cuname = (dwarf_diename (cu) ?: "<unknown>"); printf ("mod: %s CU: [%" PRIx64 "] %s\n", modname, dwarf_dieoffset (cu), cuname); size_t lines; if (dwfl_getsrclines (cu, &lines) != 0) continue; // No lines... for (size_t i = 0; i < lines; i++) { Dwfl_Line *line = dwfl_onesrcline (cu, i); Dwarf_Addr addr; int lineno; int colno; Dwarf_Word mtime; Dwarf_Word length; const char *src = dwfl_lineinfo (line, &addr, &lineno, &colno, &mtime, &length); Dwarf_Addr dw_bias; Dwarf_Line *dw_line = dwfl_dwarf_line (line, &dw_bias); assert (bias == dw_bias); Dwarf_Addr dw_addr; if (dwarf_lineaddr (dw_line, &dw_addr) != 0) error (EXIT_FAILURE, 0, "dwarf_lineaddr: %s", dwarf_errmsg (-1)); assert (addr == dw_addr + dw_bias); unsigned int dw_op_index; if (dwarf_lineop_index (dw_line, &dw_op_index) != 0) error (EXIT_FAILURE, 0, "dwarf_lineop_index: %s", dwarf_errmsg (-1)); int dw_lineno; if (dwarf_lineno (dw_line, &dw_lineno) != 0) error (EXIT_FAILURE, 0, "dwarf_lineno: %s", dwarf_errmsg (-1)); assert (lineno == dw_lineno); int dw_colno; if (dwarf_linecol (dw_line, &dw_colno) != 0) error (EXIT_FAILURE, 0, "dwarf_lineno: %s", dwarf_errmsg (-1)); assert (colno == dw_colno); bool begin; if (dwarf_linebeginstatement (dw_line, &begin) != 0) error (EXIT_FAILURE, 0, "dwarf_linebeginstatement: %s", dwarf_errmsg (-1)); bool end; if (dwarf_lineendsequence (dw_line, &end) != 0) error (EXIT_FAILURE, 0, "dwarf_lineendsequence: %s", dwarf_errmsg (-1)); bool pend; if (dwarf_lineprologueend (dw_line, &pend) != 0) error (EXIT_FAILURE, 0, "dwarf_lineprologueend: %s", dwarf_errmsg (-1)); bool ebegin; if (dwarf_lineepiloguebegin (dw_line, &ebegin) != 0) error (EXIT_FAILURE, 0, "dwarf_lineepiloguebegin: %s", dwarf_errmsg (-1)); bool block; if (dwarf_lineblock (dw_line, &block) != 0) error (EXIT_FAILURE, 0, "dwarf_lineblock: %s", dwarf_errmsg (-1)); unsigned int isa; if (dwarf_lineisa (dw_line, &isa) != 0) error (EXIT_FAILURE, 0, "dwarf_lineisa: %s", dwarf_errmsg (-1)); unsigned int disc; if (dwarf_linediscriminator (dw_line, &disc) != 0) error (EXIT_FAILURE, 0, "dwarf_linediscriminator: %s", dwarf_errmsg (-1)); const char *dw_src; Dwarf_Word dw_mtime; Dwarf_Word dw_length; dw_src = dwarf_linesrc (dw_line, &dw_mtime, &dw_length); assert (strcmp (src, dw_src) == 0); assert (mtime == dw_mtime); assert (length == dw_length); printf ("%zd %#" PRIx64 " %s:%d:%d\n" " time: %#" PRIX64 ", len: %" PRIu64 ", idx: %d, b: %d, e: %d" ", pe: %d, eb: %d, block: %d" ", isa: %d, disc: %d\n", i, addr, src, lineno, colno, mtime, length, dw_op_index, begin, end, pend, ebegin, block, isa, disc); Dwarf_Die *linecu = dwfl_linecu (line); assert (cu == linecu); Dwfl_Module *linemod = dwfl_linemodule (line); assert (mod == linemod); } } } while (cu != NULL); dwfl_end (dwfl); return 0; }