From: Alan Modra Date: Fri, 14 Oct 2022 11:29:23 +0000 (+1030) Subject: zlib-gabi to zstd woes X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=206e9791cb09459bf92603428370c16bfde282ac;p=binutils-gdb.git zlib-gabi to zstd woes So we had a zlib-gabi .debug_info section that increased in size with zstd, so much so that it was better to leave the section uncompressed. Things went horribly wrong when the section was read again later. The section was read again off disk using the uncompressed size. So you get the zlib section again with some garbage at the end. Fix that particular problem by setting the section flag SEC_IN_MEMORY. Any future read will get sec->contents. Also, if the section is to be left uncompressed, the input SHF_COMPRESSED flag needs to be reset otherwise objcopy will copy it to output. Finally, bfd_convert_section_contents needed a small update to handle zstd compressed sections, and I've deleted bfd_cache_section_contents. * bfd.c (bfd_convert_section_contents): Handle zstd. * compress.c (bfd_compress_section_contents): When section contents are uncompressed set SEC_IN_MEMORY flag, compress_status to COMRESS_SECTION_NONE, and clear SHF_COMPRESSED. Set SEC_IN_MEMORY for compressed contents. (bfd_get_full_section_contents): Don't check section size against file size when SEC_IN_MEMORY. (bfd_cache_section_contents): Delete function. * elf32-arm.c (elf32_arm_get_synthetic_symtab): Expand bfd_cache_section_contents here. * bfd-in2.h: Regenerate. --- diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 25e1806e689..534a46439fc 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -7964,9 +7964,6 @@ bfd_byte *bfd_simple_get_relocated_section_contents bool bfd_get_full_section_contents (bfd *abfd, asection *section, bfd_byte **ptr); -void bfd_cache_section_contents - (asection *sec, void *contents); - bool bfd_is_section_compressed_info (bfd *abfd, asection *section, int *compression_header_size_p, diff --git a/bfd/bfd.c b/bfd/bfd.c index 5f2033bee7a..4fca8250082 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2801,14 +2801,14 @@ bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, 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_type, &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_32 (obfd, ELFCOMPRESS_ZLIB, &echdr->ch_type); + bfd_put_32 (obfd, chdr.ch_type, &echdr->ch_type); bfd_put_32 (obfd, 0, &echdr->ch_reserved); bfd_put_64 (obfd, chdr.ch_size, &echdr->ch_size); bfd_put_64 (obfd, chdr.ch_addralign, &echdr->ch_addralign); diff --git a/bfd/compress.c b/bfd/compress.c index 364df14142b..9608a0a6341 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -151,7 +151,8 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec) free (input_buffer); bfd_set_section_alignment (sec, uncompressed_alignment_pow); sec->contents = buffer; - sec->compress_status = COMPRESS_SECTION_DONE; + sec->flags |= SEC_IN_MEMORY; + sec->compress_status = COMPRESS_SECTION_NONE; sec->size = uncompressed_size; input_buffer = buffer; } @@ -206,6 +207,7 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec) if (compressed_size >= uncompressed_size) { memcpy (buffer, input_buffer, uncompressed_size); + elf_section_flags (sec) &= ~SHF_COMPRESSED; sec->compress_status = COMPRESS_SECTION_NONE; } else @@ -216,6 +218,7 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec) sec->compress_status = COMPRESS_SECTION_DONE; } sec->contents = buffer; + sec->flags |= SEC_IN_MEMORY; free (input_buffer); return uncompressed_size; } @@ -268,6 +271,7 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) ufile_ptr filesize = bfd_get_file_size (abfd); if (filesize > 0 && filesize < sz + && (bfd_section_flags (sec) & SEC_IN_MEMORY) == 0 /* PR 24753: Linker created sections can be larger than the file size, eg if they are being used to hold stubs. */ && (bfd_section_flags (sec) & SEC_LINKER_CREATED) == 0 @@ -380,29 +384,6 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) } } -/* -FUNCTION - bfd_cache_section_contents - -SYNOPSIS - void bfd_cache_section_contents - (asection *sec, void *contents); - -DESCRIPTION - Stash @var(contents) so any following reads of @var(sec) do - not need to decompress again. -*/ - -void -bfd_cache_section_contents (asection *sec, void *contents) -{ - if (sec->compress_status == DECOMPRESS_SECTION_ZLIB - || sec->compress_status == DECOMPRESS_SECTION_ZSTD) - sec->compress_status = COMPRESS_SECTION_DONE; - sec->contents = contents; - sec->flags |= SEC_IN_MEMORY; -} - /* FUNCTION bfd_is_section_compressed_info diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 0852b38ae4c..ec18a8ab362 100644 --- a/bfd/elf32-arm.c +++ b/bfd/elf32-arm.c @@ -20020,9 +20020,11 @@ elf32_arm_get_synthetic_symtab (bfd *abfd, data = plt->contents; if (data == NULL) { - if (!bfd_get_full_section_contents (abfd, (asection *) plt, &data) || data == NULL) + if (!bfd_get_full_section_contents (abfd, plt, &data) + || data == NULL) return -1; - bfd_cache_section_contents ((asection *) plt, data); + plt->contents = data; + plt->flags |= SEC_IN_MEMORY; } count = relplt->size / hdr->sh_entsize;