This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Fixing objcopy --only-keep-debug


Hi Guys,

  It seems to me that "objcopy --only-keep-debug" is not doing what it
  is supposed to do, ie strip all non-debug sections, leaving a valid,
  but truncated binary file:

   % cat foo.c
   int main (void) { return 0; }

  % gcc -g foo.c -o foo
  % objcopy --only-keep-debug foo foo.debuginfo
  % readelf -S foo.debuginfo

  There are 35 section headers, starting at offset 0xbf8:

  Section Headers:
    [Nr] Name              Type             Address           Offset
         Size              EntSize          Flags  Link  Info  Align
    [ 0]                   NULL             0000000000000000  00000000
         0000000000000000  0000000000000000           0     0     0
    [ 1] .interp           NOBITS           0000000000400238  00000238
         000000000000001c  0000000000000000   A       0     0     1
    [ 2] .note.ABI-tag     NOTE             0000000000400254  00000254
         0000000000000020  0000000000000000   A       0     0     4
    [ 3] .note.gnu.build-i NOTE             0000000000400274  00000274
         0000000000000024  0000000000000000   A       0     0     4
    [ 4] .gnu.hash         NOBITS           0000000000400298  00000298
         000000000000001c  0000000000000000   A       0     0     8
    [ 5] .dynsym           NOBITS           00000000004002b8  00000298
         0000000000000048  0000000000000018   A       0     1     8

  and so on, for 35 sections in total, including .text, .rodata and lots
  of other sections that I would not expect to find in a .debuginfo file.

  This strikes me as wrong, so I am proposing the attached patch.  But
  since I am paranoid I am checking here first to see if anyone has a
  reason for keeping the current behaviour.

  Oh, as an added bonus (?) the patch also extends objcopy's --verbose
  option so that it lists sections and symbols that are stripped during
  a copy.  I found this to be quite helpful in debugging the patch, and
  maybe others will like it too.  The patch also adds a couple of tests
  to the binutils testsuite to check the new behaviour.

  I have regression tested the patch with no new failures on lots of
  different targets, so I am fairly confident that it will not break
  anything. 

  Any comments or objections ?

Cheers
  Nick

binutils/ChangeLog
2015-07-28  Nick Clifton  <nickc@redhat.com>

	* objcopy (is_non_debug_strip_section): New function.
        (filer_symbols): Use the new function.  Report any stripped
        symbols.
        (setup_section): Likewise.
	* doc/binutils.texi (objcopy): Document that the --verbose
	option displays any stripped sections or symbols.

binutils/testsuite/ChangeLog
2015-07-28  Nick Clifton  <nickc@redhat.com>

	* binutils-all/strip-12.s: New source file.  Contains debug
	sections and non-debug sections.
        * binutils-all/strip-12.d: New test driver.  Checks that
	--only-keep-debug leaves debug sections in the copied file.
        * binutils-all/strip-13.d: New test driver.  Checks that
	--only-keep-debug strips out the text and data sections.
	* binutils-all/objcopy.exp: Run the new tests.

bfd/ChangeLog
2015-07-28  Nick Clifton  <nickc@redhat.com>

	* elf.c (ignore_section_sym): Check that output_section exists
	before testing its owner.

diff --git a/bfd/elf.c b/bfd/elf.c
index 9776854..b71a51f 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -3552,7 +3552,8 @@ ignore_section_sym (bfd *abfd, asymbol *sym)
 	   && type_ptr->internal_elf_sym.st_shndx != 0
 	   && bfd_is_abs_section (sym->section))
 	  || !(sym->section->owner == abfd
-	       || (sym->section->output_section->owner == abfd
+	       || (sym->section->output_section != NULL
+		   && sym->section->output_section->owner == abfd
 		   && sym->section->output_offset == 0)
 	       || bfd_is_abs_section (sym->section)));
 }
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 466f125..baa882e 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -1877,6 +1877,9 @@ Show the version number of @command{objcopy}.
 Verbose output: list all object files modified.  In the case of
 archives, @samp{objcopy -V} lists all members of the archive.
 
+Also displays a list of any section or symbol stripped from the input
+whilst copying to the output.
+
 @item --help
 Show a summary of the options to @command{objcopy}.
 
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index bb6ca44..fb69d27 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -1080,7 +1080,7 @@ is_update_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
 /* See if a non-group section is being removed.  */
 
 static bfd_boolean
-is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
+is_strip_section_1 (bfd *abfd, asection *sec)
 {
   if (sections_removed || sections_copied)
     {
@@ -1133,6 +1133,26 @@ is_strip_section_1 (bfd *abfd ATTRIBUTE_UNUSED, asection *sec)
   return FALSE;
 }
 
+/* Returns TRUE iff SEC is a section to be stripped when --only-keep-debug
+   is active.  */
+
+static bfd_boolean
+is_non_debug_strip_section (bfd *abfd, asection *sec)
+{
+  const char * name;
+
+  if (strip_symbols != STRIP_NONDEBUG)
+    return FALSE;
+
+  if ((bfd_get_section_flags (abfd, sec) & SEC_DEBUGGING))
+    return FALSE;
+
+  name = bfd_get_section_name (abfd, sec);
+
+  /* Leave in the .dynamic section and any notes.  */
+  return (strcmp (name, ".dynamic") != 0  && ! CONST_STRNEQ (name, ".note."));
+}
+
 /* See if a section is being removed.  */
 
 static bfd_boolean
@@ -1360,7 +1380,9 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
 	      || is_specified_symbol (name, keep_specific_htab)))
 	keep = TRUE;
 
