diff options
Diffstat (limited to '0007-PR23919-Handle-ELF-compressed-header-alignment.patch')
-rw-r--r-- | 0007-PR23919-Handle-ELF-compressed-header-alignment.patch | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/0007-PR23919-Handle-ELF-compressed-header-alignment.patch b/0007-PR23919-Handle-ELF-compressed-header-alignment.patch new file mode 100644 index 000000000000..b551c4075a12 --- /dev/null +++ b/0007-PR23919-Handle-ELF-compressed-header-alignment.patch @@ -0,0 +1,316 @@ +commit 4207142d6a5d2359170c5f9a140fc1a2351fbda9 +Author: Mark Wielaard <mark@klomp.org> +Date: Tue Nov 27 11:59:10 2018 +0000 + + 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. + +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index ee8cd7ef0b..6d92c51cb9 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -7419,7 +7419,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); + +@@ -8006,7 +8007,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 15becd7ae8..2b658298ea 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 bebda20195..604971dd4c 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 39744009ab..afb039f7b7 100644 +--- a/binutils/readelf.c ++++ b/binutils/readelf.c +@@ -13397,12 +13397,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; +@@ -13544,12 +13538,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; +@@ -13719,12 +13707,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 |