static int touch_module(Dwfl_Module *mod, void **userdata, const char *name, Dwarf_Addr start_addr, void *arg) { struct exe_mapping_data ***tailp = arg; const char *filename = NULL; GElf_Addr bias; Dwarf_Addr base; if (dwfl_module_getelf (mod, &bias) == NULL) { warn("cannot find ELF for '%s': %s", name, dwfl_errmsg(-1)); return DWARF_CB_OK; } dwfl_module_info(mod, NULL, &base, NULL, NULL, NULL, &filename, NULL); if (filename) { **tailp = sr_mallocz(sizeof(struct exe_mapping_data)); (**tailp)->start = (uint64_t)base; (**tailp)->filename = sr_strdup(filename); *tailp = &((**tailp)->next); } return DWARF_CB_OK; }
static int __report_module(struct addr_location *al, u64 ip, struct unwind_info *ui) { Dwfl_Module *mod; struct dso *dso = NULL; /* * Some callers will use al->sym, so we can't just use the * cheaper thread__find_map() here. */ thread__find_symbol(ui->thread, PERF_RECORD_MISC_USER, ip, al); if (al->map) dso = al->map->dso; if (!dso) return 0; mod = dwfl_addrmodule(ui->dwfl, ip); if (mod) { Dwarf_Addr s; dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); if (s != al->map->start) mod = 0; } if (!mod) mod = dwfl_report_elf(ui->dwfl, dso->short_name, (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start, false); return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; }
static void print_address (Dwfl_Module *mod, Dwarf_Addr address) { int n = dwfl_module_relocations (mod); if (n < 0) error (0, 0, "dwfl_module_relocations: %s", dwfl_errmsg (-1)); else if (n > 0) { int i = dwfl_module_relocate_address (mod, &address); if (i < 0) error (0, 0, "dwfl_module_relocate_address: %s", dwfl_errmsg (-1)); else { const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL); const char *secname = dwfl_module_relocation_info (mod, i, NULL); if (n > 1 || secname[0] != '\0') printf ("%s(%s)+%#" PRIx64, modname, secname, address); else printf ("%s+%#" PRIx64, modname, address); return; } } printf ("%#" PRIx64, address); }
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 __report_module(struct addr_location *al, u64 ip, struct unwind_info *ui) { Dwfl_Module *mod; struct dso *dso = NULL; thread__find_addr_location(ui->thread, PERF_RECORD_MISC_USER, MAP__FUNCTION, ip, al); if (al->map) dso = al->map->dso; if (!dso) return 0; mod = dwfl_addrmodule(ui->dwfl, ip); if (mod) { Dwarf_Addr s; dwfl_module_info(mod, NULL, &s, NULL, NULL, NULL, NULL, NULL); if (s != al->map->start) mod = 0; } if (!mod) mod = dwfl_report_elf(ui->dwfl, dso->short_name, (dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start, false); return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1; }
/* 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; }
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; }
static int handle_function (Dwarf_Die *funcdie, void *arg) { struct args *a = arg; const char *name = dwarf_diename (funcdie); char **argv = a->argv; if (argv[0] != NULL) { bool match; do match = fnmatch (*argv, name, 0) == 0; while (!match && *++argv); if (!match) return 0; } printf ("(%s) %s: ", dwfl_module_info (dwfl_cumodule (a->cu), NULL, NULL, NULL, NULL, NULL, NULL, NULL), name); const Dwarf_Op *locops; int nlocops = dwfl_module_return_value_location (dwfl_cumodule (a->cu), funcdie, &locops); if (nlocops < 0) error (EXIT_FAILURE, 0, "dwfl_module_return_value_location: %s", dwfl_errmsg (-1)); else if (nlocops == 0) puts ("returns no value"); else { printf ("return value location:"); for (int i = 0; i < nlocops; ++i) printf (" {%#x, %#" PRIx64 "}", locops[i].atom, locops[i].number); puts (""); } return 0; }