From 89dbeac7460eaa2c6b0149b8abfac880ecefbfe3 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 6 Dec 2022 08:43:31 +1030 Subject: Compression header enum Define an enum instead of using ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD in bfd and binutils, and move some functions from bfd.c to compress.c. When looking at the COFF/PE debug compression support, I wondered about extending it to support zstd. I likely won't do that, but the compression header ch_type field isn't just ELF specific if these headers are to be used in COFF/PE too. bfd/ * bfd.c (bfd_update_compression_header), (bfd_check_compression_header, bfd_get_compression_header_size), (bfd_convert_section_size, bfd_convert_section_contents): Move to.. * compress.c: ..here. (enum compression_type): New. Use it throughout file. * elf.c (_bfd_elf_make_section_from_shdr): Replace uses of ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD with ch_compress_zlib and ch_compress_zstd. * bfd-in2.h: Regenerate. binutils/ * readelf.c (process_section_headers, dump_section_as_strings), (dump_section_as_bytes, load_specific_debug_section): Replace uses of ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD with ch_compress_zlib and ch_compress_zstd. --- bfd/bfd.c | 352 -------------------------------------------------------------- 1 file changed, 352 deletions(-) (limited to 'bfd/bfd.c') diff --git a/bfd/bfd.c b/bfd/bfd.c index b9d4aa4..8d9c9c6 100644 --- a/bfd/bfd.c +++ b/bfd/bfd.c @@ -2477,358 +2477,6 @@ bfd_demangle (bfd *abfd, const char *name, int options) return res; } -/* -FUNCTION - bfd_update_compression_header - -SYNOPSIS - void bfd_update_compression_header - (bfd *abfd, bfd_byte *contents, asection *sec); - -DESCRIPTION - Set the compression header at CONTENTS of SEC in ABFD and update - elf_section_flags for compression. -*/ - -void -bfd_update_compression_header (bfd *abfd, bfd_byte *contents, - asection *sec) -{ - if ((abfd->flags & BFD_COMPRESS) == 0) - abort (); - - switch (bfd_get_flavour (abfd)) - { - case bfd_target_elf_flavour: - if ((abfd->flags & BFD_COMPRESS_GABI) != 0) - { - const struct elf_backend_data *bed = get_elf_backend_data (abfd); - struct bfd_elf_section_data * esd = elf_section_data (sec); - const unsigned int ch_type = abfd->flags & BFD_COMPRESS_ZSTD - ? ELFCOMPRESS_ZSTD - : ELFCOMPRESS_ZLIB; - - /* Set the SHF_COMPRESSED bit. */ - elf_section_flags (sec) |= SHF_COMPRESSED; - - if (bed->s->elfclass == ELFCLASS32) - { - Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; - bfd_put_32 (abfd, ch_type, &echdr->ch_type); - bfd_put_32 (abfd, sec->size, &echdr->ch_size); - bfd_put_32 (abfd, 1u << sec->alignment_power, - &echdr->ch_addralign); - /* bfd_log2 (alignof (Elf32_Chdr)) */ - bfd_set_section_alignment (sec, 2); - esd->this_hdr.sh_addralign = 4; - } - else - { - Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; - bfd_put_32 (abfd, ch_type, &echdr->ch_type); - bfd_put_32 (abfd, 0, &echdr->ch_reserved); - bfd_put_64 (abfd, sec->size, &echdr->ch_size); - bfd_put_64 (abfd, UINT64_C (1) << sec->alignment_power, - &echdr->ch_addralign); - /* bfd_log2 (alignof (Elf64_Chdr)) */ - bfd_set_section_alignment (sec, 3); - esd->this_hdr.sh_addralign = 8; - } - break; - } - - /* Clear the SHF_COMPRESSED bit. */ - elf_section_flags (sec) &= ~SHF_COMPRESSED; - /* Fall through. */ - - default: - /* Write the zlib header. It should be "ZLIB" followed by - the uncompressed section size, 8 bytes in big-endian - 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 (sec, 0); - break; - } -} - -/* - FUNCTION - bfd_check_compression_header - - SYNOPSIS - bool bfd_check_compression_header - (bfd *abfd, bfd_byte *contents, asection *sec, - unsigned int *ch_type, - bfd_size_type *uncompressed_size, - unsigned int *uncompressed_alignment_power); - -DESCRIPTION - Check the compression header at CONTENTS of SEC in ABFD and store the - ch_type in CH_TYPE, 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. -*/ - -bool -bfd_check_compression_header (bfd *abfd, bfd_byte *contents, - asection *sec, - unsigned int *ch_type, - 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) - { - Elf_Internal_Chdr chdr; - const struct elf_backend_data *bed = get_elf_backend_data (abfd); - if (bed->s->elfclass == ELFCLASS32) - { - Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; - chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type); - chdr.ch_size = bfd_get_32 (abfd, &echdr->ch_size); - chdr.ch_addralign = bfd_get_32 (abfd, &echdr->ch_addralign); - } - else - { - Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; - chdr.ch_type = bfd_get_32 (abfd, &echdr->ch_type); - chdr.ch_size = bfd_get_64 (abfd, &echdr->ch_size); - chdr.ch_addralign = bfd_get_64 (abfd, &echdr->ch_addralign); - } - *ch_type = chdr.ch_type; - if ((chdr.ch_type == ELFCOMPRESS_ZLIB - || chdr.ch_type == ELFCOMPRESS_ZSTD) - && chdr.ch_addralign == (chdr.ch_addralign & -chdr.ch_addralign)) - { - *uncompressed_size = chdr.ch_size; - *uncompressed_alignment_power = bfd_log2 (chdr.ch_addralign); - return true; - } - } - - return false; -} - -/* -FUNCTION - bfd_get_compression_header_size - -SYNOPSIS - int bfd_get_compression_header_size (bfd *abfd, asection *sec); - -DESCRIPTION - Return the size of the compression header of SEC in ABFD. - -RETURNS - Return the size of the compression header in bytes. -*/ - -int -bfd_get_compression_header_size (bfd *abfd, asection *sec) -{ - if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) - { - if (sec == NULL) - { - if (!(abfd->flags & BFD_COMPRESS_GABI)) - return 0; - } - else if (!(elf_section_flags (sec) & SHF_COMPRESSED)) - return 0; - - if (get_elf_backend_data (abfd)->s->elfclass == ELFCLASS32) - return sizeof (Elf32_External_Chdr); - else - return sizeof (Elf64_External_Chdr); - } - - return 0; -} - -/* -FUNCTION - bfd_convert_section_size - -SYNOPSIS - bfd_size_type bfd_convert_section_size - (bfd *ibfd, asection *isec, bfd *obfd, bfd_size_type size); - -DESCRIPTION - Convert the size @var{size} of the section @var{isec} in input - BFD @var{ibfd} to the section size in output BFD @var{obfd}. -*/ - -bfd_size_type -bfd_convert_section_size (bfd *ibfd, sec_ptr isec, bfd *obfd, - bfd_size_type size) -{ - bfd_size_type hdr_size; - - /* Do nothing if either input or output aren't ELF. */ - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return size; - - /* Do nothing if ELF classes of input and output are the same. */ - if (get_elf_backend_data (ibfd)->s->elfclass - == get_elf_backend_data (obfd)->s->elfclass) - return size; - - /* Convert GNU property size. */ - if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) - return _bfd_elf_convert_gnu_property_size (ibfd, obfd); - - /* Do nothing if input file will be decompressed. */ - if ((ibfd->flags & BFD_DECOMPRESS)) - return size; - - /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ - hdr_size = bfd_get_compression_header_size (ibfd, isec); - if (hdr_size == 0) - return size; - - /* Adjust the size of the output SHF_COMPRESSED section. */ - if (hdr_size == sizeof (Elf32_External_Chdr)) - return (size - sizeof (Elf32_External_Chdr) - + sizeof (Elf64_External_Chdr)); - else - return (size - sizeof (Elf64_External_Chdr) - + sizeof (Elf32_External_Chdr)); -} - -/* -FUNCTION - bfd_convert_section_contents - -SYNOPSIS - bool bfd_convert_section_contents - (bfd *ibfd, asection *isec, bfd *obfd, - bfd_byte **ptr, bfd_size_type *ptr_size); - -DESCRIPTION - Convert the contents, stored in @var{*ptr}, of the section - @var{isec} in input BFD @var{ibfd} to output BFD @var{obfd} - if needed. The original buffer pointed to by @var{*ptr} may - be freed and @var{*ptr} is returned with memory malloc'd by this - function, and the new size written to @var{ptr_size}. -*/ - -bool -bfd_convert_section_contents (bfd *ibfd, sec_ptr isec, bfd *obfd, - bfd_byte **ptr, bfd_size_type *ptr_size) -{ - bfd_byte *contents; - bfd_size_type ihdr_size, ohdr_size, size; - Elf_Internal_Chdr chdr; - bool use_memmove; - - /* Do nothing if either input or output aren't ELF. */ - if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour - || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return true; - - /* Do nothing if ELF classes of input and output are the same. */ - if (get_elf_backend_data (ibfd)->s->elfclass - == get_elf_backend_data (obfd)->s->elfclass) - return true; - - /* Convert GNU properties. */ - if (startswith (isec->name, NOTE_GNU_PROPERTY_SECTION_NAME)) - return _bfd_elf_convert_gnu_properties (ibfd, isec, obfd, ptr, - ptr_size); - - /* Do nothing if input file will be decompressed. */ - if ((ibfd->flags & BFD_DECOMPRESS)) - return true; - - /* Do nothing if the input section isn't a SHF_COMPRESSED section. */ - ihdr_size = bfd_get_compression_header_size (ibfd, isec); - if (ihdr_size == 0) - return true; - - /* PR 25221. Check for corrupt input sections. */ - if (ihdr_size > bfd_get_section_limit (ibfd, isec)) - /* FIXME: Issue a warning about a corrupt - compression header size field ? */ - return false; - - contents = *ptr; - - /* Convert the contents of the input SHF_COMPRESSED section to - output. Get the input compression header and the size of the - output compression header. */ - if (ihdr_size == sizeof (Elf32_External_Chdr)) - { - Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; - chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); - chdr.ch_size = bfd_get_32 (ibfd, &echdr->ch_size); - chdr.ch_addralign = bfd_get_32 (ibfd, &echdr->ch_addralign); - - ohdr_size = sizeof (Elf64_External_Chdr); - - use_memmove = false; - } - else if (ihdr_size != sizeof (Elf64_External_Chdr)) - { - /* FIXME: Issue a warning about a corrupt - compression header size field ? */ - return false; - } - else - { - Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) contents; - chdr.ch_type = bfd_get_32 (ibfd, &echdr->ch_type); - chdr.ch_size = bfd_get_64 (ibfd, &echdr->ch_size); - chdr.ch_addralign = bfd_get_64 (ibfd, &echdr->ch_addralign); - - ohdr_size = sizeof (Elf32_External_Chdr); - use_memmove = true; - } - - size = bfd_section_size (isec) - ihdr_size + ohdr_size; - if (!use_memmove) - { - contents = (bfd_byte *) bfd_malloc (size); - if (contents == NULL) - return false; - } - - /* Write out the output compression header. */ - if (ohdr_size == sizeof (Elf32_External_Chdr)) - { - Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) contents; - 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, 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); - } - - /* Copy the compressed contents. */ - if (use_memmove) - memmove (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); - else - { - memcpy (contents + ohdr_size, *ptr + ihdr_size, size - ohdr_size); - free (*ptr); - *ptr = contents; - } - - *ptr_size = size; - return true; -} - /* Get the linker information. */ struct bfd_link_info * -- cgit v1.1