Automatic date update in version.in
[binutils-gdb.git] / bfd / elf32-pru.c
blobe76b483b526424f1b73db72fa393265e26bcfaed
1 /* 32-bit ELF support for TI PRU.
2 Copyright (C) 2014-2024 Free Software Foundation, Inc.
3 Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
4 Based on elf32-nios2.c
6 This file is part of BFD, the Binary File Descriptor library.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
23 /* This file handles TI PRU ELF targets. */
25 #include "sysdep.h"
26 #include "bfd.h"
27 #include "libbfd.h"
28 #include "bfdlink.h"
29 #include "genlink.h"
30 #include "elf-bfd.h"
31 #include "elf/pru.h"
32 #include "opcode/pru.h"
33 #include "libiberty.h"
35 /* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */
36 #define OCTETS_PER_BYTE(ABFD, SEC) 1
38 #define SWAP_VALS(A,B) \
39 do { \
40 (A) ^= (B); \
41 (B) ^= (A); \
42 (A) ^= (B); \
43 } while (0)
45 /* Enable debugging printout at stdout with this variable. */
46 static bool debug_relax = false;
48 /* Forward declarations. */
49 static bfd_reloc_status_type pru_elf32_pmem_relocate
50 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
51 static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate
52 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
53 static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate
54 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
55 static bfd_reloc_status_type pru_elf32_ldi32_relocate
56 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
57 static bfd_reloc_status_type bfd_elf_pru_diff_relocate
58 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
60 /* Target vector. */
61 extern const bfd_target pru_elf32_vec;
63 /* The relocation table used for SHT_REL sections. */
64 static reloc_howto_type elf_pru_howto_table_rel[] = {
65 /* No relocation. */
66 HOWTO (R_PRU_NONE, /* type */
67 0, /* rightshift */
68 0, /* size */
69 0, /* bitsize */
70 false, /* pc_relative */
71 0, /* bitpos */
72 complain_overflow_dont,/* complain_on_overflow */
73 bfd_elf_generic_reloc, /* special_function */
74 "R_PRU_NONE", /* name */
75 false, /* partial_inplace */
76 0, /* src_mask */
77 0, /* dst_mask */
78 false), /* pcrel_offset */
80 HOWTO (R_PRU_16_PMEM,
82 2, /* short */
83 32,
84 false,
86 complain_overflow_dont,
87 bfd_elf_generic_reloc,
88 "R_PRU_16_PMEM",
89 false,
90 0, /* src_mask */
91 0xffff,
92 false),
94 HOWTO (R_PRU_U16_PMEMIMM,
97 32,
98 false,
100 complain_overflow_unsigned,
101 pru_elf32_pmem_relocate,
102 "R_PRU_U16_PMEMIMM",
103 false,
104 0, /* src_mask */
105 0x00ffff00,
106 false),
108 HOWTO (R_PRU_BFD_RELOC_16,
110 2, /* short */
112 false,
114 complain_overflow_bitfield,
115 bfd_elf_generic_reloc,
116 "R_PRU_BFD_RELOC16",
117 false,
118 0, /* src_mask */
119 0x0000ffff,
120 false),
122 /* 16-bit unsigned immediate relocation. */
123 HOWTO (R_PRU_U16, /* type */
124 0, /* rightshift */
125 4, /* size */
126 16, /* bitsize */
127 false, /* pc_relative */
128 8, /* bitpos */
129 complain_overflow_unsigned, /* complain on overflow */
130 bfd_elf_generic_reloc, /* special function */
131 "R_PRU_U16", /* name */
132 false, /* partial_inplace */
133 0, /* src_mask */
134 0x00ffff00, /* dest_mask */
135 false), /* pcrel_offset */
137 HOWTO (R_PRU_32_PMEM,
139 4, /* long */
141 false,
143 complain_overflow_dont,
144 pru_elf32_pmem_relocate,
145 "R_PRU_32_PMEM",
146 false,
147 0, /* src_mask */
148 0xffffffff,
149 false),
151 HOWTO (R_PRU_BFD_RELOC_32,
153 4, /* long */
155 false,
157 complain_overflow_dont,
158 bfd_elf_generic_reloc,
159 "R_PRU_BFD_RELOC32",
160 false,
161 0, /* src_mask */
162 0xffffffff,
163 false),
165 HOWTO (R_PRU_S10_PCREL,
169 true,
171 complain_overflow_bitfield,
172 pru_elf32_s10_pcrel_relocate,
173 "R_PRU_S10_PCREL",
174 false,
175 0, /* src_mask */
176 0x060000ff,
177 true),
179 HOWTO (R_PRU_U8_PCREL,
183 true,
185 complain_overflow_unsigned,
186 pru_elf32_u8_pcrel_relocate,
187 "R_PRU_U8_PCREL",
188 false,
189 0, /* src_mask */
190 0x000000ff,
191 true),
193 HOWTO (R_PRU_LDI32,
194 0, /* rightshift */
195 8, /* size */
196 32, /* bitsize */
197 false, /* pc_relative */
198 0, /* bitpos */
199 complain_overflow_unsigned, /* complain on overflow */
200 pru_elf32_ldi32_relocate, /* special function */
201 "R_PRU_LDI32", /* name */
202 false, /* partial_inplace */
203 0, /* src_mask */
204 0xffffffff, /* dest_mask */
205 false), /* pcrel_offset */
207 /* GNU-specific relocations. */
208 HOWTO (R_PRU_GNU_BFD_RELOC_8,
210 1, /* byte */
212 false,
214 complain_overflow_bitfield,
215 bfd_elf_generic_reloc,
216 "R_PRU_BFD_RELOC8",
217 false,
218 0, /* src_mask */
219 0x000000ff,
220 false),
222 HOWTO (R_PRU_GNU_DIFF8, /* type */
223 0, /* rightshift */
224 1, /* size */
225 8, /* bitsize */
226 false, /* pc_relative */
227 0, /* bitpos */
228 complain_overflow_bitfield, /* complain_on_overflow */
229 bfd_elf_pru_diff_relocate, /* special_function */
230 "R_PRU_DIFF8", /* name */
231 false, /* partial_inplace */
232 0, /* src_mask */
233 0xff, /* dst_mask */
234 false), /* pcrel_offset */
236 HOWTO (R_PRU_GNU_DIFF16, /* type */
237 0, /* rightshift */
238 2, /* size */
239 16, /* bitsize */
240 false, /* pc_relative */
241 0, /* bitpos */
242 complain_overflow_bitfield, /* complain_on_overflow */
243 bfd_elf_pru_diff_relocate,/* special_function */
244 "R_PRU_DIFF16", /* name */
245 false, /* partial_inplace */
246 0, /* src_mask */
247 0xffff, /* dst_mask */
248 false), /* pcrel_offset */
250 HOWTO (R_PRU_GNU_DIFF32, /* type */
251 0, /* rightshift */
252 4, /* size */
253 32, /* bitsize */
254 false, /* pc_relative */
255 0, /* bitpos */
256 complain_overflow_bitfield, /* complain_on_overflow */
257 bfd_elf_pru_diff_relocate,/* special_function */
258 "R_PRU_DIFF32", /* name */
259 false, /* partial_inplace */
260 0, /* src_mask */
261 0xffffffff, /* dst_mask */
262 false), /* pcrel_offset */
264 HOWTO (R_PRU_GNU_DIFF16_PMEM, /* type */
265 0, /* rightshift */
266 2, /* size */
267 16, /* bitsize */
268 false, /* pc_relative */
269 0, /* bitpos */
270 complain_overflow_bitfield, /* complain_on_overflow */
271 bfd_elf_pru_diff_relocate,/* special_function */
272 "R_PRU_DIFF16_PMEM", /* name */
273 false, /* partial_inplace */
274 0, /* src_mask */
275 0xffff, /* dst_mask */
276 false), /* pcrel_offset */
278 HOWTO (R_PRU_GNU_DIFF32_PMEM, /* type */
279 0, /* rightshift */
280 4, /* size */
281 32, /* bitsize */
282 false, /* pc_relative */
283 0, /* bitpos */
284 complain_overflow_bitfield, /* complain_on_overflow */
285 bfd_elf_pru_diff_relocate,/* special_function */
286 "R_PRU_DIFF32_PMEM", /* name */
287 false, /* partial_inplace */
288 0, /* src_mask */
289 0xffffffff, /* dst_mask */
290 false), /* pcrel_offset */
292 /* Add other relocations here. */
295 static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1];
297 /* Return the howto for relocation RTYPE. */
299 static reloc_howto_type *
300 lookup_howto (unsigned int rtype)
302 static bool initialized = false;
303 int i;
304 int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel)
305 / sizeof (elf_pru_howto_table_rel[0]));
307 if (! initialized)
309 initialized = true;
310 memset (elf_code_to_howto_index, 0xff,
311 sizeof (elf_code_to_howto_index));
312 for (i = 0; i < howto_tbl_size; i++)
313 elf_code_to_howto_index[elf_pru_howto_table_rel[i].type] = i;
316 if (rtype > R_PRU_ILLEGAL)
317 return NULL;
318 i = elf_code_to_howto_index[rtype];
319 if (i >= howto_tbl_size)
320 return NULL;
321 return elf_pru_howto_table_rel + i;
324 /* Map for converting BFD reloc types to PRU reloc types. */
326 struct elf_reloc_map
328 bfd_reloc_code_real_type bfd_val;
329 enum elf_pru_reloc_type elf_val;
332 static const struct elf_reloc_map pru_reloc_map[] =
334 {BFD_RELOC_NONE, R_PRU_NONE},
335 {BFD_RELOC_PRU_16_PMEM, R_PRU_16_PMEM},
336 {BFD_RELOC_PRU_U16_PMEMIMM, R_PRU_U16_PMEMIMM},
337 {BFD_RELOC_16, R_PRU_BFD_RELOC_16},
338 {BFD_RELOC_PRU_U16, R_PRU_U16},
339 {BFD_RELOC_PRU_32_PMEM, R_PRU_32_PMEM},
340 {BFD_RELOC_32, R_PRU_BFD_RELOC_32},
341 {BFD_RELOC_PRU_S10_PCREL, R_PRU_S10_PCREL},
342 {BFD_RELOC_PRU_U8_PCREL, R_PRU_U8_PCREL},
343 {BFD_RELOC_PRU_LDI32, R_PRU_LDI32},
345 {BFD_RELOC_8, R_PRU_GNU_BFD_RELOC_8},
346 {BFD_RELOC_PRU_GNU_DIFF8, R_PRU_GNU_DIFF8},
347 {BFD_RELOC_PRU_GNU_DIFF16, R_PRU_GNU_DIFF16},
348 {BFD_RELOC_PRU_GNU_DIFF32, R_PRU_GNU_DIFF32},
349 {BFD_RELOC_PRU_GNU_DIFF16_PMEM, R_PRU_GNU_DIFF16_PMEM},
350 {BFD_RELOC_PRU_GNU_DIFF32_PMEM, R_PRU_GNU_DIFF32_PMEM},
354 /* Assorted hash table functions. */
356 /* Create an entry in a PRU ELF linker hash table. */
358 static struct bfd_hash_entry *
359 link_hash_newfunc (struct bfd_hash_entry *entry,
360 struct bfd_hash_table *table, const char *string)
362 /* Allocate the structure if it has not already been allocated by a
363 subclass. */
364 if (entry == NULL)
366 entry = bfd_hash_allocate (table,
367 sizeof (struct elf_link_hash_entry));
368 if (entry == NULL)
369 return entry;
372 /* Call the allocation method of the superclass. */
373 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
375 return entry;
378 /* Implement bfd_elf32_bfd_reloc_type_lookup:
379 Given a BFD reloc type, return a howto structure. */
381 static reloc_howto_type *
382 pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
383 bfd_reloc_code_real_type code)
385 unsigned int i;
387 for (i = 0; i < ARRAY_SIZE (pru_reloc_map); ++i)
388 if (pru_reloc_map[i].bfd_val == code)
389 return lookup_howto ((unsigned int) pru_reloc_map[i].elf_val);
390 return NULL;
393 /* Implement bfd_elf32_bfd_reloc_name_lookup:
394 Given a reloc name, return a howto structure. */
396 static reloc_howto_type *
397 pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
398 const char *r_name)
400 unsigned int i;
402 for (i = 0; i < ARRAY_SIZE (elf_pru_howto_table_rel); i++)
403 if (elf_pru_howto_table_rel[i].name
404 && strcasecmp (elf_pru_howto_table_rel[i].name, r_name) == 0)
405 return &elf_pru_howto_table_rel[i];
407 return NULL;
410 /* Implement elf_info_to_howto:
411 Given a ELF32 relocation, fill in a arelent structure. */
413 static bool
414 pru_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr,
415 Elf_Internal_Rela *dst)
417 unsigned int r_type;
419 r_type = ELF32_R_TYPE (dst->r_info);
420 if (r_type >= R_PRU_ILLEGAL)
422 /* xgettext:c-format */
423 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
424 bfd_set_error (bfd_error_bad_value);
425 return false;
428 cache_ptr->howto = lookup_howto (r_type);
429 return cache_ptr->howto != NULL;
432 /* Do the relocations that require special handling. */
433 /* Produce a word address for program memory. Linker scripts will put .text
434 at a high offset in order to differentiate it from .data. So here we also
435 mask the high bits of PMEM address.
437 But why 1MB when internal Program Memory much smaller? We want to catch
438 unintended overflows.
440 Why not use (1<<31) as an offset and a mask? Sitara DDRAM usually resides
441 there, and users might want to put some shared carveout memory region in
442 their linker scripts. So 0x80000000 might be a valid .data address.
444 Note that we still keep and pass down the original howto. This way we
445 can reuse this function for several different relocations. */
446 static bfd_reloc_status_type
447 pru_elf32_do_pmem_relocate (bfd *abfd, reloc_howto_type *howto,
448 asection *input_section,
449 bfd_byte *data, bfd_vma offset,
450 bfd_vma symbol_value, bfd_vma addend)
452 symbol_value = symbol_value + addend;
453 addend = 0;
454 symbol_value &= 0x3fffff;
455 return _bfd_final_link_relocate (howto, abfd, input_section,
456 data, offset, symbol_value, addend);
459 /* Direct copy of _bfd_final_link_relocate, but with special
460 "fill-in". This copy-paste mumbo jumbo is only needed because BFD
461 cannot deal correctly with non-contiguous bit fields. */
462 static bfd_reloc_status_type
463 pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto,
464 asection *input_section,
465 bfd_byte *contents, bfd_vma address,
466 bfd_vma relocation, bfd_vma addend)
468 bfd_byte *location;
469 bfd_vma x = 0;
470 bfd_vma qboff;
471 bfd_reloc_status_type flag = bfd_reloc_ok;
473 /* Sanity check the address. */
474 if (address > bfd_get_section_limit (input_bfd, input_section))
475 return bfd_reloc_outofrange;
477 BFD_ASSERT (howto->pc_relative);
478 BFD_ASSERT (howto->pcrel_offset);
480 relocation = relocation + addend - (input_section->output_section->vma
481 + input_section->output_offset) - address;
483 location = contents + address;
485 /* Get the value we are going to relocate. */
486 BFD_ASSERT (bfd_get_reloc_size (howto) == 4);
487 x = bfd_get_32 (input_bfd, location);
489 qboff = GET_BROFF_SIGNED (x) << howto->rightshift;
490 relocation += qboff;
492 BFD_ASSERT (howto->complain_on_overflow == complain_overflow_bitfield);
494 if (relocation > 2047 && relocation < (bfd_vma)-2048l)
495 flag = bfd_reloc_overflow;
497 /* Check that target address is word-aligned. */
498 if (relocation & ((1 << howto->rightshift) - 1))
499 flag = bfd_reloc_outofrange;
501 relocation >>= (bfd_vma) howto->rightshift;
503 /* Fill-in the RELOCATION to the right bits of X. */
504 SET_BROFF_URAW (x, relocation);
506 bfd_put_32 (input_bfd, x, location);
508 return flag;
511 static bfd_reloc_status_type
512 pru_elf32_do_u8_pcrel_relocate (bfd *abfd, reloc_howto_type *howto,
513 asection *input_section,
514 bfd_byte *data, bfd_vma offset,
515 bfd_vma symbol_value, bfd_vma addend)
517 bfd_vma relocation;
519 BFD_ASSERT (howto->pc_relative);
520 BFD_ASSERT (howto->pcrel_offset);
522 relocation = symbol_value + addend - (input_section->output_section->vma
523 + input_section->output_offset) - offset;
524 relocation >>= howto->rightshift;
526 /* 0 and 1 are invalid target labels for LOOP. We cannot
527 encode this info in HOWTO, so catch such cases here. */
528 if (relocation < 2)
529 return bfd_reloc_outofrange;
531 return _bfd_final_link_relocate (howto, abfd, input_section,
532 data, offset, symbol_value, addend);
535 /* Idea and code taken from elf32-d30v. */
536 static bfd_reloc_status_type
537 pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
538 asection *input_section,
539 bfd_byte *data, bfd_vma offset,
540 bfd_vma symbol_value, bfd_vma addend)
542 bfd_vma relocation;
543 bfd_size_type octets = offset * OCTETS_PER_BYTE (abfd, input_section);
544 bfd_byte *location;
545 unsigned long in1, in2;
547 /* A hacked-up version of _bfd_final_link_relocate() follows. */
549 /* Sanity check the address. */
550 if (octets + bfd_get_reloc_size (howto)
551 > bfd_get_section_limit_octets (abfd, input_section))
552 return bfd_reloc_outofrange;
554 /* This function assumes that we are dealing with a basic relocation
555 against a symbol. We want to compute the value of the symbol to
556 relocate to. This is just VALUE, the value of the symbol, plus
557 ADDEND, any addend associated with the reloc. */
558 relocation = symbol_value + addend;
560 BFD_ASSERT (!howto->pc_relative);
562 /* A hacked-up version of _bfd_relocate_contents() follows. */
563 location = data + octets;
565 BFD_ASSERT (!howto->pc_relative);
567 in1 = bfd_get_32 (abfd, location);
568 in2 = bfd_get_32 (abfd, location + 4);
570 SET_INSN_FIELD (IMM16, in1, relocation >> 16);
571 SET_INSN_FIELD (IMM16, in2, relocation & 0xffff);
573 bfd_put_32 (abfd, in1, location);
574 bfd_put_32 (abfd, in2, location + 4);
576 /* Old GAS and LD versions have a bug, where the two
577 LDI instructions are swapped. Detect such object
578 files and bail. */
579 if (GET_INSN_FIELD (RDSEL, in1) != RSEL_31_16)
581 /* xgettext:c-format */
582 _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
583 abfd);
584 return bfd_reloc_notsupported;
587 return bfd_reloc_ok;
590 /* HOWTO handlers for relocations that require special handling. */
592 static bfd_reloc_status_type
593 pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
594 asymbol *symbol, void *data,
595 asection *input_section, bfd *output_bfd,
596 char **error_message)
598 /* If this is a relocatable link (output_bfd test tells us), just
599 call the generic function. Any adjustment will be done at final
600 link time. */
601 if (output_bfd != NULL)
602 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
603 input_section, output_bfd, error_message);
605 BFD_ASSERT (0);
606 return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
607 input_section,
608 data, reloc_entry->address,
609 (symbol->value
610 + symbol->section->output_section->vma
611 + symbol->section->output_offset),
612 reloc_entry->addend);
615 static bfd_reloc_status_type
616 pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry,
617 asymbol *symbol, void *data,
618 asection *input_section, bfd *output_bfd,
619 char **error_message)
621 /* If this is a relocatable link (output_bfd test tells us), just
622 call the generic function. Any adjustment will be done at final
623 link time. */
624 if (output_bfd != NULL)
625 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
626 input_section, output_bfd, error_message);
628 return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
629 input_section, data,
630 reloc_entry->address,
631 (symbol->value
632 + symbol->section->output_section->vma
633 + symbol->section->output_offset),
634 reloc_entry->addend);
637 static bfd_reloc_status_type
638 pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
639 void *data, asection *input_section,
640 bfd *output_bfd,
641 char **error_message)
643 /* If this is a relocatable link (output_bfd test tells us), just
644 call the generic function. Any adjustment will be done at final
645 link time. */
646 if (output_bfd != NULL)
647 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
648 input_section, output_bfd, error_message);
650 return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
651 input_section,
652 data, reloc_entry->address,
653 (symbol->value
654 + symbol->section->output_section->vma
655 + symbol->section->output_offset),
656 reloc_entry->addend);
659 static bfd_reloc_status_type
660 pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
661 void *data, asection *input_section,
662 bfd *output_bfd,
663 char **error_message)
665 /* If this is a relocatable link (output_bfd test tells us), just
666 call the generic function. Any adjustment will be done at final
667 link time. */
668 if (output_bfd != NULL)
669 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
670 input_section, output_bfd, error_message);
672 return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
673 input_section,
674 data, reloc_entry->address,
675 (symbol->value
676 + symbol->section->output_section->vma
677 + symbol->section->output_offset),
678 reloc_entry->addend);
682 /* Implement elf_backend_relocate_section. */
683 static int
684 pru_elf32_relocate_section (bfd *output_bfd,
685 struct bfd_link_info *info,
686 bfd *input_bfd,
687 asection *input_section,
688 bfd_byte *contents,
689 Elf_Internal_Rela *relocs,
690 Elf_Internal_Sym *local_syms,
691 asection **local_sections)
693 struct bfd_elf_section_data * esd = elf_section_data (input_section);
694 Elf_Internal_Shdr *symtab_hdr;
695 struct elf_link_hash_entry **sym_hashes;
696 Elf_Internal_Rela *rel;
697 Elf_Internal_Rela *relend;
698 bool is_rel_reloc;
700 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
701 sym_hashes = elf_sym_hashes (input_bfd);
702 relend = relocs + input_section->reloc_count;
704 /* See if we have a REL type relocation. */
705 is_rel_reloc = (esd->rel.hdr != NULL);
706 /* Sanity check - only one type of relocation per section.
707 FIXME: Theoretically it is possible to have both types,
708 but if that happens how can we distinguish between the two ? */
709 BFD_ASSERT (! is_rel_reloc || ! esd->rela.hdr);
711 for (rel = relocs; rel < relend; rel++)
713 reloc_howto_type *howto;
714 unsigned long r_symndx;
715 Elf_Internal_Sym *sym;
716 asection *sec;
717 struct elf_link_hash_entry *h;
718 bfd_vma relocation;
719 bfd_reloc_status_type r = bfd_reloc_ok;
720 const char *name = NULL;
721 const char* msg = (const char*) NULL;
722 bool unresolved_reloc;
723 bfd_vma addend;
725 /* If we are using a REL relocation then the addend should be empty. */
726 BFD_ASSERT (! is_rel_reloc || rel->r_addend == 0);
728 r_symndx = ELF32_R_SYM (rel->r_info);
730 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
731 h = NULL;
732 sym = NULL;
733 sec = NULL;
735 if (r_symndx < symtab_hdr->sh_info)
737 sym = local_syms + r_symndx;
738 sec = local_sections[r_symndx];
739 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
741 else
743 bool warned, ignored;
745 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
746 r_symndx, symtab_hdr, sym_hashes,
747 h, sec, relocation,
748 unresolved_reloc, warned, ignored);
751 if (sec && discarded_section (sec))
752 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
753 rel, 1, relend, howto, 0, contents);
755 /* Nothing more to do unless this is a final link. */
756 if (bfd_link_relocatable (info))
757 continue;
759 if (howto)
761 switch (howto->type)
763 case R_PRU_NONE:
764 /* We don't need to find a value for this symbol. It's just a
765 marker. */
766 r = bfd_reloc_ok;
767 break;
769 case R_PRU_U16:
770 if (is_rel_reloc)
772 unsigned long insn;
773 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
774 addend = GET_INSN_FIELD (IMM16, insn);
776 else
777 addend = rel->r_addend;
778 r = _bfd_final_link_relocate (howto, input_bfd,
779 input_section, contents,
780 rel->r_offset, relocation,
781 addend);
782 break;
784 case R_PRU_U16_PMEMIMM:
785 case R_PRU_32_PMEM:
786 case R_PRU_16_PMEM:
787 if (is_rel_reloc && howto->type == R_PRU_U16_PMEMIMM)
789 unsigned long insn;
790 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
791 addend = GET_INSN_FIELD (IMM16, insn) << 2;
793 else if (is_rel_reloc && howto->type == R_PRU_32_PMEM)
795 addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
796 addend <<= 2;
798 else if (is_rel_reloc && howto->type == R_PRU_16_PMEM)
800 addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
801 addend <<= 2;
803 else
805 BFD_ASSERT (!is_rel_reloc);
806 addend = rel->r_addend;
808 r = pru_elf32_do_pmem_relocate (input_bfd, howto,
809 input_section,
810 contents, rel->r_offset,
811 relocation, addend);
812 break;
813 case R_PRU_S10_PCREL:
814 BFD_ASSERT (! is_rel_reloc);
815 r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
816 input_section,
817 contents,
818 rel->r_offset,
819 relocation,
820 rel->r_addend);
821 break;
822 case R_PRU_U8_PCREL:
823 BFD_ASSERT (! is_rel_reloc);
824 r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
825 input_section,
826 contents,
827 rel->r_offset,
828 relocation,
829 rel->r_addend);
830 break;
831 case R_PRU_LDI32:
832 if (is_rel_reloc)
834 unsigned long in1, in2;
835 in1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
836 in2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
837 addend = (GET_INSN_FIELD (IMM16, in1) << 16)
838 | GET_INSN_FIELD (IMM16, in2);
840 else
842 addend = rel->r_addend;
844 r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
845 input_section,
846 contents,
847 rel->r_offset,
848 relocation,
849 addend);
850 break;
851 case R_PRU_GNU_DIFF8:
852 case R_PRU_GNU_DIFF16:
853 case R_PRU_GNU_DIFF32:
854 case R_PRU_GNU_DIFF16_PMEM:
855 case R_PRU_GNU_DIFF32_PMEM:
856 /* GNU extensions support only rela. */
857 BFD_ASSERT (! is_rel_reloc);
858 /* Nothing to do here, as contents already contain the
859 diff value. */
860 r = bfd_reloc_ok;
861 break;
863 case R_PRU_BFD_RELOC_16:
864 if (is_rel_reloc)
865 addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
866 else
867 addend = rel->r_addend;
868 r = _bfd_final_link_relocate (howto, input_bfd,
869 input_section, contents,
870 rel->r_offset, relocation,
871 addend);
872 break;
874 case R_PRU_BFD_RELOC_32:
875 if (is_rel_reloc)
876 addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
877 else
878 addend = rel->r_addend;
879 r = _bfd_final_link_relocate (howto, input_bfd,
880 input_section, contents,
881 rel->r_offset, relocation,
882 addend);
883 break;
885 case R_PRU_GNU_BFD_RELOC_8:
886 BFD_ASSERT (! is_rel_reloc);
887 r = _bfd_final_link_relocate (howto, input_bfd,
888 input_section, contents,
889 rel->r_offset, relocation,
890 rel->r_addend);
891 break;
893 default:
894 BFD_ASSERT (0);
895 break;
898 else
899 r = bfd_reloc_notsupported;
901 if (r != bfd_reloc_ok)
903 if (h != NULL)
904 name = h->root.root.string;
905 else
907 name = bfd_elf_string_from_elf_section (input_bfd,
908 symtab_hdr->sh_link,
909 sym->st_name);
910 if (name == NULL || *name == '\0')
911 name = bfd_section_name (sec);
914 switch (r)
916 case bfd_reloc_overflow:
917 (*info->callbacks->reloc_overflow) (info, NULL, name,
918 howto->name, (bfd_vma) 0,
919 input_bfd, input_section,
920 rel->r_offset);
921 break;
923 case bfd_reloc_undefined:
924 (*info->callbacks->undefined_symbol) (info, name, input_bfd,
925 input_section,
926 rel->r_offset, true);
927 break;
929 case bfd_reloc_outofrange:
930 if (msg == NULL)
931 msg = _("relocation out of range");
932 break;
934 case bfd_reloc_notsupported:
935 if (msg == NULL)
936 msg = _("unsupported relocation");
937 break;
939 case bfd_reloc_dangerous:
940 if (msg == NULL)
941 msg = _("dangerous relocation");
942 break;
944 default:
945 if (msg == NULL)
946 msg = _("unknown error");
947 break;
950 if (msg)
952 (*info->callbacks->warning) (info, msg, name, input_bfd,
953 input_section, rel->r_offset);
954 return false;
958 return true;
962 /* Perform a diff relocation. Nothing to do, as the difference value is
963 already written into the section's contents. */
965 static bfd_reloc_status_type
966 bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
967 arelent *reloc_entry ATTRIBUTE_UNUSED,
968 asymbol *symbol ATTRIBUTE_UNUSED,
969 void *data ATTRIBUTE_UNUSED,
970 asection *input_section ATTRIBUTE_UNUSED,
971 bfd *output_bfd ATTRIBUTE_UNUSED,
972 char **error_message ATTRIBUTE_UNUSED)
974 return bfd_reloc_ok;
978 /* Returns whether the relocation type passed is a diff reloc. */
980 static bool
981 elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
983 return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
984 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
985 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
986 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
987 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
990 /* Reduce the diff value written in the section by count if the shrinked
991 insn address happens to fall between the two symbols for which this
992 diff reloc was emitted. */
994 static void
995 elf32_pru_adjust_diff_reloc_value (bfd *abfd,
996 struct bfd_section *isec,
997 Elf_Internal_Rela *irel,
998 bfd_vma symval,
999 bfd_vma shrinked_insn_address,
1000 int count)
1002 unsigned char *reloc_contents = NULL;
1003 unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
1004 if (isec_contents == NULL)
1006 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
1007 return;
1009 elf_section_data (isec)->this_hdr.contents = isec_contents;
1012 reloc_contents = isec_contents + irel->r_offset;
1014 /* Read value written in object file. */
1015 bfd_signed_vma x = 0;
1016 switch (ELF32_R_TYPE (irel->r_info))
1018 case R_PRU_GNU_DIFF8:
1020 x = bfd_get_signed_8 (abfd, reloc_contents);
1021 break;
1023 case R_PRU_GNU_DIFF16:
1025 x = bfd_get_signed_16 (abfd, reloc_contents);
1026 break;
1028 case R_PRU_GNU_DIFF32:
1030 x = bfd_get_signed_32 (abfd, reloc_contents);
1031 break;
1033 case R_PRU_GNU_DIFF16_PMEM:
1035 x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
1036 break;
1038 case R_PRU_GNU_DIFF32_PMEM:
1040 x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
1041 break;
1043 default:
1045 BFD_FAIL ();
1049 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
1050 into the object file at the reloc offset. sym2's logical value is
1051 symval (<start_of_section>) + reloc addend. Compute the start and end
1052 addresses and check if the shrinked insn falls between sym1 and sym2. */
1054 bfd_vma end_address = symval + irel->r_addend;
1055 bfd_vma start_address = end_address - x;
1057 /* Shrink the absolute DIFF value (get the to labels "closer"
1058 together), because we have removed data between labels. */
1059 if (x < 0)
1061 x += count;
1062 /* In case the signed x is negative, restore order. */
1063 SWAP_VALS (end_address, start_address);
1065 else
1067 x -= count;
1070 /* Reduce the diff value by count bytes and write it back into section
1071 contents. */
1073 if (shrinked_insn_address >= start_address
1074 && shrinked_insn_address <= end_address)
1076 switch (ELF32_R_TYPE (irel->r_info))
1078 case R_PRU_GNU_DIFF8:
1080 bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
1081 break;
1083 case R_PRU_GNU_DIFF16:
1085 bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
1086 break;
1088 case R_PRU_GNU_DIFF32:
1090 bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
1091 break;
1093 case R_PRU_GNU_DIFF16_PMEM:
1095 bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
1096 break;
1098 case R_PRU_GNU_DIFF32_PMEM:
1100 bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
1101 break;
1103 default:
1105 BFD_FAIL ();
1112 /* Delete some bytes from a section while changing the size of an instruction.
1113 The parameter "addr" denotes the section-relative offset pointing just
1114 behind the shrinked instruction. "addr+count" point at the first
1115 byte just behind the original unshrinked instruction.
1117 Idea copied from the AVR port. */
1119 static bool
1120 pru_elf_relax_delete_bytes (bfd *abfd,
1121 asection *sec,
1122 bfd_vma addr,
1123 int count)
1125 Elf_Internal_Shdr *symtab_hdr;
1126 unsigned int sec_shndx;
1127 bfd_byte *contents;
1128 Elf_Internal_Rela *irel, *irelend;
1129 Elf_Internal_Sym *isym;
1130 Elf_Internal_Sym *isymbuf = NULL;
1131 bfd_vma toaddr;
1132 struct elf_link_hash_entry **sym_hashes;
1133 struct elf_link_hash_entry **end_hashes;
1134 unsigned int symcount;
1136 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1137 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1138 contents = elf_section_data (sec)->this_hdr.contents;
1140 toaddr = sec->size;
1142 irel = elf_section_data (sec)->relocs;
1143 irelend = irel + sec->reloc_count;
1145 /* Actually delete the bytes. */
1146 if (toaddr - addr - count > 0)
1147 memmove (contents + addr, contents + addr + count,
1148 (size_t) (toaddr - addr - count));
1149 sec->size -= count;
1151 /* Adjust all the reloc addresses. */
1152 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1154 bfd_vma old_reloc_address;
1156 old_reloc_address = (sec->output_section->vma
1157 + sec->output_offset + irel->r_offset);
1159 /* Get the new reloc address. */
1160 if ((irel->r_offset > addr
1161 && irel->r_offset < toaddr))
1163 if (debug_relax)
1164 printf ("Relocation at address 0x%x needs to be moved.\n"
1165 "Old section offset: 0x%x, New section offset: 0x%x \n",
1166 (unsigned int) old_reloc_address,
1167 (unsigned int) irel->r_offset,
1168 (unsigned int) ((irel->r_offset) - count));
1170 irel->r_offset -= count;
1175 /* The reloc's own addresses are now ok. However, we need to readjust
1176 the reloc's addend, i.e. the reloc's value if two conditions are met:
1177 1.) the reloc is relative to a symbol in this section that
1178 is located in front of the shrinked instruction
1179 2.) symbol plus addend end up behind the shrinked instruction.
1181 The most common case where this happens are relocs relative to
1182 the section-start symbol.
1184 This step needs to be done for all of the sections of the bfd. */
1187 struct bfd_section *isec;
1189 for (isec = abfd->sections; isec; isec = isec->next)
1191 bfd_vma symval;
1192 bfd_vma shrinked_insn_address;
1194 if (isec->reloc_count == 0)
1195 continue;
1197 shrinked_insn_address = (sec->output_section->vma
1198 + sec->output_offset + addr);
1200 irel = elf_section_data (isec)->relocs;
1201 /* PR 12161: Read in the relocs for this section if necessary. */
1202 if (irel == NULL)
1203 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, true);
1205 for (irelend = irel + isec->reloc_count;
1206 irel < irelend;
1207 irel++)
1209 /* Read this BFD's local symbols if we haven't done
1210 so already. */
1211 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1213 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1214 if (isymbuf == NULL)
1215 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1216 symtab_hdr->sh_info, 0,
1217 NULL, NULL, NULL);
1218 if (isymbuf == NULL)
1219 return false;
1222 /* Get the value of the symbol referred to by the reloc. */
1223 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1225 /* A local symbol. */
1226 asection *sym_sec;
1228 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1229 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1230 symval = isym->st_value;
1231 /* If the reloc is absolute, it will not have
1232 a symbol or section associated with it. */
1233 if (sym_sec == sec)
1235 symval += sym_sec->output_section->vma
1236 + sym_sec->output_offset;
1238 if (debug_relax)
1239 printf ("Checking if the relocation's "
1240 "addend needs corrections.\n"
1241 "Address of anchor symbol: 0x%x \n"
1242 "Address of relocation target: 0x%x \n"
1243 "Address of relaxed insn: 0x%x \n",
1244 (unsigned int) symval,
1245 (unsigned int) (symval + irel->r_addend),
1246 (unsigned int) shrinked_insn_address);
1248 /* Shrink the special DIFF relocations. */
1249 if (elf32_pru_is_diff_reloc (irel))
1251 elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1252 symval,
1253 shrinked_insn_address,
1254 count);
1257 /* Fix the addend, if it is affected. */
1258 if (symval <= shrinked_insn_address
1259 && (symval + irel->r_addend) > shrinked_insn_address)
1262 irel->r_addend -= count;
1264 if (debug_relax)
1265 printf ("Relocation's addend needed to be fixed \n");
1268 /* else...Reference symbol is absolute.
1269 No adjustment needed. */
1271 /* else...Reference symbol is extern. No need for adjusting
1272 the addend. */
1277 /* Adjust the local symbols defined in this section. */
1278 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1279 /* Fix PR 9841, there may be no local symbols. */
1280 if (isym != NULL)
1282 Elf_Internal_Sym *isymend;
1284 isymend = isym + symtab_hdr->sh_info;
1285 for (; isym < isymend; isym++)
1287 if (isym->st_shndx == sec_shndx)
1289 if (isym->st_value > addr
1290 && isym->st_value <= toaddr)
1291 isym->st_value -= count;
1293 if (isym->st_value <= addr
1294 && isym->st_value + isym->st_size > addr)
1296 /* If this assert fires then we have a symbol that ends
1297 part way through an instruction. Does that make
1298 sense? */
1299 BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1300 isym->st_size -= count;
1306 /* Now adjust the global symbols defined in this section. */
1307 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1308 - symtab_hdr->sh_info);
1309 sym_hashes = elf_sym_hashes (abfd);
1310 end_hashes = sym_hashes + symcount;
1311 for (; sym_hashes < end_hashes; sym_hashes++)
1313 struct elf_link_hash_entry *sym_hash = *sym_hashes;
1314 if ((sym_hash->root.type == bfd_link_hash_defined
1315 || sym_hash->root.type == bfd_link_hash_defweak)
1316 && sym_hash->root.u.def.section == sec)
1318 if (sym_hash->root.u.def.value > addr
1319 && sym_hash->root.u.def.value <= toaddr)
1320 sym_hash->root.u.def.value -= count;
1322 if (sym_hash->root.u.def.value <= addr
1323 && (sym_hash->root.u.def.value + sym_hash->size > addr))
1325 /* If this assert fires then we have a symbol that ends
1326 part way through an instruction. Does that make
1327 sense? */
1328 BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1329 >= addr + count);
1330 sym_hash->size -= count;
1335 return true;
1338 static bool
1339 pru_elf32_relax_section (bfd *abfd, asection *sec,
1340 struct bfd_link_info *link_info,
1341 bool *again)
1343 Elf_Internal_Shdr * symtab_hdr;
1344 Elf_Internal_Rela * internal_relocs;
1345 Elf_Internal_Rela * irel;
1346 Elf_Internal_Rela * irelend;
1347 bfd_byte * contents = NULL;
1348 Elf_Internal_Sym * isymbuf = NULL;
1350 /* Assume nothing changes. */
1351 *again = false;
1353 /* We don't have to do anything for a relocatable link, if
1354 this section does not have relocs, or if this is not a
1355 code section. */
1356 if (bfd_link_relocatable (link_info)
1357 || sec->reloc_count == 0
1358 || (sec->flags & SEC_RELOC) == 0
1359 || (sec->flags & SEC_HAS_CONTENTS) == 0
1360 || (sec->flags & SEC_CODE) == 0)
1361 return true;
1363 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1365 /* Get a copy of the native relocations. */
1366 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1367 link_info->keep_memory);
1368 if (internal_relocs == NULL)
1369 goto error_return;
1371 /* Walk through them looking for relaxing opportunities. */
1372 irelend = internal_relocs + sec->reloc_count;
1374 for (irel = internal_relocs; irel < irelend; irel++)
1376 bfd_vma symval;
1378 /* Get the section contents if we haven't done so already. */
1379 if (contents == NULL)
1381 /* Get cached copy if it exists. */
1382 if (elf_section_data (sec)->this_hdr.contents != NULL)
1383 contents = elf_section_data (sec)->this_hdr.contents;
1384 else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1385 goto error_return;
1388 /* Read this BFD's local symbols if we haven't done so already. */
1389 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1391 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1392 if (isymbuf == NULL)
1393 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1394 symtab_hdr->sh_info, 0,
1395 NULL, NULL, NULL);
1396 if (isymbuf == NULL)
1397 goto error_return;
1400 /* Get the value of the symbol referred to by the reloc. */
1401 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1403 /* A local symbol. */
1404 Elf_Internal_Sym *isym;
1405 asection *sym_sec;
1407 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1408 if (isym->st_shndx == SHN_UNDEF)
1409 sym_sec = bfd_und_section_ptr;
1410 else if (isym->st_shndx == SHN_ABS)
1411 sym_sec = bfd_abs_section_ptr;
1412 else if (isym->st_shndx == SHN_COMMON)
1413 sym_sec = bfd_com_section_ptr;
1414 else
1415 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1416 symval = (isym->st_value
1417 + sym_sec->output_section->vma + sym_sec->output_offset);
1419 else
1421 unsigned long indx;
1422 struct elf_link_hash_entry *h;
1424 /* An external symbol. */
1425 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1426 h = elf_sym_hashes (abfd)[indx];
1427 BFD_ASSERT (h != NULL);
1429 if (h->root.type != bfd_link_hash_defined
1430 && h->root.type != bfd_link_hash_defweak)
1431 /* This appears to be a reference to an undefined
1432 symbol. Just ignore it--it will be caught by the
1433 regular reloc processing. */
1434 continue;
1436 symval = (h->root.u.def.value
1437 + h->root.u.def.section->output_section->vma
1438 + h->root.u.def.section->output_offset);
1441 /* For simplicity of coding, we are going to modify the section
1442 contents, the section relocs, and the BFD symbol table. We
1443 must tell the rest of the code not to free up this
1444 information. It would be possible to instead create a table
1445 of changes which have to be made, as is done in coff-mips.c;
1446 that would be more work, but would require less memory when
1447 the linker is run. */
1449 /* Check if we can remove an LDI instruction from the LDI32
1450 pseudo instruction if the upper 16 operand bits are zero. */
1451 if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1453 bfd_vma value = symval + irel->r_addend;
1455 if (debug_relax)
1456 printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1458 if ((long) value >> 16 == 0)
1460 unsigned long insn;
1462 /* Note that we've changed the relocs, section contents. */
1463 elf_section_data (sec)->relocs = internal_relocs;
1464 elf_section_data (sec)->this_hdr.contents = contents;
1465 symtab_hdr->contents = (unsigned char *) isymbuf;
1467 /* Make the second instruction load the 16-bit constant
1468 into the full 32-bit register. */
1469 insn = bfd_get_32 (abfd, contents + irel->r_offset + 4);
1471 /* Old GAS and LD versions have a bug, where the two
1472 LDI instructions are swapped. Detect such object
1473 files and bail. */
1474 if (GET_INSN_FIELD (RDSEL, insn) != RSEL_15_0)
1476 /* xgettext:c-format */
1477 _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
1478 abfd);
1479 goto error_return;
1482 SET_INSN_FIELD (RDSEL, insn, RSEL_31_0);
1483 bfd_put_32 (abfd, insn, contents + irel->r_offset + 4);
1485 /* Delete the first LDI instruction. Note that there should
1486 be no relocations or symbols pointing to the second LDI
1487 instruction. */
1488 if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 4))
1489 goto error_return;
1491 /* We're done with deletion of the first instruction.
1492 Set a regular LDI relocation for the second instruction
1493 we left to load the 16-bit value into the 32-bit
1494 register. */
1495 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1496 R_PRU_U16);
1498 /* That will change things, so, we should relax again.
1499 Note that this is not required, and it may be slow. */
1500 *again = true;
1505 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1507 if (!link_info->keep_memory)
1508 free (isymbuf);
1509 else
1511 /* Cache the symbols for elf_link_input_bfd. */
1512 symtab_hdr->contents = (unsigned char *) isymbuf;
1516 if (contents != NULL
1517 && elf_section_data (sec)->this_hdr.contents != contents)
1519 if (!link_info->keep_memory)
1520 free (contents);
1521 else
1523 /* Cache the section contents for elf_link_input_bfd. */
1524 elf_section_data (sec)->this_hdr.contents = contents;
1528 if (elf_section_data (sec)->relocs != internal_relocs)
1529 free (internal_relocs);
1531 return true;
1533 error_return:
1534 if (symtab_hdr->contents != (unsigned char *) isymbuf)
1535 free (isymbuf);
1536 if (elf_section_data (sec)->this_hdr.contents != contents)
1537 free (contents);
1538 if (elf_section_data (sec)->relocs != internal_relocs)
1539 free (internal_relocs);
1541 return false;
1544 /* Free the derived linker hash table. */
1545 static void
1546 pru_elf32_link_hash_table_free (bfd *obfd)
1548 _bfd_elf_link_hash_table_free (obfd);
1551 /* Implement bfd_elf32_bfd_link_hash_table_create. */
1552 static struct bfd_link_hash_table *
1553 pru_elf32_link_hash_table_create (bfd *abfd)
1555 struct elf_link_hash_table *ret;
1556 size_t amt = sizeof (struct elf_link_hash_table);
1558 ret = bfd_zmalloc (amt);
1559 if (ret == NULL)
1560 return NULL;
1562 if (!_bfd_elf_link_hash_table_init (ret, abfd,
1563 link_hash_newfunc,
1564 sizeof (struct
1565 elf_link_hash_entry),
1566 PRU_ELF_DATA))
1568 free (ret);
1569 return NULL;
1572 ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1574 return &ret->root;
1577 #define ELF_ARCH bfd_arch_pru
1578 #define ELF_TARGET_ID PRU_ELF_DATA
1579 #define ELF_MACHINE_CODE EM_TI_PRU
1581 #define ELF_MAXPAGESIZE 1
1583 #define bfd_elf32_bfd_link_hash_table_create \
1584 pru_elf32_link_hash_table_create
1586 /* Relocation table lookup macros. */
1588 #define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup
1589 #define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup
1591 #define elf_info_to_howto pru_elf32_info_to_howto
1592 #define elf_info_to_howto_rel NULL
1594 /* elf backend functions. */
1596 /* TI folks like to use a mix of REL and RELA relocations. See also
1597 the MSP430 and TI C6X backends. */
1598 #define elf_backend_may_use_rel_p 1
1599 #define elf_backend_may_use_rela_p 1
1600 #define elf_backend_default_use_rela_p 1
1602 #define elf_backend_rela_normal 1
1604 #define elf_backend_relocate_section pru_elf32_relocate_section
1605 #define bfd_elf32_bfd_relax_section pru_elf32_relax_section
1606 #define elf_backend_can_gc_sections 1
1608 #define elf_backend_default_execstack 0
1610 #define TARGET_LITTLE_SYM pru_elf32_vec
1611 #define TARGET_LITTLE_NAME "elf32-pru"
1613 #include "elf32-target.h"