| From bb9c8cc3c5f4ffd6019a8c53adead429954162e1 Mon Sep 17 00:00:00 2001 |
| From: Mark Wielaard <mark@klomp.org> |
| Date: Tue, 27 Nov 2018 11:59:10 +0000 |
| Subject: [PATCH 1/2] Handle ELF compressed header alignment correctly by |
| setting up the section alignment correctly for the Elf32_Chdr or Elf64_Chdr |
| type and respect the ch_addralign field when decompressing the section data. |
| |
| PR binutils/23919 |
| binutils* readelf.c (dump_sections_as_strings): Remove bogus addralign check. |
| (dump_sections_as_bytes): Likewise. |
| (load_specific_debug_sections): Likewise. |
| * testsuite/binutils-all/dw2-3.rS: Adjust alignment. |
| * testsuite/binutils-all/dw2-3.rt: Likewise. |
| |
| bfd * bfd.c (bfd_update_compression_header): Explicitly set alignment. |
| (bfd_check_compression_header): Add uncompressed_alignment_power |
| argument. Check ch_addralign is a power of 2. |
| * bfd-in2.h: Regenerated. |
| * compress.c (bfd_compress_section_contents): Get and set |
| orig_uncompressed_alignment_pow if section is decompressed. |
| (bfd_is_section_compressed_with_header): Add and get |
| uncompressed_align_pow_p argument. |
| (bfd_is_section_compressed): Add uncompressed_align_power argument |
| to bfd_is_section_compressed_with_header call. |
| (bfd_init_section_decompress_status): Get and set |
| uncompressed_alignment_power. |
| * elf.c (_bfd_elf_make_section_from_shdr): Add |
| uncompressed_align_power argument to |
| bfd_is_section_compressed_with_header call. |
| --- |
| bfd/bfd-in2.h | 6 ++-- |
| bfd/bfd.c | 20 ++++++++++---- |
| bfd/compress.c | 35 +++++++++++++++++------- |
| bfd/elf.c | 5 ++-- |
| binutils/readelf.c | 18 ------------ |
| binutils/testsuite/binutils-all/dw2-3.rS | 2 +- |
| binutils/testsuite/binutils-all/dw2-3.rt | 2 +- |
| 7 files changed, 49 insertions(+), 39 deletions(-) |
| |
| Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4207142d6a5d2359170c5f9a140fc1a2351fbda9] |
| Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| |
| diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h |
| index f53dbb5e8c..d0c2190d0b 100644 |
| --- a/bfd/bfd-in2.h |
| +++ b/bfd/bfd-in2.h |
| @@ -7279,7 +7279,8 @@ void bfd_update_compression_header |
| |
| bfd_boolean bfd_check_compression_header |
| (bfd *abfd, bfd_byte *contents, asection *sec, |
| - bfd_size_type *uncompressed_size); |
| + bfd_size_type *uncompressed_size, |
| + unsigned int *uncompressed_alignment_power); |
| |
| int bfd_get_compression_header_size (bfd *abfd, asection *sec); |
| |
| @@ -7855,7 +7856,8 @@ void bfd_cache_section_contents |
| bfd_boolean bfd_is_section_compressed_with_header |
| (bfd *abfd, asection *section, |
| int *compression_header_size_p, |
| - bfd_size_type *uncompressed_size_p); |
| + bfd_size_type *uncompressed_size_p, |
| + unsigned int *uncompressed_alignment_power_p); |
| |
| bfd_boolean bfd_is_section_compressed |
| (bfd *abfd, asection *section); |
| diff --git a/bfd/bfd.c b/bfd/bfd.c |
| index 851710401e..ea10d7b185 100644 |
| --- a/bfd/bfd.c |
| +++ b/bfd/bfd.c |
| @@ -2332,6 +2332,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| bfd_put_32 (abfd, sec->size, &echdr->ch_size); |
| bfd_put_32 (abfd, 1 << sec->alignment_power, |
| &echdr->ch_addralign); |
| + /* bfd_log2 (alignof (Elf32_Chdr)) */ |
| + bfd_set_section_alignment (abfd, sec, 2); |
| } |
| else |
| { |
| @@ -2342,6 +2344,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| bfd_put_64 (abfd, sec->size, &echdr->ch_size); |
| bfd_put_64 (abfd, 1 << sec->alignment_power, |
| &echdr->ch_addralign); |
| + /* bfd_log2 (alignof (Elf64_Chdr)) */ |
| + bfd_set_section_alignment (abfd, sec, 3); |
| } |
| } |
| else |
| @@ -2354,6 +2358,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| order. */ |
| memcpy (contents, "ZLIB", 4); |
| bfd_putb64 (sec->size, contents + 4); |
| + /* No way to keep the original alignment, just use 1 always. */ |
| + bfd_set_section_alignment (abfd, sec, 0); |
| } |
| } |
| } |
| @@ -2368,12 +2374,14 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| SYNOPSIS |
| bfd_boolean bfd_check_compression_header |
| (bfd *abfd, bfd_byte *contents, asection *sec, |
| - bfd_size_type *uncompressed_size); |
| + bfd_size_type *uncompressed_size, |
| + unsigned int *uncompressed_alignment_power); |
| |
| DESCRIPTION |
| Check the compression header at CONTENTS of SEC in ABFD and |
| - store the uncompressed size in UNCOMPRESSED_SIZE if the |
| - compression header is valid. |
| + store the uncompressed size in UNCOMPRESSED_SIZE and the |
| + uncompressed data alignment in UNCOMPRESSED_ALIGNMENT_POWER |
| + if the compression header is valid. |
| |
| RETURNS |
| Return TRUE if the compression header is valid. |
| @@ -2382,7 +2390,8 @@ RETURNS |
| bfd_boolean |
| bfd_check_compression_header (bfd *abfd, bfd_byte *contents, |
| asection *sec, |
| - bfd_size_type *uncompressed_size) |
| + bfd_size_type *uncompressed_size, |
| + unsigned int *uncompressed_alignment_power) |
| { |
| if (bfd_get_flavour (abfd) == bfd_target_elf_flavour |
| && (elf_section_flags (sec) & SHF_COMPRESSED) != 0) |
| @@ -2404,9 +2413,10 @@ bfd_check_compression_header (bfd *abfd, bfd_byte *contents, |
| chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign); |
| } |
| if (chdr.ch_type == ELFCOMPRESS_ZLIB |
| - && chdr.ch_addralign == 1U << sec->alignment_power) |
| + && chdr.ch_addralign == (1U << bfd_log2 (chdr.ch_addralign))) |
| { |
| *uncompressed_size = chdr.ch_size; |
| + *uncompressed_alignment_power = bfd_log2 (chdr.ch_addralign); |
| return TRUE; |
| } |
| } |
| diff --git a/bfd/compress.c b/bfd/compress.c |
| index 53e566e498..97ea624eb8 100644 |
| --- a/bfd/compress.c |
| +++ b/bfd/compress.c |
| @@ -84,11 +84,13 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, |
| int zlib_size = 0; |
| int orig_compression_header_size; |
| bfd_size_type orig_uncompressed_size; |
| + unsigned int orig_uncompressed_alignment_pow; |
| int header_size = bfd_get_compression_header_size (abfd, NULL); |
| bfd_boolean compressed |
| = bfd_is_section_compressed_with_header (abfd, sec, |
| &orig_compression_header_size, |
| - &orig_uncompressed_size); |
| + &orig_uncompressed_size, |
| + &orig_uncompressed_alignment_pow); |
| |
| /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size, |
| overhead in .zdebug* section. */ |
| @@ -153,6 +155,9 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, |
| return 0; |
| } |
| free (uncompressed_buffer); |
| + bfd_set_section_alignment (abfd, sec, |
| + orig_uncompressed_alignment_pow); |
| + |
| sec->contents = buffer; |
| sec->compress_status = COMPRESS_SECTION_DONE; |
| return orig_uncompressed_size; |
| @@ -364,20 +369,24 @@ SYNOPSIS |
| bfd_boolean bfd_is_section_compressed_with_header |
| (bfd *abfd, asection *section, |
| int *compression_header_size_p, |
| - bfd_size_type *uncompressed_size_p); |
| + bfd_size_type *uncompressed_size_p, |
| + unsigned int *uncompressed_alignment_power_p); |
| |
| DESCRIPTION |
| Return @code{TRUE} if @var{section} is compressed. Compression |
| - header size is returned in @var{compression_header_size_p} and |
| - uncompressed size is returned in @var{uncompressed_size_p}. If |
| - compression is unsupported, compression header size is returned |
| - with -1 and uncompressed size is returned with 0. |
| + header size is returned in @var{compression_header_size_p}, |
| + uncompressed size is returned in @var{uncompressed_size_p} |
| + and the uncompressed data alignement power is returned in |
| + @var{uncompressed_align_pow_p}. If compression is |
| + unsupported, compression header size is returned with -1 |
| + and uncompressed size is returned with 0. |
| */ |
| |
| bfd_boolean |
| bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, |
| int *compression_header_size_p, |
| - bfd_size_type *uncompressed_size_p) |
| + bfd_size_type *uncompressed_size_p, |
| + unsigned int *uncompressed_align_pow_p) |
| { |
| bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
| int compression_header_size; |
| @@ -412,7 +421,8 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, |
| if (compression_header_size != 0) |
| { |
| if (!bfd_check_compression_header (abfd, header, sec, |
| - uncompressed_size_p)) |
| + uncompressed_size_p, |
| + uncompressed_align_pow_p)) |
| compression_header_size = -1; |
| } |
| /* Check for the pathalogical case of a debug string section that |
| @@ -449,9 +459,11 @@ bfd_is_section_compressed (bfd *abfd, sec_ptr sec) |
| { |
| int compression_header_size; |
| bfd_size_type uncompressed_size; |
| + unsigned int uncompressed_align_power; |
| return (bfd_is_section_compressed_with_header (abfd, sec, |
| &compression_header_size, |
| - &uncompressed_size) |
| + &uncompressed_size, |
| + &uncompressed_align_power) |
| && compression_header_size >= 0 |
| && uncompressed_size > 0); |
| } |
| @@ -480,6 +492,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
| int compression_header_size; |
| int header_size; |
| bfd_size_type uncompressed_size; |
| + unsigned int uncompressed_alignment_power = 0; |
| |
| compression_header_size = bfd_get_compression_header_size (abfd, sec); |
| if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) |
| @@ -508,7 +521,8 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
| uncompressed_size = bfd_getb64 (header + 4); |
| } |
| else if (!bfd_check_compression_header (abfd, header, sec, |
| - &uncompressed_size)) |
| + &uncompressed_size, |
| + &uncompressed_alignment_power)) |
| { |
| bfd_set_error (bfd_error_wrong_format); |
| return FALSE; |
| @@ -516,6 +530,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
| |
| sec->compressed_size = sec->size; |
| sec->size = uncompressed_size; |
| + bfd_set_section_alignment (abfd, sec, uncompressed_alignment_power); |
| sec->compress_status = DECOMPRESS_SECTION_SIZED; |
| |
| return TRUE; |
| diff --git a/bfd/elf.c b/bfd/elf.c |
| index 828241d48a..c4f131ddcf 100644 |
| --- a/bfd/elf.c |
| +++ b/bfd/elf.c |
| @@ -1177,11 +1177,12 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, |
| enum { nothing, compress, decompress } action = nothing; |
| int compression_header_size; |
| bfd_size_type uncompressed_size; |
| + unsigned int uncompressed_align_power; |
| bfd_boolean compressed |
| = bfd_is_section_compressed_with_header (abfd, newsect, |
| &compression_header_size, |
| - &uncompressed_size); |
| - |
| + &uncompressed_size, |
| + &uncompressed_align_power); |
| if (compressed) |
| { |
| /* Compressed section. Check if we should decompress. */ |
| diff --git a/binutils/readelf.c b/binutils/readelf.c |
| index f4df697a7d..4b0efa884f 100644 |
| --- a/binutils/readelf.c |
| +++ b/binutils/readelf.c |
| @@ -13345,12 +13345,6 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) |
| printable_section_name (filedata, section), chdr.ch_type); |
| return FALSE; |
| } |
| - else if (chdr.ch_addralign != section->sh_addralign) |
| - { |
| - warn (_("compressed section '%s' is corrupted\n"), |
| - printable_section_name (filedata, section)); |
| - return FALSE; |
| - } |
| uncompressed_size = chdr.ch_size; |
| start += compression_header_size; |
| new_size -= compression_header_size; |
| @@ -13492,12 +13486,6 @@ dump_section_as_bytes (Elf_Internal_Shdr * section, |
| printable_section_name (filedata, section), chdr.ch_type); |
| return FALSE; |
| } |
| - else if (chdr.ch_addralign != section->sh_addralign) |
| - { |
| - warn (_("compressed section '%s' is corrupted\n"), |
| - printable_section_name (filedata, section)); |
| - return FALSE; |
| - } |
| uncompressed_size = chdr.ch_size; |
| start += compression_header_size; |
| new_size -= compression_header_size; |
| @@ -13667,12 +13655,6 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, |
| section->name, chdr.ch_type); |
| return FALSE; |
| } |
| - else if (chdr.ch_addralign != sec->sh_addralign) |
| - { |
| - warn (_("compressed section '%s' is corrupted\n"), |
| - section->name); |
| - return FALSE; |
| - } |
| uncompressed_size = chdr.ch_size; |
| start += compression_header_size; |
| size -= compression_header_size; |
| diff --git a/binutils/testsuite/binutils-all/dw2-3.rS b/binutils/testsuite/binutils-all/dw2-3.rS |
| index f1637e9149..86bc73d9a2 100644 |
| --- a/binutils/testsuite/binutils-all/dw2-3.rS |
| +++ b/binutils/testsuite/binutils-all/dw2-3.rS |
| @@ -1,3 +1,3 @@ |
| #... |
| - +\[[ 0-9]+\] .debug_info +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +C +0 +0 +1 |
| + +\[[ 0-9]+\] .debug_info +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +C +0 +0 +(4|8) |
| #pass |
| diff --git a/binutils/testsuite/binutils-all/dw2-3.rt b/binutils/testsuite/binutils-all/dw2-3.rt |
| index f59cbaa22b..74e7f8deca 100644 |
| --- a/binutils/testsuite/binutils-all/dw2-3.rt |
| +++ b/binutils/testsuite/binutils-all/dw2-3.rt |
| @@ -1,6 +1,6 @@ |
| #... |
| +\[[ 0-9]+\] .debug_info |
| - +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0 +0 +1 |
| + +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0 +0 +(4|8) |
| +\[0+800\]: COMPRESSED |
| +ZLIB, 0+9d, 1 |
| #pass |
| -- |
| 2.20.1 |
| |