Brad Bishop | 977dc1a | 2019-02-06 16:01:43 -0500 | [diff] [blame] | 1 | From bb9c8cc3c5f4ffd6019a8c53adead429954162e1 Mon Sep 17 00:00:00 2001 |
| 2 | From: Mark Wielaard <mark@klomp.org> |
| 3 | Date: Tue, 27 Nov 2018 11:59:10 +0000 |
| 4 | Subject: [PATCH 1/2] Handle ELF compressed header alignment correctly by |
| 5 | setting up the section alignment correctly for the Elf32_Chdr or Elf64_Chdr |
| 6 | type and respect the ch_addralign field when decompressing the section data. |
| 7 | |
| 8 | PR binutils/23919 |
| 9 | binutils* readelf.c (dump_sections_as_strings): Remove bogus addralign check. |
| 10 | (dump_sections_as_bytes): Likewise. |
| 11 | (load_specific_debug_sections): Likewise. |
| 12 | * testsuite/binutils-all/dw2-3.rS: Adjust alignment. |
| 13 | * testsuite/binutils-all/dw2-3.rt: Likewise. |
| 14 | |
| 15 | bfd * bfd.c (bfd_update_compression_header): Explicitly set alignment. |
| 16 | (bfd_check_compression_header): Add uncompressed_alignment_power |
| 17 | argument. Check ch_addralign is a power of 2. |
| 18 | * bfd-in2.h: Regenerated. |
| 19 | * compress.c (bfd_compress_section_contents): Get and set |
| 20 | orig_uncompressed_alignment_pow if section is decompressed. |
| 21 | (bfd_is_section_compressed_with_header): Add and get |
| 22 | uncompressed_align_pow_p argument. |
| 23 | (bfd_is_section_compressed): Add uncompressed_align_power argument |
| 24 | to bfd_is_section_compressed_with_header call. |
| 25 | (bfd_init_section_decompress_status): Get and set |
| 26 | uncompressed_alignment_power. |
| 27 | * elf.c (_bfd_elf_make_section_from_shdr): Add |
| 28 | uncompressed_align_power argument to |
| 29 | bfd_is_section_compressed_with_header call. |
| 30 | --- |
| 31 | bfd/bfd-in2.h | 6 ++-- |
| 32 | bfd/bfd.c | 20 ++++++++++---- |
| 33 | bfd/compress.c | 35 +++++++++++++++++------- |
| 34 | bfd/elf.c | 5 ++-- |
| 35 | binutils/readelf.c | 18 ------------ |
| 36 | binutils/testsuite/binutils-all/dw2-3.rS | 2 +- |
| 37 | binutils/testsuite/binutils-all/dw2-3.rt | 2 +- |
| 38 | 7 files changed, 49 insertions(+), 39 deletions(-) |
| 39 | |
| 40 | Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4207142d6a5d2359170c5f9a140fc1a2351fbda9] |
| 41 | Signed-off-by: Khem Raj <raj.khem@gmail.com> |
| 42 | |
| 43 | diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h |
| 44 | index f53dbb5e8c..d0c2190d0b 100644 |
| 45 | --- a/bfd/bfd-in2.h |
| 46 | +++ b/bfd/bfd-in2.h |
| 47 | @@ -7279,7 +7279,8 @@ void bfd_update_compression_header |
| 48 | |
| 49 | bfd_boolean bfd_check_compression_header |
| 50 | (bfd *abfd, bfd_byte *contents, asection *sec, |
| 51 | - bfd_size_type *uncompressed_size); |
| 52 | + bfd_size_type *uncompressed_size, |
| 53 | + unsigned int *uncompressed_alignment_power); |
| 54 | |
| 55 | int bfd_get_compression_header_size (bfd *abfd, asection *sec); |
| 56 | |
| 57 | @@ -7855,7 +7856,8 @@ void bfd_cache_section_contents |
| 58 | bfd_boolean bfd_is_section_compressed_with_header |
| 59 | (bfd *abfd, asection *section, |
| 60 | int *compression_header_size_p, |
| 61 | - bfd_size_type *uncompressed_size_p); |
| 62 | + bfd_size_type *uncompressed_size_p, |
| 63 | + unsigned int *uncompressed_alignment_power_p); |
| 64 | |
| 65 | bfd_boolean bfd_is_section_compressed |
| 66 | (bfd *abfd, asection *section); |
| 67 | diff --git a/bfd/bfd.c b/bfd/bfd.c |
| 68 | index 851710401e..ea10d7b185 100644 |
| 69 | --- a/bfd/bfd.c |
| 70 | +++ b/bfd/bfd.c |
| 71 | @@ -2332,6 +2332,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| 72 | bfd_put_32 (abfd, sec->size, &echdr->ch_size); |
| 73 | bfd_put_32 (abfd, 1 << sec->alignment_power, |
| 74 | &echdr->ch_addralign); |
| 75 | + /* bfd_log2 (alignof (Elf32_Chdr)) */ |
| 76 | + bfd_set_section_alignment (abfd, sec, 2); |
| 77 | } |
| 78 | else |
| 79 | { |
| 80 | @@ -2342,6 +2344,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| 81 | bfd_put_64 (abfd, sec->size, &echdr->ch_size); |
| 82 | bfd_put_64 (abfd, 1 << sec->alignment_power, |
| 83 | &echdr->ch_addralign); |
| 84 | + /* bfd_log2 (alignof (Elf64_Chdr)) */ |
| 85 | + bfd_set_section_alignment (abfd, sec, 3); |
| 86 | } |
| 87 | } |
| 88 | else |
| 89 | @@ -2354,6 +2358,8 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| 90 | order. */ |
| 91 | memcpy (contents, "ZLIB", 4); |
| 92 | bfd_putb64 (sec->size, contents + 4); |
| 93 | + /* No way to keep the original alignment, just use 1 always. */ |
| 94 | + bfd_set_section_alignment (abfd, sec, 0); |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | @@ -2368,12 +2374,14 @@ bfd_update_compression_header (bfd *abfd, bfd_byte *contents, |
| 99 | SYNOPSIS |
| 100 | bfd_boolean bfd_check_compression_header |
| 101 | (bfd *abfd, bfd_byte *contents, asection *sec, |
| 102 | - bfd_size_type *uncompressed_size); |
| 103 | + bfd_size_type *uncompressed_size, |
| 104 | + unsigned int *uncompressed_alignment_power); |
| 105 | |
| 106 | DESCRIPTION |
| 107 | Check the compression header at CONTENTS of SEC in ABFD and |
| 108 | - store the uncompressed size in UNCOMPRESSED_SIZE if the |
| 109 | - compression header is valid. |
| 110 | + store the uncompressed size in UNCOMPRESSED_SIZE and the |
| 111 | + uncompressed data alignment in UNCOMPRESSED_ALIGNMENT_POWER |
| 112 | + if the compression header is valid. |
| 113 | |
| 114 | RETURNS |
| 115 | Return TRUE if the compression header is valid. |
| 116 | @@ -2382,7 +2390,8 @@ RETURNS |
| 117 | bfd_boolean |
| 118 | bfd_check_compression_header (bfd *abfd, bfd_byte *contents, |
| 119 | asection *sec, |
| 120 | - bfd_size_type *uncompressed_size) |
| 121 | + bfd_size_type *uncompressed_size, |
| 122 | + unsigned int *uncompressed_alignment_power) |
| 123 | { |
| 124 | if (bfd_get_flavour (abfd) == bfd_target_elf_flavour |
| 125 | && (elf_section_flags (sec) & SHF_COMPRESSED) != 0) |
| 126 | @@ -2404,9 +2413,10 @@ bfd_check_compression_header (bfd *abfd, bfd_byte *contents, |
| 127 | chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign); |
| 128 | } |
| 129 | if (chdr.ch_type == ELFCOMPRESS_ZLIB |
| 130 | - && chdr.ch_addralign == 1U << sec->alignment_power) |
| 131 | + && chdr.ch_addralign == (1U << bfd_log2 (chdr.ch_addralign))) |
| 132 | { |
| 133 | *uncompressed_size = chdr.ch_size; |
| 134 | + *uncompressed_alignment_power = bfd_log2 (chdr.ch_addralign); |
| 135 | return TRUE; |
| 136 | } |
| 137 | } |
| 138 | diff --git a/bfd/compress.c b/bfd/compress.c |
| 139 | index 53e566e498..97ea624eb8 100644 |
| 140 | --- a/bfd/compress.c |
| 141 | +++ b/bfd/compress.c |
| 142 | @@ -84,11 +84,13 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, |
| 143 | int zlib_size = 0; |
| 144 | int orig_compression_header_size; |
| 145 | bfd_size_type orig_uncompressed_size; |
| 146 | + unsigned int orig_uncompressed_alignment_pow; |
| 147 | int header_size = bfd_get_compression_header_size (abfd, NULL); |
| 148 | bfd_boolean compressed |
| 149 | = bfd_is_section_compressed_with_header (abfd, sec, |
| 150 | &orig_compression_header_size, |
| 151 | - &orig_uncompressed_size); |
| 152 | + &orig_uncompressed_size, |
| 153 | + &orig_uncompressed_alignment_pow); |
| 154 | |
| 155 | /* Either ELF compression header or the 12-byte, "ZLIB" + 8-byte size, |
| 156 | overhead in .zdebug* section. */ |
| 157 | @@ -153,6 +155,9 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec, |
| 158 | return 0; |
| 159 | } |
| 160 | free (uncompressed_buffer); |
| 161 | + bfd_set_section_alignment (abfd, sec, |
| 162 | + orig_uncompressed_alignment_pow); |
| 163 | + |
| 164 | sec->contents = buffer; |
| 165 | sec->compress_status = COMPRESS_SECTION_DONE; |
| 166 | return orig_uncompressed_size; |
| 167 | @@ -364,20 +369,24 @@ SYNOPSIS |
| 168 | bfd_boolean bfd_is_section_compressed_with_header |
| 169 | (bfd *abfd, asection *section, |
| 170 | int *compression_header_size_p, |
| 171 | - bfd_size_type *uncompressed_size_p); |
| 172 | + bfd_size_type *uncompressed_size_p, |
| 173 | + unsigned int *uncompressed_alignment_power_p); |
| 174 | |
| 175 | DESCRIPTION |
| 176 | Return @code{TRUE} if @var{section} is compressed. Compression |
| 177 | - header size is returned in @var{compression_header_size_p} and |
| 178 | - uncompressed size is returned in @var{uncompressed_size_p}. If |
| 179 | - compression is unsupported, compression header size is returned |
| 180 | - with -1 and uncompressed size is returned with 0. |
| 181 | + header size is returned in @var{compression_header_size_p}, |
| 182 | + uncompressed size is returned in @var{uncompressed_size_p} |
| 183 | + and the uncompressed data alignement power is returned in |
| 184 | + @var{uncompressed_align_pow_p}. If compression is |
| 185 | + unsupported, compression header size is returned with -1 |
| 186 | + and uncompressed size is returned with 0. |
| 187 | */ |
| 188 | |
| 189 | bfd_boolean |
| 190 | bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, |
| 191 | int *compression_header_size_p, |
| 192 | - bfd_size_type *uncompressed_size_p) |
| 193 | + bfd_size_type *uncompressed_size_p, |
| 194 | + unsigned int *uncompressed_align_pow_p) |
| 195 | { |
| 196 | bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; |
| 197 | int compression_header_size; |
| 198 | @@ -412,7 +421,8 @@ bfd_is_section_compressed_with_header (bfd *abfd, sec_ptr sec, |
| 199 | if (compression_header_size != 0) |
| 200 | { |
| 201 | if (!bfd_check_compression_header (abfd, header, sec, |
| 202 | - uncompressed_size_p)) |
| 203 | + uncompressed_size_p, |
| 204 | + uncompressed_align_pow_p)) |
| 205 | compression_header_size = -1; |
| 206 | } |
| 207 | /* Check for the pathalogical case of a debug string section that |
| 208 | @@ -449,9 +459,11 @@ bfd_is_section_compressed (bfd *abfd, sec_ptr sec) |
| 209 | { |
| 210 | int compression_header_size; |
| 211 | bfd_size_type uncompressed_size; |
| 212 | + unsigned int uncompressed_align_power; |
| 213 | return (bfd_is_section_compressed_with_header (abfd, sec, |
| 214 | &compression_header_size, |
| 215 | - &uncompressed_size) |
| 216 | + &uncompressed_size, |
| 217 | + &uncompressed_align_power) |
| 218 | && compression_header_size >= 0 |
| 219 | && uncompressed_size > 0); |
| 220 | } |
| 221 | @@ -480,6 +492,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
| 222 | int compression_header_size; |
| 223 | int header_size; |
| 224 | bfd_size_type uncompressed_size; |
| 225 | + unsigned int uncompressed_alignment_power = 0; |
| 226 | |
| 227 | compression_header_size = bfd_get_compression_header_size (abfd, sec); |
| 228 | if (compression_header_size > MAX_COMPRESSION_HEADER_SIZE) |
| 229 | @@ -508,7 +521,8 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
| 230 | uncompressed_size = bfd_getb64 (header + 4); |
| 231 | } |
| 232 | else if (!bfd_check_compression_header (abfd, header, sec, |
| 233 | - &uncompressed_size)) |
| 234 | + &uncompressed_size, |
| 235 | + &uncompressed_alignment_power)) |
| 236 | { |
| 237 | bfd_set_error (bfd_error_wrong_format); |
| 238 | return FALSE; |
| 239 | @@ -516,6 +530,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) |
| 240 | |
| 241 | sec->compressed_size = sec->size; |
| 242 | sec->size = uncompressed_size; |
| 243 | + bfd_set_section_alignment (abfd, sec, uncompressed_alignment_power); |
| 244 | sec->compress_status = DECOMPRESS_SECTION_SIZED; |
| 245 | |
| 246 | return TRUE; |
| 247 | diff --git a/bfd/elf.c b/bfd/elf.c |
| 248 | index 828241d48a..c4f131ddcf 100644 |
| 249 | --- a/bfd/elf.c |
| 250 | +++ b/bfd/elf.c |
| 251 | @@ -1177,11 +1177,12 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, |
| 252 | enum { nothing, compress, decompress } action = nothing; |
| 253 | int compression_header_size; |
| 254 | bfd_size_type uncompressed_size; |
| 255 | + unsigned int uncompressed_align_power; |
| 256 | bfd_boolean compressed |
| 257 | = bfd_is_section_compressed_with_header (abfd, newsect, |
| 258 | &compression_header_size, |
| 259 | - &uncompressed_size); |
| 260 | - |
| 261 | + &uncompressed_size, |
| 262 | + &uncompressed_align_power); |
| 263 | if (compressed) |
| 264 | { |
| 265 | /* Compressed section. Check if we should decompress. */ |
| 266 | diff --git a/binutils/readelf.c b/binutils/readelf.c |
| 267 | index f4df697a7d..4b0efa884f 100644 |
| 268 | --- a/binutils/readelf.c |
| 269 | +++ b/binutils/readelf.c |
| 270 | @@ -13345,12 +13345,6 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) |
| 271 | printable_section_name (filedata, section), chdr.ch_type); |
| 272 | return FALSE; |
| 273 | } |
| 274 | - else if (chdr.ch_addralign != section->sh_addralign) |
| 275 | - { |
| 276 | - warn (_("compressed section '%s' is corrupted\n"), |
| 277 | - printable_section_name (filedata, section)); |
| 278 | - return FALSE; |
| 279 | - } |
| 280 | uncompressed_size = chdr.ch_size; |
| 281 | start += compression_header_size; |
| 282 | new_size -= compression_header_size; |
| 283 | @@ -13492,12 +13486,6 @@ dump_section_as_bytes (Elf_Internal_Shdr * section, |
| 284 | printable_section_name (filedata, section), chdr.ch_type); |
| 285 | return FALSE; |
| 286 | } |
| 287 | - else if (chdr.ch_addralign != section->sh_addralign) |
| 288 | - { |
| 289 | - warn (_("compressed section '%s' is corrupted\n"), |
| 290 | - printable_section_name (filedata, section)); |
| 291 | - return FALSE; |
| 292 | - } |
| 293 | uncompressed_size = chdr.ch_size; |
| 294 | start += compression_header_size; |
| 295 | new_size -= compression_header_size; |
| 296 | @@ -13667,12 +13655,6 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, |
| 297 | section->name, chdr.ch_type); |
| 298 | return FALSE; |
| 299 | } |
| 300 | - else if (chdr.ch_addralign != sec->sh_addralign) |
| 301 | - { |
| 302 | - warn (_("compressed section '%s' is corrupted\n"), |
| 303 | - section->name); |
| 304 | - return FALSE; |
| 305 | - } |
| 306 | uncompressed_size = chdr.ch_size; |
| 307 | start += compression_header_size; |
| 308 | size -= compression_header_size; |
| 309 | diff --git a/binutils/testsuite/binutils-all/dw2-3.rS b/binutils/testsuite/binutils-all/dw2-3.rS |
| 310 | index f1637e9149..86bc73d9a2 100644 |
| 311 | --- a/binutils/testsuite/binutils-all/dw2-3.rS |
| 312 | +++ b/binutils/testsuite/binutils-all/dw2-3.rS |
| 313 | @@ -1,3 +1,3 @@ |
| 314 | #... |
| 315 | - +\[[ 0-9]+\] .debug_info +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +C +0 +0 +1 |
| 316 | + +\[[ 0-9]+\] .debug_info +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ [0-9a-f]+ +C +0 +0 +(4|8) |
| 317 | #pass |
| 318 | diff --git a/binutils/testsuite/binutils-all/dw2-3.rt b/binutils/testsuite/binutils-all/dw2-3.rt |
| 319 | index f59cbaa22b..74e7f8deca 100644 |
| 320 | --- a/binutils/testsuite/binutils-all/dw2-3.rt |
| 321 | +++ b/binutils/testsuite/binutils-all/dw2-3.rt |
| 322 | @@ -1,6 +1,6 @@ |
| 323 | #... |
| 324 | +\[[ 0-9]+\] .debug_info |
| 325 | - +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0 +0 +1 |
| 326 | + +(PROGBITS|MIPS_DWARF) +0+ +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0 +0 +(4|8) |
| 327 | +\[0+800\]: COMPRESSED |
| 328 | +ZLIB, 0+9d, 1 |
| 329 | #pass |
| 330 | -- |
| 331 | 2.20.1 |
| 332 | |