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; }
static int frame_callback (Dwfl_Frame *state, void *frame_arg) { Dwarf_Addr pc; bool isactivation; if (! dwfl_frame_pc (state, &pc, &isactivation)) { error (0, 0, "%s", dwfl_errmsg (-1)); return DWARF_CB_ABORT; } Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1); /* Get PC->SYMNAME. */ Dwfl_Thread *thread = dwfl_frame_thread (state); Dwfl *dwfl = dwfl_thread_dwfl (thread); Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted); const char *symname = NULL; if (mod) symname = dwfl_module_addrname (mod, pc_adjusted); printf ("%#" PRIx64 "\t%s\n", (uint64_t) pc, symname); if (symname && (strcmp (symname, "main") == 0 || strcmp (symname, ".main") == 0)) { kill (dwfl_pid (dwfl), SIGKILL); exit (0); } return DWARF_CB_OK; }
/* This callback is invoked for every frame in a thread. From a Dwfl_Frame, we * are able to extract the program counter (PC), and from that, the procedure * name via a Dwfl_Module. */ static int frame_cb(Dwfl_Frame *frame, void *userdata) { Dwarf_Addr pc; Dwarf_Addr pc_adjusted; Dwfl_Module *module; const char *procname; const char *modname; bool activation; GString **bt = (GString **)userdata; if (!dwfl_frame_pc(frame, &pc, &activation)) { tm_dwfl_err("Failed to find program counter for current frame"); return DWARF_CB_ABORT; } // The return address may be beyond the calling address, putting the // current PC in a different context. Subtracting 1 from PC in this // case generally puts it back in the same context, thus fixing the // virtual unwind for this frame. See the DWARF standard for details. if (!activation) { pc_adjusted = pc - 1; } else { pc_adjusted = pc; } module = dwfl_addrmodule(d_core, pc_adjusted); if (!module) { // TODO: decide if it's worth creating a record in this // situation, since there are likely no symbols available for a // backtrace... telem_log(LOG_ERR, "Failed to find module from dwfl_addrmodule" " (process '%s', PID %u)\n", proc_name, (unsigned int)core_for_pid); return DWARF_CB_ABORT; } modname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL); procname = dwfl_module_addrname(module, pc_adjusted); if (procname && modname) { g_string_append_printf(*bt, "#%u %s() - [%s]\n", frame_counter++, procname, modname); } else if (modname) { g_string_append_printf(*bt, "#%u ??? - [%s]\n", frame_counter++, modname); } else { // TODO: decide on "no symbol" representation g_string_append_printf(*bt, "#%u (no symbols)\n", frame_counter++); } return DWARF_CB_OK; }
static int frame_callback(Dwfl_Frame *frame, void *userdata) { struct stack_context *c = userdata; Dwarf_Addr pc, pc_adjusted, bias = 0; _cleanup_free_ Dwarf_Die *scopes = NULL; const char *fname = NULL, *symbol = NULL; Dwfl_Module *module; bool is_activation; assert(frame); assert(c); if (c->n_frame >= FRAMES_MAX) return DWARF_CB_ABORT; if (!dwfl_frame_pc(frame, &pc, &is_activation)) return DWARF_CB_ABORT; pc_adjusted = pc - (is_activation ? 0 : 1); module = dwfl_addrmodule(c->dwfl, pc_adjusted); if (module) { Dwarf_Die *s, *cudie; int n; cudie = dwfl_module_addrdie(module, pc_adjusted, &bias); if (cudie) { n = dwarf_getscopes(cudie, pc_adjusted - bias, &scopes); for (s = scopes; s < scopes + n; s++) { if (IN_SET(dwarf_tag(s), DW_TAG_subprogram, DW_TAG_inlined_subroutine, DW_TAG_entry_point)) { Dwarf_Attribute *a, space; a = dwarf_attr_integrate(s, DW_AT_MIPS_linkage_name, &space); if (!a) a = dwarf_attr_integrate(s, DW_AT_linkage_name, &space); if (a) symbol = dwarf_formstring(a); if (!symbol) symbol = dwarf_diename(s); if (symbol) break; } } } if (!symbol) symbol = dwfl_module_addrname(module, pc_adjusted); fname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL); } fprintf(c->f, "#%-2u 0x%016" PRIx64 " %s (%s)\n", c->n_frame, (uint64_t) pc, strna(symbol), strna(fname)); c->n_frame ++; return DWARF_CB_OK; }
/* This callback is invoked for every frame in a thread. From a Dwfl_Frame, we * are able to extract the program counter (PC), and from that, the procedure * name via a Dwfl_Module. */ static int frame_cb(Dwfl_Frame *frame, void *userdata) { Dwarf_Addr pc; Dwarf_Addr pc_adjusted; Dwfl_Module *module; const char *procname; const char *modname; bool activation; GString **bt = (GString **)userdata; if (!dwfl_frame_pc(frame, &pc, &activation)) { errorstr = g_strdup_printf("Failed to find program counter for" " current frame: %s\n", dwfl_errmsg(-1)); return DWARF_CB_ABORT; } // The return address may be beyond the calling address, putting the // current PC in a different context. Subtracting 1 from PC in this // case generally puts it back in the same context, thus fixing the // virtual unwind for this frame. See the DWARF standard for details. if (!activation) { pc_adjusted = pc - 1; } else { pc_adjusted = pc; } module = dwfl_addrmodule(d_core, pc_adjusted); if (!module) { errorstr = g_strdup("Failed to find module for current" " frame\n"); return DWARF_CB_ABORT; } modname = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL); procname = dwfl_module_addrname(module, pc_adjusted); if (procname && modname) { g_string_append_printf(*bt, "#%u %s() - [%s]\n", frame_counter++, procname, modname); } else if (modname) { g_string_append_printf(*bt, "#%u ??? - [%s]\n", frame_counter++, modname); } else { // TODO: decide on "no symbol" representation g_string_append_printf(*bt, "#%u (no symbols)\n", frame_counter++); } return DWARF_CB_OK; }
struct sr_core_frame * resolve_frame(Dwfl *dwfl, Dwarf_Addr ip, bool minus_one) { struct sr_core_frame *frame = sr_core_frame_new(); frame->address = frame->build_id_offset = (uint64_t)ip; /* see dwfl_frame_state_pc for meaning of this parameter */ Dwarf_Addr ip_adjusted = ip - (minus_one ? 1 : 0); Dwfl_Module *mod = dwfl_addrmodule(dwfl, ip_adjusted); if (mod) { int ret; const unsigned char *build_id_bits; const char *filename, *funcname; GElf_Addr bias, bid_addr; Dwarf_Addr start; /* Initialize the module's main Elf for dwfl_module_build_id and dwfl_module_info */ /* No need to deallocate the variable 'bias' and the return value.*/ if (NULL == dwfl_module_getelf(mod, &bias)) warn("The module's main Elf was not found"); ret = dwfl_module_build_id(mod, &build_id_bits, &bid_addr); if (ret > 0) { frame->build_id = sr_mallocz(2*ret + 1); sr_bin2hex(frame->build_id, (const char *)build_id_bits, ret); } const char *modname = dwfl_module_info(mod, NULL, &start, NULL, NULL, NULL, &filename, NULL); if (modname) { frame->build_id_offset = ip - start; frame->file_name = filename ? sr_strdup(filename) : sr_strdup(modname); } funcname = dwfl_module_addrname(mod, (GElf_Addr)ip_adjusted); if (funcname) { char *demangled = sr_demangle_symbol(funcname); frame->function_name = (demangled ? demangled : sr_strdup(funcname)); } } return frame; }