aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/bfd-in2.h6
-rw-r--r--bfd/bfd.c155
-rw-r--r--binutils/ChangeLog9
-rw-r--r--binutils/objcopy.c11
-rw-r--r--binutils/testsuite/ChangeLog6
-rw-r--r--binutils/testsuite/binutils-all/compress.exp93
7 files changed, 285 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e8c783e..b552c9f 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2015-07-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/18656
+ * bfd.c (bfd_convert_section_size): New function.
+ (bfd_convert_section_contents): Likewise.
+ * bfd-in2.h: Regenerated.
+
2015-07-09 Catherine Moore <clm@codesourcery.com>
* elflink.c (bfd_elf_size_dynamic_sections): Call to
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 85f2054..e963687 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6855,6 +6855,12 @@ bfd_boolean bfd_check_compression_header
int bfd_get_compression_header_size (bfd *abfd, asection *sec);
+bfd_size_type bfd_convert_section_size
+ (bfd *ibfd, asection *isec, bfd *obfd, bfd_size_type size);
+
+bfd_boolean bfd_convert_section_contents
+ (bfd *ibfd, asection *isec, bfd *obfd, bfd_byte **ptr);
+
/* Extracted from archive.c. */
symindex bfd_get_next_mapent
(bfd *abfd, symindex previous, carsym **sym);
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 8d85de5..846ab58 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -2111,3 +2111,158 @@ bfd_get_compression_header_size (bfd *abfd, asection *sec)
return 0;
}
+
+/*
+FUNCTION
+ bfd_convert_section_size
+
+SYNOPSIS
+ bfd_size_type bfd_convert_section_size
+ (bfd *ibfd, asection *isec, bfd *obfd, bfd_size_type size);
+
+DESCRIPTION
+ Convert the size @var{size} of the section @var{isec} in input
+ BFD @var{ibfd} to the section size in output BFD @var{obfd}.
+*/
+
+bfd_size_type
+bfd_convert_section_size (bfd *ibfd, sec_ptr isec, bfd *obfd,
+ bfd_size_type size)
+{
+ bfd_size_type hdr_size;
+
+ /* Do nothing if input file will be decompressed. */
+ if ((ibfd->flags & BFD_DECOMPRESS))
+ return size;
+
+ /* Do nothing if either input or output aren't ELF. */
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return size;
+
+ /* Do nothing if ELF classes of input and output are the same. */
+ if (get_elf_backend_data (ibfd)->s->elfclass
+ == get_elf_backend_data (obfd)->s->elfclass)
+ return size;
+
+ /* Do nothing if the input section isn't a SHF_COMPRESSED section. */
+ hdr_size = bfd_get_compression_header_size (ibfd, isec);
+ if (hdr_size == 0)
+ return size;
+
+ /* Adjust the size of the output SHF_COMPRESSED section. */
+ if (hdr_size == sizeof (Elf32_External_Chdr))
+ return (size - sizeof (Elf32_External_Chdr)
+ + sizeof (Elf64_External_Chdr));
+ else
+ return (size - sizeof (Elf64_External_Chdr)
+ + sizeof (Elf32_External_Chdr));
+}
+
+/*
+FUNCTION
+ bfd_convert_section_contents
+
+SYNOPSIS
+ bfd_boolean bfd_convert_section_contents
+ (bfd *ibfd, asection *isec, bfd *obfd, bfd_byte **ptr);
+
+DESCRIPTION
+ Convert the contents, stored in @var{*ptr}, of the section
+ @var{isec} in input BFD @var{ibfd} to output BFD @var{obfd}
+ if needed. The original buffer pointed to by @var{*ptr} may
+ be freed and @var{*ptr} is returned with memory malloc'd by this
+ function.
+*/
+
+bfd_boolean
+bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd,
+ bfd_byte **ptr)
+{
+ bfd_byte *contents;
+ bfd_size_type ihdr_size, ohdr_size, size;
+ Elf_Internal_Chdr chdr;
+ bfd_boolean use_memmove;
+
+ /* Do nothing if input file will be decompressed. */
+ if ((ibfd->flags & BFD_DECOMPRESS))
+ return TRUE;
+
+ /* Do nothing if either input or output aren't ELF. */
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ /* Do nothing if ELF classes of input and output are the same. */
+ if (get_elf_backend_data (ibfd)->s->elfclass
+ == get_elf_backend_data (obfd)->s->elfclass)
+ return TRUE;
+
+ /* Do nothing if the input section isn't a SHF_COMPRESSED section. */
+ ihdr_size = bfd_get_compression_header_size (ibfd, isec);
+ if (ihdr_size == 0)
+ return TRUE;
+
+ contents = *ptr;
+
+ /* Convert the contents of the input SHF_COMPRESSED section to
+ output. Get the input compression header and the size of the
+ output compression header. */
+ if (ihdr_size == sizeof (Elf32_External_Chdr))
+ {
+ Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents;
+ chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type);
+ chdr.ch_size = bfd_get_32 (ibfd, &echdr->ch_size);
+ chdr.ch_addralign = bfd_get_32 (ibfd, &echdr->ch_addralign);
+
+ ohdr_size = sizeof (Elf64_External_Chdr);
+
+ use_memmove = FALSE;
+ }
+ else
+ {
+ Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
+ chdr.ch_type = bfd_get_64 (ibfd, &echdr->ch_type);
+ chdr.ch_size = bfd_get_64 (ibfd, &echdr->ch_size);
+ chdr.ch_addralign = bfd_get_64 (ibfd, &echdr->ch_addralign);
+
+ ohdr_size = sizeof (Elf32_External_Chdr);
+ use_memmove = TRUE;
+ }
+
+ size = bfd_get_section_size (isec) - ihdr_size + ohdr_size;
+ if (!use_memmove)
+ {
+ contents = (bfd_byte *) bfd_malloc (size);
+ if (contents == NULL)
+ return FALSE;
+ }
+
+ /* Write out the output compression header. */
+ if (ohdr_size == sizeof (Elf32_External_Chdr))
+ {
+ Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents;
+ bfd_put_32 (obfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
+ bfd_put_32 (obfd, chdr.ch_size, &echdr->ch_size);
+ bfd_put_32 (obfd, chdr.ch_addralign, &echdr->ch_addralign);
+ }
+ else
+ {
+ Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents;
+ bfd_put_64 (obfd, ELFCOMPRESS_ZLIB, &echdr->ch_type);
+ bfd_put_64 (obfd, chdr.ch_size, &echdr->ch_size);
+ bfd_put_64 (obfd, chdr.ch_addralign, &echdr->ch_addralign);
+ }
+
+ /* Copy the compressed contents. */
+ if (use_memmove)
+ memmove (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size);
+ else
+ {
+ memcpy (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size);
+ free (*ptr);
+ *ptr = contents;
+ }
+
+ return TRUE;
+}
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 09b0e1c..c504b33 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,5 +1,14 @@
2015-07-10 H.J. Lu <hongjiu.lu@intel.com>
+ PR binutils/18656
+ * objcopy.c (setup_section): Call bfd_convert_section_size
+ to get the output section size.
+ (copy_section): Get the section size from the output section
+ and call bfd_get_full_section_contents to convert section
+ contents for output.
+
+2015-07-10 H.J. Lu <hongjiu.lu@intel.com>
+
* readelf.c (dump_section_as_strings): Warn unsupported compress
type and corrupted compressed section.
(dump_section_as_bytes): Likewise.
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 7f1bd76..d6516e0 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -2872,6 +2872,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
elf_section_type (osection) = SHT_NOBITS;
size = bfd_section_size (ibfd, isection);
+ size = bfd_convert_section_size (ibfd, isection, obfd, size);
if (copy_byte >= 0)
size = (size + interleave - 1) / interleave * copy_width;
else if (extract_symbol)
@@ -3109,14 +3110,20 @@ copy_section (bfd *ibfd, sec_ptr isection, void *obfdarg)
return;
osection = isection->output_section;
- size = bfd_get_section_size (isection);
+ /* The output SHF_COMPRESSED section size is different from input if
+ ELF classes of input and output aren't the same. We must use the
+ output section size here, which has been updated in setup_section
+ via bfd_convert_section_size. */
+ size = bfd_get_section_size (osection);
if (bfd_get_section_flags (ibfd, isection) & SEC_HAS_CONTENTS
&& bfd_get_section_flags (obfd, osection) & SEC_HAS_CONTENTS)
{
bfd_byte *memhunk = NULL;
- if (!bfd_get_full_section_contents (ibfd, isection, &memhunk))
+ if (!bfd_get_full_section_contents (ibfd, isection, &memhunk)
+ || !bfd_convert_section_contents (ibfd, isection, obfd,
+ &memhunk))
{
status = 1;
bfd_nonfatal_message (NULL, ibfd, isection, NULL);
diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog
index ebc35c3..435961a 100644
--- a/binutils/testsuite/ChangeLog
+++ b/binutils/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2015-07-10 H.J. Lu <hongjiu.lu@intel.com>
+ PR binutils/18656
+ * binutils-all/compress.exp (convert_test): New proc.
+ Run conversion tests between x86-64 and x32.
+
+2015-07-10 H.J. Lu <hongjiu.lu@intel.com>
+
* binutils-all/dw2-3.W: Updated to accept .debug_* sections.
2015-05-20 Ed Maste <emaste@freebsd.org>
diff --git a/binutils/testsuite/binutils-all/compress.exp b/binutils/testsuite/binutils-all/compress.exp
index 43a3ce1..abff197 100644
--- a/binutils/testsuite/binutils-all/compress.exp
+++ b/binutils/testsuite/binutils-all/compress.exp
@@ -570,3 +570,96 @@ if { [regexp_diff objdump.out $srcdir/$subdir/dw2-3gabi.W] } then {
} else {
pass "$testname"
}
+
+proc convert_test { testname as_flags objcop_flags } {
+ global srcdir
+ global subdir
+ global testfile3
+ global copyfile
+ global OBJCOPY
+ global OBJDUMP
+
+ if { ![binutils_assemble_flags $srcdir/$subdir/dw2-3.S ${testfile3}.o "$as_flags"] } then {
+ unresolved "$testname"
+ return
+ }
+
+ set got [binutils_run $OBJCOPY "$objcop_flags ${testfile3}.o ${copyfile}.o"]
+ if ![string match "" $got] then {
+ fail "objcopy ($testname)"
+ return
+ }
+
+ set got [remote_exec host "$OBJDUMP -W ${copyfile}.o" "" "/dev/null" "objdump.out"]
+
+ if { [lindex $got 0] != 0 || ![string match "" [lindex $got 1]] } then {
+ fail "$testname (reason: unexpected output)"
+ send_log $got
+ send_log "\n"
+ return
+ }
+
+ if { [regexp_diff objdump.out $srcdir/$subdir/dw2-3.W] } then {
+ fail "$testname"
+ } else {
+ pass "$testname"
+ }
+}
+
+if { ([istarget "x86_64-*-elf*"]
+ || [istarget "x86_64-*-linux*"]) } {
+ set testname "Convert x86-64 object with zlib-gabi to x32 (1)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gabi --64" "-O elf32-x86-64"
+
+ set testname "Convert x86-64 object with zlib-gabi to x32 (2)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gabi --64" "-O elf32-x86-64 --compress-debug-sections=zlib-gnu"
+
+ set testname "Convert x86-64 object with zlib-gabi to x32 (3)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gabi --64" "-O elf32-x86-64 --decompress-debug-sections"
+
+ set testname "Convert x86-64 object with zlib-gnu to x32 (1)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gnu --64" "-O elf32-x86-64"
+
+ set testname "Convert x86-64 object with zlib-gnu to x32 (2)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gnu --64" "-O elf32-x86-64 --compress-debug-sections=zlib-gabi"
+
+ set testname "Convert x86-64 object with zlib-gnu to x32 (3)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gnu --64" "-O elf32-x86-64 --decompress-debug-sections"
+
+ set testname "Convert x86-64 object to x32 (1)"
+ convert_test "$testname" "--nocompress-debug-sections --64" "-O elf32-x86-64"
+
+ set testname "Convert x86-64 object to x32 (2)"
+ convert_test "$testname" "--nocompress-debug-sections --64" "-O elf32-x86-64 --compress-debug-sections=zlib-gabi"
+
+ set testname "Convert x86-64 object to x32 (3)"
+ convert_test "$testname" "--nocompress-debug-sections --64" "-O elf32-x86-64 --compress-debug-sections=zlib-gnu"
+
+
+ set testname "Convert x32 object with zlib-gabi to x86-64 (1)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gabi --x32" "-O elf64-x86-64"
+
+ set testname "Convert x32 object with zlib-gabi to x86-64 (2)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gabi --x32" "-O elf64-x86-64 --compress-debug-sections=zlib-gnu"
+
+ set testname "Convert x32 object with zlib-gabi to x86-64 (3)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gabi --x32" "-O elf64-x86-64 --decompress-debug-sections"
+
+ set testname "Convert x32 object with zlib-gnu to x86-64 (1)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gnu --x32" "-O elf64-x86-64"
+
+ set testname "Convert x32 object with zlib-gnu to x86-64 (2)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gnu --x32" "-O elf64-x86-64 --compress-debug-sections=zlib-gabi"
+
+ set testname "Convert x32 object with zlib-gnu to x86-64 (3)"
+ convert_test "$testname" "--compress-debug-sections=zlib-gnu --x32" "-O elf64-x86-64 --decompress-debug-sections"
+
+ set testname "Convert x32 object to x86-64 (1)"
+ convert_test "$testname" "--nocompress-debug-sections --x32" "-O elf64-x86-64"
+
+ set testname "Convert x32 object to x86-64 (2)"
+ convert_test "$testname" "--nocompress-debug-sections --x32" "-O elf64-x86-64 --compress-debug-sections=zlib-gabi"
+
+ set testname "Convert x32 object to x86-64 (3)"
+ convert_test "$testname" "--nocompress-debug-sections --x32" "-O elf64-x86-64 --compress-debug-sections=zlib-gnu"
+ }