From 206e9791cb09459bf92603428370c16bfde282ac Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 14 Oct 2022 21:59:23 +1030 Subject: 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. --- bfd/bfd-in2.h | 3 --- bfd/bfd.c | 4 ++-- bfd/compress.c | 29 +++++------------------------ bfd/elf32-arm.c | 6 ++++-- 4 files changed, 11 insertions(+), 31 deletions(-) (limited to 'bfd') diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 25e1806..534a464 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 5f2033b..4fca825 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 364df14..9608a0a 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 @@ -382,29 +386,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 SYNOPSIS diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c index 0852b38..ec18a8a 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; -- cgit v1.1