zlib-gabi to zstd woes
authorAlan Modra <amodra@gmail.com>
Fri, 14 Oct 2022 11:29:23 +0000 (21:59 +1030)
committerAlan Modra <amodra@gmail.com>
Sun, 16 Oct 2022 03:24:50 +0000 (13:54 +1030)
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
bfd/bfd.c
bfd/compress.c
bfd/elf32-arm.c

index 25e1806e689ae5166ebfc10d8da0c22effd43bc1..534a46439fc657e29608a89e680f398dbdd418b9 100644 (file)
@@ -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,
index 5f2033bee7a1500fdc0219c2af87726551ba2173..4fca82500826c4795c9d5514317e8530e72bdf9e 100644 (file)
--- 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);
index 364df14142bfb414274e5e51ca2d29c8d05af2c0..9608a0a6341e45a53bf3053c83fb3ea0e2932048 100644 (file)
@@ -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
index 0852b38ae4cf12eb4c573ed3a782918043817a38..ec18a8ab362322bf284a924647324918b8e337db 100644 (file)
@@ -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;