diff options
author | Mark Wielaard <mark@klomp.org> | 2018-05-31 16:57:09 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2018-06-01 17:27:59 +0200 |
commit | e2872c91f65301b202b84497b2b955f9e9613d00 (patch) | |
tree | 9c714039ba9dad15e5142ef4fc845974f0793752 | |
parent | a6a783a32ee0e6428c15c87e62476b74ecd77686 (diff) |
libdw: Try both the relative and absolute paths when finding a .dwo file.
We would give up if one of them failed. With this fixed a self-test with
make check succeeds when building elfutils itself with CFLAGS set to
"-gdwarf-4 -gdwarf-split -O2".
Signed-off-by: Mark Wielaard <mark@klomp.org>
-rw-r--r-- | libdw/ChangeLog | 7 | ||||
-rw-r--r-- | libdw/libdw_find_split_unit.c | 114 | ||||
-rw-r--r-- | src/ChangeLog | 5 | ||||
-rw-r--r-- | src/readelf.c | 13 |
4 files changed, 92 insertions, 47 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog index d8433eb9..17acb909 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,10 @@ +2018-05-31 Mark Wielaard <mark@klomp.org> + + * libdw_find_split_unit.c (try_split_file): New function extracted + from... + (__libdw_find_split_unit): ... here. Try both the relative and + absolute paths to find a .dwo file. + 2018-05-30 Mark Wielaard <mark@klomp.org> * libdw/dwarf_getsrclines.c (read_srclines): Change ndir and diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c index dc62e0d0..da039e50 100644 --- a/libdw/libdw_find_split_unit.c +++ b/libdw/libdw_find_split_unit.c @@ -42,6 +42,49 @@ #include <fcntl.h> #include <unistd.h> +void +try_split_file (Dwarf_CU *cu, const char *dwo_path) +{ + int split_fd = open (dwo_path, O_RDONLY); + if (split_fd != -1) + { + Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ); + if (split_dwarf != NULL) + { + Dwarf_CU *split = NULL; + while (dwarf_get_units (split_dwarf, split, &split, + NULL, NULL, NULL, NULL) == 0) + { + if (split->unit_type == DW_UT_split_compile + && cu->unit_id8 == split->unit_id8) + { + if (tsearch (split->dbg, &cu->dbg->split_tree, + __libdw_finddbg_cb) == NULL) + { + /* Something went wrong. Don't link. */ + __libdw_seterrno (DWARF_E_NOMEM); + break; + } + + /* Link skeleton and split compile units. */ + __libdw_link_skel_split (cu, split); + + /* We have everything we need from this ELF + file. And we are going to close the fd to + not run out of file descriptors. */ + elf_cntl (split_dwarf->elf, ELF_C_FDDONE); + break; + } + } + if (cu->split == (Dwarf_CU *) -1) + dwarf_end (split_dwarf); + } + /* Always close, because we don't want to run out of file + descriptors. See also the elf_fcntl ELF_C_FDDONE call + above. */ + close (split_fd); + } +} Dwarf_CU * internal_function @@ -57,63 +100,42 @@ __libdw_find_split_unit (Dwarf_CU *cu) if (cu->unit_type == DW_UT_skeleton) { Dwarf_Die cudie = CUDIE (cu); - Dwarf_Attribute compdir, dwo_name; - /* It is fine if compdir doesn't exists, but then dwo_name needs - to be an absolute path. Also try relative path first. */ - dwarf_attr (&cudie, DW_AT_comp_dir, &compdir); - if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL - || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL) + Dwarf_Attribute dwo_name; + /* It is fine if dwo_dir doesn't exists, but then dwo_name needs + to be an absolute path. */ + if (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL + || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL) { - const char *comp_dir = dwarf_formstring (&compdir); + /* First try the dwo file name in the same directory + as we found the skeleton file. */ const char *dwo_file = dwarf_formstring (&dwo_name); 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 (debugdir, comp_dir, dwo_file); if (dwo_path != NULL) { - int split_fd = open (dwo_path, O_RDONLY); - if (split_fd != -1) + try_split_file (cu, dwo_path); + free (dwo_path); + } + + if (cu->split == (Dwarf_CU *) -1) + { + /* Try compdir plus dwo_name. */ + Dwarf_Attribute compdir; + dwarf_attr (&cudie, DW_AT_comp_dir, &compdir); + const char *dwo_dir = dwarf_formstring (&compdir); + if (dwo_dir != NULL) { - Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ); - if (split_dwarf != NULL) + dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file); + if (dwo_path != NULL) { - Dwarf_CU *split = NULL; - while (dwarf_get_units (split_dwarf, split, &split, - NULL, NULL, NULL, NULL) == 0) - { - if (split->unit_type == DW_UT_split_compile - && cu->unit_id8 == split->unit_id8) - { - if (tsearch (split->dbg, &cu->dbg->split_tree, - __libdw_finddbg_cb) == NULL) - { - /* Something went wrong. Don't link. */ - __libdw_seterrno (DWARF_E_NOMEM); - break; - } - - /* Link skeleton and split compile units. */ - __libdw_link_skel_split (cu, split); - - /* We have everything we need from this - ELF file. And we are going to close - the fd to not run out of file - descriptors. */ - elf_cntl (split_dwarf->elf, ELF_C_FDDONE); - break; - } - } - if (cu->split == (Dwarf_CU *) -1) - dwarf_end (split_dwarf); + try_split_file (cu, dwo_path); + free (dwo_path); } - /* Always close, because we don't want to run - out of file descriptors. See also the - elf_fcntl ELF_C_FDDONE call above. */ - close (split_fd); } - free (dwo_path); } + /* XXX If still not found we could try stripping dirs from the + comp_dir and adding them from the comp_dir, assuming + someone moved a whole build tree around. */ } } diff --git a/src/ChangeLog b/src/ChangeLog index bd3befd6..cc12d836 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,10 @@ 2018-05-31 Mark Wielaard <mark@klomp.org> + * readelf.c (print_debug_units): Print the dwo name and id when + unable to find a .dwo file. + +2018-05-31 Mark Wielaard <mark@klomp.org> + * readelf.c (enum section_e): Make section_types not an alias of section_info. (section_all): Add section_types. diff --git a/src/readelf.c b/src/readelf.c index 18ce3f7d..0725313e 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -7680,7 +7680,18 @@ print_debug_units (Dwfl_Module *dwflmod, || dwarf_tag (&subdie) == DW_TAG_invalid) { if (!silent) - fprintf (stderr, gettext ("Could not find split compile unit")); + { + Dwarf_Attribute dwo_at; + const char *dwo_name = + (dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name, + &dwo_at)) + ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name, + &dwo_at)) + ?: "<unknown>")); + fprintf (stderr, + "Could not find split unit '%s', id: %" PRIx64 "\n", + dwo_name, unit_id); + } } else { |