diff options
-rw-r--r-- | libdw/ChangeLog | 15 | ||||
-rw-r--r-- | libdw/dwarf_begin_elf.c | 24 | ||||
-rw-r--r-- | libdw/dwarf_end.c | 3 | ||||
-rw-r--r-- | libdw/dwarf_getalt.c | 44 | ||||
-rw-r--r-- | libdw/libdwP.h | 26 | ||||
-rw-r--r-- | libdw/libdw_find_split_unit.c | 6 | ||||
-rw-r--r-- | libdwfl/ChangeLog | 10 | ||||
-rw-r--r-- | libdwfl/dwfl_module.c | 1 | ||||
-rw-r--r-- | libdwfl/dwfl_module_getdwarf.c | 23 | ||||
-rw-r--r-- | libdwfl/libdwflP.h | 2 | ||||
-rw-r--r-- | libdwfl/offline.c | 3 |
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; } |