-      if (keep && is_strip_section (abfd, bfd_get_section (sym)))
+      if (keep &&
+	  (is_strip_section (abfd, bfd_get_section (sym))
+	   || is_non_debug_strip_section (abfd, bfd_get_section (sym))))
 	keep = FALSE;
 
       if (keep)
@@ -1393,6 +1415,8 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
 
 	  to[dst_count++] = sym;
 	}
+      else if (verbose)
+	printf (_(" strip symbol %s\n"), name);
     }
 
   to[dst_count] = NULL;
@@ -2814,12 +2838,17 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
   char *prefix = NULL;
   bfd_boolean make_nobits;
 
-  if (is_strip_section (ibfd, isection))
-    return;
-
   /* Get the, possibly new, name of the output section.  */
   name = find_section_rename (ibfd, isection, & flags);
 
+  if (is_strip_section (ibfd, isection)
+      || is_non_debug_strip_section (ibfd, isection))
+    {
+      if (verbose)
+	printf (_(" strip section %s\n"), name);
+      return;
+    }
+
   /* Prefix sections.  */
   if ((prefix_alloc_sections_string)
       && (bfd_get_section_flags (ibfd, isection) & SEC_ALLOC))
diff --git a/binutils/testsuite/binutils-all/objcopy.exp b/binutils/testsuite/binutils-all/objcopy.exp
index ae21b22..ae814c9 100644
--- a/binutils/testsuite/binutils-all/objcopy.exp
+++ b/binutils/testsuite/binutils-all/objcopy.exp
@@ -968,6 +968,8 @@ if [is_elf_format] {
 	set extra_strip11 { { "as" "--isa=SHmedia --abi=64" } }
     }
     run_dump_test "strip-11" $extra_strip11
+    run_dump_test "strip-12"
+    run_dump_test "strip-13"
 
     if { [istarget "i*86-*"] || [istarget "x86_64-*-*"] } {
 	# Check to make sure we don't strip a symbol named in relocations.
--- /dev/null	2015-07-27 09:02:16.200844779 +0100
+++ binutils/testsuite/binutils-all/strip-12.s	2015-07-28 09:38:52.733228163 +0100
@@ -0,0 +1,33 @@
+	.file	"foo.c"
+	.text	
+	.globl	main
+main:
+	.file 1 "foo.c"
+	.loc 1 1 0
+	.word 0
+	.size	main, .-main
+
+	.section	.debug_info,"",%progbits
+	.long	0x4e
+	.long	0x4
+	.long	0
+
+	.section	.debug_abbrev,"",%progbits
+	.uleb128 0x1
+	.uleb128 0x11
+
+	.section	.debug_aranges,"",%progbits
+	.long	0x2c
+	.long	0x2
+
+	.section	.debug_line,"",%progbits
+
+	.section	.debug_str,"MS",%progbits,1
+	.string	"main"
+	.string	"/tmp"
+	.string	"GNU C11 5.1.1 20150618 (Red Hat 5.1.1-4) -mtune=generic -march=x86-64 -g"
+	.string	"foo.c"
+
+	.ident	"GCC: (GNU) 5.1.1 20150618 (Red Hat 5.1.1-4)"
+
+	.section	.note.GNU-stack,"",%progbits
--- /dev/null	2015-07-27 09:02:16.200844779 +0100
+++ binutils/testsuite/binutils-all/strip-12.d	2015-07-28 09:35:53.322401533 +0100
@@ -0,0 +1,14 @@
+#PROG: objcopy
+#objcopy: --only-keep-debug
+#source: strip-12.s
+#readelf: -S --wide
+#name: Ensure objcopy --only-keep-debug contains the debug sections
+
+#...
+  \[[0-9 ]+\] .debug_info[ 	]+.*
+  \[[0-9 ]+\] .debug_abbrev[ 	]+.*
+  \[[0-9 ]+\] .debug_aranges[ 	]+.*
+  \[[0-9 ]+\] .debug_line[ 	]+.*
+#...
+  \[[0-9 ]+\] .debug_str[ 	]+.*
+#pass
--- /dev/null	2015-07-27 09:02:16.200844779 +0100
+++ binutils/testsuite/binutils-all/strip-13.d	2015-07-27 17:38:42.704608471 +0100
@@ -0,0 +1,12 @@
+#PROG: objcopy
+#objcopy: --only-keep-debug
+#source: strip-12.s
+#readelf: -S 
+#name: Ensure objcopy --only-keep-debug does not contain text or data sections
+
+#failif
+#...
+  \[[0-9 ]+\] .text[ 	]+.*
+#...
+  \[[0-9 ]+\].*data[ 	]+.*
+#...
\ No newline at end of file

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]