summaryrefslogtreecommitdiffstats
path: root/src/strip.c
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2011-01-04 19:29:24 -0800
committerRoland McGrath <[email protected]>2011-01-05 09:42:09 -0800
commit0b9d1fb534604a9ba19999cd8ce8e7efce28da24 (patch)
tree691e7bdd187c53428286517e68e9b42d15c6ae37 /src/strip.c
parentf1ccc410d6bda15ed49fc5d0fef9f6f65acbfb63 (diff)
strip: Add --strip-sections option.
Diffstat (limited to 'src/strip.c')
-rw-r--r--src/strip.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/strip.c b/src/strip.c
index 7b2b889a..9b2d24a3 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -65,6 +65,7 @@ ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
/* Values for the parameters which have no short form. */
#define OPT_REMOVE_COMMENT 0x100
#define OPT_PERMISSIVE 0x101
+#define OPT_STRIP_SECTIONS 0x102
/* Definitions of arguments for argp functions. */
@@ -80,6 +81,8 @@ static const struct argp_option options[] =
{ "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
{ NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
{ NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
+ { "strip-sections", OPT_STRIP_SECTIONS, NULL, 0,
+ N_("Remove section headers (not recommended)"), 0 },
{ "preserve-dates", 'p', NULL, 0,
N_("Copy modified/access timestamps to the output"), 0 },
{ "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
@@ -140,6 +143,9 @@ static bool remove_comment;
/* If true remove all debug sections. */
static bool remove_debug;
+/* If true remove all section headers. */
+static bool remove_shdrs;
+
/* If true relax some ELF rules for input files. */
static bool permissive;
@@ -268,6 +274,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
remove_debug = true;
break;
+ case OPT_STRIP_SECTIONS:
+ remove_shdrs = true;
+ break;
+
case OPT_PERMISSIVE:
permissive = true;
break;
@@ -1639,6 +1649,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
newehdr->e_entry = ehdr->e_entry;
newehdr->e_flags = ehdr->e_flags;
newehdr->e_phoff = ehdr->e_phoff;
+
/* We need to position the section header table. */
const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
@@ -1692,6 +1703,53 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
result = 1;
}
+ if (remove_shdrs)
+ {
+ /* libelf can't cope without the section headers being properly intact.
+ So we just let it write them normally, and then we nuke them later. */
+
+ if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
+ {
+ assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
+ == offsetof (Elf32_Ehdr, e_shnum));
+ assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
+ == offsetof (Elf32_Ehdr, e_shstrndx));
+ const Elf32_Off zero_off = 0;
+ const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
+ if (pwrite_retry (fd, &zero_off, sizeof zero_off,
+ offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
+ || (pwrite_retry (fd, zero, sizeof zero,
+ offsetof (Elf32_Ehdr, e_shentsize))
+ != sizeof zero)
+ || ftruncate64 (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
+ {
+ error (0, errno, gettext ("while writing '%s'"),
+ fname);
+ result = 1;
+ }
+ }
+ else
+ {
+ assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
+ == offsetof (Elf64_Ehdr, e_shnum));
+ assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
+ == offsetof (Elf64_Ehdr, e_shstrndx));
+ const Elf64_Off zero_off = 0;
+ const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
+ if (pwrite_retry (fd, &zero_off, sizeof zero_off,
+ offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
+ || (pwrite_retry (fd, zero, sizeof zero,
+ offsetof (Elf64_Ehdr, e_shentsize))
+ != sizeof zero)
+ || ftruncate64 (fd, shdr_info[shdridx].shdr.sh_offset) < 0)
+ {
+ error (0, errno, gettext ("while writing '%s'"),
+ fname);
+ result = 1;
+ }
+ }
+ }
+
fail_close:
if (shdr_info != NULL)
{