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 <m...@klomp.org> --- libdw/ChangeLog | 7 +++ libdw/libdw_find_split_unit.c | 114 +++++++++++++++++++++++++----------------- src/ChangeLog | 5 ++ src/readelf.c | 13 ++++- 4 files changed, 92 insertions(+), 47 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index d8433eb..17acb90 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,10 @@ +2018-05-31 Mark Wielaard <m...@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 <m...@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 dc62e0d..da039e5 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 0e6f1f2..95f8a72 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-05-31 Mark Wielaard <m...@klomp.org> + + * readelf.c (print_debug_units): Print the dwo name and id when + unable to find a .dwo file. + 2018-05-30 Mark Wielaard <m...@klomp.org> * readelf.c (print_debug_loc_section): Use correct listptr for diff --git a/src/readelf.c b/src/readelf.c index db7723d..8d85dc8 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -7668,7 +7668,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)) + ?: "<unknow")); + fprintf (stderr, + "Could not find split unit '%s', id: %" PRIx64 "\n", + dwo_name, unit_id); + } } else { -- 1.8.3.1