On Wed, 2012-06-27 at 23:33 +0200, Mark Wielaard wrote: > This patch adds support for dwz multi debuginfo files to libdw. > Fedora is planning to use these in the next release: > https://fedoraproject.org/wiki/Features/DwarfCompressor > The new DW_FORMs are proposed for DWARF5: > http://www.dwarfstd.org/ShowIssue.php?issue=120604.1 > But are currently only a GNU extension written by the dwz tool: > http://sourceware.org/git/?p=dwz.git;a=summary > > libdw was already setup anticipating such a scheme, so adding support > wasn't so hard. Basically a Dwarf descriptor can now have an alternative > Dwarf descriptor that is consulted whenever one of the new DW_FROM_*alts > is seen. > > dwarf_begin_elf will find the right dwz alternative to use. But this is > currently tied somewhat to how fedora implemented this. There are also > two new functions dwarf_getalt () and dwarf_addalt () that can be used > to directly manipulate the alternative Dwarf descriptor. I anticipate > those will be used by some new libdwfl callbacks if we decide those are > necessary to support other ways to get/set alternative Dwarf > descriptors.
We (Roland, Petr and I) briefly discussed this and thought it better to not introduce any new interfaces for this at this point. So this new patch removes them and makes things a little simpler. There are no user visible changes except that debug files with a separate dwz multi file now just work. In the future libdwfl may use internal calls, which it already does, when it supports sharing (I looked briefly at the pmachata/sharing branch, but that is a lot of code and needs works to bring it forward to 2012 - the branch is from 2007). The patch (and the branch) are also rebased against current master and fixed a typo that Tom Tromey found in some comments. There is a testcase included and I tested with systemtap on fedora rawhide, which recently switched to using the dwz compressor on all packages. Patch also on mjw/dwz branch. Please take a look and yell and scream if anything looks odd. Thanks, Mark
From b1e42797293bcf34385d5cb0a18e8c773279241b Mon Sep 17 00:00:00 2001 From: Mark Wielaard <[email protected]> Date: Fri, 22 Jun 2012 12:02:45 +0200 Subject: [PATCH] libdw: Add support for DWZ multifile forms DW_FORM_GNU_ref_alt/strp_alt. DWZ multifile forms http://www.dwarfstd.org/ShowIssue.php?issue=120604.1 DW_FORM_GNU_ref_alt and DW_FORM_GNU_strp_alt reference an alternative debuginfo file. dwarf_begin and dwarf_begin_elf will try to use this automatically. There are no user visible changes to the libdw interface. dwarf_formref_die, dwarf_formstring and dwarf_formudata can now return a Dwarf_Die which comes from a CU in the alternative Dwarf descriptor. __libdw_read_offset was adjusted to take an alternative Dwarf descriptor into account. Signed-off-by: Mark Wielaard <[email protected]> --- libdw/ChangeLog | 27 ++++++ libdw/dwarf.h | 5 +- libdw/dwarf_begin.c | 1 + libdw/dwarf_begin_elf.c | 123 ++++++++++++++++++++++++++ libdw/dwarf_end.c | 4 + libdw/dwarf_error.c | 1 + libdw/dwarf_formref.c | 2 + libdw/dwarf_formref_die.c | 15 +++- libdw/dwarf_formstring.c | 15 +++- libdw/dwarf_formudata.c | 6 +- libdw/dwarf_getpubnames.c | 3 +- libdw/libdwP.h | 18 ++++- libdw/libdw_form.c | 2 + src/ChangeLog | 6 ++ src/readelf.c | 18 ++++- tests/ChangeLog | 11 +++ tests/Makefile.am | 4 +- tests/libtestfile_multi_shared.so.bz2 | Bin 0 -> 2547 bytes tests/run-readelf-dwz-multi.sh | 156 +++++++++++++++++++++++++++++++++ tests/testfile_multi.dwz.bz2 | Bin 0 -> 512 bytes tests/testfile_multi_main.bz2 | Bin 0 -> 3086 bytes 21 files changed, 403 insertions(+), 14 deletions(-) create mode 100755 tests/libtestfile_multi_shared.so.bz2 create mode 100755 tests/run-readelf-dwz-multi.sh create mode 100644 tests/testfile_multi.dwz.bz2 create mode 100755 tests/testfile_multi_main.bz2 diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 2bafdc2..572252d 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,30 @@ +2012-06-27 Mark Wielaard <[email protected]> + + * dwarf.h: Add DW_FORM_GNU_ref_alt and DW_FORM_GNU_strp_alt. + * dwarf_begin.c (dwarf_begin): Add INTDEF. + * dwarf_begin_elf.c (__check_build_id): New internal_function. + (try_debugaltlink): New function. + (open_debugaltlink): Likewise. + (check_section): Try open_debugaltlink for .gnu_debugaltlink. + * dwarf_end.c (dwarf_end): Free the alternative Dwarf descriptor if + necessary. + * dwarf_error.c (errmsgs): Add DWARF_E_NO_ALT_DEBUGLINK. + * dwarf_formref.c (__libdw_formref): Using DW_FORM_GNU_ref_alt + is an error here. + * dwarf_formref_die.c (dwarf_formref_die): Handle DW_FORM_GNU_ref_alt. + * dwarf_formstring.c (dwarf_formstring): Handle DW_FORM_GNU_strp_alt. + * dwarf_formudata.c (__libdw_formptr): Adjust __libdw_read_offset + calls. + * dwarf_getpubnames.c (get_offsets): Adjust __libdw_read_offset call. + * libdwP.h: Add DWARF_E_NO_ALT_DEBUGLINK. + (struct Dwarf): Add alt_dwarf and free_alt fields. + (__libdw_read_offset): Add dbg_ret argument, use to check with + __libdw_offset_in_section. + (__check_build_id): New function declaration. + (dwarf_begin): Define as INTDECL. + * libdw_form.c (__libdw_form_val_len): Handle DW_FORM_GNU_ref_alt + and DW_FORM_GNU_strp_alt. + 2012-07-19 Mark Wielaard <[email protected]> * dwarf.h: Add DW_OP_GNU_parameter_ref. diff --git a/libdw/dwarf.h b/libdw/dwarf.h index f41d296..81bc7fe 100644 --- a/libdw/dwarf.h +++ b/libdw/dwarf.h @@ -299,7 +299,10 @@ enum DW_FORM_sec_offset = 0x17, DW_FORM_exprloc = 0x18, DW_FORM_flag_present = 0x19, - DW_FORM_ref_sig8 = 0x20 + DW_FORM_ref_sig8 = 0x20, + + DW_FORM_GNU_ref_alt = 0x1f20, /* offset in alternate .debuginfo. */ + DW_FORM_GNU_strp_alt = 0x1f21 /* offset in alternate .debug_str. */ }; diff --git a/libdw/dwarf_begin.c b/libdw/dwarf_begin.c index 1f3fc3b..9f3050f 100644 --- a/libdw/dwarf_begin.c +++ b/libdw/dwarf_begin.c @@ -98,3 +98,4 @@ dwarf_begin (fd, cmd) return result; } +INTDEF(dwarf_begin) diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index 3e01800..fd95770 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -31,12 +31,17 @@ # include <config.h> #endif +#include <assert.h> +#include <inttypes.h> #include <stdbool.h> #include <stddef.h> #include <stdlib.h> +#include <stdio.h> #include <string.h> #include <unistd.h> +#include <sys/types.h> #include <sys/stat.h> +#include <fcntl.h> #include "libdwP.h" @@ -66,6 +71,110 @@ static const char dwarf_scnnames[IDX_last][17] = }; #define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0])) +internal_function int +__check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len) +{ + if (dw == NULL) + return -1; + + Elf *elf = dw->elf; + Elf_Scn *scn = elf_nextscn (elf, NULL); + if (scn == NULL) + return -1; + + do + { + GElf_Shdr shdr_mem; + GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); + if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE) + { + size_t pos = 0; + GElf_Nhdr nhdr; + size_t name_pos; + size_t desc_pos; + Elf_Data *data = elf_getdata (scn, NULL); + while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos, + &desc_pos)) > 0) + if (nhdr.n_type == NT_GNU_BUILD_ID + && nhdr.n_namesz == sizeof "GNU" + && ! memcmp (data->d_buf + name_pos, "GNU", sizeof "GNU")) + return (nhdr.n_descsz == id_len + && ! memcmp (data->d_buf + desc_pos, + build_id, id_len)) ? 0 : 1; + } + } + while ((scn = elf_nextscn (elf, scn)) != NULL); + + return -1; +} + +/* Try to open an debug alt link by name, checking build_id. + Marks free_alt on success, return NULL on failure. */ +static Dwarf * +try_debugaltlink (Dwarf *result, const char *try_name, + const uint8_t *build_id, const size_t id_len) +{ + int fd = open (try_name, O_RDONLY); + if (fd > 0) + { + result->alt_dwarf = INTUSE (dwarf_begin) (fd, DWARF_C_READ); + if (result->alt_dwarf != NULL) + { + Elf *elf = result->alt_dwarf->elf; + if (__check_build_id (result->alt_dwarf, build_id, id_len) == 0 + && elf_cntl (elf, ELF_C_FDREAD) == 0) + { + close (fd); + result->free_alt = 1; + return result; + } + INTUSE (dwarf_end) (result->alt_dwarf); + } + close (fd); + } + return NULL; +} + +/* For dwz multifile support, ignore if it looks wrong. */ +static Dwarf * +open_debugaltlink (Dwarf *result, const char *alt_name, + const uint8_t *build_id, const size_t id_len) +{ + /* First try the name itself, it is either an absolute path or + a relative one. Sadly we don't know relative from where at + this point. */ + if (try_debugaltlink (result, alt_name, build_id, id_len) != NULL) + return result; + + /* Lets try based on the build-id. This is somewhat distro specific, + we are following the Fedora implementation described at + https://fedoraproject.org/wiki/Releases/FeatureBuildId#Find_files_by_build_ID + */ +#define DEBUG_PREFIX "/usr/lib/debug/.build-id/" +#define PREFIX_LEN sizeof (DEBUG_PREFIX) + char id_name[PREFIX_LEN + 1 + id_len * 2 + sizeof ".debug" - 1]; + strcpy (id_name, DEBUG_PREFIX); + int n = snprintf (&id_name[PREFIX_LEN - 1], + 4, "%02" PRIx8 "/", (uint8_t) build_id[0]); + assert (n == 3); + for (size_t i = 1; i < id_len; ++i) + { + n = snprintf (&id_name[PREFIX_LEN - 1 + 3 + (i - 1) * 2], + 3, "%02" PRIx8, (uint8_t) build_id[i]); + assert (n == 2); + } + strcpy (&id_name[PREFIX_LEN - 1 + 3 + (id_len - 1) * 2], + ".debug"); + + if (try_debugaltlink (result, id_name, build_id, id_len)) + return result; + + /* Everything failed, mark this Dwarf as not having an alternate, + but don't fail the load. The user may want to set it by hand + before usage. */ + result->alt_dwarf = NULL; + return result; +} static Dwarf * check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp) @@ -110,6 +219,20 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp) return NULL; } + /* For dwz multifile support, ignore if it looks wrong. */ + if (strcmp (scnname, ".gnu_debugaltlink") == 0) + { + Elf_Data *data = elf_getdata (scn, NULL); + if (data != NULL && data->d_size != 0) + { + const char *alt_name = data->d_buf; + const void *build_id = memchr (data->d_buf, '\0', data->d_size); + const int id_len = data->d_size - (build_id - data->d_buf + 1); + if (alt_name && build_id && id_len > 0) + return open_debugaltlink (result, alt_name, build_id + 1, id_len); + } + } + /* Recognize the various sections. Most names start with .debug_. */ size_t cnt; diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c index b77988f..e65314a 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -111,6 +111,10 @@ dwarf_end (dwarf) if (dwarf->free_elf) elf_end (dwarf->elf); + /* Free the alternative Dwarf descriptor if necessary. */ + if (dwarf->free_alt) + INTUSE (dwarf_end) (dwarf->alt_dwarf); + /* Free the context descriptor. */ free (dwarf); } diff --git a/libdw/dwarf_error.c b/libdw/dwarf_error.c index 89047dc..2292914 100644 --- a/libdw/dwarf_error.c +++ b/libdw/dwarf_error.c @@ -91,6 +91,7 @@ static const char *errmsgs[] = [DWARF_E_INVALID_OFFSET] = N_("invalid offset"), [DWARF_E_NO_DEBUG_RANGES] = N_(".debug_ranges section missing"), [DWARF_E_INVALID_CFI] = N_("invalid CFI section"), + [DWARF_E_NO_ALT_DEBUGLINK] = N_("no alternative debug link found"), }; #define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0])) diff --git a/libdw/dwarf_formref.c b/libdw/dwarf_formref.c index a2554e9..86da7ea 100644 --- a/libdw/dwarf_formref.c +++ b/libdw/dwarf_formref.c @@ -72,6 +72,8 @@ __libdw_formref (attr, return_offset) case DW_FORM_ref_addr: case DW_FORM_ref_sig8: + case DW_FORM_GNU_ref_alt: + /* These aren't handled by dwarf_formref, only by dwarf_formref_die. */ __libdw_seterrno (DWARF_E_INVALID_REFERENCE); return -1; diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c index 342f6b9..f070127 100644 --- a/libdw/dwarf_formref_die.c +++ b/libdw/dwarf_formref_die.c @@ -46,7 +46,7 @@ dwarf_formref_die (attr, result) struct Dwarf_CU *cu = attr->cu; Dwarf_Off offset; - if (attr->form == DW_FORM_ref_addr) + if (attr->form == DW_FORM_ref_addr || attr->form == DW_FORM_GNU_ref_alt) { /* This has an absolute offset. */ @@ -54,11 +54,20 @@ dwarf_formref_die (attr, result) ? cu->address_size : cu->offset_size); - if (__libdw_read_offset (cu->dbg, IDX_debug_info, attr->valp, + Dwarf *dbg_ret = (attr->form == DW_FORM_GNU_ref_alt + ? cu->dbg->alt_dwarf : cu->dbg); + + if (dbg_ret == NULL) + { + __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK); + return NULL; + } + + if (__libdw_read_offset (cu->dbg, dbg_ret, IDX_debug_info, attr->valp, ref_size, &offset, IDX_debug_info, 0)) return NULL; - return INTUSE(dwarf_offdie) (cu->dbg, offset, result); + return INTUSE(dwarf_offdie) (dbg_ret, offset, result); } Elf_Data *data; diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c index fe2183a..c66454e 100644 --- a/libdw/dwarf_formstring.c +++ b/libdw/dwarf_formstring.c @@ -49,8 +49,17 @@ dwarf_formstring (attrp) return (const char *) attrp->valp; Dwarf *dbg = attrp->cu->dbg; + Dwarf *dbg_ret = attrp->form == DW_FORM_GNU_strp_alt ? dbg->alt_dwarf : dbg; - if (unlikely (attrp->form != DW_FORM_strp) + if (unlikely (dbg_ret == NULL)) + { + __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK); + return NULL; + } + + + if (unlikely (attrp->form != DW_FORM_strp + && attrp->form != DW_FORM_GNU_strp_alt) || dbg->sectiondata[IDX_debug_str] == NULL) { __libdw_seterrno (DWARF_E_NO_STRING); @@ -58,10 +67,10 @@ dwarf_formstring (attrp) } uint64_t off; - if (__libdw_read_offset (dbg, cu_sec_idx (attrp->cu), attrp->valp, + if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (attrp->cu), attrp->valp, attrp->cu->offset_size, &off, IDX_debug_str, 1)) return NULL; - return (const char *) dbg->sectiondata[IDX_debug_str]->d_buf + off; + return (const char *) dbg_ret->sectiondata[IDX_debug_str]->d_buf + off; } INTDEF(dwarf_formstring) diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c index f08e0d8..41b09e1 100644 --- a/libdw/dwarf_formudata.c +++ b/libdw/dwarf_formudata.c @@ -52,7 +52,8 @@ __libdw_formptr (Dwarf_Attribute *attr, int sec_index, Dwarf_Word offset; if (attr->form == DW_FORM_sec_offset) { - if (__libdw_read_offset (attr->cu->dbg, cu_sec_idx (attr->cu), attr->valp, + if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg, + cu_sec_idx (attr->cu), attr->valp, attr->cu->offset_size, &offset, sec_index, 0)) return NULL; } @@ -63,7 +64,8 @@ __libdw_formptr (Dwarf_Attribute *attr, int sec_index, { case DW_FORM_data4: case DW_FORM_data8: - if (__libdw_read_offset (attr->cu->dbg, cu_sec_idx (attr->cu), + if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg, + cu_sec_idx (attr->cu), attr->valp, attr->form == DW_FORM_data4 ? 4 : 8, &offset, sec_index, 0)) diff --git a/libdw/dwarf_getpubnames.c b/libdw/dwarf_getpubnames.c index 4ea3889..12728a3 100644 --- a/libdw/dwarf_getpubnames.c +++ b/libdw/dwarf_getpubnames.c @@ -102,7 +102,8 @@ get_offsets (Dwarf *dbg) } /* Get the CU offset. */ - if (__libdw_read_offset (dbg, IDX_debug_pubnames, readp + 2, len_bytes, + if (__libdw_read_offset (dbg, dbg, IDX_debug_pubnames, + readp + 2, len_bytes, &mem[cnt].cu_offset, IDX_debug_info, 3)) /* Error has been already set in reader. */ goto err_return; diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 77e1b31..da82e5d 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -116,6 +116,7 @@ enum DWARF_E_INVALID_OFFSET, DWARF_E_NO_DEBUG_RANGES, DWARF_E_INVALID_CFI, + DWARF_E_NO_ALT_DEBUGLINK }; @@ -127,6 +128,9 @@ struct Dwarf /* The underlying ELF file. */ Elf *elf; + /* dwz alternate DWARF file. */ + Dwarf *alt_dwarf; + /* The section data. */ Elf_Data *sectiondata[IDX_last]; @@ -141,6 +145,9 @@ struct Dwarf /* If true, we allocated the ELF descriptor ourselves. */ bool free_elf; + /* If true, we allocated the Dwarf descriptor for alt_dwarf ourselves. */ + bool free_alt; + /* Information for traversing the .debug_pubnames section. This is an array and separately allocated with malloc. */ struct pubnames_s @@ -580,13 +587,13 @@ __libdw_read_offset_inc (Dwarf *dbg, } static inline int -__libdw_read_offset (Dwarf *dbg, +__libdw_read_offset (Dwarf *dbg, Dwarf *dbg_ret, int sec_index, const unsigned char *addr, int width, Dwarf_Off *ret, int sec_ret, size_t size) { READ_AND_RELOCATE (__libdw_relocate_offset, (*ret)); - return __libdw_offset_in_section (dbg, sec_ret, *ret, size); + return __libdw_offset_in_section (dbg_ret, sec_ret, *ret, size); } static inline size_t @@ -617,12 +624,19 @@ unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index, Dwarf_Off *offsetp) internal_function; +/* Checks that the build_id of the underlying Elf matches the expected. + Returns zero on match, -1 on error or no build_id found or 1 when + build_id doesn't match. */ +int __check_build_id (Dwarf *dw, const uint8_t *build_id, const size_t id_len) + internal_function; + /* Aliases to avoid PLTs. */ INTDECL (dwarf_aggregate_size) INTDECL (dwarf_attr) INTDECL (dwarf_attr_integrate) +INTDECL (dwarf_begin) INTDECL (dwarf_begin_elf) INTDECL (dwarf_child) INTDECL (dwarf_dieoffset) diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c index 2ff8868..c476a6e 100644 --- a/libdw/libdw_form.c +++ b/libdw/libdw_form.c @@ -58,6 +58,8 @@ __libdw_form_val_len (Dwarf *dbg, struct Dwarf_CU *cu, unsigned int form, case DW_FORM_strp: case DW_FORM_sec_offset: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: result = cu->offset_size; break; diff --git a/src/ChangeLog b/src/ChangeLog index aa7e2a5..52e3704 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2012-06-27 Mark Wielaard <[email protected]> + + * readelf.c (dwarf_form_string): Handle DW_FORM_GNU_ref_alt and + DW_FORM_GNU_strp_alt. + (attr_callback): Likewise. + 2012-07-29 Mark Wielaard <[email protected]> * readelf.c (dwarf_lang_string): Use DW_LANG_ObjC, not DW_LANG_Objc. diff --git a/src/readelf.c b/src/readelf.c index 3a27f8f..644e0f7 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -3651,6 +3651,20 @@ dwarf_form_string (unsigned int form) if (likely (form < nknown_forms)) result = known_forms[form]; + else + { + /* GNU extensions use vendor numbers. */ + switch (form) + { + case DW_FORM_GNU_ref_alt: + result = "GNU_ref_alt"; + break; + + case DW_FORM_GNU_strp_alt: + result = "GNU_strp_alt"; + break; + } + } if (unlikely (result == NULL)) { @@ -5593,6 +5607,7 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_FORM_indirect: case DW_FORM_strp: case DW_FORM_string: + case DW_FORM_GNU_strp_alt: if (cbargs->silent) break; const char *str = dwarf_formstring (attrp); @@ -5608,7 +5623,8 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) case DW_FORM_ref8: case DW_FORM_ref4: case DW_FORM_ref2: - case DW_FORM_ref1:; + case DW_FORM_ref1: + case DW_FORM_GNU_ref_alt: if (cbargs->silent) break; Dwarf_Die ref; diff --git a/tests/ChangeLog b/tests/ChangeLog index 6133048..a5a5e12 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2012-06-27 Mark Wielaard <[email protected]> + + * Makefile.am (TESTS): Add run-readelf-dwz-multi.sh. + (EXTRA_DIST): Add run-readelf-dwz-multi.sh, + libtestfile_multi_shared.so.bz2, testfile_multi.dwz.bz2 and + testfile_multi_main.bz2. + * run-readelf-dwz-multi.sh: New test. + * libtestfile_multi_shared.so.bz2: New testfile. + * testfile_multi.dwz.bz2: New testifle. + * testfile_multi_main.bz2: New testifle. + 2012-07-19 Mark Wielaard <[email protected]> * Makefile.am (check_PROGRAMS): Add test-elf_cntl_gelf_getshdr. diff --git a/tests/Makefile.am b/tests/Makefile.am index a8b0f16..3e6dc51 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -72,7 +72,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-find-prologues.sh run-allregs.sh \ run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \ run-readelf-test4.sh run-readelf-twofiles.sh \ - run-readelf-macro.sh \ + run-readelf-macro.sh run-readelf-dwz-multi.sh \ run-native-test.sh run-bug1-test.sh \ dwfl-bug-addr-overflow run-addrname-test.sh \ dwfl-bug-fd-leak dwfl-bug-report \ @@ -142,6 +142,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile46.bz2 testfile47.bz2 testfile48.bz2 testfile48.debug.bz2 \ testfile49.bz2 testfile50.bz2 testfile51.bz2 \ run-readelf-macro.sh testfilemacro.bz2 \ + run-readelf-dwz-multi.sh libtestfile_multi_shared.so.bz2 \ + testfile_multi.dwz.bz2 testfile_multi_main.bz2 \ run-prelink-addr-test.sh \ testfile52-32.so.bz2 testfile52-32.so.debug.bz2 \ testfile52-32.prelink.so.bz2 testfile52-32.noshdrs.so.bz2 \ diff --git a/tests/libtestfile_multi_shared.so.bz2 b/tests/libtestfile_multi_shared.so.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..e9eb6a70f158fae329593180807df78be30a7621 GIT binary patch literal 2547 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 JNC(xJECB9{je`IH literal 0 HcmV?d00001 diff --git a/tests/run-readelf-dwz-multi.sh b/tests/run-readelf-dwz-multi.sh new file mode 100755 index 0000000..42e6aa4 --- /dev/null +++ b/tests/run-readelf-dwz-multi.sh @@ -0,0 +1,156 @@ +#! /bin/sh +# Copyright (C) 2012 Red Hat, Inc. +# This file is part of elfutils. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +. $srcdir/test-subr.sh + +# common.h +# +# #include <stdio.h> +# +# struct foobar +# { +# int foo; +# struct foobar *bar; +# }; +# +# extern int call_foo(struct foobar *foobar_struct_ptr); + +# main.c +# +# #include "common.h" +# +# int main(int argc, char ** argv) +# { +# struct foobar b; +# b.foo = 42; +# b.bar = &b; +# +# return call_foo(b.bar); +# } + +# shared.c +# +# #include "common.h" +# +# int call_foo(struct foobar *fb) +# { +# return fb->bar->foo - 42; +# } + +# gcc -fPIC -g -c -Wall shared.c +# gcc -shared -o libtestfile_multi_shared.so shared.o +# gcc -g -o testfile_multi_main -L. -ltestfile_multi_shared main.c -Wl,-rpath,. +# dwz -m testfile_multi.dwz testfile_multi_main libtestfile_multi_shared.so + +testfiles libtestfile_multi_shared.so testfile_multi_main testfile_multi.dwz + +testrun_compare ../src/readelf --debug-dump=info testfile_multi_main <<\EOF + +DWARF section [28] '.debug_info' at offset 0x1078: + [Offset] + Compilation unit at offset 0: + Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 + [ b] compile_unit + producer (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -mtune=generic -march=x86-64 -g" + language (data1) ISO C89 (1) + name (strp) "main.c" + comp_dir (GNU_strp_alt) "/home/mark/src/tests/dwz" + low_pc (addr) 0x00000000004006ac <main> + high_pc (udata) 44 + stmt_list (sec_offset) 0 + [ 26] imported_unit + import (GNU_ref_alt) [ b] + [ 2b] pointer_type + byte_size (data1) 8 + type (GNU_ref_alt) [ 53] + [ 31] subprogram + external (flag_present) + name (strp) "main" + decl_file (data1) 1 + decl_line (data1) 3 + prototyped (flag_present) + type (GNU_ref_alt) [ 3e] + low_pc (addr) 0x00000000004006ac <main> + high_pc (udata) 44 + frame_base (exprloc) + [ 0] call_frame_cfa + GNU_all_tail_call_sites (flag_present) + sibling (ref_udata) [ 6e] + [ 48] formal_parameter + name (strp) "argc" + decl_file (data1) 1 + decl_line (data1) 3 + type (GNU_ref_alt) [ 3e] + location (exprloc) + [ 0] fbreg -36 + [ 56] formal_parameter + name (strp) "argv" + decl_file (data1) 1 + decl_line (data1) 3 + type (ref_udata) [ 6e] + location (exprloc) + [ 0] fbreg -48 + [ 61] variable + name (string) "b" + decl_file (data1) 1 + decl_line (data1) 5 + type (GNU_ref_alt) [ 5a] + location (exprloc) + [ 0] fbreg -32 + [ 6e] pointer_type + byte_size (data1) 8 + type (ref_udata) [ 2b] +EOF + +testrun_compare ../src/readelf --debug-dump=info libtestfile_multi_shared.so <<\EOF + +DWARF section [25] '.debug_info' at offset 0x106c: + [Offset] + Compilation unit at offset 0: + Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 + [ b] compile_unit + producer (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -fpreprocessed -mtune=generic -march=x86-64 -g -fPIC" + language (data1) ISO C89 (1) + name (strp) "shared.c" + comp_dir (GNU_strp_alt) "/home/mark/src/tests/dwz" + low_pc (addr) +0x0000000000000670 <call_foo> + high_pc (udata) 23 + stmt_list (sec_offset) 0 + [ 26] imported_unit + import (GNU_ref_alt) [ b] + [ 2b] subprogram + external (flag_present) + name (strp) "call_foo" + decl_file (data1) 1 + decl_line (data1) 3 + prototyped (flag_present) + type (GNU_ref_alt) [ 3e] + low_pc (addr) +0x0000000000000670 <call_foo> + high_pc (udata) 23 + frame_base (exprloc) + [ 0] call_frame_cfa + GNU_all_call_sites (flag_present) + [ 41] formal_parameter + name (string) "fb" + decl_file (data1) 1 + decl_line (data1) 3 + type (GNU_ref_alt) [ 76] + location (exprloc) + [ 0] fbreg -24 +EOF + +exit 0 diff --git a/tests/testfile_multi.dwz.bz2 b/tests/testfile_multi.dwz.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..1f52fb69dbec5234c45d66cef98af3c7f8646bae GIT binary patch literal 512 zcmV+b0{{I&T4*^jL0KkKSxEywv;YBCfB*mQ-YZ5U!(Usaix9u>|M0+oBmh7FAOJuR z0Ra#|0{}1qj5a7iG$hpVFq&vjQJPOv6F?dO0ibBadP6~ppww!fNMbUcnwTTh!J-BP zWXQ?15s{_{G|_-1H71iyBh=BL(?AbX)M>Q<Xa+z400099uB9x7-cEyLye7G)+g-*j z5Cg?LftI(dTjP;Zkr2+*K!z2bvu2v|>vw7?P{A$)wBMyw%*JvWx(L$*3IsDXl+k2$ zKwCo-rl5-wI1a?wC@Z0*G#tZDi97M>@=wPl8<l#QP<%*KxNO?3g&({Da1T$`RUj-( z=tL!HQB{`wBZIXBC{&$M6<~1ni4&M-$0V;FNa4`9NlOZ;0LOfSdDtcoOa$r77<e2I zI!G&);RVnP$>B6aMRW|x3o^u9goHG@HeX{L&4AdTj=7MWH_i5m8>bNi@Teb1K5!T( z<9>3~3cYmk`Yp<r2m(A9lX#KqS?&W=Vi-8Dy1J7vIG<!fUt;%$2m}%*h2*A#(imD0 zZQ&r*pJZksUX22;Oa!vBVS}qAH~dNn#yJLInel=ePuk?<MVbl(2I}f_qnzOtWH#U^ zDFiJJ<tlE-p$#e`(+-N(=nHX&+N$fwa3|`kIe#yICOp|PoLRHy{}*yaI8cyD13$FD C)Y{Yl literal 0 HcmV?d00001 diff --git a/tests/testfile_multi_main.bz2 b/tests/testfile_multi_main.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..bc6ca5fd21a277cc6e1f87d96177b3bfcd57a0a3 GIT binary patch literal 3086 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 literal 0 HcmV?d00001 -- 1.7.7.6
_______________________________________________ elfutils-devel mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/elfutils-devel
