Beispiel #1
0
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;
}
Beispiel #2
0
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);
}
Beispiel #4
0
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;
}
Beispiel #7
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;
}
Beispiel #8
0
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;
}
Beispiel #9
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)) {
                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;
}
Beispiel #10
0
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;
}