static int debuginfo__init_offline_dwarf(struct debuginfo *self,
					 const char *path)
{
	Dwfl_Module *mod;
	int fd;

	fd = open(path, O_RDONLY);
	if (fd < 0)
		return fd;

	self->dwfl = dwfl_begin(&offline_callbacks);
	if (!self->dwfl)
		goto error;

	mod = dwfl_report_offline(self->dwfl, "", "", fd);
	if (!mod)
		goto error;

	self->dbg = dwfl_module_getdwarf(mod, &self->bias);
	if (!self->dbg)
		goto error;

	return 0;
error:
	if (self->dwfl)
		dwfl_end(self->dwfl);
	else
		close(fd);
	memset(self, 0, sizeof(*self));

	return -ENOENT;
}
Пример #2
0
/* Get a Dwarf from offline image */
static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
					 const char *path)
{
	int fd;

	fd = open(path, O_RDONLY);
	if (fd < 0)
		return fd;

	dbg->dwfl = dwfl_begin(&offline_callbacks);
	if (!dbg->dwfl)
		goto error;

	dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
	if (!dbg->mod)
		goto error;

	dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
	if (!dbg->dbg)
		goto error;

	return 0;
error:
	if (dbg->dwfl)
		dwfl_end(dbg->dwfl);
	else
		close(fd);
	memset(dbg, 0, sizeof(*dbg));

	return -ENOENT;
}
Пример #3
0
/* Get a Dwarf from live kernel image */
static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
					  Dwarf_Addr *bias)
{
	Dwarf *dbg;

	if (!dwflp)
		return NULL;

	*dwflp = dwfl_begin(&kernel_callbacks);
	if (!*dwflp)
		return NULL;

	/* Load the kernel dwarves: Don't care the result here */
	dwfl_linux_kernel_report_kernel(*dwflp);
	dwfl_linux_kernel_report_modules(*dwflp);

	dbg = dwfl_addrdwarf(*dwflp, addr, bias);
	/* Here, check whether we could get a real dwarf */
	if (!dbg) {
		pr_debug("Failed to find kernel dwarf at %lx\n",
			 (unsigned long)addr);
		dwfl_end(*dwflp);
		*dwflp = NULL;
	}
	return dbg;
}
Пример #4
0
struct refl *
refl_begin (void)
{
  struct refl *result = malloc (sizeof (*result));
  if (result == NULL)
    {
      __refl_seterr (REFL_E_SYSTEM);
      return NULL;
    }

  Dwfl *dwfl = dwfl_begin (&callbacks);
  if (dwfl == NULL)
    {
      __refl_seterr (REFL_E_DWFL);
      goto err_out;
    }

  dwfl_report_begin (dwfl);
  int status = dwfl_linux_proc_report (dwfl, getpid ());
  dwfl_report_end (dwfl, NULL, NULL);

  if (status < 0)
    {
      __refl_seterr (REFL_E_DWFL);
      goto err_out;
    }

  result->dwfl = dwfl;

  return result;

 err_out:
  free (result);
  return NULL;
}
Пример #5
0
// Create a libdw session with DWARF information for all loaded modules
LibdwSession *libdwInit() {
    LibdwSession *session = stgCallocBytes(1, sizeof(LibdwSession),
                                           "libdwInit");
    // Initialize ELF library
    if (elf_version(EV_CURRENT) == EV_NONE) {
        sysErrorBelch("libelf version too old!");
        return NULL;
    }

    // Initialize a libdwfl session
    static char *debuginfo_path;
    static const Dwfl_Callbacks proc_callbacks =
        {
            .find_debuginfo = dwfl_standard_find_debuginfo,
            .debuginfo_path = &debuginfo_path,
            .find_elf = dwfl_linux_proc_find_elf,
        };
    session->dwfl = dwfl_begin (&proc_callbacks);
    if (session->dwfl == NULL) {
        sysErrorBelch("dwfl_begin failed: %s", dwfl_errmsg(dwfl_errno()));
        free(session);
        return NULL;
    }

    // Report the loaded modules
    int ret = dwfl_linux_proc_report(session->dwfl, getpid());
    if (ret < 0) {
        sysErrorBelch("dwfl_linux_proc_report failed: %s",
                      dwfl_errmsg(dwfl_errno()));
        goto fail;
    }
    if (dwfl_report_end (session->dwfl, NULL, NULL) != 0) {
        sysErrorBelch("dwfl_report_end failed: %s", dwfl_errmsg(dwfl_errno()));
        goto fail;
    }

    pid_t pid = getpid();
    if (! dwfl_attach_state(session->dwfl, NULL, pid, &thread_cbs, NULL)) {
        sysErrorBelch("dwfl_attach_state failed: %s",
                      dwfl_errmsg(dwfl_errno()));
        goto fail;
    }

    return session;

 fail:
    dwfl_end(session->dwfl);
    free(session);
    return NULL;
}
int
main (void)
{
  Dwfl *dwfl = dwfl_begin (&callbacks);

  for (int i = 0; i < 5; ++i)
    {
      dwfl_report_begin (dwfl);
      dwfl_report_module (dwfl, "module1", 0, 10);
      dwfl_report_end (dwfl, NULL, NULL);
    }

  dwfl_end (dwfl);

  return 0;
}
Пример #7
0
static Dwfl *
pid_to_dwfl (pid_t pid)
{
  static char *debuginfo_path;
  static const Dwfl_Callbacks proc_callbacks =
    {
      .find_debuginfo = dwfl_standard_find_debuginfo,
      .debuginfo_path = &debuginfo_path,

      .find_elf = dwfl_linux_proc_find_elf,
    };
  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
  if (dwfl == NULL)
    error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
  report_pid (dwfl, pid);
  return dwfl;
}
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
					       Dwarf_Addr addr)
{
	self->dwfl = dwfl_begin(&kernel_callbacks);
	if (!self->dwfl)
		return -EINVAL;

	
	dwfl_linux_kernel_report_kernel(self->dwfl);
	dwfl_linux_kernel_report_modules(self->dwfl);

	self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
	
	if (!self->dbg) {
		pr_debug("Failed to find kernel dwarf at %lx\n",
			 (unsigned long)addr);
		dwfl_end(self->dwfl);
		memset(self, 0, sizeof(*self));
		return -ENOENT;
	}

	return 0;
}
Пример #9
0
/* Get a Dwarf from live kernel image */
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
					       Dwarf_Addr addr)
{
	self->dwfl = dwfl_begin(&kernel_callbacks);
	if (!self->dwfl)
		return -EINVAL;

	/* Load the kernel dwarves: Don't care the result here */
	dwfl_linux_kernel_report_kernel(self->dwfl);
	dwfl_linux_kernel_report_modules(self->dwfl);

	self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
	/* Here, check whether we could get a real dwarf */
	if (!self->dbg) {
		pr_debug("Failed to find kernel dwarf at %lx\n",
			 (unsigned long)addr);
		dwfl_end(self->dwfl);
		memset(self, 0, sizeof(*self));
		return -ENOENT;
	}

	return 0;
}
Пример #10
0
int main(void)
{
	Dwfl *dw;
	Dwfl_Module *mod;
	Dwarf_Addr bias;
	Dwarf_Die *die = NULL;

	dw = dwfl_begin(&cb);
	if (!dw)
		errx(1, "dwfl_begin %s", dwfl_errmsg(-1));

	mod = dwfl_report_offline(dw, "", "tst", -1);
	if (!mod)
		errx(1, "dwfl_begin %s", dwfl_errmsg(-1));

	while ((die = dwfl_nextcu(dw, die, &bias))) {
		print_die_rec(die, -1);
		printf("\n");
	}

	dwfl_end(dw);
	return 0;
}
Пример #11
0
/* Get a Dwarf from offline image */
static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias)
{
	Dwfl_Module *mod;
	Dwarf *dbg = NULL;

	if (!dwflp)
		return NULL;

	*dwflp = dwfl_begin(&offline_callbacks);
	if (!*dwflp)
		return NULL;

	mod = dwfl_report_offline(*dwflp, "", "", fd);
	if (!mod)
		goto error;

	dbg = dwfl_module_getdwarf(mod, bias);
	if (!dbg) {
error:
		dwfl_end(*dwflp);
		*dwflp = NULL;
	}
	return dbg;
}
Пример #12
0
struct core_handle *
open_coredump(const char *elf_file, const char *exe_file, char **error_msg)
{
    struct core_handle *ch = sr_mallocz(sizeof(*ch));
    struct exe_mapping_data *head = NULL, **tail = &head;

    /* Initialize libelf, open the file and get its Elf handle. */
    if (elf_version(EV_CURRENT) == EV_NONE)
    {
        set_error_elf("elf_version");
        goto fail_free;
    }

    /* Open input file, and parse it. */
    ch->fd = open(elf_file, O_RDONLY);
    if (ch->fd < 0)
    {
        set_error("Unable to open '%s': %s", elf_file, strerror(errno));
        goto fail_free;
    }

    ch->eh = elf_begin(ch->fd, ELF_C_READ_MMAP, NULL);
    if (ch->eh == NULL)
    {
        set_error_elf("elf_begin");
        goto fail_close;
    }

    /* Check that we are working with a coredump. */
    GElf_Ehdr ehdr;
    if (gelf_getehdr(ch->eh, &ehdr) == NULL || ehdr.e_type != ET_CORE)
    {
        set_error("File '%s' is not a coredump", elf_file);
        goto fail_elf;
    }

    executable_file = exe_file;
    ch->cb.find_elf = find_elf_core;
    ch->cb.find_debuginfo = find_debuginfo_none;
    ch->cb.section_address = dwfl_offline_section_address;
    ch->dwfl = dwfl_begin(&ch->cb);

#if _ELFUTILS_PREREQ(0, 158)
    if (dwfl_core_file_report(ch->dwfl, ch->eh, exe_file) == -1)
#else
    if (dwfl_core_file_report(ch->dwfl, ch->eh) == -1)
#endif
    {
        set_error_dwfl("dwfl_core_file_report");
        goto fail_dwfl;
    }

    if (dwfl_report_end(ch->dwfl, NULL, NULL) != 0)
    {
        set_error_dwfl("dwfl_report_end");
        goto fail_dwfl;
    }

    /* needed so that module filenames are available during unwinding */
    ptrdiff_t ret = dwfl_getmodules(ch->dwfl, touch_module, &tail, 0);
    if (ret == -1)
    {
        set_error_dwfl("dwfl_getmodules");
        goto fail_dwfl;
    }
    ch->segments = head;

    if (!head)
    {
        if (error_msg && !*error_msg)
            set_error("No segments found in coredump '%s'", elf_file);
        goto fail_dwfl;
    }

    return ch;

fail_dwfl:
    dwfl_end(ch->dwfl);
fail_elf:
    elf_end(ch->eh);
fail_close:
    close(ch->fd);
fail_free:
    free(ch);

    return NULL;
}
Пример #13
0
int coredump_make_stack_trace(int fd, const char *executable, char **ret) {

        static const Dwfl_Callbacks callbacks = {
                .find_elf = dwfl_build_id_find_elf,
                .find_debuginfo = dwfl_standard_find_debuginfo,
        };

        struct stack_context c = {};
        char *buf = NULL;
        size_t sz = 0;
        int r;

        assert(fd >= 0);
        assert(ret);

        if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
                return -errno;

        c.f = open_memstream(&buf, &sz);
        if (!c.f)
                return -ENOMEM;

        elf_version(EV_CURRENT);

        c.elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
        if (!c.elf) {
                r = -EINVAL;
                goto finish;
        }

        c.dwfl = dwfl_begin(&callbacks);
        if (!c.dwfl) {
                r = -EINVAL;
                goto finish;
        }

        if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0) {
                r = -EINVAL;
                goto finish;
        }

        if (dwfl_report_end(c.dwfl, NULL, NULL) != 0) {
                r = -EINVAL;
                goto finish;
        }

        if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) {
                r = -EINVAL;
                goto finish;
        }

        if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0) {
                r = -EINVAL;
                goto finish;
        }

        c.f = safe_fclose(c.f);

        *ret = buf;
        buf = NULL;

        r = 0;

