diff --git a/SOURCES/elfutils-0.171-new-notes-hack.patch b/SOURCES/elfutils-0.171-new-notes-hack.patch new file mode 100644 index 00000000..f14562ee --- /dev/null +++ b/SOURCES/elfutils-0.171-new-notes-hack.patch @@ -0,0 +1,30 @@ +diff --git a/src/elflint.c b/src/elflint.c +index df1b3a0..f4d82d9 100644 +--- a/src/elflint.c ++++ b/src/elflint.c +@@ -4329,6 +4329,8 @@ section [%2d] '%s': unknown core file note type %" PRIu32 + case NT_GNU_HWCAP: + case NT_GNU_BUILD_ID: + case NT_GNU_GOLD_VERSION: ++ case NT_GNU_PROPERTY_TYPE_0: ++ case 256: + break; + + case 0: +diff --git a/src/elflint.c b/src/elflint.c +index 0a26d97..1cbf570 100644 +--- a/src/elflint.c ++++ b/src/elflint.c +@@ -3906,10 +3906,11 @@ section [%2zu] '%s': size not multiple of entry size\n"), + cnt, section_name (ebl, cnt), + (int) shdr->sh_type); + ++#define SHF_GNU_BUILD_NOTE (1 << 20) + #define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \ + | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \ + | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS \ +- | SHF_COMPRESSED) ++ | SHF_COMPRESSED | SHF_GNU_BUILD_NOTE) + if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS) + { + GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS; diff --git a/SOURCES/elfutils-0.172-robustify.patch b/SOURCES/elfutils-0.172-robustify.patch new file mode 100644 index 00000000..da025273 --- /dev/null +++ b/SOURCES/elfutils-0.172-robustify.patch @@ -0,0 +1,400 @@ +Upstream commits since 0.172: + + b4dced3 readelf: While printing .debug_loc make sure that next_off doesn't overflow. + bb11e36 libdw: Make __libdw_dieabbrev more robust on failure. + 3647b5b readelf: Make sure print_form_data always consumes DW_FORM_strx[1234] data. + eaaf908 readelf: Check there are at least 4 bytes available for DWARF_FORM_block4. + 0d93f49 libdw, readelf: Don't handle DW_FORM_data16 as expression block/location. + 9495c26 libdw: aggregate_size check NULL result from get_type. + e636112 libdw: dwarf_peel_type break long chains/cycles. + 5956b8a libdw: Break dwarf_aggregate_size recursion because of type cycles. + ca0d831 libelf: Don't return unaligned data returned from elf_getdata[_rawchunk]. + +diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c +index 6e50185..75105e4 100644 +--- a/libdw/dwarf_aggregate_size.c ++++ b/libdw/dwarf_aggregate_size.c +@@ -46,13 +46,17 @@ get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem) + return type; + } + ++static int aggregate_size (Dwarf_Die *die, Dwarf_Word *size, ++ Dwarf_Die *type_mem, int depth); ++ + static int + array_size (Dwarf_Die *die, Dwarf_Word *size, +- Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem) ++ Dwarf_Attribute *attr_mem, int depth) + { + Dwarf_Word eltsize; +- if (INTUSE(dwarf_aggregate_size) (get_type (die, attr_mem, type_mem), +- &eltsize) != 0) ++ Dwarf_Die type_mem, aggregate_type_mem; ++ if (aggregate_size (get_type (die, attr_mem, &type_mem), &eltsize, ++ &aggregate_type_mem, depth) != 0) + return -1; + + /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type +@@ -167,21 +171,30 @@ array_size (Dwarf_Die *die, Dwarf_Word *size, + } + + static int +-aggregate_size (Dwarf_Die *die, Dwarf_Word *size, Dwarf_Die *type_mem) ++aggregate_size (Dwarf_Die *die, Dwarf_Word *size, ++ Dwarf_Die *type_mem, int depth) + { + Dwarf_Attribute attr_mem; + ++/* Arrays of arrays of subrange types of arrays... Don't recurse too deep. */ ++#define MAX_DEPTH 256 ++ if (die == NULL || depth++ >= MAX_DEPTH) ++ return -1; ++ + if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL) + return INTUSE(dwarf_formudata) (&attr_mem, size); + + switch (INTUSE(dwarf_tag) (die)) + { + case DW_TAG_subrange_type: +- return aggregate_size (get_type (die, &attr_mem, type_mem), +- size, type_mem); /* Tail call. */ ++ { ++ Dwarf_Die aggregate_type_mem; ++ return aggregate_size (get_type (die, &attr_mem, type_mem), ++ size, &aggregate_type_mem, depth); ++ } + + case DW_TAG_array_type: +- return array_size (die, size, &attr_mem, type_mem); ++ return array_size (die, size, &attr_mem, depth); + + /* Assume references and pointers have pointer size if not given an + explicit DW_AT_byte_size. */ +@@ -204,7 +217,7 @@ dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size) + if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0) + return -1; + +- return aggregate_size (&die_mem, size, &type_mem); ++ return aggregate_size (&die_mem, size, &type_mem, 0); + } + INTDEF (dwarf_aggregate_size) + OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144) +diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c +index 7f294fe..fc59a2a 100644 +--- a/libdw/dwarf_getlocation.c ++++ b/libdw/dwarf_getlocation.c +@@ -174,6 +174,8 @@ check_constant_offset (Dwarf_Attribute *attr, + default: + return 1; + ++ /* Note, we don't regard DW_FORM_data16 as a constant form, ++ even though technically it is according to the standard. */ + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: +@@ -665,7 +667,13 @@ dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen) + if (result != 1) + return result; + +- /* If it has a block form, it's a single location expression. */ ++ /* If it has a block form, it's a single location expression. ++ Except for DW_FORM_data16, which is a 128bit constant. */ ++ if (attr->form == DW_FORM_data16) ++ { ++ __libdw_seterrno (DWARF_E_NO_BLOCK); ++ return -1; ++ } + Dwarf_Block block; + if (INTUSE(dwarf_formblock) (attr, &block) != 0) + return -1; +@@ -863,9 +871,11 @@ dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address, + if (llbufs == NULL) + maxlocs = SIZE_MAX; + +- /* If it has a block form, it's a single location expression. */ ++ /* If it has a block form, it's a single location expression. ++ Except for DW_FORM_data16, which is a 128bit constant. */ + Dwarf_Block block; +- if (INTUSE(dwarf_formblock) (attr, &block) == 0) ++ if (attr->form != DW_FORM_data16 ++ && INTUSE(dwarf_formblock) (attr, &block) == 0) + { + if (maxlocs == 0) + return 0; +@@ -876,11 +886,14 @@ dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address, + return listlens[0] == 0 ? 0 : 1; + } + +- int error = INTUSE(dwarf_errno) (); +- if (unlikely (error != DWARF_E_NO_BLOCK)) ++ if (attr->form != DW_FORM_data16) + { +- __libdw_seterrno (error); +- return -1; ++ int error = INTUSE(dwarf_errno) (); ++ if (unlikely (error != DWARF_E_NO_BLOCK)) ++ { ++ __libdw_seterrno (error); ++ return -1; ++ } + } + + int result = check_constant_offset (attr, &llbufs[0], &listlens[0]); +@@ -938,9 +951,11 @@ dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep, + + if (offset == 0) + { +- /* If it has a block form, it's a single location expression. */ ++ /* If it has a block form, it's a single location expression. ++ Except for DW_FORM_data16, which is a 128bit constant. */ + Dwarf_Block block; +- if (INTUSE(dwarf_formblock) (attr, &block) == 0) ++ if (attr->form != DW_FORM_data16 ++ && INTUSE(dwarf_formblock) (attr, &block) == 0) + { + if (getlocation (attr->cu, &block, expr, exprlen, + cu_sec_idx (attr->cu)) != 0) +@@ -952,11 +967,14 @@ dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep, + return 1; + } + +- int error = INTUSE(dwarf_errno) (); +- if (unlikely (error != DWARF_E_NO_BLOCK)) ++ if (attr->form != DW_FORM_data16) + { +- __libdw_seterrno (error); +- return -1; ++ int error = INTUSE(dwarf_errno) (); ++ if (unlikely (error != DWARF_E_NO_BLOCK)) ++ { ++ __libdw_seterrno (error); ++ return -1; ++ } + } + + int result = check_constant_offset (attr, expr, exprlen); +diff --git a/libdw/dwarf_peel_type.c b/libdw/dwarf_peel_type.c +index 6bbfd42..59fc6f1 100644 +--- a/libdw/dwarf_peel_type.c ++++ b/libdw/dwarf_peel_type.c +@@ -46,14 +46,19 @@ dwarf_peel_type (Dwarf_Die *die, Dwarf_Die *result) + + *result = *die; + tag = INTUSE (dwarf_tag) (result); +- while (tag == DW_TAG_typedef +- || tag == DW_TAG_const_type +- || tag == DW_TAG_volatile_type +- || tag == DW_TAG_restrict_type +- || tag == DW_TAG_atomic_type +- || tag == DW_TAG_immutable_type +- || tag == DW_TAG_packed_type +- || tag == DW_TAG_shared_type) ++ ++/* Stack 8 of all these modifiers, after that it gets silly. */ ++#define MAX_DEPTH (8 * 8) ++ int max_depth = MAX_DEPTH; ++ while ((tag == DW_TAG_typedef ++ || tag == DW_TAG_const_type ++ || tag == DW_TAG_volatile_type ++ || tag == DW_TAG_restrict_type ++ || tag == DW_TAG_atomic_type ++ || tag == DW_TAG_immutable_type ++ || tag == DW_TAG_packed_type ++ || tag == DW_TAG_shared_type) ++ && max_depth-- > 0) + { + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = INTUSE (dwarf_attr_integrate) (result, DW_AT_type, +@@ -67,7 +72,7 @@ dwarf_peel_type (Dwarf_Die *die, Dwarf_Die *result) + tag = INTUSE (dwarf_tag) (result); + } + +- if (tag == DW_TAG_invalid) ++ if (tag == DW_TAG_invalid || max_depth <= 0) + return -1; + + return 0; +diff --git a/libdw/libdwP.h b/libdw/libdwP.h +index 3d8e145..eebb7d1 100644 +--- a/libdw/libdwP.h ++++ b/libdw/libdwP.h +@@ -653,8 +653,9 @@ __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp) + /* Get the abbreviation code. */ + unsigned int code; + const unsigned char *addr = die->addr; +- if (die->cu == NULL || addr >= (const unsigned char *) die->cu->endp) +- return DWARF_END_ABBREV; ++ if (unlikely (die->cu == NULL ++ || addr >= (const unsigned char *) die->cu->endp)) ++ return die->abbrev = DWARF_END_ABBREV; + get_uleb128 (code, addr, die->cu->endp); + if (readp != NULL) + *readp = addr; +diff --git a/libdw/memory-access.h b/libdw/memory-access.h +index 22918cb..a39ad6d 100644 +--- a/libdw/memory-access.h ++++ b/libdw/memory-access.h +@@ -362,6 +362,11 @@ read_3ubyte_unaligned (Dwarf *dbg, const unsigned char *p) + } + + ++#define read_3ubyte_unaligned_inc(Dbg, Addr) \ ++ ({ uint32_t t_ = read_2ubyte_unaligned (Dbg, Addr); \ ++ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 3); \ ++ t_; }) ++ + #define read_addr_unaligned_inc(Nbytes, Dbg, Addr) \ + (assert ((Nbytes) == 4 || (Nbytes) == 8), \ + ((Nbytes) == 4 ? read_4ubyte_unaligned_inc (Dbg, Addr) \ +diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c +index 97c503b..278dfa8 100644 +--- a/libelf/elf_getdata.c ++++ b/libelf/elf_getdata.c +@@ -76,7 +76,6 @@ static const Elf_Type shtype_map[EV_NUM - 1][TYPEIDX (SHT_HISUNW) + 1] = + } + }; + +-#if !ALLOW_UNALIGNED + /* Associate libelf types with their internal alignment requirements. */ + const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] = + { +@@ -115,7 +114,6 @@ const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] + } + # undef TYPE_ALIGNS + }; +-#endif + + + Elf_Type +@@ -173,8 +171,7 @@ convert_data (Elf_Scn *scn, int version __attribute__ ((unused)), int eclass, + /* Make sure the source is correctly aligned for the conversion + function to directly access the data elements. */ + char *rawdata_source; +- if (ALLOW_UNALIGNED || +- ((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) ++ if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0) + rawdata_source = scn->rawdata_base; + else + { +diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c +index 31b2fe7..d0c0b75 100644 +--- a/libelf/elf_getdata_rawchunk.c ++++ b/libelf/elf_getdata_rawchunk.c +@@ -80,8 +80,7 @@ elf_getdata_rawchunk (Elf *elf, off_t offset, size_t size, Elf_Type type) + { + /* If the file is mmap'ed we can use it directly, if aligned for type. */ + char *rawdata = elf->map_address + elf->start_offset + offset; +- if (ALLOW_UNALIGNED || +- ((uintptr_t) rawdata & (align - 1)) == 0) ++ if (((uintptr_t) rawdata & (align - 1)) == 0) + rawchunk = rawdata; + else + { +diff --git a/libelf/libelfP.h b/libelf/libelfP.h +index ca805ac..ed216c8 100644 +--- a/libelf/libelfP.h ++++ b/libelf/libelfP.h +@@ -443,15 +443,11 @@ extern int __libelf_version_initialized attribute_hidden; + # define LIBELF_EV_IDX (__libelf_version - 1) + #endif + +-#if !ALLOW_UNALIGNED + /* Array with alignment requirements of the internal types indexed by ELF + version, binary class, and type. */ + extern const uint_fast8_t __libelf_type_aligns[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden; + # define __libelf_type_align(class, type) \ + (__libelf_type_aligns[LIBELF_EV_IDX][class - 1][type] ?: 1) +-#else +-# define __libelf_type_align(class, type) 1 +-#endif + + /* Given an Elf handle and a section type returns the Elf_Data d_type. + Should not be called when SHF_COMPRESSED is set, the d_type should +diff --git a/src/readelf.c b/src/readelf.c +index f185897..313f940 100644 +--- a/src/readelf.c ++++ b/src/readelf.c +@@ -7403,11 +7403,16 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) + case DW_AT_GNU_call_site_data_value: + case DW_AT_GNU_call_site_target: + case DW_AT_GNU_call_site_target_clobbered: +- putchar ('\n'); +- print_ops (cbargs->dwflmod, cbargs->dbg, +- 12 + level * 2, 12 + level * 2, +- cbargs->version, cbargs->addrsize, cbargs->offset_size, +- attrp->cu, block.length, block.data); ++ if (form != DW_FORM_data16) ++ { ++ putchar ('\n'); ++ print_ops (cbargs->dwflmod, cbargs->dbg, ++ 12 + level * 2, 12 + level * 2, ++ cbargs->version, cbargs->addrsize, cbargs->offset_size, ++ attrp->cu, block.length, block.data); ++ } ++ else ++ print_block (block.length, block.data); + break; + } + break; +@@ -7907,7 +7912,7 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp, + break; + + case DW_FORM_block4: +- if (readendp - readp < 2) ++ if (readendp - readp < 4) + goto invalid_data; + val = read_4ubyte_unaligned_inc (dbg, readp); + if ((size_t) (readendp - readp) < val) +@@ -7994,9 +7999,9 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp, + { + Dwarf_Off idx; + if (offset_len == 8) +- idx = read_8ubyte_unaligned_inc (dbg, strreadp); ++ idx = read_8ubyte_unaligned (dbg, strreadp); + else +- idx = read_4ubyte_unaligned_inc (dbg, strreadp); ++ idx = read_4ubyte_unaligned (dbg, strreadp); + + data = dbg->sectiondata[IDX_debug_str]; + if (data == NULL || idx >= data->d_size +@@ -8013,25 +8018,25 @@ print_form_data (Dwarf *dbg, int form, const unsigned char *readp, + case DW_FORM_strx1: + if (readendp - readp < 1) + goto invalid_data; +- val = *readp; ++ val = *readp++; + goto strx_val; + + case DW_FORM_strx2: + if (readendp - readp < 2) + goto invalid_data; +- val = read_2ubyte_unaligned (dbg, readp); ++ val = read_2ubyte_unaligned_inc (dbg, readp); + goto strx_val; + + case DW_FORM_strx3: + if (readendp - readp < 3) + goto invalid_data; +- val = read_3ubyte_unaligned (dbg, readp); ++ val = read_3ubyte_unaligned_inc (dbg, readp); + goto strx_val; + + case DW_FORM_strx4: + if (readendp - readp < 4) + goto invalid_data; +- val = read_4ubyte_unaligned (dbg, readp); ++ val = read_4ubyte_unaligned_inc (dbg, readp); + goto strx_val; + + default: +@@ -9230,7 +9235,9 @@ print_debug_loc_section (Dwfl_Module *dwflmod, + listptr_idx); + const unsigned char *locp = readp; + const unsigned char *locendp; +- if (next_off == 0) ++ if (next_off == 0 ++ || next_off > (size_t) (endp ++ - (const unsigned char *) data->d_buf)) + locendp = endp; + else + locendp = (const unsigned char *) data->d_buf + next_off; diff --git a/SPECS/elfutils.spec b/SPECS/elfutils.spec index 5c1a31ba..adec855b 100644 --- a/SPECS/elfutils.spec +++ b/SPECS/elfutils.spec @@ -1,7 +1,7 @@ Name: elfutils Summary: A collection of utilities and DSOs to handle ELF files and DWARF data -Version: 0.170 -%global baserelease 4 +Version: 0.172 +%global baserelease 2 URL: http://elfutils.org/ %global source_url ftp://sourceware.org/pub/elfutils/%{version}/ License: GPLv3+ and (GPLv2+ or LGPLv3+) @@ -20,10 +20,8 @@ Release: %{baserelease}%{?dist} Source: %{?source_url}%{name}-%{version}.tar.bz2 # Patches -Patch1: elfutils-0.170-dwarf_aggregate_size.patch -Source1: testfile-sizes3.o.bz2 - -Patch2: elfutils-0.170-x86_64-backtrace-test-override.patch +Patch1: elfutils-0.171-new-notes-hack.patch +Patch2: elfutils-0.172-robustify.patch Requires: elfutils-libelf%{depsuffix} = %{version}-%{release} Requires: elfutils-libs%{depsuffix} = %{version}-%{release} @@ -33,6 +31,8 @@ BuildRequires: bison >= 1.875 BuildRequires: flex >= 2.5.4a BuildRequires: bzip2 BuildRequires: gcc >= 4.4 +# For libstdc++ demangle support +BuildRequires: libstdc++-devel BuildRequires: zlib-devel >= 1.2.2.3 BuildRequires: bzip2-devel @@ -175,13 +175,11 @@ profiling) of processes. %setup -q # Apply patches -%patch1 -p1 -b .aggregate_size -cp %SOURCE1 tests/ - -# This is only necessary for the RHEL brew build host, which seems to -# generate a corrupt core file which we cannot test properly. -%patch2 -p1 -b .x86_64_override +%patch1 -p1 -b .notes_hack +%patch2 -p1 -b .robustify +# In case the above patches added any new test scripts, make sure they +# are executable. find . -name \*.sh ! -perm -0100 -print | xargs chmod +x %build @@ -318,6 +316,32 @@ fi %endif %changelog +* Wed Jun 20 2018 Mark Wielaard - 0.172-2 +- Add elfutils-0.172-robustify.patch. (#1593328) + +* Mon Jun 11 2018 Mark Wielaard - 0.172-1 +- New upstream release. + - No functional changes compared to 0.171. + - Various bug fixes in libdw and eu-readelf dealing with bad DWARF5 + data. Thanks to running the afl fuzzer on eu-readelf and various + testcases. + - eu-readelf -N is ~15% faster. + +* Tue Jun 05 2018 Mark Wielaard - 0.171-1 +- New upstream release. + - DWARF5 and split dwarf, including GNU DebugFission, support. + - readelf: Handle all new DWARF5 sections. + --debug-dump=info+ will show split unit DIEs when found. + --dwarf-skeleton can be used when inspecting a .dwo file. + Recognizes GNU locviews with --debug-dump=loc. + - libdw: New functions dwarf_die_addr_die, dwarf_get_units, + dwarf_getabbrevattr_data and dwarf_cu_info. + libdw will now try to resolve the alt file on first use + when not set yet with dwarf_set_alt. + dwarf_aggregate_size() now works with multi-dimensional arrays. + - libdwfl: Use process_vm_readv when available instead of ptrace. + - backends: Add a RISC-V backend. + * Wed Dec 20 2017 Mark Wielaard - 0.170-4 - Add elfutils-0.170-dwarf_aggregate_size.patch (#1527966).