summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdw/ChangeLog15
-rw-r--r--libdw/dwarf_begin_elf.c24
-rw-r--r--libdw/dwarf_end.c3
-rw-r--r--libdw/dwarf_getalt.c44
-rw-r--r--libdw/libdwP.h26
-rw-r--r--libdw/libdw_find_split_unit.c6
-rw-r--r--libdwfl/ChangeLog10
-rw-r--r--libdwfl/dwfl_module.c1
-rw-r--r--libdwfl/dwfl_module_getdwarf.c23
-rw-r--r--libdwfl/libdwflP.h2
-rw-r--r--libdwfl/offline.c3
11 files changed, 112 insertions, 45 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index c91d9ff2..72ff8a73 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,5 +1,20 @@
2018-05-17 Mark Wielaard <[email protected]>
+ * dwarf_begin_elf.c (__libdw_debugdir): New function.
+ (valid_p): Call __libdw_debugdir.
+ * dwarf_end.c (dwarf_end.c): Free debugdir.
+ * dwarf_getalt.c (__libdw_filepath): Extract __libdw_debugdir logic.
+ take debugdir as argument instead of fd.
+ (find_debug_altlink): Call __libdw_filepath with debugdir.
+ * libdwP.h (struct Dwarf): Add debugdir field.
+ (__libdw_debugdir): New function prototype.
+ (__libdw_filepath): Adjust prototype to take a const char * instead of
+ an int.
+ * libdw_find_split_unit.c (__libdw_find_split_unit): Call
+ __libdw_filepath with debugdir.
+
+2018-05-17 Mark Wielaard <[email protected]>
+
* dwarf_attr_integrate.c (dwarf_attr_integrate): Handle split_compile
unit DIE, search skeleton_compile unit DIE.
* dwarf_hasattr_integrate.c (dwarf_hasattr_integrate): Likewise.
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index 61de7526..0e435c57 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -42,6 +42,7 @@
#include <fcntl.h>
#include <endian.h>
+#include "libelfP.h"
#include "libdwP.h"
@@ -184,6 +185,26 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
}
+/* Helper function to set debugdir field. We want to cache the dir
+ where we found this Dwarf ELF file to locate alt and dwo files. */
+char *
+__libdw_debugdir (int fd)
+{
+ /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25. */
+ char devfdpath[25];
+ sprintf (devfdpath, "/proc/self/fd/%u", fd);
+ char *fdpath = realpath (devfdpath, NULL);
+ char *fddir;
+ if (fdpath != NULL && fdpath[0] == '/'
+ && (fddir = strrchr (fdpath, '/')) != NULL)
+ {
+ *++fddir = '\0';
+ return fdpath;
+ }
+ return NULL;
+}
+
+
/* Check whether all the necessary DWARF information is available. */
static Dwarf *
valid_p (Dwarf *result)
@@ -225,6 +246,9 @@ valid_p (Dwarf *result)
}
}
+ if (result != NULL)
+ result->debugdir = __libdw_debugdir (result->elf->fildes);
+
return result;
}
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index 43223de0..4702f1b1 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -116,6 +116,9 @@ dwarf_end (Dwarf *dwarf)
close (dwarf->alt_fd);
}
+ /* The cached dir we found the Dwarf ELF file in. */
+ free (dwarf->debugdir);
+
/* Free the context descriptor. */
free (dwarf);
}
diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c
index 3e5af151..3339b3e1 100644
--- a/libdw/dwarf_getalt.c
+++ b/libdw/dwarf_getalt.c
@@ -47,7 +47,7 @@
char *
internal_function
-__libdw_filepath (int fd, const char *dir, const char *file)
+__libdw_filepath (const char *debugdir, const char *dir, const char *file)
{
if (file == NULL)
return NULL;
@@ -71,37 +71,25 @@ __libdw_filepath (int fd, const char *dir, const char *file)
return path;
}
- if (fd >= 0)
+ if (debugdir != NULL)
{
- /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25. */
- char devfdpath[25];
- sprintf (devfdpath, "/proc/self/fd/%u", fd);
- char *fdpath = realpath (devfdpath, NULL);
- char *path = NULL;
- char *fddir;
- if (fdpath != NULL && fdpath[0] == '/'
- && (fddir = strrchr (fdpath, '/')) != NULL)
+ size_t debugdirlen = strlen (debugdir);
+ size_t dirlen = dir != NULL ? strlen (dir) : 0;
+ size_t filelen = strlen (file);
+ size_t len = debugdirlen + 1 + dirlen + 1 + filelen + 1;
+ char *path = malloc (len);
+ if (path != NULL)
{
- *++fddir = '\0';
- size_t fdpathlen = strlen (fdpath);
- size_t dirlen = dir != NULL ? strlen (dir) : 0;
- size_t filelen = strlen (file);
- size_t len = fdpathlen + 1 + dirlen + 1 + filelen + 1;
- path = malloc (len);
- if (path != NULL)
+ char *c = mempcpy (path, debugdir, debugdirlen);
+ if (dirlen > 0)
{
- char *c = mempcpy (path, fdpath, fdpathlen);
- if (dirlen > 0)
- {
- c = mempcpy (c, dir, dirlen);
- if (dir[dirlen - 1] != '/')
- *c++ = '/';
- }
- mempcpy (c, file, filelen + 1);
+ c = mempcpy (c, dir, dirlen);
+ if (dir[dirlen - 1] != '/')
+ *c++ = '/';
}
+ mempcpy (c, file, filelen + 1);
+ return path;
}
- free (fdpath);
- return path;
}
return NULL;
@@ -151,7 +139,7 @@ find_debug_altlink (Dwarf *dbg)
/* Fall back on (possible relative) alt file path. */
if (fd < 0)
{
- char *altpath = __libdw_filepath (dbg->elf->fildes, NULL, altname);
+ char *altpath = __libdw_filepath (dbg->debugdir, NULL, altname);
if (altpath != NULL)
{
fd = TEMP_FAILURE_RETRY (open (altpath, O_RDONLY));
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index cffe6ce7..f7390057 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -148,6 +148,10 @@ struct Dwarf
/* The underlying ELF file. */
Elf *elf;
+ /* The (absolute) path to the ELF dir, if known. To help locating
+ alt and dwo files. */
+ char *debugdir;
+
/* dwz alternate DWARF file. */
Dwarf *alt_dwarf;
@@ -1051,20 +1055,26 @@ static inline Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu)
}
-/* Given a file descriptor, dir and file returns a full path. If the
- file is absolute (starts with a /) a copy of file is returned. If
+/* Helper function to set debugdir field in Dwarf, used from dwarf_begin_elf
+ and libdwfl process_file. */
+char * __libdw_debugdir (int fd);
+
+
+/* Given the directory of a debug file, an absolute or relative dir
+ to look in, and file returns a full path.
+
+ If the file is absolute (starts with a /) a copy of file is returned.
the file isn't absolute, but dir is absolute, then a path that is
the concatenation of dir and file is returned. If neither file,
nor dir is absolute, the path will be constructed using dir (if not
- NULL) and file relative to the path of the given file descriptor
- (if valid).
+ NULL) and file relative to the debugdir (if valid).
- The file descriptor may be -1 and the dir may be NULL (in which
- case they aren't used). If file is NULL, or no full path can be
- constructed NULL is returned.
+ The debugdir and the dir may be NULL (in which case they aren't used).
+ If file is NULL, or no full path can be constructed NULL is returned.
The caller is responsible for freeing the result if not NULL. */
-char * __libdw_filepath (int fd, const char *dir, const char *file)
+char * __libdw_filepath (const char *debugdir, const char *dir,
+ const char *file)
internal_function;
diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c
index 0f74b39a..bd48b9e5 100644
--- a/libdw/libdw_find_split_unit.c
+++ b/libdw/libdw_find_split_unit.c
@@ -65,10 +65,10 @@ __libdw_find_split_unit (Dwarf_CU *cu)
{
const char *comp_dir = dwarf_formstring (&compdir);
const char *dwo_file = dwarf_formstring (&dwo_name);
- int fd = cu->dbg->elf->fildes;
- char *dwo_path = __libdw_filepath (fd, NULL, dwo_file);
+ const char *debugdir = cu->dbg->debugdir;
+ char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file);
if (dwo_path == NULL && comp_dir != NULL)
- dwo_path = __libdw_filepath (fd, comp_dir, dwo_file);
+ dwo_path = __libdw_filepath (debugdir, comp_dir, dwo_file);
if (dwo_path != NULL)
{
int split_fd = open (dwo_path, O_RDONLY);
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index b6262c20..d69fe0cd 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,13 @@
+2018-05-17 Mark Wielaard <[email protected]>
+
+ * dwfl_module (__libdwfl_module_free): Free elfdir.
+ * dwfl_module_getdwarf.c (load_dw): Close file descriptors after
+ dwarf_begin_elf call. Set Dwarf debugdir if it is NULL, this is the
+ main module file and we recorded the elfdir.
+ * libdwflP.h (struct Dwfl_Module): Add elfdir field.
+ * offline.c (process_elf): Record the elfdir before we close the
+ main ELF file descriptor.
+
2018-04-10 Mark Wielaard <[email protected]>
* frame_unwind.c (unwind): If __libdwfl_frame_reg_get fails for
diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c
index 510bd691..e7dfdace 100644
--- a/libdwfl/dwfl_module.c
+++ b/libdwfl/dwfl_module.c
@@ -120,6 +120,7 @@ __libdwfl_module_free (Dwfl_Module *mod)
free (mod->reloc_info);
free (mod->name);
+ free (mod->elfdir);
free (mod);
}
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 9775aced..af6838a6 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -1335,7 +1335,18 @@ load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
result = __libdwfl_relocate (mod, debugfile->elf, true);
if (result != DWFL_E_NOERROR)
return result;
+ }
+
+ mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL);
+ if (mod->dw == NULL)
+ {
+ int err = INTUSE(dwarf_errno) ();
+ return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
+ }
+ /* Do this after dwarf_begin_elf has a chance to process the fd. */
+ if (mod->e_type == ET_REL && !debugfile->relocated)
+ {
/* Don't keep the file descriptors around. */
if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
{
@@ -1349,12 +1360,12 @@ load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
}
}
- mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL);
- if (mod->dw == NULL)
- {
- int err = INTUSE(dwarf_errno) ();
- return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
- }
+ /* We might have already closed the fd when we asked dwarf_begin_elf to
+ create an Dwarf. Help out a little in case we need to find an alt or
+ dwo file later. */
+ if (mod->dw->debugdir == NULL && mod->elfdir != NULL
+ && debugfile == &mod->main)
+ mod->dw->debugdir = strdup (mod->elfdir);
/* Until we have iterated through all CU's, we might do lazy lookups. */
mod->lazycu = 1;
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 15ca0a11..36298711 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -190,6 +190,8 @@ struct Dwfl_Module
Elf_Data *symxndxdata; /* Data in the extended section index table. */
Elf_Data *aux_symxndxdata; /* Data in the extended auxiliary table. */
+ char *elfdir; /* The dir where we found the main Elf. */
+
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. */
diff --git a/libdwfl/offline.c b/libdwfl/offline.c
index 80c80a16..d8697cf2 100644
--- a/libdwfl/offline.c
+++ b/libdwfl/offline.c
@@ -150,6 +150,9 @@ process_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
/* Don't keep the file descriptor around. */
if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
{
+ /* Grab the dir path in case we want to report this file as
+ Dwarf later. */
+ mod->elfdir = __libdw_debugdir (mod->main.fd);
close (mod->main.fd);
mod->main.fd = -1;
}