static int frame_callback(Dwfl_Frame *frame, void *data) { struct frame_callback_arg *frame_arg = data; char **error_msg = &frame_arg->error_msg; Dwarf_Addr pc; bool minus_one; if (!dwfl_frame_pc(frame, &pc, &minus_one)) { set_error_dwfl("dwfl_frame_pc"); return DWARF_CB_ABORT; } Dwfl *dwfl = dwfl_thread_dwfl(dwfl_frame_thread(frame)); struct sr_core_frame *result = resolve_frame(dwfl, pc, minus_one); /* Do not unwind below __libc_start_main. */ if (0 == sr_strcmp0(result->function_name, "__libc_start_main")) { sr_core_frame_free(result); return CB_STOP_UNWIND; } frame_arg->thread->frames = sr_core_frame_append(frame_arg->thread->frames, result); return DWARF_CB_OK; }
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; }
/* 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; }
/* 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; }
// Remember that we are traversing from the inner-most to the outer-most frame static int getBacktraceFrameCb(Dwfl_Frame *frame, void *arg) { LibdwSession *session = arg; Dwarf_Addr pc; bool is_activation; if (! dwfl_frame_pc(frame, &pc, &is_activation)) { // failed to find PC backtracePush(session->cur_bt, 0x0); } else { if (is_activation) pc -= 1; // TODO: is this right? backtracePush(session->cur_bt, (StgPtr) (uintptr_t) pc); } return DWARF_CB_OK; }