From patchwork Sun Feb 19 17:34:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulf Samuelsson X-Patchwork-Id: 59340 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:eb09:0:0:0:0:0 with SMTP id s9csp1226579wrn; Mon, 20 Feb 2023 02:14:04 -0800 (PST) X-Google-Smtp-Source: AK7set+FmkgXsC3ZnOfgAbY77zc9vdbXkRxe1Leu8gQn1EiJBGNBfE78Z09KTW0QgLCq/uOgu4se X-Received: by 2002:a17:906:7fd9:b0:8b1:a3c7:a9c9 with SMTP id r25-20020a1709067fd900b008b1a3c7a9c9mr10238184ejs.70.1676888043920; Mon, 20 Feb 2023 02:14:03 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1676888043; cv=none; d=google.com; s=arc-20160816; b=D6BdZVpMfvUK/b6vWaAM56iS3Xmckb3u4IF5XK+f3a7LMret+GhncTMGi2MsOBiaPV 7pJP/dJVaiR+S0D4XfZNNS1sv8/8dk3nN0HRNO1D8ajoLeOCoQ6kscJIahFdhbgSaPf6 D62Fp8442BUWrX0pqzth74DsU7mNm6FwRQkmT+0b0aLEQDixBMUDEo8u43Ec9KNbINu4 Bhub/HtBPo54Hp8X2+K5KNz8LyeAzBi2kfo2si9k4XY5+UjwbWNLkPkQ84P4h9/d1TPZ fOB8sUgceUVcEne/uIxX/lZz2z01tNjCBoelYG5r7x4yXnFh2aAOMgPx/SpA/Tx1oalM Rv9A== 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:references :in-reply-to:message-id:date:subject:cc:to:dmarc-filter:delivered-to :dkim-signature:dkim-filter; bh=aw6MsivypiD3QX/87z0cKwjFNCMZoc1v20EYMF3grnA=; b=S5xwpIu1KzCpsk2aAwXkssL5p7E4BJXWVRjswubiwuj7J+YXrN7ioUJ/ZFW2nzJgKp rQUPGjPBGonfWcwCUVYyM8HOA04SIxH09ukgqlYMtwRejgFU16b8SxHyKDSklvKsPeaa Tjs++4afSlL3Kz8yd2FFPkgsAbnrSvkyUTq6p66mhSdxDh1RZnS4Q7N+n3T9Axv1t3YH TxIR3NHixZ5aF+o8wY0OCTv0S5GM67InUCHL90ClRO00Sq6J3orb9/e1Tcg6oaKe5b+N SzgyjzRkL8HL/REXFMDTS9yJcZd1lSMMIVd+zoiPC4iAsgx+LbgvRHyco6YPRFXIVXsn yEug== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=QCRf0T7F; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c 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. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id e18-20020aa7d7d2000000b004ad0a583818si4957062eds.539.2023.02.20.02.14.03 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Feb 2023 02:14:03 -0800 (PST) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=QCRf0T7F; spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 2620:52:3:1:0:246e:9693:128c 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 2A1423836E99 for ; Mon, 20 Feb 2023 10:04:10 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2A1423836E99 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1676887450; bh=aw6MsivypiD3QX/87z0cKwjFNCMZoc1v20EYMF3grnA=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=QCRf0T7FK4ftw01oZ+nVuf+ORsTUSvgOd8y8Ak4K4uQlhi6YX9HGx6Kj+Uq5vbCEq pu4TY8EOmNcHcvivIX5KJxZ1L7nQEDY3J6dDaALiSrWZfPZnL+i/PTOZ7ndlDK8Jkb XBhTbV44JdCg/e8yDmZyP3Ej3HqlnKU3IqQyRYc0= X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from emagii.se (www.emagii.com [185.133.207.17]) by sourceware.org (Postfix) with ESMTPS id 46F7C3954453 for ; Mon, 20 Feb 2023 10:00:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 46F7C3954453 Received: from valinor.ownit.se (84-55-68-216.customers.ownit.se [84.55.68.216]) by emagii.se (Postfix) with ESMTPSA id B5C26120255; Sun, 19 Feb 2023 18:34:56 +0100 (CET) Received-SPF: pass (emagii.beebytevps.io: connection is authenticated) To: binutils@sourceware.org Cc: nickc@redhat.com, Ulf Samuelsson Subject: [PATCH v3 5/5] Calculate CRC64 over the .text area Date: Sun, 19 Feb 2023 18:34:50 +0100 Message-Id: <20230219173450.25555-6-binutils@emagii.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230219173450.25555-1-binutils@emagii.com> References: <20230219173450.25555-1-binutils@emagii.com> X-PPP-Message-ID: <167682809701.629690.8926287184717418382@localhost.localdomain> X-PPP-Vhost: emagii.com X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, SPF_HELO_FAIL, SPF_PASS, TXREP autolearn=unavailable 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: Ulf Samuelsson via Binutils From: Ulf Samuelsson Reply-To: binutils@emagii.com 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?1758344557149205446?= X-GMAIL-MSGID: =?utf-8?q?1758344557149205446?= From: Ulf Samuelsson Signed-off-by: Ulf Samuelsson --- ld/Makefile.am | 2 +- ld/checksum.h | 62 +++++ ld/ldlang.c | 648 ++++++++++++++++++++++++++++++++++++++++++++++++- ld/ldlang.h | 12 + ld/ldmain.c | 1 + 5 files changed, 721 insertions(+), 4 deletions(-) create mode 100755 ld/checksum.h diff --git a/ld/Makefile.am b/ld/Makefile.am index 760225c5b88..91b024d1cba 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -481,7 +481,7 @@ CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \ plugin.c ldbuildid.c ldelf.c ldelfgen.c \ pdb.c -HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \ +HFILES = checksum.h ld.h ldctor.h ldemul.h ldexp.h ldfile.h \ ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \ ldwrite.h mri.h deffile.h pe-dll.h pep-dll.h \ elf-hints-local.h plugin.h ldbuildid.h ldelf.h ldelfgen.h \ diff --git a/ld/checksum.h b/ld/checksum.h new file mode 100755 index 00000000000..6dcb1bf738d --- /dev/null +++ b/ld/checksum.h @@ -0,0 +1,62 @@ +/* + * Library: libcrc + * Author: Lammert Bies + * + * This file is licensed under the MIT License as stated below + * + * Copyright (c) 2016 Lammert Bies + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#ifndef CHECKSUM_H +#define CHECKSUM_H + +#include +#include + +#define CRC_POLY_64 0x42F0E1EBA9EA3693ull +#define CRC_POLY_64_ISO 0xD800000000000000ull +#define CRC_START_64 0x0000000000000000ull +#define CRC_START_64_INV 0xFFFFFFFFFFFFFFFFull + +#define CRC64_ADDRESS "___CRC64___" +#define CRC64_START "___CRC64_START___" +#define CRC64_END "___CRC64_END___" +#define CRC64_TABLE "___CRC64_TABLE___" + +#define CRC_POLY_32 0xEDB88320ul +#define CRC_START_32_INV 0xFFFFFFFFul + +#define CRC32_ADDRESS "___CRC32___" +#define CRC32_START "___CRC32_START___" +#define CRC32_END "___CRC32_END___" +#define CRC32_TABLE "___CRC32_TABLE___" + +enum crc_alg { + crc_algo_none=0, + crc_algo_32=4, + crc_algo_64=8 +}; + +bfd_vma crc_64 (const unsigned char *input_str, size_t num_bytes); +bfd_vma crc_64_inv(const unsigned char *input_str, size_t num_bytes); + +#endif /* CHECKSUM_H */ diff --git a/ld/ldlang.c b/ld/ldlang.c index 2852a4222d3..972013b0b58 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -18,8 +18,11 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#define DEBUG_CRC 0 + #include "sysdep.h" #include +#include #include "bfd.h" #include "libiberty.h" #include "filenames.h" @@ -42,6 +45,8 @@ #include "demangle.h" #include "hashtab.h" #include "elf-bfd.h" +#include "checksum.h" + #if BFD_SUPPORTS_PLUGINS #include "plugin.h" #endif /* BFD_SUPPORTS_PLUGINS */ @@ -145,6 +150,25 @@ int lang_statement_iteration = 0; /* Count times through one_lang_size_sections_pass after mark phase. */ static int lang_sizing_iteration = 0; +/* CRC calculation on output section */ +asection *text_section; +unsigned char *text_contents = NULL; + +enum crc_alg crc_algo = crc_algo_none; +bfd_vma crc_size = 0; /* Size of syndrome */ +bool crc_invert = false; + +bfd_vma crc64_poly = CRC_POLY_64; /* Default Polynome is CRC64 ECMA */ +bfd_vma *crc64_tab = NULL; + +uint32_t crc32_poly = CRC_POLY_32; /* Default Polynome is CRC-32 */ +bool crc32_invert = true; +uint32_t *crc32_tab = NULL; + +char *CRC_ADDRESS = NULL; +char *CRC_START = NULL; +char *CRC_END = NULL; + /* Return TRUE if the PATTERN argument is a wildcard pattern. Although backslashes are treated specially if a pattern contains wildcards, we do not consider the mere presence of a backslash to @@ -8389,7 +8413,7 @@ convert_string (const char * s) case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; - + case '0': case '1': case '2': @@ -8409,7 +8433,7 @@ convert_string (const char * s) value += (c - '0'); i++; s++; - + c = *s; if ((c >= '0') && (c <= '7')) { @@ -8427,7 +8451,7 @@ convert_string (const char * s) i--; s--; } - + c = value; } break; @@ -8524,6 +8548,624 @@ lang_add_attribute (enum statement_enum attribute) new_statement (attribute, sizeof (lang_statement_header_type), stat_ptr); } +/* ============ CRC-32 LIBCRC functions ======================================*/ + +/* + * void init_crc32_tab( void ); + * + * For optimal speed, the CRC32 calculation uses a table with pre-calculated + * bit patterns which are used in the XOR operations in the program. + * init_crc32_tab is copyright (c) 2016 Lammert Bies + */ +static +uint32_t *init_crc32_tab( uint32_t poly ) +{ + uint32_t i; + uint32_t j; + uint32_t crc; + uint32_t *crc_tab; + + crc_tab = malloc(256 * sizeof(uint32_t)); + if (crc_tab == NULL) + return NULL; + + for (i=0; i<256; i++) + { + + crc = i; + + for (j=0; j<8; j++) + { + + if ( crc & 0x00000001L ) + { + crc = ( crc >> 1 ) ^ poly; + } + else + { + crc = crc >> 1; + } + } + + crc_tab[i] = crc; + } + return crc_tab; +} /* init_crc32_tab */ + +/* + * uint32_t calc_crc32_inv( const unsigned char *input_str, size_t num_bytes ); + * + * The function calc_crc32_inv() calculates in one pass the common 32 bit CRC value for + * a byte string that is passed to the function together with a parameter + * indicating the length. + */ +static +uint32_t calc_crc32_inv( const unsigned char *input_str, size_t num_bytes ) +{ + uint32_t crc; + const unsigned char *ptr; + size_t a; + + crc = CRC_START_32_INV; + ptr = input_str; + + if ( ptr != NULL ) + { + for (a=0; a> 8) ^ + crc32_tab[(crc ^ (uint32_t) *ptr++) & 0x000000FFul ]; + } + } + + return (crc ^ 0xFFFFFFFFul); + +} /* calc_crc32_inv */ + +/* + * uint32_t calc_crc32( const unsigned char *input_str, size_t num_bytes ); + * + * The function calc_crc32() calculates in one pass the common 32 bit CRC value for + * a byte string that is passed to the function together with a parameter + * indicating the length. + */ +static +uint32_t calc_crc32( const unsigned char *input_str, size_t num_bytes ) +{ + uint32_t crc; + const unsigned char *ptr; + size_t a; + if (crc_invert) + return calc_crc32_inv(input_str, num_bytes); + + crc = 0; + ptr = input_str; + + if ( ptr != NULL ) + { + for (a=0; a> 8) ^ + crc32_tab[(crc ^ (uint32_t) *ptr++) & 0x000000FFul ]; + } + } + + return (crc); + +} /* calc_crc32 */ + +/* ============ CRC-32 public functions ======================================*/ + +extern void lang_add_crc32_syndrome(bool invert, bfd_vma poly) +{ + + if (crc_algo == crc_algo_none) /* We only allow one CRC64 */ + { + crc_algo = crc_algo_32; + crc_size = sizeof(uint32_t); + crc32_invert = invert; + crc32_poly = (uint32_t) (poly & 0xFFFFFFFF); /* Set the polynom */ + CRC_ADDRESS = CRC32_ADDRESS; + CRC_START = CRC32_START; + CRC_END = CRC32_END; + +#if (DEBUG_CRC == 1) + printf("Adding Syndrome: 0x%08lx\n", poly); +#endif + lang_add_data (LONG, exp_intop (0)); /* Reserve room for the ECC value */ + crc32_tab = init_crc32_tab(crc32_poly); + if (crc32_tab == NULL) + { + einfo (_("%F%P: can not allocate memory for CRC table: %E\n")); + return; + } + } + else + { + einfo (_("%P:%pS: warning: Only the first CRC polynome is used\n"), + NULL); + } +} + +extern void lang_add_crc32_table(void) +{ + uint32_t *crc32_table = crc32_tab; /* Use a precomputed, if it exists */ + bool local_table = false; + if (crc32_table == NULL) + { /* No luck, create a table */ + crc32_table = init_crc32_tab(crc32_poly); + if (crc32_table == NULL) + { + einfo (_("%F%P: can not allocate memory for CRC table: %E\n")); + return; + } + local_table = true; + } + for (bfd_vma i = 0 ; i < 256 ; i++) + { + lang_add_data (LONG, exp_intop (crc32_table[i])); + } + if (local_table) + free(crc32_table); +} + +/* ============ CRC-64 LIBCRC functions ======================================*/ + +/* + * bfd_vma *init_crc64_tab( bfd_vma poly ) ; + * + * For optimal speed, the CRC64 calculation uses a table with pre-calculated + * bit patterns which are used in the XOR operations in the program. + * init_crc64_tab is copyright (c) 2016 Lammert Bies + */ +static +bfd_vma *init_crc64_tab( bfd_vma poly ) +{ + bfd_vma i; + bfd_vma j; + bfd_vma c; + bfd_vma crc; + bfd_vma *crc_tab; + + crc_tab = malloc(256 * sizeof(bfd_vma)); + if (crc_tab == NULL) + return NULL; + + for (i=0; i<256; i++) + { + crc = 0; + c = i << 56; + for (j=0; j<8; j++) + { + if ( ( crc ^ c ) & 0x8000000000000000ull ) + crc = ( crc << 1 ) ^ poly; + else + crc = crc << 1; + c = c << 1; + } + crc_tab[i] = crc; + } + return crc_tab; + +} /* init_crc64_tab */ + +/* + * The function calc_crc64_inv() calculates in one pass the CRC64 64 bit CRC + * value for a byte string that is passed to the function together with a + * parameter indicating the length. + * This is used for CRC64-WE + * calc_crc64_inv is copyright (c) 2016 Lammert Bies + */ +static +bfd_vma calc_crc64_inv( const unsigned char *input_str, size_t num_bytes ) +{ + bfd_vma crc; + const unsigned char *ptr; + size_t a; + + crc = CRC_START_64_INV; + ptr = input_str; + + if ( ptr != NULL ) + { + for (a=0; a> 56) ^ (bfd_vma) *ptr++) & + 0x00000000000000FFull + ]; + } + } + return crc ^ 0xFFFFFFFFFFFFFFFFull; +} /* calc_crc64_inv */ + +/* + * bfd_vma calc_crc64( const unsigned char *input_str, size_t num_bytes ); + * + * The function calc_crc64() calculates in one pass the 64 bit CRC value + * for a byte string that is passed to the function together with a + * parameter indicating the length. + * This is used for CRC64-ECMA and CRC64-ISO + * calc_crc64 is copyright (c) 2016 Lammert Bies + */ +static +bfd_vma calc_crc64(const unsigned char *input_str, size_t num_bytes) +{ + bfd_vma crc; + const unsigned char *ptr; + size_t a; + if (crc_invert) + return calc_crc64_inv(input_str, num_bytes); + crc = CRC_START_64; + ptr = input_str; + if ( ptr != NULL ) + { + for (a=0; a> 56) ^ (bfd_vma) *ptr++) & + 0x00000000000000FFull + ]; + } + } + return crc; +} /* calc_crc64 */ + +/* ============ CRC-64 public functions ======================================*/ + +extern void lang_add_crc64_syndrome(bool invert, bfd_vma poly) +{ + + if (crc_algo == crc_algo_none) /* We only allow one CRC64 */ + { + crc_algo = crc_algo_64; + crc_size = sizeof(bfd_vma); + crc_invert = invert; + crc64_poly = poly; /* Set the polynom */ + CRC_ADDRESS = CRC64_ADDRESS; + CRC_START = CRC64_START; + CRC_END = CRC64_END; + +#if (DEBUG_CRC == 1) + printf("Adding Syndrome: 0x%08lx\n", poly); +#endif + lang_add_data (QUAD, exp_intop (0)); /* Reserve room for the ECC value */ + crc64_tab = init_crc64_tab(crc64_poly); + if (crc64_tab == NULL) + { + einfo (_("%F%P: can not allocate memory for CRC table: %E\n")); + return; + } + } + else + { + einfo (_("%P:%pS: warning: Only the first CRC polynome is used\n"), + NULL); + } +} + +extern void lang_add_crc64_table(void) +{ + bfd_vma *crc64_table = crc64_tab; /* Use a precomputed, if it exists */ + bool local_table = false; + if (crc64_table == NULL) + { /* No luck, create a table */ + crc64_table = init_crc64_tab(crc64_poly); + if (crc64_table == NULL) + { + einfo (_("%F%P: can not allocate memory for CRC table: %E\n")); + return; + } + local_table = true; + } + for (bfd_vma i = 0 ; i < 256 ; i++) + { + lang_add_data (QUAD, exp_intop (crc64_table[i])); + } + if (local_table) + free(crc64_table); +} + +/* ============ Access functions for inserting checksum in text section=======*/ +static +bool get_text_section_contents(void) +{ + /* + * Get the '.text' section + * Is there a risk that CRC needs to be calculated on more than .text? + * We do not support that... + */ + text_section = bfd_get_section_by_name (link_info.output_bfd, entry_section); + if (text_section == NULL) + { + einfo (_("%P:%pS: Cannot retrieve '.text' section for CRC calc\n"), NULL); + return false; + } + + /* Get the contents of the '.text' area so we can calculate the CRC */ + if (!bfd_malloc_and_get_section(link_info.output_bfd, + text_section->output_section, + (bfd_byte **) &text_contents)) + { + einfo (_("%P:%pS: warning: '.text' section contents unavailable\n" + "CRC generation aborted\n"), NULL); + return false; + } + +#if (DEBUG_CRC == 1) + printf("%s: [0x%08lx .. 0x%08lx]\n", + text_section->name, + text_section->lma, + text_section->lma + text_section->size -1); +#endif + return true; +} + +/* Set variable in the '.text' area */ +static +bool set_crc_checksum(bfd_vma crc, bfd_vma addr, bfd_vma size) +{ + if (!bfd_set_section_contents(link_info.output_bfd, + text_section->output_section, + &crc, + addr, + size)) + { + einfo (_("%P:%pS: warning: updating CRC failed\n" + "CRC generation aborted\n"), NULL); + return false; + } + return true; +} + +static bool symbol_lookup(char *name, bfd_vma *val) +{ + struct bfd_link_hash_entry *h; + *val = 0ull; + h = bfd_link_hash_lookup (link_info.hash, name, false, false, true); + if (h != NULL) + { + if ( + ( + (h->type == bfd_link_hash_defined) || + (h->type == bfd_link_hash_defweak) + ) && + (h->u.def.section->output_section != NULL) + ) + { + *val = (h->u.def.value + + bfd_section_vma (h->u.def.section->output_section) + + h->u.def.section->output_offset); + return true; + } + } + return false; +} + +/* ============ CRC DEBUG functions ==========================================*/ + +#if (DEBUG_CRC == 1) +static void debug_hex(char *prompt, unsigned char *section, + bfd_vma address, bfd_vma sz) +{ + bfd_vma *vma_section = (bfd_vma *) section; + bfd_vma size = (sz)/sizeof(bfd_vma); + printf("%s:\n", prompt); + for (bfd_vma i = 0 ; i < size ; i+=8) + { + printf("0x%08lx: 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n", + address + (i*sizeof(bfd_vma)), + vma_section[i+0], + vma_section[i+1], + vma_section[i+2], + vma_section[i+3]); + } +} + +static +void debug_crc_header(char *prompt) +{ + debug_hex(prompt, text_contents, text_section->vma, 64); +} +static +void debug_crc_update(bfd_vma crc, bfd_vma crc_addr) +{ + printf("CRC [0x%016lx] update at 0x%08lx succeeded\n", crc, crc_addr); +} + +static +void debug_full_textsection(void) +{ + + /* In order to see the updated content, we have to fetch it again */ + + if (!get_text_section_contents()) + { + debug_crc_header("After CRC"); + debug_hex("Full Section After CRC", + text_contents, + text_section->vma, + text_section->size); + free(text_contents); + } +} +#else +#define debug_hex(p,s,a,sz) +#define debug_crc_header(p) +#define debug_crc_update(c, a) +#define debug_full_textsection() +#endif + +/* ============ CRC common functions =========================================*/ +/* + * Multiplexing function for calculating CRC with different algorithms + * 'crc_algo' + */ +static +bfd_vma calculate_crc(const unsigned char *input_str, size_t num_bytes) +{ + if (crc_algo == crc_algo_64) + { + if (crc64_tab != NULL) + { + return calc_crc64(input_str, num_bytes); + } + } + else if (crc_algo == crc_algo_32) + { + if (crc32_tab != NULL) + { + return calc_crc32(input_str, num_bytes); + } + } + /* This should never happen */ + return 0; +} + +static +bool invalid_crc_parameters( + bfd_vma crc_addr, + bfd_vma crc_area_start, + bfd_vma crc_area_end + ) +{ + bool crc_in_section; + /* Get limits of '.text' section */ + bfd_vma text_start = text_section->lma; + bfd_vma text_end = text_section->lma + text_section->size; + + /* All three symbols must be inside the '.text' section */ + crc_in_section = + ((text_start <= crc_addr) && (crc_addr <= text_end)) && + ((text_start <= crc_area_start) && (crc_area_start <= text_end)) && + ((text_start <= crc_area_end) && (crc_area_end <= text_end)); + + if (!crc_in_section) + { + einfo (_("%P:%pS: warning: CRC area outside the '.text' section\n" + "CRC generation aborted\n"), NULL); + /* + * Maybe we should printout the text section start and end + * as well as the boundaries of the CRC check area. + */ + return true; + } + + /* + * CRC checksum must be outside the checked area + * We must check that they do not overlap in the beginning + */ + { + bool crc_valid = false; + if (crc_addr < crc_area_start) + { + if ((crc_addr + crc_size) <= crc_area_start) + { + crc_valid = true; + } + } + else if (crc_addr >= crc_area_end) + { + crc_valid = true; + } + if (!crc_valid) + { + einfo (_("%P:%pS: warning: CRC located inside checked area\n" + "CRC generation aborted\n"), NULL); + return true; + } + } + return false; +} + + +void lang_generate_crc(void) +{ + bfd_vma crc_addr, crc_area_start, crc_area_end; + bfd_vma crc; + bool can_do_crc; + + /* Return immediately, if CRC is not requested */ + if (crc_algo == crc_algo_none) + return; + + if (!get_text_section_contents()) + { + /* Error messages inside check */ + return; + } + /* + * These symbols must be present, for CRC to be generated + * They should all have been defined in a CRC## statement + * If they are not defined, then there is an internal error. + * Should we consider using symbols which cannot be parsed by the linker? + * I.E. CRC-64 is never an identifier + */ + can_do_crc = symbol_lookup(CRC_ADDRESS, &crc_addr) && + symbol_lookup(CRC_START, &crc_area_start) && + symbol_lookup(CRC_END, &crc_area_end); + + if (!can_do_crc) + { + einfo (_("%P:%pS: Internal Error - __CRC#___ symbols not defined\n" + "CRC generation aborted\n"), NULL); + return; + } + + /* Check that the addresses make sense */ + if (invalid_crc_parameters(crc_addr, crc_area_start, crc_area_end)) + { + /* Error messages inside check */ + return; + } + + /* Calculate and set the CRC */ + { + /* + * The '.text' area does not neccessarily start at 0x00000000, + * so we have to shift the indices. + */ + bfd_vma _crc_addr = crc_addr - text_section->vma; + bfd_vma _crc_area_start = crc_area_start - text_section->vma; + bfd_vma _crc_area_end = crc_area_end - text_section->vma; + + + /* This is the CRC calculation which we worked so hard for */ + debug_crc_header("Before CRC"); + crc = calculate_crc(&text_contents[_crc_area_start] , + _crc_area_end - _crc_area_start); + + + /* + * The contents of the '.text' section are no longer needed. + * It is a copy of the section contents, and will therefore be stale + * after we updated the section with the CRC checksum. + * Remove it before we set the CRC checksum, to simplify the code logic. + */ + free(text_contents); + if (set_crc_checksum(crc, _crc_addr, crc_size)) + { + debug_crc_update(crc, crc_addr); + } + } + + debug_full_textsection(); +} + +/* ============ END CRC common functions =====================================*/ + +/* ============ TIMESTAMP common functions ===================================*/ + +/* Store the time of linking in the image */ +void lang_add_timestamp (void) +{ + lang_add_data (QUAD, exp_intop ((bfd_vma) time(0))); +} + +/* ===========================================================================*/ + void lang_startup (const char *name) { diff --git a/ld/ldlang.h b/ld/ldlang.h index 2300fa5b2a3..3d514909cae 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -632,6 +632,18 @@ extern lang_output_section_statement_type *lang_output_section_statement_lookup (const char *, int, int); extern lang_output_section_statement_type *next_matching_output_section_statement (lang_output_section_statement_type *, int); +extern void lang_add_crc32_syndrome + (bool, bfd_vma); +extern void lang_add_crc32_table + (void); +extern void lang_add_crc64_syndrome + (bool, bfd_vma); +extern void lang_add_crc64_table + (void); +extern void lang_add_timestamp + (void); +extern void lang_generate_crc + (void); extern void ldlang_add_undef (const char *const, bool); extern void ldlang_add_require_defined diff --git a/ld/ldmain.c b/ld/ldmain.c index 25cc89b72f9..8b57b2dc5fc 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -527,6 +527,7 @@ main (int argc, char **argv) ldwrite (); + lang_generate_crc(); /* Calculate and store CRC on request */ if (config.map_file != NULL) lang_map (); if (command_line.cref)