]>
git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - ld/lddigest.c
1 /* Linker command language support.
2 Copyright (C) 1991-2023 Ulf Samuelsson <ulf@emagii.com>
4 This file is part of the GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
25 #include "safe-ctype.h"
39 /* CRC calculation on output section */
40 asection
*text_section
;
41 unsigned char *text_contents
= NULL
;
43 char *CRC_ADDRESS
= NULL
;
44 char *CRC_START
= NULL
;
46 char *CRC_TABLE
= NULL
;
52 const char *digest_section
= ".text";
53 const char *digest_label
= "___CRC_LABEL__";
54 bool digest_big_endian
= false;
55 bool polynome_valid
= false;
58 big_endian_host (void)
73 if (big_endian_host ())
75 return !link_info
.big_endian
;
79 return link_info
.big_endian
;
84 /* ============ CRC-32 public functions ======================================*/
87 lang_add_crc32_syndrome (algorithm_desc_t
* a
)
89 CRC_ADDRESS
= CRC32_ADDRESS
;
90 CRC_START
= CRC32_START
;
92 CRC_TABLE
= CRC32_TABLE
;
94 lang_add_data (LONG
, exp_intop (0)); /* Reserve room for the ECC value */
95 a
->crc_tab
= init_crc32_tab (a
);
96 if (a
->crc_tab
== NULL
)
98 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
104 lang_add_crc32_table (bool big_endian
)
106 uint32_t *crc32_table
= algorithm
.crc_tab
; /* Use a precomputed, if it exists */
107 bool local_table
= false;
108 if (crc32_table
== NULL
)
109 { /* No luck, create a table */
110 crc32_table
= init_crc32_tab (&algorithm
);
111 if (crc32_table
== NULL
)
113 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
118 for (bfd_vma i
= 0; i
< 256; i
++)
120 uint32_t elem
= crc32_table
[i
];
123 elem
= __builtin_bswap32 (elem
);
125 lang_add_data (LONG
, exp_intop (elem
));
131 /* ============ CRC-64 public functions ======================================*/
134 lang_add_crc64_syndrome (algorithm_desc_t
* a
)
136 CRC_ADDRESS
= CRC64_ADDRESS
;
137 CRC_START
= CRC64_START
;
139 CRC_TABLE
= CRC64_TABLE
;
140 lang_add_data (QUAD
, exp_intop (0)); /* Reserve room for the ECC value */
141 a
->crc_tab
= init_crc64_tab (a
);
142 if (a
->crc_tab
== NULL
)
144 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
151 print_hash64_table (algorithm_desc_t
* a
)
153 uint64_t *crc_tab
= a
->crc_tab
;
157 printf ("%-20ssBad Table\n", a
->name
);
163 printf ("%03d\t", i
);
164 printf ("0x%016lx, ", crc_tab
[i
+ 0]);
165 printf ("0x%016lx, ", crc_tab
[i
+ 1]);
166 printf ("0x%016lx, ", crc_tab
[i
+ 2]);
167 printf ("0x%016lx\n", crc_tab
[i
+ 3]);
170 printf ("%03d\t", i
);
171 printf ("0x%016lx, ", crc_tab
[i
+ 0]);
172 printf ("0x%016lx, ", crc_tab
[i
+ 1]);
173 printf ("0x%016lx, ", crc_tab
[i
+ 2]);
174 printf ("0x%016lx\n", crc_tab
[i
+ 3]);
178 #define print_hash64_table(x)
182 lang_add_crc64_table (bool big_endian
)
184 bfd_vma
*crc64_table
= algorithm
.crc_tab
; /* Use a precomputed, if it exists */
185 bool local_table
= false;
186 if (crc64_table
== NULL
)
187 { /* No luck, create a table */
188 crc64_table
= init_crc64_tab (&algorithm
);
189 if (crc64_table
== NULL
)
191 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
196 print_hash64_table (&algorithm
);
197 for (bfd_vma i
= 0; i
< 256; i
++)
199 bfd_vma elem
= crc64_table
[i
];
202 elem
= __builtin_bswap64 (elem
);
204 if (link_info
.big_endian
)
206 elem
= __builtin_bswap64 (elem
);
209 lang_add_data (QUAD
, exp_intop (elem
));
215 /* ============ DIGEST COMMON functions ======================================*/
218 lang_add_digest (bfd_vma size
,
222 bfd_vma ireflect
, bfd_vma oreflect
, bfd_vma reciprocal
)
224 if (algorithm
.crc_algo
!= no_algo
) /* We only allow one CRC <polynom> */
226 einfo (_("%X%P: Duplicate digest \"%s\"\n"), "in POLY command");
230 algorithm
.name
= "CUSTOM";
231 algorithm
.big_endian
= digest_big_endian
;
234 algorithm
.crc_algo
= crc_algo_64
;
235 algorithm
.crc_size
= size
;
236 algorithm
.poly
.d64
= poly
; /* Set the polynom */
237 algorithm
.initial
.d64
= initial
; /* Set seed */
238 algorithm
.xor_val
.d64
= xor_val
; /* final XOR value */
239 algorithm
.ireflect
= ireflect
;
240 algorithm
.oreflect
= oreflect
;
241 algorithm
.crc_tab
= NULL
;
242 algorithm
.reciprocal
= reciprocal
;
243 algorithm
.expected
.d64
= 0;
245 lang_add_crc64_syndrome (&algorithm
);
249 algorithm
.crc_algo
= crc_algo_32
;
250 algorithm
.crc_size
= size
;
251 algorithm
.poly
.d32
._0
= poly
; /* Set the polynom */
252 algorithm
.initial
.d32
._0
= initial
; /* Set seed */
253 algorithm
.xor_val
.d32
._0
= xor_val
; /* final XOR value */
254 algorithm
.ireflect
= ireflect
;
255 algorithm
.oreflect
= oreflect
;
256 algorithm
.crc_tab
= NULL
;
257 algorithm
.reciprocal
= reciprocal
;
258 algorithm
.expected
.d32
._0
= 0;
259 lang_add_crc32_syndrome (&algorithm
);
263 einfo (_("%F%P: Illegal Size in DIGEST: %E\n"));
269 id_start_char (char c
)
272 if (('a' <= c
) && (c
<= 'z'))
274 if (('A' <= c
) && (c
<= 'Z'))
289 if (('0' <= c
) && (c
<= '9'))
291 OK
|= id_start_char (c
);
296 lang_get_label (const char *label
, bool *big_endian
)
299 const char *p
= &label
[1];
302 *big_endian
= false; /* unless told otherwise */
303 if (command_line
.endian
== ENDIAN_BIG
)
307 if (command_line
.endian
== ENDIAN_LITTLE
)
313 if (!id_start_char (c
))
315 einfo (_("%X%P: Illegal label \"%s\" in digest command\n"), label
);
316 return "__CRC_LABEL__";
319 for (uint32_t i
= 1; *p
; i
++) /* ignore '.' in first character */
324 bool bad_endian
= false;
325 newlabel
= strndup (label
, i
); /* Memory leak */
331 bool be
= ((c0
== 'B') || (c0
== 'b')) &
332 ((c1
== 'E') || (c1
== 'e'));
333 bool le
= ((c0
== 'L') || (c0
== 'l')) &
334 ((c1
== 'E') || (c1
== 'e'));
354 einfo (_("%X%P: bad 'endian' \"%s\" in digest label\n"), label
);
358 else if (!id_char (c
))
360 einfo (_("%X%P: Illegal label \"%s\" in digest command\n"), label
);
361 return "__CRC_LABEL__";
372 lang_set_digest (char *digest
)
374 if (algorithm
.crc_algo
!= no_algo
) /* We only allow one CRC <polynom> */
376 einfo (_("%X%P: Duplicate digest \"%s\"\n"), digest
);
380 for (poly_t a
= (poly_t
) 0; a
< MAXALGO
; a
++)
383 printf ("Comparing \"%s\" with \"%s\": ", digest
, algorithms
[a
].name
);
385 if (!strcmp (digest
, algorithms
[a
].name
))
390 memcpy (&algorithm
, &algorithms
[a
], sizeof (algorithm_desc_t
));
391 algorithm
.big_endian
= digest_big_endian
;
392 if (algorithm
.crc_size
== 64)
394 lang_add_crc64_syndrome (&algorithm
);
396 else if (algorithm
.crc_size
== 32)
398 lang_add_crc32_syndrome (&algorithm
);
410 einfo (_("%X%P: Unknown digest \"%s\"\n"), digest
);
415 lang_add_digest_table (bool big_endian
)
417 if (algorithm
.crc_algo
== crc_algo_32
)
419 lang_add_crc32_table (big_endian
);
421 else if (algorithm
.crc_algo
== crc_algo_64
)
423 lang_add_crc64_table (big_endian
);
427 /* ============ CRC DEBUG functions ==========================================*/
431 debug_hex (char *prompt
, unsigned char *section
, bfd_vma address
, bfd_vma sz
)
433 bfd_vma
*vma_section
= (bfd_vma
*) section
;
434 bfd_vma size
= (sz
) / sizeof (bfd_vma
);
435 printf ("%s:\n", prompt
);
436 for (bfd_vma i
= 0; i
< size
; i
+= 8)
438 printf ("0x%08lx: 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
439 address
+ (i
* sizeof (bfd_vma
)),
441 vma_section
[i
+ 1], vma_section
[i
+ 2], vma_section
[i
+ 3]);
446 debug_crc_header (char *prompt
)
448 debug_hex (prompt
, text_contents
, text_section
->vma
, 64);
452 debug_crc_update (bfd_vma crc
, bfd_vma crc_addr
)
454 printf ("CRC [0x%016lx] update at 0x%08lx succeeded\n", crc
, crc_addr
);
457 static bool get_text_section_contents (void);
459 debug_full_textsection (void)
462 /* In order to see the updated content, we have to fetch it again */
464 if (!get_text_section_contents ())
466 debug_crc_header ("After CRC");
467 debug_hex ("Full Section After CRC",
468 text_contents
, text_section
->vma
, text_section
->size
);
469 free (text_contents
);
475 print_crc64_algorithm (algorithm_desc_t
* a
, const unsigned char *crc_data
,
478 printf ("64:%-16s, data=\"%s\", ", a
->name
, crc_data
);
479 printf ("poly=0x%016lx i=0x%1x xor=0x%1x .ir=%u .or=%u .rp=%u ",
481 a
->initial
.d32
._0
& 0xF,
482 a
->xor_val
.d32
._0
& 0xF, a
->ireflect
, a
->oreflect
, a
->reciprocal
);
483 printf ("checksum=0x%016lx, expected=0x%016lx\n", crc
, a
->expected
.d64
);
487 print_section (asection
* a
)
489 uint32_t len
= strlen (a
->name
);
490 char *name
= malloc (len
+ 4);
495 for (uint32_t i
= 0; i
< len
; i
++)
507 printf ("%-20s [0x%08lx .. 0x%08lx]\n", name
, a
->lma
, a
->lma
+ a
->size
- 1);
512 print_section_list (void)
514 bfd
*list
= link_info
.output_bfd
;
516 if (strcmp (digest_section
, ".foo"))
519 for (elem
= list
->sections
; elem
!= NULL
; elem
= elem
->next
)
521 if (elem
->name
!= NULL
)
523 print_section (elem
);
529 #define debug_hex(p,s,a,sz)
530 #define debug_crc_header(p)
531 #define debug_crc_update(c, a)
532 #define debug_full_textsection()
533 #define print_section(a)
534 #define print_section_list()
537 /* ============ Access functions for inserting checksum in text section=======*/
540 get_section_by_address (bfd_vma addr
)
542 bfd
*list
= link_info
.output_bfd
;
543 for (asection
* elem
= list
->sections
; elem
!= NULL
; elem
= elem
->next
)
545 bfd_vma lma
= elem
->lma
;
546 bfd_vma end
= lma
+ elem
->size
;
548 if ((addr
>= lma
) && (addr
< end
))
550 digest_section
= elem
->name
;
558 get_text_section_contents (void)
561 * Get the '.text' section
562 * Is there a risk that CRC needs to be calculated on more than .text?
563 * We do not support that...
565 print_section_list ();
568 bfd_get_section_by_name (link_info
.output_bfd
, digest_section
);
569 if (text_section
== NULL
)
571 einfo (_("%X%P: cannot retrieve '%s' section for CRC calculation\n"),
576 /* Get the contents of the '.text' area so we can calculate the CRC */
577 if (!bfd_malloc_and_get_section (link_info
.output_bfd
,
578 text_section
->output_section
,
579 (bfd_byte
**) & text_contents
))
581 einfo (_("%X%P: '&s' section contents unavailable\n"
582 "CRC generation aborted\n"), digest_section
);
587 print_section (text_section
);
589 printf ("%s: [0x%08lx .. 0x%08lx]\n",
591 text_section->lma, text_section->lma + text_section->size - 1);
597 /* Set variable in the '.text' area */
599 set_crc32_checksum (uint32_t crc
, bfd_vma addr
)
601 uint32_t real_crc
= crc
;
602 if (big_endian_host ())
604 if (algorithm
.big_endian
)
610 real_crc
= __builtin_bswap32 (crc
);
615 if (algorithm
.big_endian
)
617 real_crc
= __builtin_bswap32 (crc
);
625 return (bfd_set_section_contents (link_info
.output_bfd
,
626 text_section
->output_section
,
627 &real_crc
, addr
, sizeof (uint32_t)));
631 set_crc64_checksum (uint64_t crc
, bfd_vma addr
)
633 uint64_t real_crc
= crc
;
634 if (big_endian_host ())
636 if (algorithm
.big_endian
)
642 real_crc
= __builtin_bswap64 (crc
);
647 if (algorithm
.big_endian
)
649 real_crc
= __builtin_bswap64 (crc
);
657 return (bfd_set_section_contents (link_info
.output_bfd
,
658 text_section
->output_section
,
659 &real_crc
, addr
, sizeof (uint64_t)));
663 set_crc_checksum (bfd_vma crc
, bfd_vma addr
, bfd_vma size
)
668 status
= set_crc64_checksum (crc
, addr
);
672 status
= set_crc32_checksum ((uint32_t) crc
, addr
);
678 symbol_lookup (char *name
, bfd_vma
* val
)
680 struct bfd_link_hash_entry
*h
;
682 h
= bfd_link_hash_lookup (link_info
.hash
, name
, false, false, true);
685 if (((h
->type
== bfd_link_hash_defined
) ||
686 (h
->type
== bfd_link_hash_defweak
)) &&
687 (h
->u
.def
.section
->output_section
!= NULL
))
689 *val
= (h
->u
.def
.value
690 + bfd_section_vma (h
->u
.def
.section
->output_section
)
691 + h
->u
.def
.section
->output_offset
);
698 /* ============ CRC common functions =========================================*/
700 * Multiplexing function for calculating CRC with different algorithms
701 * 'algorithm.crc_algo'
704 calculate_crc (const unsigned char *input_str
, size_t num_bytes
)
706 if (algorithm
.crc_algo
== crc_algo_64
)
708 if (algorithm
.crc_tab
!= NULL
)
710 return calc_crc64 (&algorithm
, input_str
, num_bytes
);
713 else if (algorithm
.crc_algo
== crc_algo_32
)
715 if (algorithm
.crc_tab
!= NULL
)
717 return calc_crc32 (&algorithm
, input_str
, num_bytes
);
720 /* This should never happen */
725 invalid_crc_parameters (bfd_vma crc_addr
,
726 bfd_vma crc_area_start
, bfd_vma crc_area_end
)
729 bfd_vma crc_size
= algorithm
.crc_size
/ 8;
730 /* Get limits of '.text' section */
731 bfd_vma text_start
= text_section
->lma
;
732 bfd_vma text_end
= text_section
->lma
+ text_section
->size
;
734 /* All three symbols must be inside the '.text' section */
736 ((crc_addr
>= text_start
) && ((crc_addr
+ crc_size
) <= text_end
)) &&
737 ((crc_area_start
>= text_start
) && (crc_area_start
<= text_end
)) &&
738 ((crc_area_end
>= text_start
) && (crc_area_end
<= text_end
));
742 einfo (_("%X%P: The CRC digest and table should be inside the '%s' "
743 "section\n"), digest_section
);
745 * Maybe we should printout the text section start and end
746 * as well as the boundaries of the CRC check area.
752 * CRC checksum must be outside the checked area
753 * We must check that they do not overlap in the beginning
756 bool crc_valid
= false;
757 if ((crc_addr
+ crc_size
) < crc_area_start
)
761 else if (crc_addr
>= crc_area_end
)
767 einfo (_("%X%P: CRC located inside checked area\n"), NULL
);
772 if (crc_area_start
> crc_area_end
)
774 einfo (_("%X%P: CRC area starts after its end location\n"), NULL
);
782 lang_generate_crc (void)
784 bfd_vma crc_addr
, crc_area_start
, crc_area_end
;
788 /* Return immediately, if CRC is not requested */
789 if (algorithm
.crc_algo
== no_algo
)
793 * These symbols must be present, for CRC to be generated
794 * They should all have been defined in a CRC## <syndrome> statement
795 * If they are not defined, then there is an internal error.
796 * Should we consider using symbols which cannot be parsed by the linker?
797 * I.E. CRC-64 is never an identifier
799 can_do_crc
= symbol_lookup (CRC_ADDRESS
, &crc_addr
) &&
800 symbol_lookup (CRC_START
, &crc_area_start
) &&
801 symbol_lookup (CRC_END
, &crc_area_end
);
805 einfo (_("%X%P: Internal Error - __CRC#___ symbols not defined\n"),
810 if (!get_section_by_address (crc_addr
)) /* update digest_section, if needed */
812 einfo (_("%X%P: The CRC digest and table must be inside the '%s' "
813 "section\n"), digest_section
);
816 if (!get_text_section_contents ())
818 /* Error messages inside check */
822 /* Check that the addresses make sense */
823 if (invalid_crc_parameters (crc_addr
, crc_area_start
, crc_area_end
))
825 /* Error messages inside check */
829 /* Calculate and set the CRC */
832 * The '.text' area does not neccessarily start at 0x00000000,
833 * so we have to shift the indices.
835 bfd_vma _crc_addr
= crc_addr
- text_section
->vma
;
836 bfd_vma _crc_area_start
= crc_area_start
- text_section
->vma
;
837 bfd_vma _crc_area_end
= crc_area_end
- text_section
->vma
;
840 /* This is the CRC calculation which we worked so hard for */
841 debug_crc_header ("Before CRC");
843 print_hash64_table (&algorithm
);
846 crc
= calculate_crc ((const unsigned char *) "123456789", 9);
848 crc
= calculate_crc (&text_contents
[_crc_area_start
],
849 _crc_area_end
- _crc_area_start
);
853 printf ("size = 0x%08u\n", (uint32_t) (_crc_area_end
- _crc_area_start
));
854 printf ("start = 0x%016lx\n", _crc_area_start
);
855 printf ("end = 0x%016lx\n", _crc_area_end
);
856 printf ("crc = 0x%016lx\n", crc
);
858 print_crc64_algorithm (&algorithm
, &text_contents
[_crc_area_start
], crc
);
862 * The contents of the '.text' section are no longer needed.
863 * It is a copy of the section contents, and will therefore be stale
864 * after we updated the section with the CRC checksum.
865 * Remove it before we set the CRC checksum, to simplify the code logic.
867 free (text_contents
);
868 if (set_crc_checksum (crc
, _crc_addr
, algorithm
.crc_size
))
870 debug_crc_update (crc
, crc_addr
);
874 einfo (_("%X%P: updating CRC in section '%s' failed\n"),
879 debug_full_textsection ();
882 /* ============ END CRC common functions =====================================*/
885 lang_generate_digest (void)
887 /* Return immediately, if CRC is not requested */
889 printf ("%s: BEGIN\n", __FUNCTION__
);
891 if (algorithm
.crc_algo
== no_algo
)
894 /* Handle 32/64-bit CRCs */
895 if ((algorithm
.crc_algo
== crc_algo_32
)
896 || (algorithm
.crc_algo
== crc_algo_64
))
898 lang_generate_crc ();
901 printf ("%s: END\n", __FUNCTION__
);