1 /* 32-bit ELF support for TI PRU.
2 Copyright (C) 2014-2018 Free Software Foundation, Inc.
3 Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
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. */
32 #include "opcode/pru.h"
33 #include "libiberty.h"
35 #define SWAP_VALS(A,B) \
42 /* Enable debugging printout at stdout with this variable. */
43 static bfd_boolean debug_relax = FALSE;
45 /* Forward declarations. */
46 static bfd_reloc_status_type pru_elf32_pmem_relocate
47 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
48 static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate
49 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
50 static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate
51 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
52 static bfd_reloc_status_type pru_elf32_ldi32_relocate
53 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
54 static bfd_reloc_status_type bfd_elf_pru_diff_relocate
55 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
58 extern const bfd_target pru_elf32_vec;
60 /* The relocation table used for SHT_REL sections. */
61 static reloc_howto_type elf_pru_howto_table_rel[] = {
63 HOWTO (R_PRU_NONE, /* type */
65 0, /* size (0 = byte, 1 = short, 2 = long) */
67 FALSE, /* pc_relative */
69 complain_overflow_dont,/* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_PRU_NONE", /* name */
72 FALSE, /* partial_inplace */
75 FALSE), /* pcrel_offset */
83 complain_overflow_dont,
84 bfd_elf_generic_reloc,
91 HOWTO (R_PRU_U16_PMEMIMM,
97 complain_overflow_unsigned,
98 pru_elf32_pmem_relocate,
105 HOWTO (R_PRU_BFD_RELOC_16,
111 complain_overflow_bitfield,
112 bfd_elf_generic_reloc,
119 /* 16-bit unsigned immediate relocation. */
120 HOWTO (R_PRU_U16, /* type */
122 2, /* size (0 = byte, 1 = short, 2 = long) */
124 FALSE, /* pc_relative */
126 complain_overflow_unsigned, /* complain on overflow */
127 bfd_elf_generic_reloc, /* special function */
128 "R_PRU_U16", /* name */
129 FALSE, /* partial_inplace */
131 0x00ffff00, /* dest_mask */
132 FALSE), /* pcrel_offset */
134 HOWTO (R_PRU_32_PMEM,
140 complain_overflow_dont,
141 pru_elf32_pmem_relocate,
148 HOWTO (R_PRU_BFD_RELOC_32,
154 complain_overflow_dont,
155 bfd_elf_generic_reloc,
162 HOWTO (R_PRU_S10_PCREL,
168 complain_overflow_bitfield,
169 pru_elf32_s10_pcrel_relocate,
176 HOWTO (R_PRU_U8_PCREL,
182 complain_overflow_unsigned,
183 pru_elf32_u8_pcrel_relocate,
192 4, /* size (4 = 8bytes) */
194 FALSE, /* pc_relative */
196 complain_overflow_unsigned, /* complain on overflow */
197 pru_elf32_ldi32_relocate, /* special function */
198 "R_PRU_LDI32", /* name */
199 FALSE, /* partial_inplace */
201 0xffffffff, /* dest_mask */
202 FALSE), /* pcrel_offset */
204 /* GNU-specific relocations. */
205 HOWTO (R_PRU_GNU_BFD_RELOC_8,
211 complain_overflow_bitfield,
212 bfd_elf_generic_reloc,
219 HOWTO (R_PRU_GNU_DIFF8, /* type */
221 0, /* size (0 = byte, 1 = short, 2 = long) */
223 FALSE, /* pc_relative */
225 complain_overflow_bitfield, /* complain_on_overflow */
226 bfd_elf_pru_diff_relocate, /* special_function */
227 "R_PRU_DIFF8", /* name */
228 FALSE, /* partial_inplace */
231 FALSE), /* pcrel_offset */
233 HOWTO (R_PRU_GNU_DIFF16, /* type */
235 1, /* size (0 = byte, 1 = short, 2 = long) */
237 FALSE, /* pc_relative */
239 complain_overflow_bitfield, /* complain_on_overflow */
240 bfd_elf_pru_diff_relocate,/* special_function */
241 "R_PRU_DIFF16", /* name */
242 FALSE, /* partial_inplace */
244 0xffff, /* dst_mask */
245 FALSE), /* pcrel_offset */
247 HOWTO (R_PRU_GNU_DIFF32, /* type */
249 2, /* size (0 = byte, 1 = short, 2 = long) */
251 FALSE, /* pc_relative */
253 complain_overflow_bitfield, /* complain_on_overflow */
254 bfd_elf_pru_diff_relocate,/* special_function */
255 "R_PRU_DIFF32", /* name */
256 FALSE, /* partial_inplace */
258 0xffffffff, /* dst_mask */
259 FALSE), /* pcrel_offset */
261 HOWTO (R_PRU_GNU_DIFF16_PMEM, /* type */
263 1, /* size (0 = byte, 1 = short, 2 = long) */
265 FALSE, /* pc_relative */
267 complain_overflow_bitfield, /* complain_on_overflow */
268 bfd_elf_pru_diff_relocate,/* special_function */
269 "R_PRU_DIFF16_PMEM", /* name */
270 FALSE, /* partial_inplace */
272 0xffff, /* dst_mask */
273 FALSE), /* pcrel_offset */
275 HOWTO (R_PRU_GNU_DIFF32_PMEM, /* type */
277 2, /* size (0 = byte, 1 = short, 2 = long) */
279 FALSE, /* pc_relative */
281 complain_overflow_bitfield, /* complain_on_overflow */
282 bfd_elf_pru_diff_relocate,/* special_function */
283 "R_PRU_DIFF32_PMEM", /* name */
284 FALSE, /* partial_inplace */
286 0xffffffff, /* dst_mask */
287 FALSE), /* pcrel_offset */
289 /* Add other relocations here. */
292 static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1];
294 /* Return the howto for relocation RTYPE. */
296 static reloc_howto_type *
297 lookup_howto (unsigned int rtype)
299 static bfd_boolean initialized = FALSE;
301 int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel)
302 / sizeof (elf_pru_howto_table_rel[0]));
307 memset (elf_code_to_howto_index, 0xff,
308 sizeof (elf_code_to_howto_index));
309 for (i = 0; i < howto_tbl_size; i++)
310 elf_code_to_howto_index[elf_pru_howto_table_rel[i].type] = i;
313 if (rtype > R_PRU_ILLEGAL)
315 i = elf_code_to_howto_index[rtype];
316 if (i >= howto_tbl_size)
318 return elf_pru_howto_table_rel + i;
321 /* Map for converting BFD reloc types to PRU reloc types. */
325 bfd_reloc_code_real_type bfd_val;
326 enum elf_pru_reloc_type elf_val;
329 static const struct elf_reloc_map pru_reloc_map[] =
331 {BFD_RELOC_NONE, R_PRU_NONE},
332 {BFD_RELOC_PRU_16_PMEM, R_PRU_16_PMEM},
333 {BFD_RELOC_PRU_U16_PMEMIMM, R_PRU_U16_PMEMIMM},
334 {BFD_RELOC_16, R_PRU_BFD_RELOC_16},
335 {BFD_RELOC_PRU_U16, R_PRU_U16},
336 {BFD_RELOC_PRU_32_PMEM, R_PRU_32_PMEM},
337 {BFD_RELOC_32, R_PRU_BFD_RELOC_32},
338 {BFD_RELOC_PRU_S10_PCREL, R_PRU_S10_PCREL},
339 {BFD_RELOC_PRU_U8_PCREL, R_PRU_U8_PCREL},
340 {BFD_RELOC_PRU_LDI32, R_PRU_LDI32},
342 {BFD_RELOC_8, R_PRU_GNU_BFD_RELOC_8},
343 {BFD_RELOC_PRU_GNU_DIFF8, R_PRU_GNU_DIFF8},
344 {BFD_RELOC_PRU_GNU_DIFF16, R_PRU_GNU_DIFF16},
345 {BFD_RELOC_PRU_GNU_DIFF32, R_PRU_GNU_DIFF32},
346 {BFD_RELOC_PRU_GNU_DIFF16_PMEM, R_PRU_GNU_DIFF16_PMEM},
347 {BFD_RELOC_PRU_GNU_DIFF32_PMEM, R_PRU_GNU_DIFF32_PMEM},
351 /* Assorted hash table functions. */
353 /* Create an entry in a PRU ELF linker hash table. */
355 static struct bfd_hash_entry *
356 link_hash_newfunc (struct bfd_hash_entry *entry,
357 struct bfd_hash_table *table, const char *string)
359 /* Allocate the structure if it has not already been allocated by a
363 entry = bfd_hash_allocate (table,
364 sizeof (struct elf_link_hash_entry));
369 /* Call the allocation method of the superclass. */
370 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
375 /* Implement bfd_elf32_bfd_reloc_type_lookup:
376 Given a BFD reloc type, return a howto structure. */
378 static reloc_howto_type *
379 pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
380 bfd_reloc_code_real_type code)
384 for (i = 0; i < ARRAY_SIZE (pru_reloc_map); ++i)
385 if (pru_reloc_map[i].bfd_val == code)
386 return lookup_howto ((unsigned int) pru_reloc_map[i].elf_val);
390 /* Implement bfd_elf32_bfd_reloc_name_lookup:
391 Given a reloc name, return a howto structure. */
393 static reloc_howto_type *
394 pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
399 for (i = 0; i < ARRAY_SIZE (elf_pru_howto_table_rel); i++)
400 if (elf_pru_howto_table_rel[i].name
401 && strcasecmp (elf_pru_howto_table_rel[i].name, r_name) == 0)
402 return &elf_pru_howto_table_rel[i];
407 /* Implement elf_info_to_howto:
408 Given a ELF32 relocation, fill in a arelent structure. */
411 pru_elf32_info_to_howto (bfd *abfd, arelent *cache_ptr,
412 Elf_Internal_Rela *dst)
416 r_type = ELF32_R_TYPE (dst->r_info);
417 if (r_type >= R_PRU_ILLEGAL)
419 /* xgettext:c-format */
420 _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
421 bfd_set_error (bfd_error_bad_value);
425 cache_ptr->howto = lookup_howto (r_type);
426 return cache_ptr->howto != NULL;
429 /* Do the relocations that require special handling. */
430 /* Produce a word address for program memory. Linker scripts will put .text
431 at a high offset in order to differentiate it from .data. So here we also
432 mask the high bits of PMEM address.
434 But why 1MB when internal Program Memory much smaller? We want to catch
435 unintended overflows.
437 Why not use (1<<31) as an offset and a mask? Sitara DDRAM usually resides
438 there, and users might want to put some shared carveout memory region in
439 their linker scripts. So 0x80000000 might be a valid .data address.
441 Note that we still keep and pass down the original howto. This way we
442 can reuse this function for several different relocations. */
443 static bfd_reloc_status_type
444 pru_elf32_do_pmem_relocate (bfd *abfd, reloc_howto_type *howto,
445 asection *input_section,
446 bfd_byte *data, bfd_vma offset,
447 bfd_vma symbol_value, bfd_vma addend)
449 symbol_value = symbol_value + addend;
451 symbol_value &= 0x3fffff;
452 return _bfd_final_link_relocate (howto, abfd, input_section,
453 data, offset, symbol_value, addend);
456 /* Direct copy of _bfd_final_link_relocate, but with special
457 "fill-in". This copy-paste mumbo jumbo is only needed because BFD
458 cannot deal correctly with non-contiguous bit fields. */
459 static bfd_reloc_status_type
460 pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto,
461 asection *input_section,
462 bfd_byte *contents, bfd_vma address,
463 bfd_vma relocation, bfd_vma addend)
468 bfd_reloc_status_type flag = bfd_reloc_ok;
470 /* Sanity check the address. */
471 if (address > bfd_get_section_limit (input_bfd, input_section))
472 return bfd_reloc_outofrange;
474 BFD_ASSERT (howto->pc_relative);
475 BFD_ASSERT (howto->pcrel_offset);
477 relocation = relocation + addend - (input_section->output_section->vma
478 + input_section->output_offset) - address;
480 location = contents + address;
482 /* Get the value we are going to relocate. */
483 BFD_ASSERT (bfd_get_reloc_size (howto) == 4);
484 x = bfd_get_32 (input_bfd, location);
486 qboff = GET_BROFF_SIGNED (x) << howto->rightshift;
489 BFD_ASSERT (howto->complain_on_overflow == complain_overflow_bitfield);
491 if (relocation > 2047 && relocation < (bfd_vma)-2048l)
492 flag = bfd_reloc_overflow;
494 /* Check that target address is word-aligned. */
495 if (relocation & ((1 << howto->rightshift) - 1))
496 flag = bfd_reloc_outofrange;
498 relocation >>= (bfd_vma) howto->rightshift;
500 /* Fill-in the RELOCATION to the right bits of X. */
501 SET_BROFF_URAW (x, relocation);
503 bfd_put_32 (input_bfd, x, location);
508 static bfd_reloc_status_type
509 pru_elf32_do_u8_pcrel_relocate (bfd *abfd, reloc_howto_type *howto,
510 asection *input_section,
511 bfd_byte *data, bfd_vma offset,
512 bfd_vma symbol_value, bfd_vma addend)
516 BFD_ASSERT (howto->pc_relative);
517 BFD_ASSERT (howto->pcrel_offset);
519 relocation = symbol_value + addend - (input_section->output_section->vma
520 + input_section->output_offset) - offset;
521 relocation >>= howto->rightshift;
523 /* 0 and 1 are invalid target labels for LOOP. We cannot
524 encode this info in HOWTO, so catch such cases here. */
526 return bfd_reloc_outofrange;
528 return _bfd_final_link_relocate (howto, abfd, input_section,
529 data, offset, symbol_value, addend);
532 /* Idea and code taken from elf32-d30v. */
533 static bfd_reloc_status_type
534 pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
535 asection *input_section,
536 bfd_byte *data, bfd_vma offset,
537 bfd_vma symbol_value, bfd_vma addend)
539 bfd_signed_vma relocation;
540 bfd_size_type octets = offset * bfd_octets_per_byte (abfd);
542 unsigned long in1, in2, num;
544 /* A hacked-up version of _bfd_final_link_relocate() follows. */
546 /* Sanity check the address. */
547 if (octets + bfd_get_reloc_size (howto)
548 > bfd_get_section_limit_octets (abfd, input_section))
549 return bfd_reloc_outofrange;
551 /* This function assumes that we are dealing with a basic relocation
552 against a symbol. We want to compute the value of the symbol to
553 relocate to. This is just VALUE, the value of the symbol, plus
554 ADDEND, any addend associated with the reloc. */
555 relocation = symbol_value + addend;
557 BFD_ASSERT (!howto->pc_relative);
559 /* A hacked-up version of _bfd_relocate_contents() follows. */
560 location = data + offset * bfd_octets_per_byte (abfd);
562 BFD_ASSERT (!howto->pc_relative);
564 in1 = bfd_get_32 (abfd, location);
565 in2 = bfd_get_32 (abfd, location + 4);
567 /* Extract the addend - should be zero per my understanding. */
568 num = GET_INSN_FIELD (IMM16, in1) | (GET_INSN_FIELD (IMM16, in2) << 16);
573 SET_INSN_FIELD (IMM16, in1, relocation & 0xffff);
574 SET_INSN_FIELD (IMM16, in2, relocation >> 16);
576 bfd_put_32 (abfd, in1, location);
577 bfd_put_32 (abfd, in2, location + 4);
582 /* HOWTO handlers for relocations that require special handling. */
584 static bfd_reloc_status_type
585 pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
586 asymbol *symbol, void *data,
587 asection *input_section, bfd *output_bfd,
588 char **error_message)
590 /* If this is a relocatable link (output_bfd test tells us), just
591 call the generic function. Any adjustment will be done at final
593 if (output_bfd != NULL)
594 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
595 input_section, output_bfd, error_message);
597 return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
599 data, reloc_entry->address,
601 + symbol->section->output_section->vma
602 + symbol->section->output_offset),
603 reloc_entry->addend);
606 static bfd_reloc_status_type
607 pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry,
608 asymbol *symbol, void *data,
609 asection *input_section, bfd *output_bfd,
610 char **error_message)
612 /* If this is a relocatable link (output_bfd test tells us), just
613 call the generic function. Any adjustment will be done at final
615 if (output_bfd != NULL)
616 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
617 input_section, output_bfd, error_message);
619 return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
621 reloc_entry->address,
623 + symbol->section->output_section->vma
624 + symbol->section->output_offset),
625 reloc_entry->addend);
628 static bfd_reloc_status_type
629 pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
630 void *data, asection *input_section,
632 char **error_message)
634 /* If this is a relocatable link (output_bfd test tells us), just
635 call the generic function. Any adjustment will be done at final
637 if (output_bfd != NULL)
638 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
639 input_section, output_bfd, error_message);
641 return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
643 data, reloc_entry->address,
645 + symbol->section->output_section->vma
646 + symbol->section->output_offset),
647 reloc_entry->addend);
650 static bfd_reloc_status_type
651 pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
652 void *data, asection *input_section,
654 char **error_message)
656 /* If this is a relocatable link (output_bfd test tells us), just
657 call the generic function. Any adjustment will be done at final
659 if (output_bfd != NULL)
660 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
661 input_section, output_bfd, error_message);
663 return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
665 data, reloc_entry->address,
667 + symbol->section->output_section->vma
668 + symbol->section->output_offset),
669 reloc_entry->addend);
673 /* Implement elf_backend_relocate_section. */
675 pru_elf32_relocate_section (bfd *output_bfd,
676 struct bfd_link_info *info,
678 asection *input_section,
680 Elf_Internal_Rela *relocs,
681 Elf_Internal_Sym *local_syms,
682 asection **local_sections)
684 Elf_Internal_Shdr *symtab_hdr;
685 struct elf_link_hash_entry **sym_hashes;
686 Elf_Internal_Rela *rel;
687 Elf_Internal_Rela *relend;
689 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
690 sym_hashes = elf_sym_hashes (input_bfd);
691 relend = relocs + input_section->reloc_count;
693 for (rel = relocs; rel < relend; rel++)
695 reloc_howto_type *howto;
696 unsigned long r_symndx;
697 Elf_Internal_Sym *sym;
699 struct elf_link_hash_entry *h;
701 bfd_reloc_status_type r = bfd_reloc_ok;
702 const char *name = NULL;
703 const char* msg = (const char*) NULL;
704 bfd_boolean unresolved_reloc;
706 r_symndx = ELF32_R_SYM (rel->r_info);
708 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
713 if (r_symndx < symtab_hdr->sh_info)
715 sym = local_syms + r_symndx;
716 sec = local_sections[r_symndx];
717 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
721 bfd_boolean warned, ignored;
723 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
724 r_symndx, symtab_hdr, sym_hashes,
726 unresolved_reloc, warned, ignored);
729 if (sec && discarded_section (sec))
730 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
731 rel, 1, relend, howto, 0, contents);
733 /* Nothing more to do unless this is a final link. */
734 if (bfd_link_relocatable (info))
742 /* We don't need to find a value for this symbol. It's just a
747 case R_PRU_U16_PMEMIMM:
750 r = pru_elf32_do_pmem_relocate (input_bfd, howto,
752 contents, rel->r_offset,
753 relocation, rel->r_addend);
755 case R_PRU_S10_PCREL:
756 r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
764 r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
772 r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
779 case R_PRU_GNU_DIFF8:
780 case R_PRU_GNU_DIFF16:
781 case R_PRU_GNU_DIFF32:
782 case R_PRU_GNU_DIFF16_PMEM:
783 case R_PRU_GNU_DIFF32_PMEM:
784 /* Nothing to do here, as contents already contain the
790 r = _bfd_final_link_relocate (howto, input_bfd,
791 input_section, contents,
792 rel->r_offset, relocation,
798 r = bfd_reloc_notsupported;
800 if (r != bfd_reloc_ok)
803 name = h->root.root.string;
806 name = bfd_elf_string_from_elf_section (input_bfd,
809 if (name == NULL || *name == '\0')
810 name = bfd_section_name (input_bfd, sec);
815 case bfd_reloc_overflow:
816 (*info->callbacks->reloc_overflow) (info, NULL, name,
817 howto->name, (bfd_vma) 0,
818 input_bfd, input_section,
822 case bfd_reloc_undefined:
823 (*info->callbacks->undefined_symbol) (info, name, input_bfd,
825 rel->r_offset, TRUE);
828 case bfd_reloc_outofrange:
830 msg = _("relocation out of range");
833 case bfd_reloc_notsupported:
835 msg = _("unsupported relocation");
838 case bfd_reloc_dangerous:
840 msg = _("dangerous relocation");
845 msg = _("unknown error");
851 (*info->callbacks->warning) (info, msg, name, input_bfd,
852 input_section, rel->r_offset);
861 /* Perform a diff relocation. Nothing to do, as the difference value is
862 already written into the section's contents. */
864 static bfd_reloc_status_type
865 bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
866 arelent *reloc_entry ATTRIBUTE_UNUSED,
867 asymbol *symbol ATTRIBUTE_UNUSED,
868 void *data ATTRIBUTE_UNUSED,
869 asection *input_section ATTRIBUTE_UNUSED,
870 bfd *output_bfd ATTRIBUTE_UNUSED,
871 char **error_message ATTRIBUTE_UNUSED)
877 /* Returns whether the relocation type passed is a diff reloc. */
880 elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
882 return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
883 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
884 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
885 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
886 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
889 /* Reduce the diff value written in the section by count if the shrinked
890 insn address happens to fall between the two symbols for which this
891 diff reloc was emitted. */
894 elf32_pru_adjust_diff_reloc_value (bfd *abfd,
895 struct bfd_section *isec,
896 Elf_Internal_Rela *irel,
898 bfd_vma shrinked_insn_address,
901 unsigned char *reloc_contents = NULL;
902 unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
903 if (isec_contents == NULL)
905 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
908 elf_section_data (isec)->this_hdr.contents = isec_contents;
911 reloc_contents = isec_contents + irel->r_offset;
913 /* Read value written in object file. */
914 bfd_signed_vma x = 0;
915 switch (ELF32_R_TYPE (irel->r_info))
917 case R_PRU_GNU_DIFF8:
919 x = bfd_get_signed_8 (abfd, reloc_contents);
922 case R_PRU_GNU_DIFF16:
924 x = bfd_get_signed_16 (abfd, reloc_contents);
927 case R_PRU_GNU_DIFF32:
929 x = bfd_get_signed_32 (abfd, reloc_contents);
932 case R_PRU_GNU_DIFF16_PMEM:
934 x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
937 case R_PRU_GNU_DIFF32_PMEM:
939 x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
948 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
949 into the object file at the reloc offset. sym2's logical value is
950 symval (<start_of_section>) + reloc addend. Compute the start and end
951 addresses and check if the shrinked insn falls between sym1 and sym2. */
953 bfd_vma end_address = symval + irel->r_addend;
954 bfd_vma start_address = end_address - x;
956 /* Shrink the absolute DIFF value (get the to labels "closer"
957 together), because we have removed data between labels. */
961 /* In case the signed x is negative, restore order. */
962 SWAP_VALS (end_address, start_address);
969 /* Reduce the diff value by count bytes and write it back into section
972 if (shrinked_insn_address >= start_address
973 && shrinked_insn_address <= end_address)
975 switch (ELF32_R_TYPE (irel->r_info))
977 case R_PRU_GNU_DIFF8:
979 bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
982 case R_PRU_GNU_DIFF16:
984 bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
987 case R_PRU_GNU_DIFF32:
989 bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
992 case R_PRU_GNU_DIFF16_PMEM:
994 bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
997 case R_PRU_GNU_DIFF32_PMEM:
999 bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
1011 /* Delete some bytes from a section while changing the size of an instruction.
1012 The parameter "addr" denotes the section-relative offset pointing just
1013 behind the shrinked instruction. "addr+count" point at the first
1014 byte just behind the original unshrinked instruction.
1016 Idea copied from the AVR port. */
1019 pru_elf_relax_delete_bytes (bfd *abfd,
1024 Elf_Internal_Shdr *symtab_hdr;
1025 unsigned int sec_shndx;
1027 Elf_Internal_Rela *irel, *irelend;
1028 Elf_Internal_Sym *isym;
1029 Elf_Internal_Sym *isymbuf = NULL;
1031 struct elf_link_hash_entry **sym_hashes;
1032 struct elf_link_hash_entry **end_hashes;
1033 unsigned int symcount;
1035 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1036 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1037 contents = elf_section_data (sec)->this_hdr.contents;
1041 irel = elf_section_data (sec)->relocs;
1042 irelend = irel + sec->reloc_count;
1044 /* Actually delete the bytes. */
1045 if (toaddr - addr - count > 0)
1046 memmove (contents + addr, contents + addr + count,
1047 (size_t) (toaddr - addr - count));
1050 /* Adjust all the reloc addresses. */
1051 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1053 bfd_vma old_reloc_address;
1055 old_reloc_address = (sec->output_section->vma
1056 + sec->output_offset + irel->r_offset);
1058 /* Get the new reloc address. */
1059 if ((irel->r_offset > addr
1060 && irel->r_offset < toaddr))
1063 printf ("Relocation at address 0x%x needs to be moved.\n"
1064 "Old section offset: 0x%x, New section offset: 0x%x \n",
1065 (unsigned int) old_reloc_address,
1066 (unsigned int) irel->r_offset,
1067 (unsigned int) ((irel->r_offset) - count));
1069 irel->r_offset -= count;
1074 /* The reloc's own addresses are now ok. However, we need to readjust
1075 the reloc's addend, i.e. the reloc's value if two conditions are met:
1076 1.) the reloc is relative to a symbol in this section that
1077 is located in front of the shrinked instruction
1078 2.) symbol plus addend end up behind the shrinked instruction.
1080 The most common case where this happens are relocs relative to
1081 the section-start symbol.
1083 This step needs to be done for all of the sections of the bfd. */
1086 struct bfd_section *isec;
1088 for (isec = abfd->sections; isec; isec = isec->next)
1091 bfd_vma shrinked_insn_address;
1093 if (isec->reloc_count == 0)
1096 shrinked_insn_address = (sec->output_section->vma
1097 + sec->output_offset + addr - count);
1099 irel = elf_section_data (isec)->relocs;
1100 /* PR 12161: Read in the relocs for this section if necessary. */
1102 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
1104 for (irelend = irel + isec->reloc_count;
1108 /* Read this BFD's local symbols if we haven't done
1110 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1112 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1113 if (isymbuf == NULL)
1114 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1115 symtab_hdr->sh_info, 0,
1117 if (isymbuf == NULL)
1121 /* Get the value of the symbol referred to by the reloc. */
1122 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1124 /* A local symbol. */
1127 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1128 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1129 symval = isym->st_value;
1130 /* If the reloc is absolute, it will not have
1131 a symbol or section associated with it. */
1134 symval += sym_sec->output_section->vma
1135 + sym_sec->output_offset;
1138 printf ("Checking if the relocation's "
1139 "addend needs corrections.\n"
1140 "Address of anchor symbol: 0x%x \n"
1141 "Address of relocation target: 0x%x \n"
1142 "Address of relaxed insn: 0x%x \n",
1143 (unsigned int) symval,
1144 (unsigned int) (symval + irel->r_addend),
1145 (unsigned int) shrinked_insn_address);
1147 /* Shrink the special DIFF relocations. */
1148 if (elf32_pru_is_diff_reloc (irel))
1150 elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1152 shrinked_insn_address,
1156 /* Fix the addend, if it is affected. */
1157 if (symval <= shrinked_insn_address
1158 && (symval + irel->r_addend) > shrinked_insn_address)
1161 irel->r_addend -= count;
1164 printf ("Relocation's addend needed to be fixed \n");
1167 /* else...Reference symbol is absolute.
1168 No adjustment needed. */
1170 /* else...Reference symbol is extern. No need for adjusting
1176 /* Adjust the local symbols defined in this section. */
1177 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1178 /* Fix PR 9841, there may be no local symbols. */
1181 Elf_Internal_Sym *isymend;
1183 isymend = isym + symtab_hdr->sh_info;
1184 for (; isym < isymend; isym++)
1186 if (isym->st_shndx == sec_shndx)
1188 if (isym->st_value > addr
1189 && isym->st_value <= toaddr)
1190 isym->st_value -= count;
1192 if (isym->st_value <= addr
1193 && isym->st_value + isym->st_size > addr)
1195 /* If this assert fires then we have a symbol that ends
1196 part way through an instruction. Does that make
1198 BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1199 isym->st_size -= count;
1205 /* Now adjust the global symbols defined in this section. */
1206 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1207 - symtab_hdr->sh_info);
1208 sym_hashes = elf_sym_hashes (abfd);
1209 end_hashes = sym_hashes + symcount;
1210 for (; sym_hashes < end_hashes; sym_hashes++)
1212 struct elf_link_hash_entry *sym_hash = *sym_hashes;
1213 if ((sym_hash->root.type == bfd_link_hash_defined
1214 || sym_hash->root.type == bfd_link_hash_defweak)
1215 && sym_hash->root.u.def.section == sec)
1217 if (sym_hash->root.u.def.value > addr
1218 && sym_hash->root.u.def.value <= toaddr)
1219 sym_hash->root.u.def.value -= count;
1221 if (sym_hash->root.u.def.value <= addr
1222 && (sym_hash->root.u.def.value + sym_hash->size > addr))
1224 /* If this assert fires then we have a symbol that ends
1225 part way through an instruction. Does that make
1227 BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1229 sym_hash->size -= count;
1238 pru_elf32_relax_section (bfd * abfd, asection * sec,
1239 struct bfd_link_info * link_info,
1240 bfd_boolean * again)
1242 Elf_Internal_Shdr * symtab_hdr;
1243 Elf_Internal_Rela * internal_relocs;
1244 Elf_Internal_Rela * irel;
1245 Elf_Internal_Rela * irelend;
1246 bfd_byte * contents = NULL;
1247 Elf_Internal_Sym * isymbuf = NULL;
1249 /* Assume nothing changes. */
1252 /* We don't have to do anything for a relocatable link, if
1253 this section does not have relocs, or if this is not a
1255 if (bfd_link_relocatable (link_info)
1256 || (sec->flags & SEC_RELOC) == 0
1257 || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1260 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1262 /* Get a copy of the native relocations. */
1263 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1264 link_info->keep_memory);
1265 if (internal_relocs == NULL)
1268 /* Walk through them looking for relaxing opportunities. */
1269 irelend = internal_relocs + sec->reloc_count;
1271 for (irel = internal_relocs; irel < irelend; irel++)
1275 /* Get the section contents if we haven't done so already. */
1276 if (contents == NULL)
1278 /* Get cached copy if it exists. */
1279 if (elf_section_data (sec)->this_hdr.contents != NULL)
1280 contents = elf_section_data (sec)->this_hdr.contents;
1281 else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1285 /* Read this BFD's local symbols if we haven't done so already. */
1286 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1288 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1289 if (isymbuf == NULL)
1290 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1291 symtab_hdr->sh_info, 0,
1293 if (isymbuf == NULL)
1297 /* Get the value of the symbol referred to by the reloc. */
1298 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1300 /* A local symbol. */
1301 Elf_Internal_Sym *isym;
1304 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1305 if (isym->st_shndx == SHN_UNDEF)
1306 sym_sec = bfd_und_section_ptr;
1307 else if (isym->st_shndx == SHN_ABS)
1308 sym_sec = bfd_abs_section_ptr;
1309 else if (isym->st_shndx == SHN_COMMON)
1310 sym_sec = bfd_com_section_ptr;
1312 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1313 symval = (isym->st_value
1314 + sym_sec->output_section->vma + sym_sec->output_offset);
1319 struct elf_link_hash_entry *h;
1321 /* An external symbol. */
1322 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1323 h = elf_sym_hashes (abfd)[indx];
1324 BFD_ASSERT (h != NULL);
1326 if (h->root.type != bfd_link_hash_defined
1327 && h->root.type != bfd_link_hash_defweak)
1328 /* This appears to be a reference to an undefined
1329 symbol. Just ignore it--it will be caught by the
1330 regular reloc processing. */
1333 symval = (h->root.u.def.value
1334 + h->root.u.def.section->output_section->vma
1335 + h->root.u.def.section->output_offset);
1338 /* For simplicity of coding, we are going to modify the section
1339 contents, the section relocs, and the BFD symbol table. We
1340 must tell the rest of the code not to free up this
1341 information. It would be possible to instead create a table
1342 of changes which have to be made, as is done in coff-mips.c;
1343 that would be more work, but would require less memory when
1344 the linker is run. */
1346 /* Check if we can remove an LDI instruction from the LDI32
1347 pseudo instruction if the upper 16 operand bits are zero. */
1348 if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1350 bfd_vma value = symval + irel->r_addend;
1353 printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1355 if ((long) value >> 16 == 0)
1357 /* Note that we've changed the relocs, section contents. */
1358 elf_section_data (sec)->relocs = internal_relocs;
1359 elf_section_data (sec)->this_hdr.contents = contents;
1360 symtab_hdr->contents = (unsigned char *) isymbuf;
1363 if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 4, 4))
1366 /* We're done with deletion of the second instruction.
1367 Set a regular LDI relocation for the first instruction
1368 we left to load the 16-bit value into the 32-bit
1370 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1373 /* That will change things, so, we should relax again.
1374 Note that this is not required, and it may be slow. */
1380 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1382 if (!link_info->keep_memory)
1386 /* Cache the symbols for elf_link_input_bfd. */
1387 symtab_hdr->contents = (unsigned char *) isymbuf;
1391 if (contents != NULL
1392 && elf_section_data (sec)->this_hdr.contents != contents)
1394 if (!link_info->keep_memory)
1398 /* Cache the section contents for elf_link_input_bfd. */
1399 elf_section_data (sec)->this_hdr.contents = contents;
1403 if (internal_relocs != NULL
1404 && elf_section_data (sec)->relocs != internal_relocs)
1405 free (internal_relocs);
1410 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1412 if (contents != NULL
1413 && elf_section_data (sec)->this_hdr.contents != contents)
1415 if (internal_relocs != NULL
1416 && elf_section_data (sec)->relocs != internal_relocs)
1417 free (internal_relocs);
1422 /* Free the derived linker hash table. */
1424 pru_elf32_link_hash_table_free (bfd *obfd)
1426 _bfd_elf_link_hash_table_free (obfd);
1429 /* Implement bfd_elf32_bfd_link_hash_table_create. */
1430 static struct bfd_link_hash_table *
1431 pru_elf32_link_hash_table_create (bfd *abfd)
1433 struct elf_link_hash_table *ret;
1434 bfd_size_type amt = sizeof (struct elf_link_hash_table);
1436 ret = bfd_zmalloc (amt);
1440 if (!_bfd_elf_link_hash_table_init (ret, abfd,
1443 elf_link_hash_entry),
1450 ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1455 #define ELF_ARCH bfd_arch_pru
1456 #define ELF_TARGET_ID PRU_ELF_DATA
1457 #define ELF_MACHINE_CODE EM_TI_PRU
1459 #define ELF_MAXPAGESIZE 1
1461 #define bfd_elf32_bfd_link_hash_table_create \
1462 pru_elf32_link_hash_table_create
1464 /* Relocation table lookup macros. */
1466 #define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup
1467 #define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup
1469 /* elf_info_to_howto (using RELA relocations). */
1471 #define elf_info_to_howto pru_elf32_info_to_howto
1473 /* elf backend functions. */
1475 #define elf_backend_rela_normal 1
1477 #define elf_backend_relocate_section pru_elf32_relocate_section
1478 #define bfd_elf32_bfd_relax_section pru_elf32_relax_section
1480 #define TARGET_LITTLE_SYM pru_elf32_vec
1481 #define TARGET_LITTLE_NAME "elf32-pru"
1483 #include "elf32-target.h"