From e893aab0d12284c8909ebacfca529c0b554abb9c Mon Sep 17 00:00:00 2001 From: Ross Burton Date: Wed, 4 Jul 2018 12:11:08 +0100 Subject: Consolidate error.h inclusion in system.h error.h isn't standard and so isn't part of the musl C library. To easy future porting, consolidate the inclusion of error.h into system.h. https://sourceware.org/bugzilla/show_bug.cgi?id=21008 Signed-off-by: Ross Burton --- src/ChangeLog | 19 +++++++++++++++++++ src/addr2line.c | 1 - src/ar.c | 1 - src/arlib.c | 2 +- src/arlib2.c | 1 - src/elfcmp.c | 3 +-- src/elfcompress.c | 2 +- src/elflint.c | 1 - src/findtextrel.c | 3 +-- src/nm.c | 1 - src/objdump.c | 1 - src/ranlib.c | 1 - src/readelf.c | 1 - src/size.c | 1 - src/stack.c | 1 - src/strings.c | 1 - src/strip.c | 1 - src/unstrip.c | 2 +- 18 files changed, 24 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 6d962bbb..606a5973 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,22 @@ +2018-07-04 Ross Burton + + * addr2line.c: Remove error.h include. + * ar.c: Likewise. + * arlib.c: Likewise and add system.h include. + * arlib2.c: Likewise. + * elfcmp.c: Likewise. + * elfcompress.c: Likewise. + * elflint.c: Likewise. + * findtextrel.c: Likewise. + * nm.c: Likewise. + * objdump.c: Likewise. + * ranlib.c: Likewise. + * readelf.c: Likewise. + * stack.c: Likewise. + * strings.c: Likewise. + * strip.c: Likewise. + * unstrip.c: Likewise. + 2018-06-25 Mark Wielaard * readelf.c (print_decoded_line_section): Use dwarf_next_lines diff --git a/src/addr2line.c b/src/addr2line.c index 5acafa00..b7eb893e 100644 --- a/src/addr2line.c +++ b/src/addr2line.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/src/ar.c b/src/ar.c index 818115bd..6f98f75d 100644 --- a/src/ar.c +++ b/src/ar.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/src/arlib.c b/src/arlib.c index e0839aab..778e0878 100644 --- a/src/arlib.c +++ b/src/arlib.c @@ -21,7 +21,6 @@ #endif #include -#include #include #include #include @@ -31,6 +30,7 @@ #include +#include "system.h" #include "arlib.h" diff --git a/src/arlib2.c b/src/arlib2.c index 553fc57b..11f44e5d 100644 --- a/src/arlib2.c +++ b/src/arlib2.c @@ -20,7 +20,6 @@ # include #endif -#include #include #include #include diff --git a/src/elfcmp.c b/src/elfcmp.c index 50464207..b40df8bf 100644 --- a/src/elfcmp.c +++ b/src/elfcmp.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -36,7 +35,7 @@ #include #include "../libelf/elf-knowledge.h" #include "../libebl/libeblP.h" - +#include "system.h" /* Prototypes of local functions. */ static Elf *open_file (const char *fname, int *fdp, Ebl **eblp); diff --git a/src/elfcompress.c b/src/elfcompress.c index 25378a45..bdb0e3b5 100644 --- a/src/elfcompress.c +++ b/src/elfcompress.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -34,6 +33,7 @@ #include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(dwelf) #include +#include "system.h" #include "libeu.h" #include "printversion.h" diff --git a/src/elflint.c b/src/elflint.c index 0a26d97d..eec799b2 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/src/findtextrel.c b/src/findtextrel.c index 8f1e239a..49731592 100644 --- a/src/findtextrel.c +++ b/src/findtextrel.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,7 @@ #include #include - +#include "system.h" struct segments { diff --git a/src/nm.c b/src/nm.c index 969c6d35..ffe8ca69 100644 --- a/src/nm.c +++ b/src/nm.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/src/objdump.c b/src/objdump.c index 0dd9a6aa..6b365d5c 100644 --- a/src/objdump.c +++ b/src/objdump.c @@ -21,7 +21,6 @@ #endif #include -#include #include #include #include diff --git a/src/ranlib.c b/src/ranlib.c index cc0ee233..b9083484 100644 --- a/src/ranlib.c +++ b/src/ranlib.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/src/readelf.c b/src/readelf.c index faed61a6..7cf0d18a 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/src/size.c b/src/size.c index ad8dbcbb..5ff3f2af 100644 --- a/src/size.c +++ b/src/size.c @@ -21,7 +21,6 @@ #endif #include -#include #include #include #include diff --git a/src/stack.c b/src/stack.c index 52ae3a86..c5f347e1 100644 --- a/src/stack.c +++ b/src/stack.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/src/strings.c b/src/strings.c index 03d0f133..ef40d5ec 100644 --- a/src/strings.c +++ b/src/strings.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/src/strip.c b/src/strip.c index 773ed548..791347c1 100644 --- a/src/strip.c +++ b/src/strip.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include diff --git a/src/unstrip.c b/src/unstrip.c index f368e696..057efef3 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +47,7 @@ #include #include #include +#include "system.h" #include "libdwelf.h" #include "libeu.h" #include "printversion.h" -- cgit v1.2.3 From 3012cda4bafa723c1894f74ab80b2c9ee7aad2d2 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 4 Jul 2018 16:08:05 +0200 Subject: readelf: Don't shadow index function from string.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On some ancient GCC versions (4.4.7 at least) -Wshadow warns about local variables "shadowing" global function definitions. readelf.c: In function ‘print_debug_addr_section’: readelf.c:5265: error: declaration of ‘index’ shadows a global declaration /usr/include/string.h:489: error: shadowed declaration is here This is silly of course, but easy to work around. Signed-off-by: Mark Wielaard --- src/ChangeLog | 6 ++++++ src/readelf.c | 14 +++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 606a5973..e0f1b513 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2018-07-04 Mark Wielaard + + * readelf.c (print_debug_addr_section): Rename index var to uidx. + (attr_callback): Rename index var to word. + (print_debug_str_offsets_section): Rename index var to uidx. + 2018-07-04 Ross Burton * addr2line.c: Remove error.h include. diff --git a/src/readelf.c b/src/readelf.c index 7cf0d18a..7b5707f8 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -5261,14 +5261,14 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)), addresses /= 10; } - unsigned int index = 0; + unsigned int uidx = 0; size_t index_offset = readp - (const unsigned char *) data->d_buf; printf (" Addresses start at offset 0x%zx:\n", index_offset); while (readp <= next_unitp - address_size) { Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg, readp); - printf (" [%*u] ", digits, index++); + printf (" [%*u] ", digits, uidx++); print_dwarf_addr (dwflmod, address_size, addr, addr); printf ("\n"); } @@ -6966,12 +6966,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg) } if (form != DW_FORM_addr ) { - Dwarf_Word index; - if (dwarf_formudata (attrp, &index) != 0) + Dwarf_Word word; + if (dwarf_formudata (attrp, &word) != 0) goto attrval_out; printf (" %*s%-20s (%s) [%" PRIx64 "] ", (int) (level * 2), "", dwarf_attr_name (attr), - dwarf_form_name (form), index); + dwarf_form_name (form), word); } else printf (" %*s%-20s (%s) ", @@ -10255,7 +10255,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)), offsets /= 10; } - unsigned int index = 0; + unsigned int uidx = 0; size_t index_offset = readp - (const unsigned char *) data->d_buf; printf (" Offsets start at 0x%zx:\n", index_offset); while (readp <= next_unitp - offset_size) @@ -10267,7 +10267,7 @@ print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)), offset = read_8ubyte_unaligned_inc (dbg, readp); const char *str = dwarf_getstring (dbg, offset, NULL); printf (" [%*u] [%*" PRIx64 "] \"%s\"\n", - digits, index++, (int) offset_size * 2, offset, str ?: "???"); + digits, uidx++, (int) offset_size * 2, offset, str ?: "???"); } printf ("\n"); -- cgit v1.2.3 From 4d240015c63d7cb702b70f7b17c8535c8223858a Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 21 Jul 2018 16:10:25 +0200 Subject: elfcompress: Swap fchmod and fchown calls on new file. Calling fchmod with a suid bit on a file might silently fail or the suid bit might be slilently cleared by a call to fchown if already set. Swap the calls so that the owner is set first and then set the suid bit. https://bugzilla.redhat.com/show_bug.cgi?id=1607044 Reported-and-tested-by: Igor Gnatenko Signed-off-by: Mark Wielaard --- src/ChangeLog | 4 ++++ src/elfcompress.c | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index e0f1b513..0e9ab301 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2018-07-21 Mark Wielaard + + * elfcompress.c (process_file): Swap fchmod and fchown calls. + 2018-07-04 Mark Wielaard * readelf.c (print_debug_addr_section): Rename index var to uidx. diff --git a/src/elfcompress.c b/src/elfcompress.c index bdb0e3b5..1a0f9845 100644 --- a/src/elfcompress.c +++ b/src/elfcompress.c @@ -1235,13 +1235,16 @@ process_file (const char *fname) elf_end (elfnew); elfnew = NULL; - /* Try to match mode and owner.group of the original file. */ - if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0) - if (verbose >= 0) - error (0, errno, "Couldn't fchmod %s", fnew); + /* Try to match mode and owner.group of the original file. + Note to set suid bits we have to make sure the owner is setup + correctly first. Otherwise fchmod will drop them silently + or fchown may clear them. */ if (fchown (fdnew, st.st_uid, st.st_gid) != 0) if (verbose >= 0) error (0, errno, "Couldn't fchown %s", fnew); + if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0) + if (verbose >= 0) + error (0, errno, "Couldn't fchmod %s", fnew); /* Finally replace the old file with the new file. */ if (foutput == NULL) -- cgit v1.2.3 From ed62996defc619d0def86a5ed223a48486b97a70 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 21 Jul 2018 17:07:12 +0200 Subject: elfcompress: Don't rewrite file if no section data needs to be updated. If the input and output file are the same and no section needs to be updated we really don't need to rewrite the file. Check whether any matching section is already compressed or decompressed. Skip the section if it doesn't need to be changed. If no section data needs updating end with success without rewriting/updating file. With --force the file will still always be updated/rewritten even if no section data needs to be (de)compressed. Acked-by: Igor Gnatenko Signed-off-by: Mark Wielaard --- src/ChangeLog | 7 +++++++ src/elfcompress.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 0e9ab301..39214c39 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2018-07-21 Mark Wielaard + + * elfcompress.c (get_sections): New function. + (process_file): Check whether section needs to change. Don't rewrite + file if no section data needs changing. + (main): Update 'force' help text. + 2018-07-21 Mark Wielaard * elfcompress.c (process_file): Swap fchmod and fchown calls. diff --git a/src/elfcompress.c b/src/elfcompress.c index 1a0f9845..6ba6af41 100644 --- a/src/elfcompress.c +++ b/src/elfcompress.c @@ -1,5 +1,5 @@ /* Compress or decompress an ELF file. - Copyright (C) 2015, 2016 Red Hat, Inc. + Copyright (C) 2015, 2016, 2018 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -286,6 +286,15 @@ process_file (const char *fname) return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0; } + /* How many sections are we going to change? */ + size_t get_sections (void) + { + size_t s = 0; + for (size_t i = 0; i < shnum / WORD_BITS + 1; i++) + s += __builtin_popcount (sections[i]); + return s; + } + int cleanup (int res) { elf_end (elf); @@ -422,6 +431,9 @@ process_file (const char *fname) names change and whether there is a symbol table that might need to be adjusted be if the section header name table is changed. + If nothing needs changing, and the input and output file are the + same, we are done. + Second a collection pass that creates the Elf sections and copies the data. This pass will compress/decompress section data when needed. And it will collect all data needed if we'll need to @@ -464,7 +476,26 @@ process_file (const char *fname) if (section_name_matches (sname)) { - if (shdr->sh_type != SHT_NOBITS + if (!force && type == T_DECOMPRESS + && (shdr->sh_flags & SHF_COMPRESSED) == 0 + && strncmp (sname, ".zdebug", strlen (".zdebug")) != 0) + { + if (verbose > 0) + printf ("[%zd] %s already decompressed\n", ndx, sname); + } + else if (!force && type == T_COMPRESS_ZLIB + && (shdr->sh_flags & SHF_COMPRESSED) != 0) + { + if (verbose > 0) + printf ("[%zd] %s already compressed\n", ndx, sname); + } + else if (!force && type == T_COMPRESS_GNU + && strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) + { + if (verbose > 0) + printf ("[%zd] %s already GNU compressed\n", ndx, sname); + } + else if (shdr->sh_type != SHT_NOBITS && (shdr->sh_flags & SHF_ALLOC) == 0) { set_section (ndx); @@ -518,6 +549,14 @@ process_file (const char *fname) } } + if (foutput == NULL && get_sections () == 0) + { + if (verbose > 0) + printf ("Nothing to do.\n"); + fnew = NULL; + return cleanup (0); + } + if (adjust_names) { names = dwelf_strtab_init (true); @@ -1279,7 +1318,7 @@ main (int argc, char **argv) N_("Print a message for each section being (de)compressed"), 0 }, { "force", 'f', NULL, 0, - N_("Force compression of section even if it would become larger"), + N_("Force compression of section even if it would become larger or update/rewrite the file even if no section would be (de)compressed"), 0 }, { "permissive", 'p', NULL, 0, N_("Relax a few rules to handle slightly broken ELF files"), -- cgit v1.2.3 From 98ec9737922faef025ab10de15b9a653f46eaf53 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 21 Jul 2018 23:40:11 +0200 Subject: unstrip: Handle SHT_GROUP sections in ET_REL files. SHT_GROUP sections are put in both the stripped and debug file. Handle correcting the symbol table/name entry of the group only once. The testfile was generated with the gcc annobin plugin. Signed-off-by: Mark Wielaard --- src/ChangeLog | 4 ++++ src/unstrip.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 39214c39..791b627b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2018-07-21 Mark Wielaard + + * unstrip.c (adjust_all_relocs): Skip SHT_GROUP sections. + 2018-07-21 Mark Wielaard * elfcompress.c (get_sections): New function. diff --git a/src/unstrip.c b/src/unstrip.c index 057efef3..cb1f7dc0 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -563,7 +563,11 @@ adjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr, GElf_Shdr shdr_mem; GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); ELF_CHECK (shdr != NULL, _("cannot get section header: %s")); - if (shdr->sh_type != SHT_NOBITS && shdr->sh_link == new_sh_link) + /* Don't redo SHT_GROUP, groups are in both the stripped and debug, + it will already have been done by adjust_relocs for the + stripped_symtab. */ + if (shdr->sh_type != SHT_NOBITS && shdr->sh_type != SHT_GROUP + && shdr->sh_link == new_sh_link) adjust_relocs (scn, scn, shdr, map, symshdr); } } -- cgit v1.2.3 From 9718c94bbce0dabe0ce048efa3a2a6d1ea08bce5 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 24 Jul 2018 23:34:19 +0200 Subject: unstrip: Also check sh_size in compare_unalloc_sections. compare_unalloc_sections only checked sh_flags and the section names. This would cause stripped/debug section mismatches when there were multiple sections with the same name and flags. Fix this by also checking the size of the section matches. Add a testcase that has two ".group" sections created on i386 with the gcc annobin plugin. Signed-off-by: Mark Wielaard --- src/ChangeLog | 4 ++++ src/unstrip.c | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 791b627b..a01bd756 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2018-07-24 Mark Wielaard + + * unstrip.c (compare_unalloc_sections): Also compare sh_size. + 2018-07-21 Mark Wielaard * unstrip.c (adjust_all_relocs): Skip SHT_GROUP sections. diff --git a/src/unstrip.c b/src/unstrip.c index cb1f7dc0..ec46c952 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -709,6 +709,12 @@ compare_unalloc_sections (const GElf_Shdr *shdr1, const GElf_Shdr *shdr2, if (shdr1->sh_flags > shdr2->sh_flags) return 1; + /* Sizes should be the same. */ + if (shdr1->sh_size < shdr2->sh_size) + return -1; + if (shdr1->sh_size > shdr2->sh_size) + return 1; + /* Sort by name as last resort. */ return strcmp (name1, name2); } -- cgit v1.2.3 From c9f90a70900e753dde15cc9348dcf7de08b031eb Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 18 Aug 2018 13:17:45 +0200 Subject: elflint: Fix check_sysv_hash[64] sanity checks to not overflow. The sanity checks for how many words were needed in the section could overflow causing errors. Fix the checks. https://sourceware.org/bugzilla/show_bug.cgi?id=23542 Signed-off-by: Mark Wielaard --- src/ChangeLog | 7 +++++++ src/elflint.c | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index a01bd756..8c89f83d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2018-08-18 Mark Wielaard + + * elflint.c (check_sysv_hash): Calculate needed size using unsigned + long long int to prevent overflow. + (check_sysv_hash64): Calculate maxwords used separately before + comparison to prevent overflow. + 2018-07-24 Mark Wielaard * unstrip.c (compare_unalloc_sections): Also compare sh_size. diff --git a/src/elflint.c b/src/elflint.c index eec799b2..90e8fed4 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -2023,7 +2023,7 @@ check_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0]; Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1]; - if (shdr->sh_size < (2 + nbucket + nchain) * sizeof (Elf32_Word)) + if (shdr->sh_size < (2ULL + nbucket + nchain) * sizeof (Elf32_Word)) { ERROR (gettext ("\ section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), @@ -2077,7 +2077,10 @@ check_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx, Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0]; Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1]; - if (shdr->sh_size < (2 + nbucket + nchain) * sizeof (Elf64_Xword)) + uint64_t maxwords = shdr->sh_size / sizeof (Elf64_Xword); + if (maxwords < 2 + || maxwords - 2 < nbucket + || maxwords - 2 - nbucket < nchain) { ERROR (gettext ("\ section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"), -- cgit v1.2.3 From 29e31978ba51c1051743a503ee325b5ebc03d7e9 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 18 Aug 2018 13:27:48 +0200 Subject: libdw, readelf: Make sure there is enough data to read full aranges header. dwarf_getaranges didn't check if there was enough data left to read both the address and segment size. readelf didn't check there was enough data left to read the segment size. https://sourceware.org/bugzilla/show_bug.cgi?id=23541 Signed-off-by: Mark Wielaard --- src/ChangeLog | 5 +++++ src/readelf.c | 2 ++ 2 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 8c89f83d..2f9f7747 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-08-18 Mark Wielaard + + * readelf.c (print_debug_aranges_section): Make sure there is enough + data to read the header segment size. + 2018-08-18 Mark Wielaard * elflint.c (check_sysv_hash): Calculate needed size using unsigned diff --git a/src/readelf.c b/src/readelf.c index 7b5707f8..7b488ac5 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -5447,6 +5447,8 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), goto next_table; } + if (readp + 1 > readendp) + goto invalid_data; unsigned int segment_size = *readp++; printf (gettext (" Segment size: %6" PRIu64 "\n\n"), (uint64_t) segment_size); -- cgit v1.2.3 From 08ed26703d658b7ae57ab60b865d05c1cde777e3 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 30 Jul 2018 00:27:52 +0200 Subject: strip: Handle mixed allocated/non-allocated sections. Normally in non-ET_REL files all allocated sections come before all non-allocated sections. eu-strip relies on this when stripping a file and calculating the file offsets. But recently on Fedora there are non-allocated .gnu.build.attributes NOTE sections in the middle of the allocated sections, with a sh_offset field that is larger then the next section. This confuses eu-strip so much that it might corrupt the stripped file. Work around this by calculating the sh_offset fields in two phases when detecting mixed allocated/non-allocated sections. First handle the allocated ones, then use the offset after the last allocated section to calculate the offsets of the non-allocated sections left in the stripped file. Signed-off-by: Mark Wielaard --- src/ChangeLog | 6 +++++ src/strip.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 71 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 2f9f7747..29d36446 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2018-07-30 Mark Wielaard + + * strip.c (handle_elf): Track allocated/unallocated sections seen. Set + section offset of unallocated sections after handling all allocated + sections. + 2018-08-18 Mark Wielaard * readelf.c (print_debug_aranges_section): Make sure there is enough diff --git a/src/strip.c b/src/strip.c index 791347c1..1367de77 100644 --- a/src/strip.c +++ b/src/strip.c @@ -661,6 +661,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info)); } + /* Track whether allocated sections all come before non-allocated ones. */ + bool seen_allocated = false; + bool seen_unallocated = false; + bool mixed_allocated_unallocated = false; + /* Prepare section information data structure. */ scn = NULL; cnt = 1; @@ -676,6 +681,17 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL) INTERNAL_ERROR (fname); + /* Normally (in non-ET_REL files) we see all allocated sections first, + then all non-allocated. */ + if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0) + seen_unallocated = true; + else + { + if (seen_unallocated && seen_allocated) + mixed_allocated_unallocated = true; + seen_allocated = true; + } + /* Get the name of the section. */ shdr_info[cnt].name = elf_strptr (elf, shstrndx, shdr_info[cnt].shdr.sh_name); @@ -1535,24 +1551,58 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, } } - /* If we have to, compute the offset of the section. */ - if (shdr_info[cnt].shdr.sh_offset == 0) - shdr_info[cnt].shdr.sh_offset - = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1) - & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1))); - - /* Set the section header in the new file. */ - if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0)) - /* There cannot be any overflows. */ - INTERNAL_ERROR (fname); + /* If we have to, compute the offset of the section. + If allocate and unallocated sections are mixed, we only update + the allocated ones now. The unallocated ones come second. */ + if (! mixed_allocated_unallocated + || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0) + { + if (shdr_info[cnt].shdr.sh_offset == 0) + shdr_info[cnt].shdr.sh_offset + = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1) + & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1))); + + /* Set the section header in the new file. */ + if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0)) + /* There cannot be any overflows. */ + INTERNAL_ERROR (fname); - /* Remember the last section written so far. */ - GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS - ? shdr_info[cnt].shdr.sh_size : 0); - if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz) - lastoffset = shdr_info[cnt].shdr.sh_offset + filesz; + /* Remember the last section written so far. */ + GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS + ? shdr_info[cnt].shdr.sh_size : 0); + if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz) + lastoffset = shdr_info[cnt].shdr.sh_offset + filesz; + } } + /* We might have to update the unallocated sections after we done the + allocated ones. lastoffset is set to right after the last allocated + section. */ + if (mixed_allocated_unallocated) + for (cnt = 1; cnt <= shdridx; ++cnt) + if (shdr_info[cnt].idx > 0) + { + scn = elf_getscn (newelf, shdr_info[cnt].idx); + if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0) + { + if (shdr_info[cnt].shdr.sh_offset == 0) + shdr_info[cnt].shdr.sh_offset + = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1) + & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1))); + + /* Set the section header in the new file. */ + if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0)) + /* There cannot be any overflows. */ + INTERNAL_ERROR (fname); + + /* Remember the last section written so far. */ + GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS + ? shdr_info[cnt].shdr.sh_size : 0); + if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz) + lastoffset = shdr_info[cnt].shdr.sh_offset + filesz; + } + } + /* Adjust symbol references if symbol tables changed. */ if (any_symtab_changes) /* Find all relocation sections which use this symbol table. */ -- cgit v1.2.3 From ba2a7f4fa5f453c2b0a729bf519240a8f66a1867 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 4 Aug 2018 20:36:09 +0200 Subject: backends: Always use elf_getshdrstrndx in check_special_symbol. The check_special_symbol backend functions used the Ehdr e_shstrndx field to get at the name of sections. This is not correct if there are more than SHN_LORESERVE sections. Always use elf_getshdrstrndx to get the shstrtab section. And drop the Ehdr argument that isn't necessary anymore. Signed-off-by: Mark Wielaard --- src/ChangeLog | 5 +++++ src/elflint.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 29d36446..a118519f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-09-12 Mark Wielaard + + * elflint.c (check_symtab): Call ebl_check_special_symbol without + ehdr. + 2018-07-30 Mark Wielaard * strip.c (handle_elf): Track allocated/unallocated sections seen. Set diff --git a/src/elflint.c b/src/elflint.c index 90e8fed4..b49436ca 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -796,7 +796,7 @@ section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n"), st_value = sym->st_value; if (GELF_ST_TYPE (sym->st_info) != STT_TLS) { - if (! ebl_check_special_symbol (ebl, ehdr, sym, name, + if (! ebl_check_special_symbol (ebl, sym, name, destshdr)) { if (st_value - sh_addr > destshdr->sh_size) @@ -997,7 +997,7 @@ section [%2d] '%s'\n"), if (destshdr != NULL) { /* Found it. */ - if (!ebl_check_special_symbol (ebl, ehdr, sym, name, + if (!ebl_check_special_symbol (ebl, sym, name, destshdr)) { if (ehdr->e_type != ET_REL -- cgit v1.2.3 From 68e8b84743bdb389776e3aa2bae27aba7f435fdb Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 1 Aug 2018 16:51:03 +0200 Subject: libebl: Use elf_getshdrstrndx in ebl_section_strip_p. The ebl_section_strip_p function used the Ehdr e_shstrndx field to get at the name of the (debug) sections. This is not correct if there are more than SHN_LORESERVE sections. Use elf_getshdrstrndx to get at the shstrtab section. And drop the Ehdr argument that isn't necessary anymore. Signed-off-by: Mark Wielaard --- src/ChangeLog | 5 +++++ src/elfcmp.c | 4 ++-- src/strip.c | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index a118519f..7d046ec3 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-09-12 Mark Wielaard + + * elfcmp.c (main): Call ebl_section_strip_p without ehdr. + * strip.c (handle_elf): Likewise. + 2018-09-12 Mark Wielaard * elflint.c (check_symtab): Call ebl_check_special_symbol without diff --git a/src/elfcmp.c b/src/elfcmp.c index b40df8bf..b68df688 100644 --- a/src/elfcmp.c +++ b/src/elfcmp.c @@ -254,7 +254,7 @@ main (int argc, char *argv[]) sname1 = elf_strptr (elf1, ehdr1->e_shstrndx, shdr1->sh_name); } while (scn1 != NULL - && ebl_section_strip_p (ebl1, ehdr1, shdr1, sname1, true, false)); + && ebl_section_strip_p (ebl1, shdr1, sname1, true, false)); GElf_Shdr shdr2_mem; GElf_Shdr *shdr2; @@ -267,7 +267,7 @@ main (int argc, char *argv[]) sname2 = elf_strptr (elf2, ehdr2->e_shstrndx, shdr2->sh_name); } while (scn2 != NULL - && ebl_section_strip_p (ebl2, ehdr2, shdr2, sname2, true, false)); + && ebl_section_strip_p (ebl2, shdr2, sname2, true, false)); if (scn1 == NULL || scn2 == NULL) break; diff --git a/src/strip.c b/src/strip.c index 1367de77..dc712364 100644 --- a/src/strip.c +++ b/src/strip.c @@ -817,7 +817,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, /* Check whether the section can be removed. Since we will create a new .shstrtab assume it will be removed too. */ if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) - : (ebl_section_strip_p (ebl, ehdr, &shdr_info[cnt].shdr, + : (ebl_section_strip_p (ebl, &shdr_info[cnt].shdr, shdr_info[cnt].name, remove_comment, remove_debug) || cnt == ehdr->e_shstrndx @@ -978,7 +978,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, original table in the debug file. Unless it is a redundant data marker to a debug (data only) section. */ - if (! (ebl_section_strip_p (ebl, ehdr, + if (! (ebl_section_strip_p (ebl, &shdr_info[scnidx].shdr, shdr_info[scnidx].name, remove_comment, -- cgit v1.2.3 From be4ea50a689dcfdb46079f8f5ce616107a77cdc4 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 13 Sep 2018 13:52:46 +0200 Subject: elfcmp: Get, check and shdrstrndx for section names. elfcmp would use the Ehdr e_shstrndx field to find the shdr string index table. Use elf_getshdrstrndx instead to be able to handle ELF files with more than SHN_LORESERVE sections. Signed-off-by: Mark Wielaard --- src/ChangeLog | 4 ++++ src/elfcmp.c | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 7d046ec3..79da69b0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2018-09-13 Mark Wielaard + + * elfcmp.c (main): Get, check and shdrstrndx for section names. + 2018-09-12 Mark Wielaard * elfcmp.c (main): Call ebl_section_strip_p without ehdr. diff --git a/src/elfcmp.c b/src/elfcmp.c index b68df688..d5dc1ff2 100644 --- a/src/elfcmp.c +++ b/src/elfcmp.c @@ -235,6 +235,22 @@ main (int argc, char *argv[]) DIFFERENCE; } + size_t shstrndx1; + size_t shstrndx2; + if (elf_getshdrstrndx (elf1, &shstrndx1) != 0) + error (2, 0, gettext ("cannot get hdrstrndx of '%s': %s"), + fname1, elf_errmsg (-1)); + if (elf_getshdrstrndx (elf2, &shstrndx2) != 0) + error (2, 0, gettext ("cannot get hdrstrndx of '%s': %s"), + fname2, elf_errmsg (-1)); + if (shstrndx1 != shstrndx2) + { + if (! quiet) + error (0, 0, gettext ("%s %s diff: shdr string index"), + fname1, fname2); + DIFFERENCE; + } + /* Iterate over all sections. We expect the sections in the two files to match exactly. */ Elf_Scn *scn1 = NULL; @@ -251,7 +267,7 @@ main (int argc, char *argv[]) scn1 = elf_nextscn (elf1, scn1); shdr1 = gelf_getshdr (scn1, &shdr1_mem); if (shdr1 != NULL) - sname1 = elf_strptr (elf1, ehdr1->e_shstrndx, shdr1->sh_name); + sname1 = elf_strptr (elf1, shstrndx1, shdr1->sh_name); } while (scn1 != NULL && ebl_section_strip_p (ebl1, shdr1, sname1, true, false)); @@ -264,7 +280,7 @@ main (int argc, char *argv[]) scn2 = elf_nextscn (elf2, scn2); shdr2 = gelf_getshdr (scn2, &shdr2_mem); if (shdr2 != NULL) - sname2 = elf_strptr (elf2, ehdr2->e_shstrndx, shdr2->sh_name); + sname2 = elf_strptr (elf2, shstrndx2, shdr2->sh_name); } while (scn2 != NULL && ebl_section_strip_p (ebl2, shdr2, sname2, true, false)); -- cgit v1.2.3 From 583d106753e805e75a6cbfeab79aa2965e042f69 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 12 Sep 2018 23:38:47 +0200 Subject: elflint: Use shnum and shstrndx instead of ehdr field directly. We already got the right shnum and shstrndx. But were still using e_shnum in one check for ELFCLASS64 (it was correct for ELFCLASS32). And when getting section names in check_symtab we still used e_shstrndx in two places. Signed-off-by: Mark Wielaard --- src/ChangeLog | 7 +++++++ src/elflint.c | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 79da69b0..a093a737 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2018-09-13 Mark Wielaard + + * elflint.c (check_elf_header): Use shnum instead of e_shnum for all + checks. + (check_symtab): Use shstrndx instead of e_shstrndx to get section + names. + 2018-09-13 Mark Wielaard * elfcmp.c (main): Get, check and shdrstrndx for section names. diff --git a/src/elflint.c b/src/elflint.c index b49436ca..3d445954 100644 --- a/src/elflint.c +++ b/src/elflint.c @@ -541,7 +541,7 @@ invalid number of program header table entries\n")); if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr)) ERROR (gettext ("invalid section header size: %hd\n"), ehdr->e_shentsize); - else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size) + else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size) ERROR (gettext ("invalid section header position or size\n")); } } @@ -956,7 +956,7 @@ section [%2d] '%s': symbol %zu: non-local section symbol\n"), destshdr = gelf_getshdr (gscn, &destshdr_mem); assert (destshdr != NULL); const char *sname = elf_strptr (ebl->elf, - ehdr->e_shstrndx, + shstrndx, destshdr->sh_name); if (sname != NULL) { @@ -977,7 +977,7 @@ section [%2d] '%s': symbol %zu: non-local section symbol\n"), const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF) ? NULL - : elf_strptr (ebl->elf, ehdr->e_shstrndx, + : elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); if (sname == NULL) { -- cgit v1.2.3 From d5b050281e43754ac444e39d3e392831f4488c59 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 4 Aug 2018 20:29:25 +0200 Subject: strip,unstrip: Use and set shdrstrndx consistently. In various places in strip we used e_shstrndx instead of shdrstrndx and we didn't setup the shdrstrndx for the debug file. In unstrip we forgot to copy the shdrstrndx in case the -o output option was used. Added a new testcase that adds many sections to a testfile and runs strip, elflint, unstrip and elfcmp. Signed-off-by: Mark Wielaard --- src/ChangeLog | 7 +++++++ src/strip.c | 43 +++++++++++++++++++++++++++++++++++++++---- src/unstrip.c | 21 ++++++++++++++++++++- 3 files changed, 66 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index a093a737..524c81ac 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2018-09-13 Mark Wielaard + + * strip.c (handle_elf): Check against shstrndx, not e_shstrndx. + Explicitly set shdrstrndx for debug file. + * unstrip.c (copy_elf): Explicitly copy shstrndx. + (find_alloc_sections_prelink): Document shnum usage. + 2018-09-13 Mark Wielaard * elflint.c (check_elf_header): Use shnum instead of e_shnum for all diff --git a/src/strip.c b/src/strip.c index dc712364..4a3db1b5 100644 --- a/src/strip.c +++ b/src/strip.c @@ -820,7 +820,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, : (ebl_section_strip_p (ebl, &shdr_info[cnt].shdr, shdr_info[cnt].name, remove_comment, remove_debug) - || cnt == ehdr->e_shstrndx + || cnt == shstrndx || section_name_matches (remove_secs, shdr_info[cnt].name))) { /* The user might want to explicitly keep this one. */ @@ -1081,7 +1081,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, && shdr_info[cnt].debug_data == NULL && shdr_info[cnt].shdr.sh_type != SHT_NOTE && shdr_info[cnt].shdr.sh_type != SHT_GROUP - && cnt != ehdr->e_shstrndx); + && cnt != shstrndx); /* Set the section header in the new file. */ GElf_Shdr debugshdr = shdr_info[cnt].shdr; @@ -1134,7 +1134,42 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, debugehdr->e_version = ehdr->e_version; debugehdr->e_entry = ehdr->e_entry; debugehdr->e_flags = ehdr->e_flags; - debugehdr->e_shstrndx = ehdr->e_shstrndx; + + size_t shdrstrndx; + if (elf_getshdrstrndx (elf, &shdrstrndx) < 0) + { + error (0, 0, gettext ("%s: error while getting shdrstrndx: %s"), + fname, elf_errmsg (-1)); + result = 1; + goto fail_close; + } + + if (shstrndx < SHN_LORESERVE) + debugehdr->e_shstrndx = shdrstrndx; + else + { + debugehdr->e_shstrndx = SHN_XINDEX; + Elf_Scn *scn0 = elf_getscn (debugelf, 0); + GElf_Shdr shdr0_mem; + GElf_Shdr *shdr0 = gelf_getshdr (scn0, &shdr0_mem); + if (shdr0 == NULL) + { + error (0, 0, gettext ("%s: error getting zero section: %s"), + debug_fname, elf_errmsg (-1)); + result = 1; + goto fail_close; + } + + shdr0->sh_link = shdrstrndx; + if (gelf_update_shdr (scn0, shdr0) == 0) + { + error (0, 0, gettext ("%s: error while updating zero section: %s"), + debug_fname, elf_errmsg (-1)); + result = 1; + goto fail_close; + } + + } if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0)) { @@ -1187,7 +1222,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, the .shstrtab section which we would add again. */ bool removing_sections = !(cnt == idx || (cnt == idx + 1 - && shdr_info[ehdr->e_shstrndx].idx == 0)); + && shdr_info[shstrndx].idx == 0)); if (output_fname == NULL && !removing_sections) goto fail_close; diff --git a/src/unstrip.c b/src/unstrip.c index ec46c952..e6f09478 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -239,8 +239,27 @@ copy_elf (Elf *outelf, Elf *inelf) ELF_CHECK (gelf_newehdr (outelf, gelf_getclass (inelf)), _("cannot create ELF header: %s")); + size_t shstrndx; + ELF_CHECK (elf_getshdrstrndx (inelf, &shstrndx) == 0, + _("cannot get shdrstrndx:%s")); + GElf_Ehdr ehdr_mem; GElf_Ehdr *ehdr = gelf_getehdr (inelf, &ehdr_mem); + if (shstrndx < SHN_LORESERVE) + ehdr->e_shstrndx = shstrndx; + else + { + ehdr->e_shstrndx = SHN_XINDEX; + Elf_Scn *scn0 = elf_getscn (outelf, 0); + GElf_Shdr shdr0_mem; + GElf_Shdr *shdr0 = gelf_getshdr (scn0, &shdr0_mem); + ELF_CHECK (shdr0 != NULL, + _("cannot get new zero section: %s")); + shdr0->sh_link = shstrndx; + ELF_CHECK (gelf_update_shdr (scn0, shdr0), + _("cannot update new zero section: %s")); + } + ELF_CHECK (gelf_update_ehdr (outelf, ehdr), _("cannot copy ELF header: %s")); @@ -1025,7 +1044,7 @@ find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab, _("cannot read '.gnu.prelink_undo' section: %s")); uint_fast16_t phnum; - uint_fast16_t shnum; + uint_fast16_t shnum; /* prelink doesn't handle > SHN_LORESERVE. */ if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) { phnum = ehdr.e32.e_phnum; -- cgit v1.2.3 From 7859092379225482ffd4b49de2d18ad2d69ce810 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 4 Aug 2018 22:30:15 +0200 Subject: readelf: Use elf_getshdrnum in print_shdr and print_phdr. print_shdr didn't print the correct number of sections if there were more than SHN_LORESERVE sections. print_phdr wouldn't match up the (allocated) sections and segements if there were more than SHN_LORESERVE sections in the ELF file. Signed-off-by: Mark Wielaard --- src/ChangeLog | 5 +++++ src/readelf.c | 25 ++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 524c81ac..6a702ee1 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2018-09-13 Mark Wielaard + + * readelf.c (print_shdr): Get number of section with elf_getshdrnum. + (print_phdr): Likewise. + 2018-09-13 Mark Wielaard * strip.c (handle_elf): Check against shstrndx, not e_shstrndx. diff --git a/src/readelf.c b/src/readelf.c index 7b488ac5..bddcd703 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1184,15 +1184,24 @@ print_shdr (Ebl *ebl, GElf_Ehdr *ehdr) size_t shstrndx; if (! print_file_header) - printf (gettext ("\ -There are %d section headers, starting at offset %#" PRIx64 ":\n\ + { + size_t sections; + if (unlikely (elf_getshdrnum (ebl->elf, §ions) < 0)) + error (EXIT_FAILURE, 0, + gettext ("cannot get number of sections: %s"), + elf_errmsg (-1)); + + printf (gettext ("\ +There are %zd section headers, starting at offset %#" PRIx64 ":\n\ \n"), - ehdr->e_shnum, ehdr->e_shoff); + sections, ehdr->e_shoff); + } /* Get the section header string table index. */ if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, - gettext ("cannot get section header string table index")); + gettext ("cannot get section header string table index: %s"), + elf_errmsg (-1)); puts (gettext ("Section Headers:")); @@ -1384,7 +1393,13 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) } } - if (ehdr->e_shnum == 0) + size_t sections; + if (unlikely (elf_getshdrnum (ebl->elf, §ions) < 0)) + error (EXIT_FAILURE, 0, + gettext ("cannot get number of sections: %s"), + elf_errmsg (-1)); + + if (sections == 0) /* No sections in the file. Punt. */ return; -- cgit v1.2.3