finish:
        if (c.dwfl)
                dwfl_end(c.dwfl);

        if (c.elf)
                elf_end(c.elf);

        safe_fclose(c.f);

        free(buf);

        return r;
}
Пример #14
0
/*
 * Return:
 *	0 if return address for the program counter @pc is on stack
 *	1 if return address is in LR and no new stack frame was allocated
 *	2 if return address is in LR and a new frame was allocated (but not
 *		yet used)
 *	-1 in case of errors
 */
static int check_return_addr(struct dso *dso, u64 map_start, Dwarf_Addr pc)
{
	int		rc = -1;
	Dwfl		*dwfl;
	Dwfl_Module	*mod;
	Dwarf_Frame	*frame;
	int		ra_regno;
	Dwarf_Addr	start = pc;
	Dwarf_Addr	end = pc;
	bool		signalp;
	const char	*exec_file = dso->long_name;

	dwfl = dso->dwfl;

	if (!dwfl) {
		dwfl = dwfl_begin(&offline_callbacks);
		if (!dwfl) {
			pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
			return -1;
		}

		mod = dwfl_report_elf(dwfl, exec_file, exec_file, -1,
						map_start, false);
		if (!mod) {
			pr_debug("dwfl_report_elf() failed %s\n",
						dwarf_errmsg(-1));
			/*
			 * We normally cache the DWARF debug info and never
			 * call dwfl_end(). But to prevent fd leak, free in
			 * case of error.
			 */
			dwfl_end(dwfl);
			goto out;
		}
		dso->dwfl = dwfl;
	}

	mod = dwfl_addrmodule(dwfl, pc);
	if (!mod) {
		pr_debug("dwfl_addrmodule() failed, %s\n", dwarf_errmsg(-1));
		goto out;
	}

	/*
	 * To work with split debug info files (eg: glibc), check both
	 * .eh_frame and .debug_frame sections of the ELF header.
	 */
	frame = get_eh_frame(mod, pc);
	if (!frame) {
		frame = get_dwarf_frame(mod, pc);
		if (!frame)
			goto out;
	}

	ra_regno = dwarf_frame_info(frame, &start, &end, &signalp);
	if (ra_regno < 0) {
		pr_debug("Return address register unavailable: %s\n",
				dwarf_errmsg(-1));
		goto out;
	}

	rc = check_return_reg(ra_regno, frame);

out:
	return rc;
}