diff options
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 6 | ||||
-rw-r--r-- | bfd/bfd.c | 155 | ||||
-rw-r--r-- | binutils/ChangeLog | 9 | ||||
-rw-r--r-- | binutils/objcopy.c | 11 | ||||
-rw-r--r-- | binutils/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | binutils/testsuite/binutils-all/compress.exp | 93 |
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); @@ -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" + } |