[PATCH v5 08/10] DIGEST: CRC-32/64 algorithms
binutils@emagii.com
binutils@emagii.com
Wed Feb 22 16:16:07 GMT 2023
From: Ulf Samuelsson <ulf@emagii.com>
Creation of CRC tables
Calculations of CRC
Functions to add data into the output section
Signed-off-by: Ulf Samuelsson <ulf@emagii.com>
---
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 <ldgram.h>
+#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 <polynom> */
+ {
+ 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 <polynom> */
+ {
+ 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 <polynom> */
+ {
+ 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 <polynom> */
+ {
+ 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## <syndrome> 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 <stddef.h>
+#include <stdint.h>
+
+#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
More information about the Binutils
mailing list