]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - ld/lddigest.c
DIGEST: calculation
[thirdparty/binutils-gdb.git] / ld / lddigest.c
1 /* Linker command language support.
2 Copyright (C) 1991-2023 Ulf Samuelsson <ulf@emagii.com>
3
4 This file is part of the GNU Binutils.
5
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.
10
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.
15
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. */
20
21 #define DEBUG_CRC 0
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "safe-ctype.h"
26 #include "obstack.h"
27 #include "bfdlink.h"
28 #include "ctf-api.h"
29
30 #include "ld.h"
31 #include "ldmain.h"
32 #include "ldexp.h"
33 #include "ldlang.h"
34 #include <ldgram.h>
35 #include "ldlex.h"
36 #include "ldmisc.h"
37 #include "lddigest.h"
38
39 /* CRC calculation on output section */
40 asection *text_section;
41 unsigned char *text_contents = NULL;
42
43 char *CRC_ADDRESS = NULL;
44 char *CRC_START = NULL;
45 char *CRC_END = NULL;
46 char *CRC_TABLE = NULL;
47
48
49
50
51
52 const char *digest_section = ".text";
53 const char *digest_label = "___CRC_LABEL__";
54 bool digest_big_endian = false;
55 bool polynome_valid = false;
56
57 static bool
58 big_endian_host (void)
59 {
60 union
61 {
62 uint32_t i;
63 char c[4];
64 } e = { 0x01000000 };
65
66 return e.c[0];
67 }
68
69 #if 0
70 static bool
71 swap_endian (void)
72 {
73 if (big_endian_host ())
74 {
75 return !link_info.big_endian;
76 }
77 else
78 {
79 return link_info.big_endian;
80 }
81 }
82 #endif
83
84 /* ============ CRC-32 public functions ======================================*/
85
86 void
87 lang_add_crc32_syndrome (algorithm_desc_t * a)
88 {
89 CRC_ADDRESS = CRC32_ADDRESS;
90 CRC_START = CRC32_START;
91 CRC_END = CRC32_END;
92 CRC_TABLE = CRC32_TABLE;
93
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)
97 {
98 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
99 return;
100 }
101 }
102
103 static void
104 lang_add_crc32_table (bool big_endian)
105 {
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)
112 {
113 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
114 return;
115 }
116 local_table = true;
117 }
118 for (bfd_vma i = 0; i < 256; i++)
119 {
120 uint32_t elem = crc32_table[i];
121 if (big_endian)
122 {
123 elem = __builtin_bswap32 (elem);
124 }
125 lang_add_data (LONG, exp_intop (elem));
126 }
127 if (local_table)
128 free (crc32_table);
129 }
130
131 /* ============ CRC-64 public functions ======================================*/
132
133 void
134 lang_add_crc64_syndrome (algorithm_desc_t * a)
135 {
136 CRC_ADDRESS = CRC64_ADDRESS;
137 CRC_START = CRC64_START;
138 CRC_END = CRC64_END;
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)
143 {
144 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
145 return;
146 }
147 }
148
149 #if (DEBUG_CRC == 1)
150 static void
151 print_hash64_table (algorithm_desc_t * a)
152 {
153 uint64_t *crc_tab = a->crc_tab;
154 uint32_t i;
155 if (crc_tab == NULL)
156 {
157 printf ("%-20ssBad Table\n", a->name);
158 return;
159
160 }
161
162 i = 0;
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]);
168 printf ("\t...\n");
169 i = 252;
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]);
175 printf ("\n");
176 }
177 #else
178 #define print_hash64_table(x)
179 #endif
180
181 static void
182 lang_add_crc64_table (bool big_endian)
183 {
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)
190 {
191 einfo (_("%F%P: can not allocate memory for CRC table: %E\n"));
192 return;
193 }
194 local_table = true;
195 }
196 print_hash64_table (&algorithm);
197 for (bfd_vma i = 0; i < 256; i++)
198 {
199 bfd_vma elem = crc64_table[i];
200 if (big_endian)
201 {
202 elem = __builtin_bswap64 (elem);
203 }
204 if (link_info.big_endian)
205 {
206 elem = __builtin_bswap64 (elem);
207 }
208
209 lang_add_data (QUAD, exp_intop (elem));
210 }
211 if (local_table)
212 free (crc64_table);
213 }
214
215 /* ============ DIGEST COMMON functions ======================================*/
216
217 void
218 lang_add_digest (bfd_vma size,
219 bfd_vma poly,
220 bfd_vma initial,
221 bfd_vma xor_val,
222 bfd_vma ireflect, bfd_vma oreflect, bfd_vma reciprocal)
223 {
224 if (algorithm.crc_algo != no_algo) /* We only allow one CRC <polynom> */
225 {
226 einfo (_("%X%P: Duplicate digest \"%s\"\n"), "in POLY command");
227 return;
228 }
229
230 algorithm.name = "CUSTOM";
231 algorithm.big_endian = digest_big_endian;
232 if (size == 64)
233 {
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;
244
245 lang_add_crc64_syndrome (&algorithm);
246 }
247 else if (size == 32)
248 {
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);
260 }
261 else
262 {
263 einfo (_("%F%P: Illegal Size in DIGEST: %E\n"));
264 return;
265 }
266 }
267
268 static bool
269 id_start_char (char c)
270 {
271 bool OK = false;
272 if (('a' <= c) && (c <= 'z'))
273 OK |= true;
274 if (('A' <= c) && (c <= 'Z'))
275 OK |= true;
276 if ('_' == c)
277 OK |= true;
278 if ('-' == c)
279 OK |= true;
280 if ('.' == c)
281 OK |= true;
282 return OK;
283 }
284
285 static bool
286 id_char (char c)
287 {
288 bool OK = false;
289 if (('0' <= c) && (c <= '9'))
290 OK |= true;
291 OK |= id_start_char (c);
292 return OK;
293 }
294
295 const char *
296 lang_get_label (const char *label, bool *big_endian)
297 {
298 char *newlabel;
299 const char *p = &label[1];
300 char c;
301
302 *big_endian = false; /* unless told otherwise */
303 if (command_line.endian == ENDIAN_BIG)
304 {
305 *big_endian = true;
306 }
307 if (command_line.endian == ENDIAN_LITTLE)
308 {
309 *big_endian = false;
310 }
311 c = *label;
312
313 if (!id_start_char (c))
314 {
315 einfo (_("%X%P: Illegal label \"%s\" in digest command\n"), label);
316 return "__CRC_LABEL__";
317 }
318
319 for (uint32_t i = 1; *p; i++) /* ignore '.' in first character */
320 {
321 c = *p;
322 if (c == '#')
323 {
324 bool bad_endian = false;
325 newlabel = strndup (label, i); /* Memory leak */
326 p++;
327 if (strlen (p) == 2)
328 {
329 char c0 = *p++;
330 char c1 = *p;
331 bool be = ((c0 == 'B') || (c0 == 'b')) &
332 ((c1 == 'E') || (c1 == 'e'));
333 bool le = ((c0 == 'L') || (c0 == 'l')) &
334 ((c1 == 'E') || (c1 == 'e'));
335 if (be)
336 {
337 *big_endian = true;
338 }
339 else if (le)
340 {
341 *big_endian = false;
342 }
343 else
344 {
345 bad_endian = true;
346 }
347 }
348 else
349 {
350 bad_endian = true;
351 }
352 if (bad_endian)
353 {
354 einfo (_("%X%P: bad 'endian' \"%s\" in digest label\n"), label);
355 }
356 return newlabel;
357 }
358 else if (!id_char (c))
359 {
360 einfo (_("%X%P: Illegal label \"%s\" in digest command\n"), label);
361 return "__CRC_LABEL__";
362 }
363 else
364 {
365 p++;
366 }
367 }
368 return label;
369 }
370
371 bool
372 lang_set_digest (char *digest)
373 {
374 if (algorithm.crc_algo != no_algo) /* We only allow one CRC <polynom> */
375 {
376 einfo (_("%X%P: Duplicate digest \"%s\"\n"), digest);
377 return false;
378 }
379
380 for (poly_t a = (poly_t) 0; a < MAXALGO; a++)
381 {
382 #if (DEBUG_CRC == 1)
383 printf ("Comparing \"%s\" with \"%s\": ", digest, algorithms[a].name);
384 #endif
385 if (!strcmp (digest, algorithms[a].name))
386 {
387 #if (DEBUG_CRC == 1)
388 printf ("OK\n");
389 #endif
390 memcpy (&algorithm, &algorithms[a], sizeof (algorithm_desc_t));
391 algorithm.big_endian = digest_big_endian;
392 if (algorithm.crc_size == 64)
393 {
394 lang_add_crc64_syndrome (&algorithm);
395 }
396 else if (algorithm.crc_size == 32)
397 {
398 lang_add_crc32_syndrome (&algorithm);
399 }
400
401 return true;
402 }
403 #if (DEBUG_CRC == 1)
404 else
405 {
406 printf ("FAIL\n");
407 }
408 #endif
409 }
410 einfo (_("%X%P: Unknown digest \"%s\"\n"), digest);
411 return false;
412 }
413
414 void
415 lang_add_digest_table (bool big_endian)
416 {
417 if (algorithm.crc_algo == crc_algo_32)
418 {
419 lang_add_crc32_table (big_endian);
420 }
421 else if (algorithm.crc_algo == crc_algo_64)
422 {
423 lang_add_crc64_table (big_endian);
424 }
425 }
426
427 /* ============ CRC DEBUG functions ==========================================*/
428
429 #if (DEBUG_CRC == 1)
430 static void
431 debug_hex (char *prompt, unsigned char *section, bfd_vma address, bfd_vma sz)
432 {
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)
437 {
438 printf ("0x%08lx: 0x%016lx 0x%016lx 0x%016lx 0x%016lx\n",
439 address + (i * sizeof (bfd_vma)),
440 vma_section[i + 0],
441 vma_section[i + 1], vma_section[i + 2], vma_section[i + 3]);
442 }
443 }
444
445 static void
446 debug_crc_header (char *prompt)
447 {
448 debug_hex (prompt, text_contents, text_section->vma, 64);
449 }
450
451 static void
452 debug_crc_update (bfd_vma crc, bfd_vma crc_addr)
453 {
454 printf ("CRC [0x%016lx] update at 0x%08lx succeeded\n", crc, crc_addr);
455 }
456
457 static bool get_text_section_contents (void);
458 static void
459 debug_full_textsection (void)
460 {
461
462 /* In order to see the updated content, we have to fetch it again */
463
464 if (!get_text_section_contents ())
465 {
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);
470 }
471 }
472
473
474 static void
475 print_crc64_algorithm (algorithm_desc_t * a, const unsigned char *crc_data,
476 uint64_t crc)
477 {
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 ",
480 a->poly.d64,
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);
484 }
485
486 static void
487 print_section (asection * a)
488 {
489 uint32_t len = strlen (a->name);
490 char *name = malloc (len + 4);
491 char *p = name;
492 if (p != NULL)
493 {
494 *p++ = '"';
495 for (uint32_t i = 0; i < len; i++)
496 {
497 *p++ = a->name[i];
498 }
499 *p++ = '"';
500 *p++ = ':';
501 *p++ = '\0';
502 }
503 else
504 {
505 p = "\"?\"";
506 }
507 printf ("%-20s [0x%08lx .. 0x%08lx]\n", name, a->lma, a->lma + a->size - 1);
508 free (name);
509 }
510
511 static void
512 print_section_list (void)
513 {
514 bfd *list = link_info.output_bfd;
515 asection *elem;
516 if (strcmp (digest_section, ".foo"))
517 return;
518
519 for (elem = list->sections; elem != NULL; elem = elem->next)
520 {
521 if (elem->name != NULL)
522 {
523 print_section (elem);
524 }
525 }
526 }
527
528 #else
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()
535 #endif
536
537 /* ============ Access functions for inserting checksum in text section=======*/
538
539 static bool
540 get_section_by_address (bfd_vma addr)
541 {
542 bfd *list = link_info.output_bfd;
543 for (asection * elem = list->sections; elem != NULL; elem = elem->next)
544 {
545 bfd_vma lma = elem->lma;
546 bfd_vma end = lma + elem->size;
547
548 if ((addr >= lma) && (addr < end))
549 {
550 digest_section = elem->name;
551 return true;
552 }
553 }
554 return false;
555 }
556
557 static bool
558 get_text_section_contents (void)
559 {
560 /*
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...
564 */
565 print_section_list ();
566
567 text_section =
568 bfd_get_section_by_name (link_info.output_bfd, digest_section);
569 if (text_section == NULL)
570 {
571 einfo (_("%X%P: cannot retrieve '%s' section for CRC calculation\n"),
572 digest_section);
573 return false;
574 }
575
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))
580 {
581 einfo (_("%X%P: '&s' section contents unavailable\n"
582 "CRC generation aborted\n"), digest_section);
583 return false;
584 }
585
586 #if (DEBUG_CRC == 1)
587 print_section (text_section);
588 /*
589 printf ("%s: [0x%08lx .. 0x%08lx]\n",
590 text_section->name,
591 text_section->lma, text_section->lma + text_section->size - 1);
592 */
593 #endif
594 return true;
595 }
596
597 /* Set variable in the '.text' area */
598 static bool
599 set_crc32_checksum (uint32_t crc, bfd_vma addr)
600 {
601 uint32_t real_crc = crc;
602 if (big_endian_host ())
603 {
604 if (algorithm.big_endian)
605 {
606 /* We are OK */
607 }
608 else
609 {
610 real_crc = __builtin_bswap32 (crc);
611 }
612 }
613 else
614 {
615 if (algorithm.big_endian)
616 {
617 real_crc = __builtin_bswap32 (crc);
618 }
619 else
620 {
621 /* We are OK */
622 }
623 }
624
625 return (bfd_set_section_contents (link_info.output_bfd,
626 text_section->output_section,
627 &real_crc, addr, sizeof (uint32_t)));
628 }
629
630 static bool
631 set_crc64_checksum (uint64_t crc, bfd_vma addr)
632 {
633 uint64_t real_crc = crc;
634 if (big_endian_host ())
635 {
636 if (algorithm.big_endian)
637 {
638 /* We are OK */
639 }
640 else
641 {
642 real_crc = __builtin_bswap64 (crc);
643 }
644 }
645 else
646 {
647 if (algorithm.big_endian)
648 {
649 real_crc = __builtin_bswap64 (crc);
650 }
651 else
652 {
653 /* We are OK */
654 }
655 }
656 /* True if OK */
657 return (bfd_set_section_contents (link_info.output_bfd,
658 text_section->output_section,
659 &real_crc, addr, sizeof (uint64_t)));
660 }
661
662 static bool
663 set_crc_checksum (bfd_vma crc, bfd_vma addr, bfd_vma size)
664 {
665 bool status;
666 if (size == 64)
667 {
668 status = set_crc64_checksum (crc, addr);
669 }
670 else
671 {
672 status = set_crc32_checksum ((uint32_t) crc, addr);
673 }
674 return status;
675 }
676
677 static bool
678 symbol_lookup (char *name, bfd_vma * val)
679 {
680 struct bfd_link_hash_entry *h;
681 *val = 0ull;
682 h = bfd_link_hash_lookup (link_info.hash, name, false, false, true);
683 if (h != NULL)
684 {
685 if (((h->type == bfd_link_hash_defined) ||
686 (h->type == bfd_link_hash_defweak)) &&
687 (h->u.def.section->output_section != NULL))
688 {
689 *val = (h->u.def.value
690 + bfd_section_vma (h->u.def.section->output_section)
691 + h->u.def.section->output_offset);
692 return true;
693 }
694 }
695 return false;
696 }
697
698 /* ============ CRC common functions =========================================*/
699 /*
700 * Multiplexing function for calculating CRC with different algorithms
701 * 'algorithm.crc_algo'
702 */
703 static bfd_vma
704 calculate_crc (const unsigned char *input_str, size_t num_bytes)
705 {
706 if (algorithm.crc_algo == crc_algo_64)
707 {
708 if (algorithm.crc_tab != NULL)
709 {
710 return calc_crc64 (&algorithm, input_str, num_bytes);
711 }
712 }
713 else if (algorithm.crc_algo == crc_algo_32)
714 {
715 if (algorithm.crc_tab != NULL)
716 {
717 return calc_crc32 (&algorithm, input_str, num_bytes);
718 }
719 }
720 /* This should never happen */
721 return 0;
722 }
723
724 static bool
725 invalid_crc_parameters (bfd_vma crc_addr,
726 bfd_vma crc_area_start, bfd_vma crc_area_end)
727 {
728 bool crc_in_section;
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;
733
734 /* All three symbols must be inside the '.text' section */
735 crc_in_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));
739
740 if (!crc_in_section)
741 {
742 einfo (_("%X%P: The CRC digest and table should be inside the '%s' "
743 "section\n"), digest_section);
744 /*
745 * Maybe we should printout the text section start and end
746 * as well as the boundaries of the CRC check area.
747 */
748 return true;
749 }
750
751 /*
752 * CRC checksum must be outside the checked area
753 * We must check that they do not overlap in the beginning
754 */
755 {
756 bool crc_valid = false;
757 if ((crc_addr + crc_size) < crc_area_start)
758 {
759 crc_valid = true;
760 }
761 else if (crc_addr >= crc_area_end)
762 {
763 crc_valid = true;
764 }
765 if (!crc_valid)
766 {
767 einfo (_("%X%P: CRC located inside checked area\n"), NULL);
768 return true;
769 }
770 }
771
772 if (crc_area_start > crc_area_end)
773 {
774 einfo (_("%X%P: CRC area starts after its end location\n"), NULL);
775 return true;
776 }
777
778 return false;
779 }
780
781 void
782 lang_generate_crc (void)
783 {
784 bfd_vma crc_addr, crc_area_start, crc_area_end;
785 bfd_vma crc;
786 bool can_do_crc;
787
788 /* Return immediately, if CRC is not requested */
789 if (algorithm.crc_algo == no_algo)
790 return;
791
792 /*
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
798 */
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);
802
803 if (!can_do_crc)
804 {
805 einfo (_("%X%P: Internal Error - __CRC#___ symbols not defined\n"),
806 NULL);
807 return;
808 }
809
810 if (!get_section_by_address (crc_addr)) /* update digest_section, if needed */
811 {
812 einfo (_("%X%P: The CRC digest and table must be inside the '%s' "
813 "section\n"), digest_section);
814 }
815
816 if (!get_text_section_contents ())
817 {
818 /* Error messages inside check */
819 return;
820 }
821
822 /* Check that the addresses make sense */
823 if (invalid_crc_parameters (crc_addr, crc_area_start, crc_area_end))
824 {
825 /* Error messages inside check */
826 return;
827 }
828
829 /* Calculate and set the CRC */
830 {
831 /*
832 * The '.text' area does not neccessarily start at 0x00000000,
833 * so we have to shift the indices.
834 */
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;
838
839
840 /* This is the CRC calculation which we worked so hard for */
841 debug_crc_header ("Before CRC");
842
843 print_hash64_table (&algorithm);
844
845 #if (DEBUG_CRC == 1)
846 crc = calculate_crc ((const unsigned char *) "123456789", 9);
847 #else
848 crc = calculate_crc (&text_contents[_crc_area_start],
849 _crc_area_end - _crc_area_start);
850 #endif
851
852 #if (DEBUG_CRC == 1)
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);
857
858 print_crc64_algorithm (&algorithm, &text_contents[_crc_area_start], crc);
859 #endif
860
861 /*
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.
866 */
867 free (text_contents);
868 if (set_crc_checksum (crc, _crc_addr, algorithm.crc_size))
869 {
870 debug_crc_update (crc, crc_addr);
871 }
872 else
873 {
874 einfo (_("%X%P: updating CRC in section '%s' failed\n"),
875 digest_section);
876 }
877 }
878
879 debug_full_textsection ();
880 }
881
882 /* ============ END CRC common functions =====================================*/
883
884 void
885 lang_generate_digest (void)
886 {
887 /* Return immediately, if CRC is not requested */
888 #if (DEBUG_CRC == 1)
889 printf ("%s: BEGIN\n", __FUNCTION__);
890 #endif
891 if (algorithm.crc_algo == no_algo)
892 return;
893
894 /* Handle 32/64-bit CRCs */
895 if ((algorithm.crc_algo == crc_algo_32)
896 || (algorithm.crc_algo == crc_algo_64))
897 {
898 lang_generate_crc ();
899 }
900 #if (DEBUG_CRC == 1)
901 printf ("%s: END\n", __FUNCTION__);
902 #endif
903 }