Change the behaviour of the --only-keep-debug option to objcopy and strip so that the sh_link and sh_info fields in stripped section headers are preserved.

bfd	* elf.c (_bfd_elf_copy_private_bfd_data): Copy the sh_link and
	sh_info fields of sections whose type has been changed to
	SHT_NOBITS.

bin	* doc/binutils.texi: Document that the --only-keep-debug option
	to strip and objcopy preserves the section headers of stripped
	sections.

tests	* binutils-all/objcopy.exp (keep_debug_symbols_and_check_links):
	New proc.  Checks that debug-info-only binaries retain the
	sh_link field in stripped sections.
This commit is contained in:
Nick Clifton 2015-08-05 16:16:39 +01:00
parent 260439cb8e
commit 63b9bbb7d7
6 changed files with 157 additions and 2 deletions

View File

@ -1,3 +1,9 @@
2015-08-05 Nick Clifton <nickc@redhat.com>
* elf.c (_bfd_elf_copy_private_bfd_data): Copy the sh_link and
sh_info fields of sections whose type has been changed to
SHT_NOBITS.
2015-08-04 Yuriy M. Kaminskiy" <yumkam@gmail.com>
Tyler Hicks <tyhicks@canonical.com>

View File

@ -1203,6 +1203,63 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
/* Copy object attributes. */
_bfd_elf_copy_obj_attributes (ibfd, obfd);
/* This is an feature for objcopy --only-keep-debug: When a section's type
is changed to NOBITS, we preserve the sh_link and sh_info fields so that
they can be matched up with the original. */
Elf_Internal_Shdr ** iheaders = elf_elfsections (ibfd);
Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
if (iheaders != NULL && oheaders != NULL)
{
unsigned int i;
for (i = 0; i < elf_numsections (obfd); i++)
{
unsigned int j;
Elf_Internal_Shdr * oheader = oheaders[i];
if (oheader == NULL
|| oheader->sh_type != SHT_NOBITS
|| oheader->sh_size == 0
|| (oheader->sh_info != 0 && oheader->sh_link != 0))
continue;
/* Scan for the matching section in the input bfd.
FIXME: We could use something better than a linear scan here.
Unfortunately we cannot compare names as the output string table
is empty, so instead we check size, address and type. */
for (j = 0; j < elf_numsections (ibfd); j++)
{
Elf_Internal_Shdr * iheader = iheaders[j];
if (iheader->sh_type != SHT_NOBITS
&& iheader->sh_size == oheader->sh_size
&& iheader->sh_addr == oheader->sh_addr
&& (iheader->sh_info != oheader->sh_info
|| iheader->sh_link != oheader->sh_link))
{
/* Note: Strictly speaking these assignments are wrong.
The sh_link and sh_info fields should point to the
relevent sections in the output BFD, which may not be in
the same location as they were in the input BFD. But the
whole point of this action is to preserve the original
values of the sh_link and sh_info fields, so that they
can be matched up with the section headers in the
original file. So strictly speaking we may be creating
an invalid ELF file, but it is only for a file that just
contains debug info and only for sections without any
contents. */
if (oheader->sh_link == 0)
oheader->sh_link = iheader->sh_link;
if (oheader->sh_info == 0)
oheader->sh_info = iheader->sh_info;
break;
}
}
}
}
return TRUE;
}

View File

@ -1,3 +1,9 @@
2015-08-05 Nick Clifton <nickc@redhat.com>
* doc/binutils.texi: Document that the --only-keep-debug option
to strip and objcopy preserves the section headers of stripped
sections.
2015-08-04 Yuriy M. Kaminskiy" <yumkam@gmail.com>
Tyler Hicks <tyhicks@canonical.com>

View File

@ -1731,6 +1731,12 @@ Strip a file, removing contents of any sections that would not be
stripped by @option{--strip-debug} and leaving the debugging sections
intact. In ELF files, this preserves all note sections in the output.
Note - the section headers of the stripped sections are preserved,
including their sizes, but the contents of the section are discarded.
The section headers are preserved so that other tools can match up the
debuginfo file with the real executable, even if that executable has
been relocated to a different address space.
The intention is that this option will be used in conjunction with
@option{--add-gnu-debuglink} to create a two part executable. One a
stripped binary which will occupy less space in RAM and in a
@ -3074,9 +3080,16 @@ When stripping a file, perhaps with @option{--strip-debug} or
which would otherwise get stripped.
@item --only-keep-debug
Strip a file, removing contents of any sections that would not be
Strip a file, emptying the contents of any sections that would not be
stripped by @option{--strip-debug} and leaving the debugging sections
intact. In ELF files, this preserves all note sections in the output.
intact. In ELF files, this preserves all the note sections in the
output as well.
Note - the section headers of the stripped sections are preserved,
including their sizes, but the contents of the section are discarded.
The section headers are preserved so that other tools can match up the
debuginfo file with the real executable, even if that executable has
been relocated to a different address space.
The intention is that this option will be used in conjunction with
@option{--add-gnu-debuglink} to create a two part executable. One a

