From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from emagii.se (www.emagii.com [185.133.207.17]) by sourceware.org (Postfix) with ESMTPS id 19B273858439 for ; Wed, 22 Feb 2023 16:17:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 19B273858439 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=emagii.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=emagii.com Received: from valinor.ownit.se (84-55-68-216.customers.ownit.se [84.55.68.216]) by emagii.se (Postfix) with ESMTPSA id 4B47512029D; Wed, 22 Feb 2023 17:17:26 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=emagii.com; s=default; t=1677082651; bh=CIZLaOoXEcfuVJ3Kz7C209PcdHccsQlC1kgaoxO2HlM=; h=From:To:Subject; b=sGv7yKXb5hxQrN/aaeOtsAtsS9LsjHwY9wpJp+XtbN+nB1p8TZTZ2VYlpMbHAFzGr PPVGA2EaOOC0zFcNhg/OSTVVU+1n7GrB5oCgHc3F3LuRqM8MoBNBh6F6i2xYdKjSWx g64jWZFJBzwvIJcOsXCW4JaM9FneNdLQfiu0J6RE= Authentication-Results: emagii.beebytevps.io; spf=pass (sender IP is 84.55.68.216) smtp.mailfrom=binutils@emagii.com smtp.helo=valinor.ownit.se Received-SPF: pass (emagii.beebytevps.io: connection is authenticated) From: binutils@emagii.com To: binutils@sourceware.org Cc: nickc@redhat.com, Ulf Samuelsson Subject: [PATCH v5 08/10] DIGEST: CRC-32/64 algorithms Date: Wed, 22 Feb 2023 17:16:07 +0100 Message-Id: <20230222161609.239928-9-binutils@emagii.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230222161609.239928-1-binutils@emagii.com> References: <20230222161609.239928-1-binutils@emagii.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-PPP-Message-ID: <167708265030.2544758.11194658605663492131@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=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Ulf Samuelsson Creation of CRC tables Calculations of CRC Functions to add data into the output section Signed-off-by: Ulf Samuelsson --- ld/ldcrc32.c | 138 ++++++++++++ ld/ldcrc64.c | 131 ++++++++++++ ld/lddigest.c | 575 ++++++++++++++++++++++++++++++++++++++++++++++++++ ld/lddigest.h | 97 +++++++++ 4 files changed, 941 insertions(+) create mode 100644 ld/ldcrc32.c create mode 100644 ld/ldcrc64.c create mode 100644 ld/lddigest.c create mode 100755 ld/lddigest.h diff --git a/ld/ldcrc32.c b/ld/ldcrc32.c new file mode 100644 index 00000000000..67a85e89d1b --- /dev/null +++ b/ld/ldcrc32.c @@ -0,0 +1,138 @@ +/* + * 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. + * + */ + +#include "sysdep.h" +#include "bfd.h" +#include "lddigest.h" + +/* ============ 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 + */ +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. + */ + +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 < num_bytes; a++) + { + crc = (crc >> 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. + */ +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 < num_bytes; a++) + { + crc = (crc >> 8) ^ + crc32_tab[(crc ^ (uint32_t) * ptr++) & 0x000000FFul]; + } + } + + return (crc); + +} /* calc_crc32 */ diff --git a/ld/ldcrc64.c b/ld/ldcrc64.c new file mode 100644 index 00000000000..4c2bc89a78d --- /dev/null +++ b/ld/ldcrc64.c @@ -0,0 +1,131 @@ +/* + * 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. + * + */ + +#include "sysdep.h" +#include "bfd.h" +#include "lddigest.h" + +/* ============ 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 + */ +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 + */ +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 < num_bytes; a++) + { + crc = (crc << 8) ^ + crc64_tab[((crc >> 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 + */ +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 < num_bytes; a++) + { + crc = (crc << 8) ^ + crc64_tab[((crc >> 56) ^ (bfd_vma) * ptr++) & + 0x00000000000000FFull]; + } + } + return crc; +} /* calc_crc64 */ diff --git a/ld/lddigest.c b/ld/lddigest.c new file mode 100644 index 00000000000..bed71a54cd1 --- /dev/null +++ b/ld/lddigest.c @@ -0,0 +1,575 @@ +/* Linker command language support. + Copyright (C) 1991-2023 Free Software Foundation, Inc. + + This file is part of the GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define DEBUG_CRC 0 + +#include "sysdep.h" +#include "bfd.h" +#include "safe-ctype.h" +#include "obstack.h" +#include "bfdlink.h" +#include "ctf-api.h" + +#include "ld.h" +#include "ldmain.h" +#include "ldexp.h" +#include "ldlang.h" +#include +#include "ldlex.h" +#include "ldmisc.h" +#include "lddigest.h" + +/* CRC calculation on output section */ +asection *text_section; +unsigned char *text_contents = NULL; + +algo_t crc_algo = no_algo; +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 */ +uint32_t *crc32_tab = NULL; + +char *CRC_ADDRESS = NULL; +char *CRC_START = NULL; +char *CRC_END = NULL; +char *CRC_TABLE = NULL; + +const char *digest_section = ".text"; + +/* ============ CRC-32 public functions ======================================*/ + +void +lang_add_crc32_syndrome (bool invert, bfd_vma poly) +{ + unsigned int poly32 = (unsigned int) (poly & 0xFFFFFFFF); +#if (DEBUG_CRC == 1) + printf ("%s: invert=%d, poly=0x%08ul\n", __FUNCTION__, invert, poly32); +#endif + if (crc_algo == no_algo) /* We only allow one CRC64 */ + { + crc_algo = crc_algo_32; + crc_size = sizeof (uint32_t); + crc_invert = invert; + crc32_poly = poly32; /* Set the polynom */ + CRC_ADDRESS = CRC32_ADDRESS; + CRC_START = CRC32_START; + CRC_END = CRC32_END; + CRC_TABLE = CRC32_TABLE; + +#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); + } +} + +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 public functions ======================================*/ + +void +lang_add_crc64_syndrome (bool invert, bfd_vma poly) +{ +#if (DEBUG_CRC == 1) + printf ("%s: invert=%d poly=0x%016lu\n", __FUNCTION__, invert, poly); +#endif + if (crc_algo == no_algo) /* 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; + CRC_TABLE = CRC64_TABLE; + +#if (DEBUG_CRC == 1) + printf ("Adding Syndrome: 0x%016lu\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); + } +} + +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 */ +#if (DEBUG_CRC == 1) + printf ("%s: Init CRC64 Tab\n", __FUNCTION__); +#endif + crc64_table = init_crc64_tab (crc64_poly); +#if (DEBUG_CRC == 1) + printf ("%s: Init CRC64 Tab DONE\n", __FUNCTION__); +#endif + if (crc64_table == NULL) + { + einfo (_("%F%P: can not allocate memory for CRC table: %E\n")); + return; + } + local_table = true; + } +#if (DEBUG_CRC == 1) + printf ("%s: Adding to table\n", __FUNCTION__); +#endif + for (bfd_vma i = 0; i < 256; i++) + { + lang_add_data (QUAD, exp_intop (crc64_table[i])); + } + if (local_table) + free (crc64_table); +} + +/* ============ DIGEST COMMON functions ======================================*/ + +void +lang_add_digest (bool invert, bfd_vma size, bfd_vma poly) +{ + if (crc_algo != no_algo) /* We only allow one CRC */ + { + einfo (_("%P:%pS: warning: Only the first CRC polynome is used\n"), + NULL); + return; + } + + if (size == 32) + { + lang_add_crc32_syndrome (invert, poly); + } + else if (size == 64) + { + lang_add_crc64_syndrome (invert, poly); + } + else + { + einfo (_("%F%P: Illegal Size in DIGEST: %E\n")); + return; + } +} + +bool +lang_set_digest (char *digest) +{ +#if (DEBUG_CRC == 1) + printf ("%s: DIGEST=%s\n", __FUNCTION__, digest); +#endif + if (crc_algo != no_algo) /* We only allow one CRC */ + { + einfo (_("%P:%pS: warning: Only the first CRC polynome is used\n"), + NULL); + return false; + } + + if (!strcmp (digest, "CRC64-ECMA")) + { + lang_add_crc64_syndrome (false, CRC_POLY_64); + } + else if (!strcmp (digest, "CRC64-WE")) + { + lang_add_crc64_syndrome (true, CRC_POLY_64); + } + else if (!strcmp (digest, "CRC64-ISO")) + { + lang_add_crc64_syndrome (false, CRC_POLY_64_ISO); + } + else if (!strcmp (digest, "CRC32")) + { + lang_add_crc32_syndrome (true, CRC_POLY_32); + } + else + { + einfo (_("%F%P: Unknown DIGEST: %E\n")); + return false; + } + return true; +} + +void +lang_add_digest_table (void) +{ +#if (DEBUG_CRC == 1) + printf ("%s: size=%d\n", __FUNCTION__, (int) crc_algo); +#endif + if (crc_algo == crc_algo_32) + { + lang_add_crc32_table (); + } + else if (crc_algo == crc_algo_64) + { + lang_add_crc64_table (); + } +#if (DEBUG_CRC == 1) + printf ("%s: END\n", __FUNCTION__); +#endif +} + +void +lang_set_digest_section (char *section) +{ +#if (DEBUG_CRC == 1) + printf ("%s: size=%d\n", __FUNCTION__, (int) crc_algo); +#endif + digest_section = section; +} + +/* ============ 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, digest_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) +{ +#if (DEBUG_CRC == 1) + printf ("%s\n", __FUNCTION__); +#endif + 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 == no_algo) + 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 =====================================*/ + +void +lang_generate_digest (void) +{ + /* Return immediately, if CRC is not requested */ + if (crc_algo == no_algo) + return; + + /* Handle 32/64-bit CRCs */ + if ((crc_algo == crc_algo_32) || (crc_algo == crc_algo_32)) + { + lang_generate_crc (); + } +} diff --git a/ld/lddigest.h b/ld/lddigest.h new file mode 100755 index 00000000000..ffd65df4785 --- /dev/null +++ b/ld/lddigest.h @@ -0,0 +1,97 @@ +/* + * 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 LDDIGEST_H +#define LDDIGEST_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___" + +typedef enum algorithm +{ + no_algo = 0, + sha_algo_1 = 1, + crc_algo_32 = 4, + crc_algo_64 = 8, + sha_algo_256 = 256, + sha_algo_512 +} algo_t; + + + +extern char *CRC_ADDRESS; +extern char *CRC_START; +extern char *CRC_END; +extern char *CRC_TABLE; +extern uint32_t *crc32_tab; +extern bfd_vma *crc64_tab; +extern bool crc_invert; + +extern void lang_add_crc32_syndrome (bool invert, bfd_vma poly); +extern void lang_add_crc32_table (void); +extern void lang_add_crc64_syndrome (bool invert, bfd_vma poly); +extern void lang_add_crc64_table (void); + +extern void lang_add_digest (bool invert, bfd_vma size, bfd_vma polynome); +extern bool lang_set_digest (char *digest); +extern void lang_add_digest_table (void); +extern void lang_generate_crc (void); +extern void lang_generate_digest (void); +extern void lang_set_digest_section (char *section); + +/* CRC-32 */ +extern uint32_t *init_crc32_tab (uint32_t poly); +extern uint32_t calc_crc32_inv + (const unsigned char *input_str, size_t num_bytes); +extern uint32_t calc_crc32 (const unsigned char *input_str, size_t num_bytes); + +/* CR-64 */ +extern bfd_vma *init_crc64_tab (bfd_vma poly); +extern bfd_vma calc_crc64_inv + (const unsigned char *input_str, size_t num_bytes); +extern bfd_vma calc_crc64 (const unsigned char *input_str, size_t num_bytes); + +#endif /* LDDIGEST_H */ -- 2.34.1