From patchwork Tue Dec 6 05:03:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 30082 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp2635039wrr; Mon, 5 Dec 2022 21:03:27 -0800 (PST) X-Google-Smtp-Source: AA0mqf43QLB3yV5IK+SQ4M/4TOCGVf2HbTO6m+FrBonId6ZZX2QUpogqyiji6PWqmqWDgov5uMcf X-Received: by 2002:a17:906:7c45:b0:7c0:c45c:90e4 with SMTP id g5-20020a1709067c4500b007c0c45c90e4mr14053907ejp.473.1670303007094; Mon, 05 Dec 2022 21:03:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670303007; cv=none; d=google.com; s=arc-20160816; b=u1R5QCq/YlkTIwGXB58ehjCOVtEpj0EQXvEug+kFUpMDMjJ87VXu8xIC3T6laMfX4y XIHanDOW8Hh8tbEY1w0ULuzNTCz+uTrp4I4HDrECN2pWncC5qMwEfp4praR6krDkqUdC +pPfieJYZ3tYje56TGf1gQVbyozu65TIXGyFHG75x0W6iq0e+fbD/B2bAp9oekDAdwvc 4R02BFvEutMUojDZW2ZRSpuWp9V2lxYItUD1e/hy8HbT+Bqsj2KNXVno4q76ETFv1S3E 55C3VWt1FIl8h0WLwUz/nLoU+c/eDurOFrO0z+MYASkrbZt35ooqSvWRNsjbyApHavRq 8HPQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-disposition:mime-version:message-id:subject:to:date :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=TbQBOeCPN1lNC3+oi0efiYqc5Bc5vKjdqYGKemKqSE0=; b=Og/13lThTfbqBi3YoIoJTLlfhgDj57BcP/sxdF1LXqEOoq4FmAvEBrAU1bvN4wcvnd B6jcVUlw77rXvPAHNRRh1SpwVfJcntLbuCmG6+dyBRs/JqvOy92iltUXmxRr0xpKhoX4 7Kg4Bd4FXv5WuzrxR5eDk1tLALQer1ncF3D8m0ehUjlY9uglUtAbE2DSX/rM40U72/iJ SikyjSoSSPBxxqEsgUt3817NRHQcvti0sNmFgru1fbHASdOxUX7XvSgdX5+HcnZiY06f ZNsNx4JsUl/Cxzn+1wpqk5YuLc1lmA95FGQ9jL/r+1GWA1V+oQ9+2jEHLSNP/FRDH2Ha 8e1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b="G1Yy/dNs"; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sourceware.org Received: from sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id 17-20020a170906059100b007ae74740fa4si10269269ejn.275.2022.12.05.21.03.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Dec 2022 21:03:27 -0800 (PST) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b="G1Yy/dNs"; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C442D38187CE for ; Tue, 6 Dec 2022 05:03:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C442D38187CE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1670303003; bh=TbQBOeCPN1lNC3+oi0efiYqc5Bc5vKjdqYGKemKqSE0=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=G1Yy/dNs9wuckd/7dDRYLCAAQk4FsaZ3q2VVe9oYDiz17OLXlrrWWvM/0ytIpbZDk PJc0WFEMTg2egiB+ufwnf25VfoXeUWPeG5PSssGWtTW2vC0bNaSAAItexpuj5E5Wlk OwM3fxEIPiBFceeIOpK/O4BiXPMLbH/4p6EAcvXc= X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by sourceware.org (Postfix) with ESMTPS id EA4B03851881 for ; Tue, 6 Dec 2022 05:03:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EA4B03851881 Received: by mail-pj1-x1030.google.com with SMTP id fa4-20020a17090af0c400b002198d1328a0so804556pjb.0 for ; Mon, 05 Dec 2022 21:03:11 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-disposition:mime-version:message-id:subject:to:from:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=TbQBOeCPN1lNC3+oi0efiYqc5Bc5vKjdqYGKemKqSE0=; b=Mz+YkJbNP5FYfdDLEepU+dQmhE1U7canlpcpj7eA5lo/GWu4p8IDYh3JFAA8MCjZ1A UkE680quW8u9AaBcm+ktXh/VhDBtBAf8wvfqVYkiFJ/6M0D3wQLqgKowY1Th74ClhLwc 94bSVgTFPd40c9Ty7P+4F7XlMWnxgCbdzsawywV+wA8mlV3PruV1hBQgEQoD5yo2MOIf vKLWhvZ+ZMsze+1A5YQMtXlpxodkdp7l3fqcI8E6WbuGBZVbwMiRBLFXZ+CJKPYzrRxr O7POnf31Eha2Xo14O3POx7xhnI09Bv20K6+SPwchcSXaHcWt+IRCGSa2bYNMRs/xMddr ucWA== X-Gm-Message-State: ANoB5plDn+zWFxpcuhfJ5aY9lXgHbtUGf6XVR4lh4RUhgbJf7sVOK1Xe SA1pdlkdmFwqdE/9KNaTtywGISS4dzw= X-Received: by 2002:a17:90a:708a:b0:20a:eaab:137 with SMTP id g10-20020a17090a708a00b0020aeaab0137mr94048243pjk.206.1670302989976; Mon, 05 Dec 2022 21:03:09 -0800 (PST) Received: from squeak.grove.modra.org (158.106.96.58.static.exetel.com.au. [58.96.106.158]) by smtp.gmail.com with ESMTPSA id t10-20020a1709027fca00b00186c3727294sm10638456plb.270.2022.12.05.21.03.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Dec 2022 21:03:09 -0800 (PST) Received: by squeak.grove.modra.org (Postfix, from userid 1000) id 7A6F51140E48; Tue, 6 Dec 2022 15:33:06 +1030 (ACDT) Date: Tue, 6 Dec 2022 15:33:06 +1030 To: binutils@sourceware.org Subject: Compression header enum Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-3036.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Alan Modra via Binutils From: Alan Modra Reply-To: Alan Modra Errors-To: binutils-bounces+ouuuleilei=gmail.com@sourceware.org Sender: "Binutils" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751439645795905864?= X-GMAIL-MSGID: =?utf-8?q?1751439645795905864?= 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. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 15f3c8c8f12..24f9305c47c 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -7286,24 +7286,6 @@ bfd_vma bfd_emul_get_commonpagesize (const char *); char *bfd_demangle (bfd *, const char *, int); -void bfd_update_compression_header - (bfd *abfd, bfd_byte *contents, asection *sec); - -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); - -int bfd_get_compression_header_size (bfd *abfd, asection *sec); - -bfd_size_type bfd_convert_section_size - (bfd *ibfd, asection *isec, bfd *obfd, bfd_size_type size); - -bool bfd_convert_section_contents - (bfd *ibfd, asection *isec, bfd *obfd, - bfd_byte **ptr, bfd_size_type *ptr_size); - /* Extracted from archive.c. */ symindex bfd_get_next_mapent (bfd *abfd, symindex previous, carsym **sym); @@ -7963,6 +7945,13 @@ bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); /* Extracted from compress.c. */ +enum compression_type +{ + ch_none = 0, + ch_compress_zlib = 1 , /* Compressed with zlib. */ + ch_compress_zstd = 2 /* Compressed with zstd (www.zstandard.org). */ +}; + static inline char * bfd_debug_name_to_zdebug (bfd *abfd, const char *name) { @@ -7988,6 +7977,18 @@ bfd_zdebug_name_to_debug (bfd *abfd, const char *name) return new_name; } +void bfd_update_compression_header + (bfd *abfd, bfd_byte *contents, asection *sec); + +int bfd_get_compression_header_size (bfd *abfd, asection *sec); + +bfd_size_type bfd_convert_section_size + (bfd *ibfd, asection *isec, bfd *obfd, bfd_size_type size); + +bool bfd_convert_section_contents + (bfd *ibfd, asection *isec, bfd *obfd, + bfd_byte **ptr, bfd_size_type *ptr_size); + bool bfd_get_full_section_contents (bfd *abfd, asection *section, bfd_byte **ptr); @@ -7996,7 +7997,7 @@ bool bfd_is_section_compressed_info int *compression_header_size_p, bfd_size_type *uncompressed_size_p, unsigned int *uncompressed_alignment_power_p, - unsigned int *ch_type); + enum compression_type *ch_type); bool bfd_is_section_compressed (bfd *abfd, asection *section); diff --git a/bfd/bfd.c b/bfd/bfd.c index b9d4aa44d9c..8d9c9c67743 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 * diff --git a/bfd/compress.c b/bfd/compress.c index 6b083468ca8..a4e6a8ee7b5 100644 --- a/bfd/compress.c +++ b/bfd/compress.c @@ -32,6 +32,13 @@ /* CODE_FRAGMENT +.enum compression_type +.{ +. ch_none = 0, +. ch_compress_zlib = 1 , {* Compressed with zlib. *} +. ch_compress_zstd = 2 {* Compressed with zstd (www.zstandard.org). *} +.}; +. .static inline char * .bfd_debug_name_to_zdebug (bfd *abfd, const char *name) .{ @@ -59,6 +66,342 @@ CODE_FRAGMENT . */ +/* +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); + enum compression_type ch_type = (abfd->flags & BFD_COMPRESS_ZSTD + ? ch_compress_zstd + : ch_compress_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; + } +} + +/* 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. */ + +static bool +bfd_check_compression_header (bfd *abfd, bfd_byte *contents, + asection *sec, + enum compression_type *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 == ch_compress_zlib + || chdr.ch_type == ch_compress_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; +} + static bool decompress_contents (bool is_zstd, bfd_byte *compressed_buffer, bfd_size_type compressed_size, @@ -128,7 +471,7 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec) int orig_header_size; bfd_size_type uncompressed_size; unsigned int uncompressed_alignment_pow; - unsigned int ch_type = 0; + enum compression_type ch_type = ch_none; int new_header_size = bfd_get_compression_header_size (abfd, NULL); bool compressed = bfd_is_section_compressed_info (abfd, sec, @@ -146,7 +489,7 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec) overhead in .zdebug* section. */ if (!new_header_size) new_header_size = 12; - if (ch_type == 0) + if (ch_type == ch_none) orig_header_size = 12; input_buffer = sec->contents; @@ -157,7 +500,7 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec) /* If we are converting between zlib-gnu and zlib-gabi then the compressed contents just need to be moved. */ - update = (ch_type < ELFCOMPRESS_ZSTD + update = (ch_type < ch_compress_zstd && (abfd->flags & BFD_COMPRESS_ZSTD) == 0); /* Uncompress when not just moving contents or when compressed @@ -169,7 +512,7 @@ bfd_compress_section_contents (bfd *abfd, sec_ptr sec) if (buffer == NULL) return 0; - if (!decompress_contents (ch_type == ELFCOMPRESS_ZSTD, + if (!decompress_contents (ch_type == ch_compress_zstd, input_buffer + orig_header_size, zlib_size, buffer, buffer_size)) { @@ -408,7 +751,7 @@ SYNOPSIS int *compression_header_size_p, bfd_size_type *uncompressed_size_p, unsigned int *uncompressed_alignment_power_p, - unsigned int *ch_type); + enum compression_type *ch_type); DESCRIPTION Return @code{TRUE} if @var{section} is compressed. Compression @@ -425,7 +768,7 @@ bfd_is_section_compressed_info (bfd *abfd, sec_ptr sec, int *compression_header_size_p, bfd_size_type *uncompressed_size_p, unsigned int *uncompressed_align_pow_p, - unsigned int *ch_type) + enum compression_type *ch_type) { bfd_byte header[MAX_COMPRESSION_HEADER_SIZE]; int compression_header_size; @@ -501,7 +844,7 @@ bfd_is_section_compressed (bfd *abfd, sec_ptr sec) int compression_header_size; bfd_size_type uncompressed_size; unsigned int uncompressed_align_power; - unsigned int ch_type; + enum compression_type ch_type; return (bfd_is_section_compressed_info (abfd, sec, &compression_header_size, &uncompressed_size, @@ -536,7 +879,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) int header_size; bfd_size_type uncompressed_size; unsigned int uncompressed_alignment_power = 0; - unsigned int ch_type; + enum compression_type ch_type; z_stream strm; compression_header_size = bfd_get_compression_header_size (abfd, sec); @@ -564,7 +907,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) return false; } uncompressed_size = bfd_getb64 (header + 4); - ch_type = 0; + ch_type = ch_none; } else if (!bfd_check_compression_header (abfd, header, sec, &ch_type, @@ -587,7 +930,7 @@ bfd_init_section_decompress_status (bfd *abfd, sec_ptr sec) sec->compressed_size = sec->size; sec->size = uncompressed_size; bfd_set_section_alignment (sec, uncompressed_alignment_power); - sec->compress_status = (ch_type == ELFCOMPRESS_ZSTD + sec->compress_status = (ch_type == ch_compress_zstd ? DECOMPRESS_SECTION_ZSTD : DECOMPRESS_SECTION_ZLIB); return true; diff --git a/bfd/elf.c b/bfd/elf.c index 9e490c968c1..a013f8885c7 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -1184,7 +1184,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, int compression_header_size; bfd_size_type uncompressed_size; unsigned int uncompressed_align_power; - unsigned int ch_type = 0; + enum compression_type ch_type = ch_none; bool compressed = bfd_is_section_compressed_info (abfd, newsect, &compression_header_size, @@ -1206,10 +1206,10 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, action = compress; else { - unsigned int new_ch_type = 0; + enum compression_type new_ch_type = ch_none; if ((abfd->flags & BFD_COMPRESS_GABI) != 0) new_ch_type = ((abfd->flags & BFD_COMPRESS_ZSTD) != 0 - ? ELFCOMPRESS_ZSTD : ELFCOMPRESS_ZLIB); + ? ch_compress_zstd : ch_compress_zlib); if (new_ch_type != ch_type) action = compress; } diff --git a/binutils/readelf.c b/binutils/readelf.c index 1bd6df9448a..bce93782952 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -7803,9 +7803,9 @@ process_section_headers (Filedata * filedata) printf (_(" []\n")); else { - if (chdr.ch_type == ELFCOMPRESS_ZLIB) + if (chdr.ch_type == ch_compress_zlib) printf (" ZLIB, "); - else if (chdr.ch_type == ELFCOMPRESS_ZSTD) + else if (chdr.ch_type == ch_compress_zstd) printf (" ZSTD, "); else printf (_(" [: 0x%x], "), @@ -15369,10 +15369,10 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) by get_compression_header. */ goto error_out; - if (chdr.ch_type == ELFCOMPRESS_ZLIB) + if (chdr.ch_type == ch_compress_zlib) ; #ifdef HAVE_ZSTD - else if (chdr.ch_type == ELFCOMPRESS_ZSTD) + else if (chdr.ch_type == ch_compress_zstd) is_zstd = true; #endif else @@ -15592,10 +15592,10 @@ dump_section_as_bytes (Elf_Internal_Shdr *section, by get_compression_header. */ goto error_out; - if (chdr.ch_type == ELFCOMPRESS_ZLIB) + if (chdr.ch_type == ch_compress_zlib) ; #ifdef HAVE_ZSTD - else if (chdr.ch_type == ELFCOMPRESS_ZSTD) + else if (chdr.ch_type == ch_compress_zstd) is_zstd = true; #endif else @@ -16024,10 +16024,10 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, by get_compression_header. */ return false; - if (chdr.ch_type == ELFCOMPRESS_ZLIB) + if (chdr.ch_type == ch_compress_zlib) ; #ifdef HAVE_ZSTD - else if (chdr.ch_type == ELFCOMPRESS_ZSTD) + else if (chdr.ch_type == ch_compress_zstd) is_zstd = true; #endif else