libdwfl: Move dwz alt multi file searching to find_debuginfo callback.

Don't hard code the Dwarf dwz alt multi file search but allow the user
to override it through the standard Dwfl_Callbacks. Also move ownership
completely to the user of dwarf_setalt by removing free_alt from Dwarf
and adding alt, fd and elf fields to Dwfl_Module. Add a relative .dwz
file test case.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
This commit is contained in:
Mark Wielaard
2014-05-01 14:48:27 +02:00
parent d81d32d2a4
commit df85bf9902
16 changed files with 461 additions and 169 deletions
+6
View File
@@ -1,3 +1,9 @@
2014-05-01 Mark Wielaard <mjw@redhat.com>
* libdwP.h (struct Dwarf): Remove free_alt.
* dwarf_end.c (dwarf_end): Don't check free_alt, don't end alt_dwarf.
* dwarf_setalt.c (dwarf_setalt): Don't check or set free_alt.
2014-04-30 Mark Wielaard <mjw@redhat.com>
* libdw.map (ELFUTILS_0.159): Add dwelf_elf_gnu_build_id.
+1 -5
View File
@@ -1,5 +1,5 @@
/* Release debugging handling context.
Copyright (C) 2002-2011 Red Hat, Inc.
Copyright (C) 2002-2011, 2014 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -111,10 +111,6 @@ dwarf_end (dwarf)
if (dwarf->free_elf)
elf_end (dwarf->elf);
/* Free the alternative Dwarf descriptor if necessary. */
if (dwarf->free_alt)
INTUSE (dwarf_end) (dwarf->alt_dwarf);
/* Free the context descriptor. */
free (dwarf);
}
-3
View File
@@ -35,9 +35,6 @@
void
dwarf_setalt (Dwarf *main, Dwarf *alt)
{
if (main->free_alt)
INTUSE (dwarf_end) (main->alt_dwarf);
main->free_alt = false;
main->alt_dwarf = alt;
}
INTDEF (dwarf_setalt)
+1 -4
View File
@@ -1,5 +1,5 @@
/* Internal definitions for libdwarf.
Copyright (C) 2002-2011, 2013 Red Hat, Inc.
Copyright (C) 2002-2011, 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -147,9 +147,6 @@ struct Dwarf
/* If true, we allocated the ELF descriptor ourselves. */
bool free_elf;
/* If true, we allocated the Dwarf descriptor for alt_dwarf ourselves. */
bool free_alt;
/* Information for traversing the .debug_pubnames section. This is
an array and separately allocated with malloc. */
struct pubnames_s
+33
View File
@@ -1,3 +1,36 @@
2014-05-01 Mark Wielaard <mjw@redhat.com>
* libdwflP.h (struct Dwfl_Module): Add alt, alt_fd and alt_elf fields.
(__libdwfl_open_mod_by_build_id): Renamed __libdwfl_open_by_build_id.
(__libdwfl_open_by_build_id): New declaration that takes an explicit
build-id.
* dwfl_build_id_find_debuginfo.c (dwfl_build_id_find_debuginfo): If
we already have the Dwarf then look for the alt dwz multi file by
build-id.
* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Add the
build-id we are looking for as argument.
(__libdwfl_open_mod_by_build_id): New function, calls
__libdwfl_open_by_build_id.
(dwfl_build_id_find_elf): Call __libdwfl_open_mod_by_build_id.
* dwfl_module.c (__libdwfl_module_free): Release alt, alt_elf and
close alt_fd if necessary.
* dwfl_module_getdwarf.c (__check_build_id): Removed.
(try_debugaltlink): Removed.
(open_debugaltlink): Removed.
(open_elf_file): First half of open_elf that just opens the elf
file but doesn't setup the load address.
(open_elf): Call open_elf_file.
(find_debug_altlink): New function.
(load_dw): Remove loading of dwz multifile.
(find_dw): Call find_debug_altlink.
* find-debuginfo.c (validate): Handle alt debug case using
dwelf_dwarf_gnu_debugaltlink and mod->alt_elf.
(find_debuginfo_in_path): Handle alt debug files possibly in .dwz
subdirs.
* linux-kernel-modules.c (try_kernel_name): Use fakemod.debug.name
to store name to find by dwfl_standard_find_debuginfo instead of
allocating an extra variable on stack.
2014-04-30 Mark Wielaard <mjw@redhat.com>
* dwfl_module_build_id.c (__libdwfl_find_elf_build_id): Moved to
+53 -2
View File
@@ -1,5 +1,5 @@
/* Find the debuginfo file for a module from its build ID.
Copyright (C) 2007, 2009 Red Hat, Inc.
Copyright (C) 2007, 2009, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -41,10 +41,61 @@ dwfl_build_id_find_debuginfo (Dwfl_Module *mod,
char **debuginfo_file_name)
{
int fd = -1;
/* Are we looking for a separate debug file for the main file or for
an alternate (dwz multi) debug file? Alternatively we could check
whether the dwbias == -1. */
if (mod->dw != NULL)
{
const void *build_id;
const char *altname;
ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
&altname,
&build_id);
if (build_id_len > 0)
fd = __libdwfl_open_by_build_id (mod, true, debuginfo_file_name,
build_id_len, build_id);
if (fd >= 0)
{
/* We need to open an Elf handle on the file so we can check its
build ID note for validation. Backdoor the handle into the
module data structure since we had to open it early anyway. */
Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf,
true, false);
if (error != DWFL_E_NOERROR)
__libdwfl_seterrno (error);
else
{
const void *alt_build_id;
ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf,
&alt_build_id);
if (alt_len > 0 && alt_len == build_id_len
&& memcmp (build_id, alt_build_id, alt_len) == 0)
return fd;
else
{
/* A mismatch! */
elf_end (mod->alt_elf);
mod->alt_elf = NULL;
close (fd);
fd = -1;
}
free (*debuginfo_file_name);
*debuginfo_file_name = NULL;
errno = 0;
}
}
return fd;
}
/* We don't even have the Dwarf yet and it isn't in the main file.
Try to find separate debug file now using the module build id. */
const unsigned char *bits;
GElf_Addr vaddr;
if (INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr) > 0)
fd = __libdwfl_open_by_build_id (mod, true, debuginfo_file_name);
fd = __libdwfl_open_mod_by_build_id (mod, true, debuginfo_file_name);
if (fd >= 0)
{
/* We need to open an Elf handle on the file so we can check its
+20 -12
View File
@@ -1,5 +1,5 @@
/* Find an ELF file for a module from its build ID.
Copyright (C) 2007-2010 Red Hat, Inc.
Copyright (C) 2007-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -34,17 +34,9 @@
int
internal_function
__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name,
const size_t id_len, const uint8_t *id)
{
/* If *FILE_NAME was primed into the module, leave it there
as the fallback when we have nothing to offer. */
errno = 0;
if (mod->build_id_len <= 0)
return -1;
const size_t id_len = mod->build_id_len;
const uint8_t *id = mod->build_id_bits;
/* Search debuginfo_path directories' .build-id/ subdirectories. */
char id_name[sizeof "/.build-id/" + 1 + id_len * 2 + sizeof ".debug" - 1];
@@ -108,6 +100,22 @@ __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
return fd;
}
int
internal_function
__libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
{
/* If *FILE_NAME was primed into the module, leave it there
as the fallback when we have nothing to offer. */
errno = 0;
if (mod->build_id_len <= 0)
return -1;
const size_t id_len = mod->build_id_len;
const uint8_t *id = mod->build_id_bits;
return __libdwfl_open_by_build_id (mod, debug, file_name, id_len, id);
}
int
dwfl_build_id_find_elf (Dwfl_Module *mod,
void **userdata __attribute__ ((unused)),
@@ -133,7 +141,7 @@ dwfl_build_id_find_elf (Dwfl_Module *mod,
close (fd);
}
}
int fd = __libdwfl_open_by_build_id (mod, false, file_name);
int fd = __libdwfl_open_mod_by_build_id (mod, false, file_name);
if (fd >= 0)
{
Dwfl_Error error = __libdw_open_file (&fd, elfp, true, false);
+12 -2
View File
@@ -1,5 +1,5 @@
/* Maintenance of module list in libdwfl.
Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -71,7 +71,17 @@ __libdwfl_module_free (Dwfl_Module *mod)
}
if (mod->dw != NULL)
INTUSE(dwarf_end) (mod->dw);
{
INTUSE(dwarf_end) (mod->dw);
if (mod->alt != NULL)
{
INTUSE(dwarf_end) (mod->alt);
if (mod->alt_elf != NULL)
elf_end (mod->alt_elf);
if (mod->alt_fd != -1)
close (mod->alt_fd);
}
}
if (mod->ebl != NULL)
ebl_closebackend (mod->ebl);
+93 -115
View File
@@ -34,99 +34,10 @@
#include "../libdw/libdwP.h" /* DWARF_E_* values are here. */
#include "../libelf/libelfP.h"
#ifdef ENABLE_DWZ
internal_function int
__check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len)
{
if (dw == NULL)
return -1;
Elf *elf = dw->elf;
const void *elf_build_id;
ssize_t elf_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
if (elf_id_len < 0)
return -1;
return (id_len == (size_t) elf_id_len
&& memcmp (build_id, elf_build_id, id_len) == 0) ? 0 : 1;
}
/* Try to open an debug alt link by name, checking build_id.
Marks free_alt on success, return NULL on failure. */
static Dwarf *
try_debugaltlink (Dwarf *result, const char *try_name,
const uint8_t *build_id, const size_t id_len)
{
int fd = open (try_name, O_RDONLY);
if (fd > 0)
{
Dwarf *alt_dwarf = INTUSE (dwarf_begin) (fd, DWARF_C_READ);
if (alt_dwarf != NULL)
{
Elf *elf = alt_dwarf->elf;
if (__check_build_id (alt_dwarf, build_id, id_len) == 0
&& elf_cntl (elf, ELF_C_FDREAD) == 0)
{
close (fd);
INTUSE (dwarf_setalt) (result, alt_dwarf);
result->free_alt = true;
return result;
}
INTUSE (dwarf_end) (result->alt_dwarf);
}
close (fd);
}
return NULL;
}
/* For dwz multifile support, ignore if it looks wrong. */
static Dwarf *
open_debugaltlink (Dwarf *result, const char *alt_name,
const uint8_t *build_id, const size_t id_len)
{
/* First try the name itself, it is either an absolute path or
a relative one. Sadly we don't know relative from where at
this point. */
if (try_debugaltlink (result, alt_name, build_id, id_len) != NULL)
return result;
/* Lets try based on the build-id. This is somewhat distro specific,
we are following the Fedora implementation described at
https://fedoraproject.org/wiki/Releases/FeatureBuildId#Find_files_by_build_ID
*/
#define DEBUG_PREFIX "/usr/lib/debug/.build-id/"
#define PREFIX_LEN sizeof (DEBUG_PREFIX)
char id_name[PREFIX_LEN + 1 + id_len * 2 + sizeof ".debug" - 1];
strcpy (id_name, DEBUG_PREFIX);
int n = snprintf (&id_name[PREFIX_LEN - 1],
4, "%02" PRIx8 "/", (uint8_t) build_id[0]);
assert (n == 3);
for (size_t i = 1; i < id_len; ++i)
{
n = snprintf (&id_name[PREFIX_LEN - 1 + 3 + (i - 1) * 2],
3, "%02" PRIx8, (uint8_t) build_id[i]);
assert (n == 2);
}
strcpy (&id_name[PREFIX_LEN - 1 + 3 + (id_len - 1) * 2],
".debug");
if (try_debugaltlink (result, id_name, build_id, id_len))
return result;
/* Everything failed, mark this Dwarf as not having an alternate,
but don't fail the load. The user may want to set it by hand
before usage. */
result->alt_dwarf = NULL;
return result;
}
#endif /* ENABLE_DWZ */
/* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD.
When we return success, FILE->elf and FILE->vaddr are set up. */
static inline Dwfl_Error
open_elf (Dwfl_Module *mod, struct dwfl_file *file)
open_elf_file (Elf **elf, int *fd, char **name)
{
if (file->elf == NULL)
if (*elf == NULL)
{
/* CBFAIL uses errno if it's set, so clear it first in case we don't
set it with an open failure below. */
@@ -134,25 +45,36 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file)
/* If there was a pre-primed file name left that the callback left
behind, try to open that file name. */
if (file->fd < 0 && file->name != NULL)
file->fd = TEMP_FAILURE_RETRY (open64 (file->name, O_RDONLY));
if (*fd < 0 && *name != NULL)
*fd = TEMP_FAILURE_RETRY (open64 (*name, O_RDONLY));
if (file->fd < 0)
if (*fd < 0)
return CBFAIL;
Dwfl_Error error = __libdw_open_file (&file->fd, &file->elf, true, false);
if (error != DWFL_E_NOERROR)
return error;
return __libdw_open_file (fd, elf, true, false);
}
else if (unlikely (elf_kind (file->elf) != ELF_K_ELF))
else if (unlikely (elf_kind (*elf) != ELF_K_ELF))
{
elf_end (file->elf);
file->elf = NULL;
close (file->fd);
file->fd = -1;
elf_end (*elf);
*elf = NULL;
close (*fd);
*fd = -1;
return DWFL_E_BADELF;
}
/* Elf file already open and looks fine. */
return DWFL_E_NOERROR;
}
/* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD.
When we return success, FILE->elf and FILE->vaddr are set up. */
static inline Dwfl_Error
open_elf (Dwfl_Module *mod, struct dwfl_file *file)
{
Dwfl_Error error = open_elf_file (&file->elf, &file->fd, &file->name);
if (error != DWFL_E_NOERROR)
return error;
GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (file->elf, &ehdr_mem);
if (ehdr == NULL)
{
@@ -586,6 +508,57 @@ find_debuginfo (Dwfl_Module *mod)
return result;
}
#ifdef ENABLE_DWZ
/* Try to find the alternative debug link for the given DWARF and set
it if found. Only called when mod->dw is already setup but still
might need an alternative (dwz multi) debug file. filename is either
the main or debug name from which the Dwarf was created. */
static void
find_debug_altlink (Dwfl_Module *mod, const char *filename)
{
assert (mod->dw != NULL);
const char *altname;
const void *build_id;
ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
&altname,
&build_id);
if (build_id_len > 0)
{
/* We could store altfile in the module, but don't really need it. */
char *altfile = NULL;
mod->alt_fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
filename,
altname,
0,
&altfile);
/* The (internal) callbacks might just set mod->alt_elf directly
because they open the Elf anyway for sanity checking.
Otherwise open either the given file name or use the fd
returned. */
Dwfl_Error error = open_elf_file (&mod->alt_elf, &mod->alt_fd,
&altfile);
if (error == DWFL_E_NOERROR)
{
mod->alt = INTUSE(dwarf_begin_elf) (mod->alt_elf,
DWARF_C_READ, NULL);
if (mod->alt == NULL)
{
elf_end (mod->alt_elf);
mod->alt_elf = NULL;
close (mod->alt_fd);
mod->alt_fd = -1;
}
else
dwarf_setalt (mod->dw, mod->alt);
}
free (altfile); /* See above, we don't really need it. */
}
}
#endif /* ENABLE_DWZ */
/* Try to find a symbol table in FILE.
Returns DWFL_E_NOERROR if a proper one is found.
@@ -1209,19 +1182,6 @@ load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
}
#ifdef ENABLE_DWZ
/* For dwz multifile support, ignore if it looks wrong. */
{
const void *build_id;
const char *alt_name;
size_t id_len = INTUSE (dwelf_dwarf_gnu_debugaltlink) (mod->dw,
&alt_name,
&build_id);
if (id_len > 0)
open_debugaltlink (mod->dw, alt_name, build_id, id_len);
}
#endif /* ENABLE_DWZ */
/* Until we have iterated through all CU's, we might do lazy lookups. */
mod->lazycu = 1;
@@ -1248,6 +1208,13 @@ find_dw (Dwfl_Module *mod)
case DWFL_E_NOERROR:
mod->debug.elf = mod->main.elf;
mod->debug.address_sync = mod->main.address_sync;
#ifdef ENABLE_DWZ
/* The Dwarf might need an alt debug file, find that now after
everything about the debug file has been setup (the
find_debuginfo callback might need it). */
find_debug_altlink (mod, mod->main.name);
#endif /* ENABLE_DWZ */
return;
case DWFL_E_NO_DWARF:
@@ -1263,6 +1230,17 @@ find_dw (Dwfl_Module *mod)
{
case DWFL_E_NOERROR:
mod->dwerr = load_dw (mod, &mod->debug);
if (mod->dwerr == DWFL_E_NOERROR)
{
#ifdef ENABLE_DWZ
/* The Dwarf might need an alt debug file, find that now after
everything about the debug file has been setup (the
find_debuginfo callback might need it). */
find_debug_altlink (mod, mod->debug.name);
#endif /* ENABLE_DWZ */
return;
}
break;
case DWFL_E_CB: /* The find_debuginfo hook failed. */
+89 -9
View File
@@ -1,5 +1,5 @@
/* Standard find_debuginfo callback for libdwfl.
Copyright (C) 2005-2010 Red Hat, Inc.
Copyright (C) 2005-2010, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -84,6 +84,45 @@ check_crc (int fd, GElf_Word debuglink_crc)
static bool
validate (Dwfl_Module *mod, int fd, bool check, GElf_Word debuglink_crc)
{
/* For alt debug files always check the build-id from the Dwarf and alt. */
if (mod->dw != NULL)
{
bool valid = false;
const void *build_id;
const char *altname;
ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
&altname,
&build_id);
if (build_id_len > 0)
{
/* We need to open an Elf handle on the file so we can check its
build ID note for validation. Backdoor the handle into the
module data structure since we had to open it early anyway. */
Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf,
false, false);
if (error != DWFL_E_NOERROR)
__libdwfl_seterrno (error);
else
{
const void *alt_build_id;
ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf,
&alt_build_id);
if (alt_len > 0 && alt_len == build_id_len
&& memcmp (build_id, alt_build_id, alt_len) == 0)
valid = true;
else
{
/* A mismatch! */
elf_end (mod->alt_elf);
mod->alt_elf = NULL;
close (fd);
fd = -1;
}
}
}
return valid;
}
/* If we have a build ID, check only that. */
if (mod->build_id_len > 0)
{
@@ -124,7 +163,9 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
const char *file_basename = file_name == NULL ? NULL : basename (file_name);
if (debuglink_file == NULL)
{
if (file_basename == NULL)
/* For a alt debug multi file we need a name, for a separate debug
name we may be able to fall back on file_basename.debug. */
if (file_basename == NULL || mod->dw != NULL)
{
errno = 0;
return -1;
@@ -174,38 +215,67 @@ find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
check = *p++ == '+';
check = check && cancheck;
const char *dir, *subdir;
const char *dir, *subdir, *file;
switch (p[0])
{
case '\0':
/* An empty entry says to try the main file's directory. */
dir = file_dirname;
subdir = NULL;
file = debuglink_file;
break;
case '/':
/* An absolute path says to look there for a subdirectory
named by the main file's absolute directory.
This cannot be applied to a relative file name. */
if (file_dirname == NULL || file_dirname[0] != '/')
named by the main file's absolute directory. This cannot
be applied to a relative file name. For alt debug files
it means to look for the basename file in that dir or the
.dwz subdir (see below). */
if (mod->dw == NULL
&& (file_dirname == NULL || file_dirname[0] != '/'))
continue;
dir = p;
subdir = file_dirname + 1;
if (mod->dw == NULL)
{
subdir = file_dirname + 1;
file = debuglink_file;
}
else
{
subdir = NULL;
file = basename (debuglink_file);
}
break;
default:
/* A relative path says to try a subdirectory of that name
in the main file's directory. */
dir = file_dirname;
subdir = p;
file = debuglink_file;
break;
}
char *fname = NULL;
int fd = try_open (&main_stat, dir, subdir, debuglink_file, &fname);
int fd = try_open (&main_stat, dir, subdir, file, &fname);
if (fd < 0)
switch (errno)
{
case ENOENT:
case ENOTDIR:
/* If we are looking for the alt file also try the .dwz subdir.
But only if this is the empty or absolute path. */
if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/'))
{
fd = try_open (&main_stat, dir, ".dwz",
basename (file), &fname);
if (fd < 0)
{
if (errno != ENOENT && errno != ENOTDIR)
return -1;
else
continue;
}
break;
}
continue;
default:
return -1;
@@ -240,11 +310,21 @@ dwfl_standard_find_debuginfo (Dwfl_Module *mod,
GElf_Addr vaddr;
if (INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr) > 0)
{
/* Dropping most arguments means we cannot rely on them in
dwfl_build_id_find_debuginfo. But leave it that way since
some user code out there also does this, so we'll have to
handle it anyway. */
int fd = INTUSE(dwfl_build_id_find_debuginfo) (mod,
NULL, NULL, 0,
NULL, NULL, 0,
debuginfo_file_name);
if (fd >= 0 || mod->debug.elf != NULL || errno != 0)
/* Did the build_id callback find something or report an error?
Then we are done. Otherwise fallback on path based search. */
if (fd >= 0
|| (mod->dw == NULL && mod->debug.elf != NULL)
|| (mod->dw != NULL && mod->alt_elf != NULL)
|| errno != 0)
return fd;
}
+9 -1
View File
@@ -182,6 +182,9 @@ struct Dwfl_Module
Elf_Data *aux_symxndxdata; /* Data in the extended auxiliary table. */
Dwarf *dw; /* libdw handle for its debugging info. */
Dwarf *alt; /* Dwarf used for dwarf_setalt, or NULL. */
int alt_fd; /* descriptor, only valid when alt != NULL. */
Elf *alt_elf; /* Elf for alt Dwarf. */
Dwfl_Error symerr; /* Previous failure to load symbols. */
Dwfl_Error dwerr; /* Previous failure to load DWARF. */
@@ -518,8 +521,13 @@ extern int __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
internal_function;
/* Open a main or debuginfo file by its build ID, returns the fd. */
extern int __libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug,
char **file_name) internal_function;
/* Same, but takes an explicit build_id, can also be used for alt debug. */
extern int __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug,
char **file_name) internal_function;
char **file_name, const size_t id_len,
const uint8_t *id) internal_function;
extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len)
attribute_hidden;
+5 -6
View File
@@ -1,5 +1,5 @@
/* Standard libdwfl callbacks for debugging the running Linux kernel.
Copyright (C) 2005-2011, 2013 Red Hat, Inc.
Copyright (C) 2005-2011, 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -88,23 +88,22 @@ try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug)
if (fd < 0)
{
char *debugfname = NULL;
Dwfl_Module fakemod = { .dwfl = dwfl };
/* First try the file's unadorned basename as DEBUGLINK_FILE,
to look for "vmlinux" files. */
fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
*fname, basename (*fname), 0,
&debugfname);
&fakemod.debug.name);
if (fd < 0 && try_debug)
/* Next, let the call use the default of basename + ".debug",
to look for "vmlinux.debug" files. */
fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
*fname, NULL, 0,
&debugfname);
if (debugfname != NULL)
&fakemod.debug.name);
if (fakemod.debug.name != NULL)
{
free (*fname);
*fname = debugfname;
*fname = fakemod.debug.name;
}
}
+5
View File
@@ -1,3 +1,8 @@
2014-05-01 Mark Wielaard <mjw@redhat.com>
* readelf.c (find_no_debuginfo): Call dwfl_standard_find_debuginfo
if looking for alternate debug file.
2014-04-11 Mark Wielaard <mjw@redhat.com>
* Makefile.am (AM_CPPFLAGS): Add -I libdwelf.
+24 -10
View File
@@ -693,18 +693,32 @@ process_dwflmod (Dwfl_Module *dwflmod,
return DWARF_CB_OK;
}
/* Stub libdwfl callback, only the ELF handle already open is ever used. */
/* Stub libdwfl callback, only the ELF handle already open is ever used.
Only used for finding the alternate debug file if the Dwarf comes from
the main file. We are not interested in separate debuginfo. */
static int
find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
void **userdata __attribute__ ((unused)),
const char *modname __attribute__ ((unused)),
Dwarf_Addr base __attribute__ ((unused)),
const char *file_name __attribute__ ((unused)),
const char *debuglink_file __attribute__ ((unused)),
GElf_Word debuglink_crc __attribute__ ((unused)),
char **debuginfo_file_name __attribute__ ((unused)))
find_no_debuginfo (Dwfl_Module *mod,
void **userdata,
const char *modname,
Dwarf_Addr base,
const char *file_name,
const char *debuglink_file,
GElf_Word debuglink_crc,
char **debuginfo_file_name)
{
return -1;
Dwarf_Addr dwbias;
dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
/* We are only interested if the Dwarf has been setup on the main
elf file but is only missing the alternate debug link. If dwbias
hasn't even been setup, this is searching for separate debuginfo
for the main elf. We don't care in that case. */
if (dwbias == (Dwarf_Addr) -1)
return -1;
return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
file_name, debuglink_file,
debuglink_crc, debuginfo_file_name);
}
/* Process one input file. */
+5
View File
@@ -1,3 +1,8 @@
2014-05-01 Mark Wielaard <mjw@redhat.com>
* run-readelf-dwz-multi.sh: Add tests with alt debug files in .dwz
subdir.
2014-04-30 Mark Wielaard <mjw@redhat.com>
* buildid.c, buildid.sh, testfile42_noshdrs.bz2: New files.
+105
View File
@@ -136,6 +136,69 @@ DWARF section [28] '.debug_info' at offset 0x1078:
type (ref_udata) [ 2b]
EOF
# Same as above, but find alt debug file in a .dwz subdir.
mkdir .dwz
mv testfile_multi.dwz .dwz
testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile_multi_main <<\EOF
DWARF section [28] '.debug_info' at offset 0x1078:
[Offset]
Compilation unit at offset 0:
Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
[ b] compile_unit
producer (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -mtune=generic -march=x86-64 -g"
language (data1) C89 (1)
name (strp) "main.c"
comp_dir (GNU_strp_alt) "/home/mark/src/tests/dwz"
low_pc (addr) 0x00000000004006ac <main>
high_pc (udata) 44 (0x00000000004006d8)
stmt_list (sec_offset) 0
[ 26] imported_unit
import (GNU_ref_alt) [ b]
[ 2b] pointer_type
byte_size (data1) 8
type (GNU_ref_alt) [ 53]
[ 31] subprogram
external (flag_present)
name (strp) "main"
decl_file (data1) 1
decl_line (data1) 3
prototyped (flag_present)
type (GNU_ref_alt) [ 3e]
low_pc (addr) 0x00000000004006ac <main>
high_pc (udata) 44 (0x00000000004006d8)
frame_base (exprloc)
[ 0] call_frame_cfa
GNU_all_tail_call_sites (flag_present)
sibling (ref_udata) [ 6e]
[ 48] formal_parameter
name (strp) "argc"
decl_file (data1) 1
decl_line (data1) 3
type (GNU_ref_alt) [ 3e]
location (exprloc)
[ 0] fbreg -36
[ 56] formal_parameter
name (strp) "argv"
decl_file (data1) 1
decl_line (data1) 3
type (ref_udata) [ 6e]
location (exprloc)
[ 0] fbreg -48
[ 61] variable
name (string) "b"
decl_file (data1) 1
decl_line (data1) 5
type (GNU_ref_alt) [ 5a]
location (exprloc)
[ 0] fbreg -32
[ 6e] pointer_type
byte_size (data1) 8
type (ref_udata) [ 2b]
EOF
mv .dwz/testfile_multi.dwz .
rmdir .dwz
testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info libtestfile_multi_shared.so <<\EOF
DWARF section [25] '.debug_info' at offset 0x106c:
@@ -173,6 +236,48 @@ DWARF section [25] '.debug_info' at offset 0x106c:
[ 0] fbreg -24
EOF
# Same as above, but find alt debug file in a .dwz subdir.
mkdir .dwz
mv testfile_multi.dwz .dwz
testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info libtestfile_multi_shared.so <<\EOF
DWARF section [25] '.debug_info' at offset 0x106c:
[Offset]
Compilation unit at offset 0:
Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
[ b] compile_unit
producer (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -fpreprocessed -mtune=generic -march=x86-64 -g -fPIC"
language (data1) C89 (1)
name (strp) "shared.c"
comp_dir (GNU_strp_alt) "/home/mark/src/tests/dwz"
low_pc (addr) +0x0000000000000670 <call_foo>
high_pc (udata) 23 (+0x0000000000000687)
stmt_list (sec_offset) 0
[ 26] imported_unit
import (GNU_ref_alt) [ b]
[ 2b] subprogram
external (flag_present)
name (strp) "call_foo"
decl_file (data1) 1
decl_line (data1) 3
prototyped (flag_present)
type (GNU_ref_alt) [ 3e]
low_pc (addr) +0x0000000000000670 <call_foo>
high_pc (udata) 23 (+0x0000000000000687)
frame_base (exprloc)
[ 0] call_frame_cfa
GNU_all_call_sites (flag_present)
[ 41] formal_parameter
name (string) "fb"
decl_file (data1) 1
decl_line (data1) 3
type (GNU_ref_alt) [ 76]
location (exprloc)
[ 0] fbreg -24
EOF
mv .dwz/testfile_multi.dwz .
rmdir .dwz
testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile-dwzstr <<\EOF
DWARF section [28] '.debug_info' at offset 0x1088: