summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2018-09-14 12:28:58 +0200
committerMark Wielaard <[email protected]>2018-09-14 12:28:58 +0200
commit029c76f0d4b06584e370b5fc0112712ba99a6219 (patch)
tree20c91ff0dc7125251b26ded357e71c542b67d5cc /src
parent94c975eefdfbfa9319b7bab69600c76fe6be7910 (diff)
parent52b6b2f1f49e7385527e9f311f248092be0c0b61 (diff)
Merge branch 'master' into mjw/RH-DTSdts-0.174
elfutils 0.174 release Removed new M68K and RISCV tests.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog95
-rw-r--r--src/addr2line.c1
-rw-r--r--src/ar.c1
-rw-r--r--src/arlib.c2
-rw-r--r--src/arlib2.c1
-rw-r--r--src/elfcmp.c27
-rw-r--r--src/elfcompress.c58
-rw-r--r--src/elflint.c18
-rw-r--r--src/findtextrel.c3
-rw-r--r--src/nm.c1
-rw-r--r--src/objdump.c1
-rw-r--r--src/ranlib.c1
-rw-r--r--src/readelf.c42
-rw-r--r--src/size.c1
-rw-r--r--src/stack.c1
-rw-r--r--src/strings.c1
-rw-r--r--src/strip.c128
-rw-r--r--src/unstrip.c35
18 files changed, 345 insertions, 72 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 6d962bbb..6a702ee1 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,98 @@
+2018-09-13 Mark Wielaard <[email protected]>
+
+ * readelf.c (print_shdr): Get number of section with elf_getshdrnum.
+ (print_phdr): Likewise.
+
+2018-09-13 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
+
+ * elfcmp.c (main): Get, check and shdrstrndx for section names.
+
+2018-09-12 Mark Wielaard <[email protected]>
+
+ * elfcmp.c (main): Call ebl_section_strip_p without ehdr.
+ * strip.c (handle_elf): Likewise.
+
+2018-09-12 Mark Wielaard <[email protected]>
+
+ * elflint.c (check_symtab): Call ebl_check_special_symbol without
+ ehdr.
+
+2018-07-30 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * readelf.c (print_debug_aranges_section): Make sure there is enough
+ data to read the header segment size.
+
+2018-08-18 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * unstrip.c (compare_unalloc_sections): Also compare sh_size.
+
+2018-07-21 Mark Wielaard <[email protected]>
+
+ * unstrip.c (adjust_all_relocs): Skip SHT_GROUP sections.
+
+2018-07-21 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * elfcompress.c (process_file): Swap fchmod and fchown calls.
+
+2018-07-04 Mark Wielaard <[email protected]>
+
+ * 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 <[email protected]>
+
+ * 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 <[email protected]>
* 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 <argp.h>
#include <assert.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libdwfl.h>
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 <argp.h>
#include <assert.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <libintl.h>
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 <assert.h>
-#include <error.h>
#include <gelf.h>
#include <inttypes.h>
#include <libintl.h>
@@ -31,6 +30,7 @@
#include <libeu.h>
+#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 <config.h>
#endif
-#include <error.h>
#include <libintl.h>
#include <limits.h>
#include <string.h>
diff --git a/src/elfcmp.c b/src/elfcmp.c
index 50464207..d5dc1ff2 100644
--- a/src/elfcmp.c
+++ b/src/elfcmp.c
@@ -23,7 +23,6 @@
#include <argp.h>
#include <assert.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <locale.h>
#include <libintl.h>
@@ -36,7 +35,7 @@
#include <printversion.h>
#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);
@@ -236,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;
@@ -252,10 +267,10 @@ 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, ehdr1, shdr1, sname1, true, false));
+ && ebl_section_strip_p (ebl1, shdr1, sname1, true, false));
GElf_Shdr shdr2_mem;
GElf_Shdr *shdr2;
@@ -265,10 +280,10 @@ 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, ehdr2, shdr2, sname2, true, false));
+ && ebl_section_strip_p (ebl2, shdr2, sname2, true, false));
if (scn1 == NULL || scn2 == NULL)
break;
diff --git a/src/elfcompress.c b/src/elfcompress.c
index 25378a45..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
@@ -18,7 +18,6 @@
#include <config.h>
#include <assert.h>
#include <argp.h>
-#include <error.h>
#include <stdbool.h>
#include <stdlib.h>
#include <inttypes.h>
@@ -34,6 +33,7 @@
#include ELFUTILS_HEADER(ebl)
#include ELFUTILS_HEADER(dwelf)
#include <gelf.h>
+#include "system.h"
#include "libeu.h"
#include "printversion.h"
@@ -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);
@@ -1235,13 +1274,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)
@@ -1276,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"),
diff --git a/src/elflint.c b/src/elflint.c
index 0a26d97d..3d445954 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -24,7 +24,6 @@
#include <assert.h>
#include <byteswap.h>
#include <endian.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <inttypes.h>
@@ -542,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"));
}
}
@@ -797,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)
@@ -957,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)
{
@@ -978,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)
{
@@ -998,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
@@ -2024,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"),
@@ -2078,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"),
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 <argp.h>
#include <assert.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <libdw.h>
@@ -37,7 +36,7 @@
#include <unistd.h>
#include <printversion.h>
-
+#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 <ctype.h>
#include <dwarf.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <inttypes.h>
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 <argp.h>
-#include <error.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libintl.h>
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 <argp.h>
#include <assert.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <libintl.h>
diff --git a/src/readelf.c b/src/readelf.c
index faed61a6..bddcd703 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -24,7 +24,6 @@
#include <ctype.h>
#include <dwarf.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <inttypes.h>
@@ -1185,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, &sections) < 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:"));
@@ -1385,7 +1393,13 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
}
}
- if (ehdr->e_shnum == 0)
+ size_t sections;
+ if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 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;
@@ -5262,14 +5276,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");
}
@@ -5448,6 +5462,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);
@@ -6967,12 +6983,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) ",
@@ -10256,7 +10272,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)
@@ -10268,7 +10284,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");
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 <argp.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <inttypes.h>
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 <config.h>
#include <assert.h>
#include <argp.h>
-#include <error.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
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 <ctype.h>
#include <endian.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <inttypes.h>
diff --git a/src/strip.c b/src/strip.c
index 773ed548..4a3db1b5 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -24,7 +24,6 @@
#include <assert.h>
#include <byteswap.h>
#include <endian.h>
-#include <error.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <gelf.h>
@@ -662,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;
@@ -677,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);
@@ -802,10 +817,10 @@ 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
+ || cnt == shstrndx
|| section_name_matches (remove_secs, shdr_info[cnt].name)))
{
/* The user might want to explicitly keep this one. */
@@ -963,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,
@@ -1066,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;
@@ -1119,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))
{
@@ -1172,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;
@@ -1536,24 +1586,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. */
diff --git a/src/unstrip.c b/src/unstrip.c
index f368e696..e6f09478 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -31,7 +31,6 @@
#include <argp.h>
#include <assert.h>
#include <errno.h>
-#include <error.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <libintl.h>
@@ -48,6 +47,7 @@
#include <gelf.h>
#include <libebl.h>
#include <libdwfl.h>
+#include "system.h"
#include "libdwelf.h"
#include "libeu.h"
#include "printversion.h"
@@ -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"));
@@ -563,7 +582,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);
}
}
@@ -705,6 +728,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);
}
@@ -1015,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;