strip: Add --strip-sections option.
authorRoland McGrath <roland@redhat.com>
Wed, 5 Jan 2011 03:29:24 +0000 (19:29 -0800)
committerRoland McGrath <roland@redhat.com>
Wed, 5 Jan 2011 17:42:09 +0000 (09:42 -0800)
src/ChangeLog
src/strip.c

index 7a15192..9d42c55 100644 (file)
@@ -1,3 +1,9 @@
+2011-01-04  Roland McGrath  <roland@redhat.com>
+
+       * strip.c (remove_shdrs): New variable.
+       (options, parse_opt): Grok --strip-sections to set it.
+       (handle_elf): When that's set, truncate off .shstrtab and shdrs.
+
 2010-11-10  Roland McGrath  <roland@redhat.com>
 
        * findtextrel.c (process_file): Don't assume order of sections.
index 7b2b889..9b2d24a 100644 (file)
@@ -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)
     {