This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
RFC: Fixing objcopy --only-keep-debug
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Tue, 28 Jul 2015 12:06:56 +0100
- Subject: RFC: Fixing objcopy --only-keep-debug
- Authentication-results: sourceware.org; auth=none
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