View File

@ -1,3 +1,9 @@
2015-08-05 Nick Clifton <nickc@redhat.com>
* binutils-all/objcopy.exp (keep_debug_symbols_and_check_links):
New proc. Checks that debug-info-only binaries retain the
sh_link field in stripped sections.
2015-08-04 Nick Clifton <nickc@redhat.com>
* lib/utils-lib.exp (run_dump_test): Document DUMPPROG, readelf

View File

@ -829,12 +829,70 @@ proc keep_debug_symbols_and_test_copy { prog1 flags1 test1 prog2 flags2 test2 }
pass $test2
}
# Tests that in a debug only copy of a file the sections
# headers whoes types have been changed to NOBITS still
# retain their sh_link fields.
proc keep_debug_symbols_and_check_links { prog flags test } {
global READELF
remote_file build delete tmpdir/striprog
remote_download build tmpdir/copyprog tmpdir/striprog
if [is_remote host] {
set copyfile [remote_download host tmpdir/striprog]
} else {
set copyfile tmpdir/striprog
}
set exec_output [binutils_run $prog "$flags ${copyfile}"]
if ![string match "" $exec_output] {
fail $test
return
}
set got [binutils_run $READELF "-S --wide ${copyfile}"]
set fails 0
# Regexp to match a section with NOBITS type and extract its name and sh_link fields
while {[regexp \
{[^a-zA-Z]+([a-zA-Z0-9_\.]+)[ ]+NOBITS[ ]+[0-9a-fA-F]+ [0-9a-fA-F]+ [0-9a-fA-F]+ [0-9]+[ A]+([0-9]+)(.*)} \
$got all name link rest]} {
set sh_link 0x$link
if {$sh_link == 0} {
# Only some NOBITS sections should have a non-zero sh_link field.
# Look for them by name.
verbose "NOBITS section .$name has a 0 sh_link field\n"
switch $name {
"rela.*" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
"rel.*" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
"hash" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
"gnu_version" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
"dynsym" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
"gnu.version_r" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
"dynamic" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
"symtab" { set fails 1 ; send_log "Expected non-zero sh_link for .$name\n" }
}
}
set got $rest
}
if {$fails == 0} {
pass $test
} else {
fail $test
}
}
set test1 "simple objcopy of executable"
set test2 "run objcopy of executable"
set test3 "run stripped executable"
set test4 "run stripped executable with saving a symbol"
set test5 "keep only debug data"
set test6 "simple objcopy of debug data"
if [is_elf_format] {
set test7 "NOBITS sections retain sh_link field"
}
switch [copy_setup] {
"1" {
@ -847,6 +905,9 @@ switch [copy_setup] {
untested $test4
untested $test5
untested $test6
if [is_elf_format] {
untested $test7
}
}
"3" {
copy_executable "$OBJCOPY" "$OBJCOPYFLAGS" "$test1" ""
@ -855,6 +916,9 @@ switch [copy_setup] {
unsupported $test4
unsupported $test5
unsupported $test6
if [is_elf_format] {
unsupported $test7
}
}
"0" {
copy_executable "$OBJCOPY" "$OBJCOPYFLAGS" "$test1" "$test2"
@ -862,6 +926,9 @@ switch [copy_setup] {
strip_executable_with_saving_a_symbol "$STRIP" "-K main -K _main $STRIPFLAGS" "$test4"
keep_debug_symbols_and_test_copy "$STRIP" "--only-keep-debug $STRIPFLAGS" "$test5" \
"$OBJCOPY" "$OBJCOPYFLAGS" "$test6"
if [is_elf_format] {
keep_debug_symbols_and_check_links "$STRIP" "--only-keep-debug $STRIPFLAGS" "$test7"
}
}
}