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; }