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;
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 SET_INSN_FIELD (IMM16, in1, relocation >> 16);
568 SET_INSN_FIELD (IMM16, in2, relocation & 0xffff);
570 bfd_put_32 (abfd, in1, location);
571 bfd_put_32 (abfd, in2, location + 4);
573 /* Old GAS and LD versions have a bug, where the two
574 LDI instructions are swapped. Detect such object
576 if (GET_INSN_FIELD (RDSEL, in1) != RSEL_31_16)
578 /* xgettext:c-format */
579 _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
581 return bfd_reloc_notsupported;
587 /* HOWTO handlers for relocations that require special handling. */
589 static bfd_reloc_status_type
590 pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
591 asymbol *symbol, void *data,
592 asection *input_section, bfd *output_bfd,
593 char **error_message)
595 /* If this is a relocatable link (output_bfd test tells us), just
596 call the generic function. Any adjustment will be done at final
598 if (output_bfd != NULL)
599 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
600 input_section, output_bfd, error_message);
603 return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
605 data, reloc_entry->address,
607 + symbol->section->output_section->vma
608 + symbol->section->output_offset),
609 reloc_entry->addend);
612 static bfd_reloc_status_type
613 pru_elf32_s10_pcrel_relocate (bfd *abfd, arelent *reloc_entry,
614 asymbol *symbol, void *data,
615 asection *input_section, bfd *output_bfd,
616 char **error_message)
618 /* If this is a relocatable link (output_bfd test tells us), just
619 call the generic function. Any adjustment will be done at final
621 if (output_bfd != NULL)
622 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
623 input_section, output_bfd, error_message);
625 return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
627 reloc_entry->address,
629 + symbol->section->output_section->vma
630 + symbol->section->output_offset),
631 reloc_entry->addend);
634 static bfd_reloc_status_type
635 pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
636 void *data, asection *input_section,
638 char **error_message)
640 /* If this is a relocatable link (output_bfd test tells us), just
641 call the generic function. Any adjustment will be done at final
643 if (output_bfd != NULL)
644 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
645 input_section, output_bfd, error_message);
647 return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
649 data, reloc_entry->address,
651 + symbol->section->output_section->vma
652 + symbol->section->output_offset),
653 reloc_entry->addend);
656 static bfd_reloc_status_type
657 pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
658 void *data, asection *input_section,
660 char **error_message)
662 /* If this is a relocatable link (output_bfd test tells us), just
663 call the generic function. Any adjustment will be done at final
665 if (output_bfd != NULL)
666 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
667 input_section, output_bfd, error_message);
669 return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
671 data, reloc_entry->address,
673 + symbol->section->output_section->vma
674 + symbol->section->output_offset),
675 reloc_entry->addend);
679 /* Implement elf_backend_relocate_section. */
681 pru_elf32_relocate_section (bfd *output_bfd,
682 struct bfd_link_info *info,
684 asection *input_section,
686 Elf_Internal_Rela *relocs,
687 Elf_Internal_Sym *local_syms,
688 asection **local_sections)
690 struct bfd_elf_section_data * esd = elf_section_data (input_section);
691 Elf_Internal_Shdr *symtab_hdr;
692 struct elf_link_hash_entry **sym_hashes;
693 Elf_Internal_Rela *rel;
694 Elf_Internal_Rela *relend;
695 bfd_boolean is_rel_reloc;
697 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
698 sym_hashes = elf_sym_hashes (input_bfd);
699 relend = relocs + input_section->reloc_count;
701 /* See if we have a REL type relocation. */
702 is_rel_reloc = (esd->rel.hdr != NULL);
703 /* Sanity check - only one type of relocation per section.
704 FIXME: Theoretically it is possible to have both types,
705 but if that happens how can we distinguish between the two ? */
706 BFD_ASSERT (! is_rel_reloc || ! esd->rela.hdr);
708 for (rel = relocs; rel < relend; rel++)
710 reloc_howto_type *howto;
711 unsigned long r_symndx;
712 Elf_Internal_Sym *sym;
714 struct elf_link_hash_entry *h;
716 bfd_reloc_status_type r = bfd_reloc_ok;
717 const char *name = NULL;
718 const char* msg = (const char*) NULL;
719 bfd_boolean unresolved_reloc;
722 /* If we are using a REL relocation then the addend should be empty. */
723 BFD_ASSERT (! is_rel_reloc || rel->r_addend == 0);
725 r_symndx = ELF32_R_SYM (rel->r_info);
727 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
732 if (r_symndx < symtab_hdr->sh_info)
734 sym = local_syms + r_symndx;
735 sec = local_sections[r_symndx];
736 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
740 bfd_boolean warned, ignored;
742 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
743 r_symndx, symtab_hdr, sym_hashes,
745 unresolved_reloc, warned, ignored);
748 if (sec && discarded_section (sec))
749 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
750 rel, 1, relend, howto, 0, contents);
752 /* Nothing more to do unless this is a final link. */
753 if (bfd_link_relocatable (info))
761 /* We don't need to find a value for this symbol. It's just a
770 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
771 addend = GET_INSN_FIELD (IMM16, insn);
774 addend = rel->r_addend;
775 r = _bfd_final_link_relocate (howto, input_bfd,
776 input_section, contents,
777 rel->r_offset, relocation,
781 case R_PRU_U16_PMEMIMM:
784 if (is_rel_reloc && howto->type == R_PRU_U16_PMEMIMM)
787 insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
788 addend = GET_INSN_FIELD (IMM16, insn) << 2;
790 else if (is_rel_reloc && howto->type == R_PRU_32_PMEM)
792 addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
795 else if (is_rel_reloc && howto->type == R_PRU_16_PMEM)
797 addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
802 BFD_ASSERT (!is_rel_reloc);
803 addend = rel->r_addend;
805 r = pru_elf32_do_pmem_relocate (input_bfd, howto,
807 contents, rel->r_offset,
810 case R_PRU_S10_PCREL:
811 BFD_ASSERT (! is_rel_reloc);
812 r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
820 BFD_ASSERT (! is_rel_reloc);
821 r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
831 unsigned long in1, in2;
832 in1 = bfd_get_32 (input_bfd, contents + rel->r_offset);
833 in2 = bfd_get_32 (input_bfd, contents + rel->r_offset + 4);
834 addend = (GET_INSN_FIELD (IMM16, in1) << 16)
835 | GET_INSN_FIELD (IMM16, in2);
839 addend = rel->r_addend;
841 r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
848 case R_PRU_GNU_DIFF8:
849 case R_PRU_GNU_DIFF16:
850 case R_PRU_GNU_DIFF32:
851 case R_PRU_GNU_DIFF16_PMEM:
852 case R_PRU_GNU_DIFF32_PMEM:
853 /* GNU extensions support only rela. */
854 BFD_ASSERT (! is_rel_reloc);
855 /* Nothing to do here, as contents already contain the
860 case R_PRU_BFD_RELOC_16:
862 addend = bfd_get_16 (input_bfd, contents + rel->r_offset);
864 addend = rel->r_addend;
865 r = _bfd_final_link_relocate (howto, input_bfd,
866 input_section, contents,
867 rel->r_offset, relocation,
871 case R_PRU_BFD_RELOC_32:
873 addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
875 addend = rel->r_addend;
876 r = _bfd_final_link_relocate (howto, input_bfd,
877 input_section, contents,
878 rel->r_offset, relocation,
882 case R_PRU_GNU_BFD_RELOC_8:
883 BFD_ASSERT (! is_rel_reloc);
884 r = _bfd_final_link_relocate (howto, input_bfd,
885 input_section, contents,
886 rel->r_offset, relocation,
896 r = bfd_reloc_notsupported;
898 if (r != bfd_reloc_ok)
901 name = h->root.root.string;
904 name = bfd_elf_string_from_elf_section (input_bfd,
907 if (name == NULL || *name == '\0')
908 name = bfd_section_name (input_bfd, sec);
913 case bfd_reloc_overflow:
914 (*info->callbacks->reloc_overflow) (info, NULL, name,
915 howto->name, (bfd_vma) 0,
916 input_bfd, input_section,
920 case bfd_reloc_undefined:
921 (*info->callbacks->undefined_symbol) (info, name, input_bfd,
923 rel->r_offset, TRUE);
926 case bfd_reloc_outofrange:
928 msg = _("relocation out of range");
931 case bfd_reloc_notsupported:
933 msg = _("unsupported relocation");
936 case bfd_reloc_dangerous:
938 msg = _("dangerous relocation");
943 msg = _("unknown error");
949 (*info->callbacks->warning) (info, msg, name, input_bfd,
950 input_section, rel->r_offset);
959 /* Perform a diff relocation. Nothing to do, as the difference value is
960 already written into the section's contents. */
962 static bfd_reloc_status_type
963 bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
964 arelent *reloc_entry ATTRIBUTE_UNUSED,
965 asymbol *symbol ATTRIBUTE_UNUSED,
966 void *data ATTRIBUTE_UNUSED,
967 asection *input_section ATTRIBUTE_UNUSED,
968 bfd *output_bfd ATTRIBUTE_UNUSED,
969 char **error_message ATTRIBUTE_UNUSED)
975 /* Returns whether the relocation type passed is a diff reloc. */
978 elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
980 return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
981 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
982 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
983 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
984 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
987 /* Reduce the diff value written in the section by count if the shrinked
988 insn address happens to fall between the two symbols for which this
989 diff reloc was emitted. */
992 elf32_pru_adjust_diff_reloc_value (bfd *abfd,
993 struct bfd_section *isec,
994 Elf_Internal_Rela *irel,
996 bfd_vma shrinked_insn_address,
999 unsigned char *reloc_contents = NULL;
1000 unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
1001 if (isec_contents == NULL)
1003 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
1006 elf_section_data (isec)->this_hdr.contents = isec_contents;
1009 reloc_contents = isec_contents + irel->r_offset;
1011 /* Read value written in object file. */
1012 bfd_signed_vma x = 0;
1013 switch (ELF32_R_TYPE (irel->r_info))
1015 case R_PRU_GNU_DIFF8:
1017 x = bfd_get_signed_8 (abfd, reloc_contents);
1020 case R_PRU_GNU_DIFF16:
1022 x = bfd_get_signed_16 (abfd, reloc_contents);
1025 case R_PRU_GNU_DIFF32:
1027 x = bfd_get_signed_32 (abfd, reloc_contents);
1030 case R_PRU_GNU_DIFF16_PMEM:
1032 x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
1035 case R_PRU_GNU_DIFF32_PMEM:
1037 x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
1046 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
1047 into the object file at the reloc offset. sym2's logical value is
1048 symval (<start_of_section>) + reloc addend. Compute the start and end
1049 addresses and check if the shrinked insn falls between sym1 and sym2. */
1051 bfd_vma end_address = symval + irel->r_addend;
1052 bfd_vma start_address = end_address - x;
1054 /* Shrink the absolute DIFF value (get the to labels "closer"
1055 together), because we have removed data between labels. */
1059 /* In case the signed x is negative, restore order. */
1060 SWAP_VALS (end_address, start_address);
1067 /* Reduce the diff value by count bytes and write it back into section
1070 if (shrinked_insn_address >= start_address
1071 && shrinked_insn_address <= end_address)
1073 switch (ELF32_R_TYPE (irel->r_info))
1075 case R_PRU_GNU_DIFF8:
1077 bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
1080 case R_PRU_GNU_DIFF16:
1082 bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
1085 case R_PRU_GNU_DIFF32:
1087 bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
1090 case R_PRU_GNU_DIFF16_PMEM:
1092 bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
1095 case R_PRU_GNU_DIFF32_PMEM:
1097 bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
1109 /* Delete some bytes from a section while changing the size of an instruction.
1110 The parameter "addr" denotes the section-relative offset pointing just
1111 behind the shrinked instruction. "addr+count" point at the first
1112 byte just behind the original unshrinked instruction.
1114 Idea copied from the AVR port. */
1117 pru_elf_relax_delete_bytes (bfd *abfd,
1122 Elf_Internal_Shdr *symtab_hdr;
1123 unsigned int sec_shndx;
1125 Elf_Internal_Rela *irel, *irelend;
1126 Elf_Internal_Sym *isym;
1127 Elf_Internal_Sym *isymbuf = NULL;
1129 struct elf_link_hash_entry **sym_hashes;
1130 struct elf_link_hash_entry **end_hashes;
1131 unsigned int symcount;
1133 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1134 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1135 contents = elf_section_data (sec)->this_hdr.contents;
1139 irel = elf_section_data (sec)->relocs;
1140 irelend = irel + sec->reloc_count;
1142 /* Actually delete the bytes. */
1143 if (toaddr - addr - count > 0)
1144 memmove (contents + addr, contents + addr + count,
1145 (size_t) (toaddr - addr - count));
1148 /* Adjust all the reloc addresses. */
1149 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1151 bfd_vma old_reloc_address;
1153 old_reloc_address = (sec->output_section->vma
1154 + sec->output_offset + irel->r_offset);
1156 /* Get the new reloc address. */
1157 if ((irel->r_offset > addr
1158 && irel->r_offset < toaddr))
1161 printf ("Relocation at address 0x%x needs to be moved.\n"
1162 "Old section offset: 0x%x, New section offset: 0x%x \n",
1163 (unsigned int) old_reloc_address,
1164 (unsigned int) irel->r_offset,
1165 (unsigned int) ((irel->r_offset) - count));
1167 irel->r_offset -= count;
1172 /* The reloc's own addresses are now ok. However, we need to readjust
1173 the reloc's addend, i.e. the reloc's value if two conditions are met:
1174 1.) the reloc is relative to a symbol in this section that
1175 is located in front of the shrinked instruction
1176 2.) symbol plus addend end up behind the shrinked instruction.
1178 The most common case where this happens are relocs relative to
1179 the section-start symbol.
1181 This step needs to be done for all of the sections of the bfd. */
1184 struct bfd_section *isec;
1186 for (isec = abfd->sections; isec; isec = isec->next)
1189 bfd_vma shrinked_insn_address;
1191 if (isec->reloc_count == 0)
1194 shrinked_insn_address = (sec->output_section->vma
1195 + sec->output_offset + addr);
1197 irel = elf_section_data (isec)->relocs;
1198 /* PR 12161: Read in the relocs for this section if necessary. */
1200 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
1202 for (irelend = irel + isec->reloc_count;
1206 /* Read this BFD's local symbols if we haven't done
1208 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1210 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1211 if (isymbuf == NULL)
1212 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1213 symtab_hdr->sh_info, 0,
1215 if (isymbuf == NULL)
1219 /* Get the value of the symbol referred to by the reloc. */
1220 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1222 /* A local symbol. */
1225 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1226 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1227 symval = isym->st_value;
1228 /* If the reloc is absolute, it will not have
1229 a symbol or section associated with it. */
1232 symval += sym_sec->output_section->vma
1233 + sym_sec->output_offset;
1236 printf ("Checking if the relocation's "
1237 "addend needs corrections.\n"
1238 "Address of anchor symbol: 0x%x \n"
1239 "Address of relocation target: 0x%x \n"
1240 "Address of relaxed insn: 0x%x \n",
1241 (unsigned int) symval,
1242 (unsigned int) (symval + irel->r_addend),
1243 (unsigned int) shrinked_insn_address);
1245 /* Shrink the special DIFF relocations. */
1246 if (elf32_pru_is_diff_reloc (irel))
1248 elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1250 shrinked_insn_address,
1254 /* Fix the addend, if it is affected. */
1255 if (symval <= shrinked_insn_address
1256 && (symval + irel->r_addend) > shrinked_insn_address)
1259 irel->r_addend -= count;
1262 printf ("Relocation's addend needed to be fixed \n");
1265 /* else...Reference symbol is absolute.
1266 No adjustment needed. */
1268 /* else...Reference symbol is extern. No need for adjusting
1274 /* Adjust the local symbols defined in this section. */
1275 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1276 /* Fix PR 9841, there may be no local symbols. */
1279 Elf_Internal_Sym *isymend;
1281 isymend = isym + symtab_hdr->sh_info;
1282 for (; isym < isymend; isym++)
1284 if (isym->st_shndx == sec_shndx)
1286 if (isym->st_value > addr
1287 && isym->st_value <= toaddr)
1288 isym->st_value -= count;
1290 if (isym->st_value <= addr
1291 && isym->st_value + isym->st_size > addr)
1293 /* If this assert fires then we have a symbol that ends
1294 part way through an instruction. Does that make
1296 BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1297 isym->st_size -= count;
1303 /* Now adjust the global symbols defined in this section. */
1304 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1305 - symtab_hdr->sh_info);
1306 sym_hashes = elf_sym_hashes (abfd);
1307 end_hashes = sym_hashes + symcount;
1308 for (; sym_hashes < end_hashes; sym_hashes++)
1310 struct elf_link_hash_entry *sym_hash = *sym_hashes;
1311 if ((sym_hash->root.type == bfd_link_hash_defined
1312 || sym_hash->root.type == bfd_link_hash_defweak)
1313 && sym_hash->root.u.def.section == sec)
1315 if (sym_hash->root.u.def.value > addr
1316 && sym_hash->root.u.def.value <= toaddr)
1317 sym_hash->root.u.def.value -= count;
1319 if (sym_hash->root.u.def.value <= addr
1320 && (sym_hash->root.u.def.value + sym_hash->size > addr))
1322 /* If this assert fires then we have a symbol that ends
1323 part way through an instruction. Does that make
1325 BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1327 sym_hash->size -= count;
1336 pru_elf32_relax_section (bfd * abfd, asection * sec,
1337 struct bfd_link_info * link_info,
1338 bfd_boolean * again)
1340 Elf_Internal_Shdr * symtab_hdr;
1341 Elf_Internal_Rela * internal_relocs;
1342 Elf_Internal_Rela * irel;
1343 Elf_Internal_Rela * irelend;
1344 bfd_byte * contents = NULL;
1345 Elf_Internal_Sym * isymbuf = NULL;
1347 /* Assume nothing changes. */
1350 /* We don't have to do anything for a relocatable link, if
1351 this section does not have relocs, or if this is not a
1353 if (bfd_link_relocatable (link_info)
1354 || (sec->flags & SEC_RELOC) == 0
1355 || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1358 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1360 /* Get a copy of the native relocations. */
1361 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1362 link_info->keep_memory);
1363 if (internal_relocs == NULL)
1366 /* Walk through them looking for relaxing opportunities. */
1367 irelend = internal_relocs + sec->reloc_count;
1369 for (irel = internal_relocs; irel < irelend; irel++)
1373 /* Get the section contents if we haven't done so already. */
1374 if (contents == NULL)
1376 /* Get cached copy if it exists. */
1377 if (elf_section_data (sec)->this_hdr.contents != NULL)
1378 contents = elf_section_data (sec)->this_hdr.contents;
1379 else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1383 /* Read this BFD's local symbols if we haven't done so already. */
1384 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1386 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1387 if (isymbuf == NULL)
1388 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1389 symtab_hdr->sh_info, 0,
1391 if (isymbuf == NULL)
1395 /* Get the value of the symbol referred to by the reloc. */
1396 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1398 /* A local symbol. */
1399 Elf_Internal_Sym *isym;
1402 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1403 if (isym->st_shndx == SHN_UNDEF)
1404 sym_sec = bfd_und_section_ptr;
1405 else if (isym->st_shndx == SHN_ABS)
1406 sym_sec = bfd_abs_section_ptr;
1407 else if (isym->st_shndx == SHN_COMMON)
1408 sym_sec = bfd_com_section_ptr;
1410 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1411 symval = (isym->st_value
1412 + sym_sec->output_section->vma + sym_sec->output_offset);
1417 struct elf_link_hash_entry *h;
1419 /* An external symbol. */
1420 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1421 h = elf_sym_hashes (abfd)[indx];
1422 BFD_ASSERT (h != NULL);
1424 if (h->root.type != bfd_link_hash_defined
1425 && h->root.type != bfd_link_hash_defweak)
1426 /* This appears to be a reference to an undefined
1427 symbol. Just ignore it--it will be caught by the
1428 regular reloc processing. */
1431 symval = (h->root.u.def.value
1432 + h->root.u.def.section->output_section->vma
1433 + h->root.u.def.section->output_offset);
1436 /* For simplicity of coding, we are going to modify the section
1437 contents, the section relocs, and the BFD symbol table. We
1438 must tell the rest of the code not to free up this
1439 information. It would be possible to instead create a table
1440 of changes which have to be made, as is done in coff-mips.c;
1441 that would be more work, but would require less memory when
1442 the linker is run. */
1444 /* Check if we can remove an LDI instruction from the LDI32
1445 pseudo instruction if the upper 16 operand bits are zero. */
1446 if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1448 bfd_vma value = symval + irel->r_addend;
1451 printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1453 if ((long) value >> 16 == 0)
1457 /* Note that we've changed the relocs, section contents. */
1458 elf_section_data (sec)->relocs = internal_relocs;
1459 elf_section_data (sec)->this_hdr.contents = contents;
1460 symtab_hdr->contents = (unsigned char *) isymbuf;
1462 /* Make the second instruction load the 16-bit constant
1463 into the full 32-bit register. */
1464 insn = bfd_get_32 (abfd, contents + irel->r_offset + 4);
1466 /* Old GAS and LD versions have a bug, where the two
1467 LDI instructions are swapped. Detect such object
1469 if (GET_INSN_FIELD (RDSEL, insn) != RSEL_15_0)
1471 /* xgettext:c-format */
1472 _bfd_error_handler (_("error: %pB: old incompatible object file detected"),
1477 SET_INSN_FIELD (RDSEL, insn, RSEL_31_0);
1478 bfd_put_32 (abfd, insn, contents + irel->r_offset + 4);
1480 /* Delete the first LDI instruction. Note that there should
1481 be no relocations or symbols pointing to the second LDI
1483 if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 4))
1486 /* We're done with deletion of the first instruction.
1487 Set a regular LDI relocation for the second instruction
1488 we left to load the 16-bit value into the 32-bit
1490 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1493 /* That will change things, so, we should relax again.
1494 Note that this is not required, and it may be slow. */
1500 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1502 if (!link_info->keep_memory)
1506 /* Cache the symbols for elf_link_input_bfd. */
1507 symtab_hdr->contents = (unsigned char *) isymbuf;
1511 if (contents != NULL
1512 && elf_section_data (sec)->this_hdr.contents != contents)
1514 if (!link_info->keep_memory)
1518 /* Cache the section contents for elf_link_input_bfd. */
1519 elf_section_data (sec)->this_hdr.contents = contents;
1523 if (internal_relocs != NULL
1524 && elf_section_data (sec)->relocs != internal_relocs)
1525 free (internal_relocs);
1530 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1532 if (contents != NULL
1533 && elf_section_data (sec)->this_hdr.contents != contents)
1535 if (internal_relocs != NULL
1536 && elf_section_data (sec)->relocs != internal_relocs)
1537 free (internal_relocs);
1542 /* Free the derived linker hash table. */
1544 pru_elf32_link_hash_table_free (bfd *obfd)
1546 _bfd_elf_link_hash_table_free (obfd);
1549 /* Implement bfd_elf32_bfd_link_hash_table_create. */
1550 static struct bfd_link_hash_table *
1551 pru_elf32_link_hash_table_create (bfd *abfd)
1553 struct elf_link_hash_table *ret;
1554 bfd_size_type amt = sizeof (struct elf_link_hash_table);
1556 ret = bfd_zmalloc (amt);
1560 if (!_bfd_elf_link_hash_table_init (ret, abfd,
1563 elf_link_hash_entry),
1570 ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1575 #define ELF_ARCH bfd_arch_pru
1576 #define ELF_TARGET_ID PRU_ELF_DATA
1577 #define ELF_MACHINE_CODE EM_TI_PRU
1579 #define ELF_MAXPAGESIZE 1
1581 #define bfd_elf32_bfd_link_hash_table_create \
1582 pru_elf32_link_hash_table_create
1584 /* Relocation table lookup macros. */
1586 #define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup
1587 #define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup
1589 #define elf_info_to_howto pru_elf32_info_to_howto
1590 #define elf_info_to_howto_rel NULL
1592 /* elf backend functions. */
1594 /* TI folks like to use a mix of REL and RELA relocations. See also
1595 the MSP430 and TI C6X backends. */
1596 #define elf_backend_may_use_rel_p 1
1597 #define elf_backend_may_use_rela_p 1
1598 #define elf_backend_default_use_rela_p 1
1600 #define elf_backend_rela_normal 1
1602 #define elf_backend_relocate_section pru_elf32_relocate_section
1603 #define bfd_elf32_bfd_relax_section pru_elf32_relax_section
1605 #define TARGET_LITTLE_SYM pru_elf32_vec
1606 #define TARGET_LITTLE_NAME "elf32-pru"
1608 #include "elf32-target.h"