From: Mark Wielaard Date: Thu, 31 May 2018 14:57:09 +0000 (+0200) Subject: libdw: Try both the relative and absolute paths when finding a .dwo file. X-Git-Tag: elfutils-0.171~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e2872c91f65301b202b84497b2b955f9e9613d00;p=thirdparty%2Felfutils.git 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 --- diff --git a/libdw/ChangeLog b/libdw/ChangeLog index d8433eb9d..17acb909d 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,10 @@ +2018-05-31 Mark Wielaard + + * 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 * 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 dc62e0d0f..da039e50a 100644 --- a/libdw/libdw_find_split_unit.c +++ b/libdw/libdw_find_split_unit.c @@ -42,6 +42,49 @@ #include #include +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 bd3befd65..cc12d836c 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-05-31 Mark Wielaard + + * readelf.c (print_debug_units): Print the dwo name and id when + unable to find a .dwo file. + 2018-05-31 Mark Wielaard * readelf.c (enum section_e): Make section_types not an alias of diff --git a/src/readelf.c b/src/readelf.c index 18ce3f7d6..0725313e4 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)) + ?: "")); + fprintf (stderr, + "Could not find split unit '%s', id: %" PRIx64 "\n", + dwo_name, unit_id); + } } else {