2018-05-17 Mark Wielaard <mark@klomp.org>
+ * 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 <mark@klomp.org>
+
* 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.
#include <fcntl.h>
#include <endian.h>
+#include "libelfP.h"
#include "libdwP.h"
}
+/* 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)
}
}
+ if (result != NULL)
+ result->debugdir = __libdw_debugdir (result->elf->fildes);
+
return result;
}
close (dwarf->alt_fd);
}
+ /* The cached dir we found the Dwarf ELF file in. */
+ free (dwarf->debugdir);
+
/* Free the context descriptor. */
free (dwarf);
}
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;
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;
/* 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));
/* 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;
}
-/* 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;
{
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);
+2018-05-17 Mark Wielaard <mark@klomp.org>
+
+ * 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 <mark@klomp.org>
* frame_unwind.c (unwind): If __libdwfl_frame_reg_get fails for
free (mod->reloc_info);
free (mod->name);
+ free (mod->elfdir);
free (mod);
}
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)
{
}
}
- 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;
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. */
/* 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;
}