1 /* 32-bit ELF support for TI PRU.
2 Copyright (C) 2014-2017 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"
34 #define SWAP_VALS(A,B) \
41 /* Enable debugging printout at stdout with this variable. */
42 static bfd_boolean debug_relax = FALSE;
44 /* Forward declarations. */
45 static bfd_reloc_status_type pru_elf32_pmem_relocate
46 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
47 static bfd_reloc_status_type pru_elf32_s10_pcrel_relocate
48 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
49 static bfd_reloc_status_type pru_elf32_u8_pcrel_relocate
50 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
51 static bfd_reloc_status_type pru_elf32_ldi32_relocate
52 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
53 static bfd_reloc_status_type bfd_elf_pru_diff_relocate
54 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
57 extern const bfd_target pru_elf32_vec;
59 /* The relocation table used for SHT_REL sections. */
60 static reloc_howto_type elf_pru_howto_table_rel[] = {
62 HOWTO (R_PRU_NONE, /* type */
64 0, /* size (0 = byte, 1 = short, 2 = long) */
66 FALSE, /* pc_relative */
68 complain_overflow_dont,/* complain_on_overflow */
69 bfd_elf_generic_reloc, /* special_function */
70 "R_PRU_NONE", /* name */
71 FALSE, /* partial_inplace */
74 FALSE), /* pcrel_offset */
82 complain_overflow_dont,
83 bfd_elf_generic_reloc,
90 HOWTO (R_PRU_U16_PMEMIMM,
96 complain_overflow_unsigned,
97 pru_elf32_pmem_relocate,
104 HOWTO (R_PRU_BFD_RELOC_16,
110 complain_overflow_bitfield,
111 bfd_elf_generic_reloc,
118 /* 16-bit unsigned immediate relocation. */
119 HOWTO (R_PRU_U16, /* type */
121 2, /* size (0 = byte, 1 = short, 2 = long) */
123 FALSE, /* pc_relative */
125 complain_overflow_unsigned, /* complain on overflow */
126 bfd_elf_generic_reloc, /* special function */
127 "R_PRU_U16", /* name */
128 FALSE, /* partial_inplace */
130 0x00ffff00, /* dest_mask */
131 FALSE), /* pcrel_offset */
133 HOWTO (R_PRU_32_PMEM,
139 complain_overflow_dont,
140 pru_elf32_pmem_relocate,
147 HOWTO (R_PRU_BFD_RELOC_32,
153 complain_overflow_dont,
154 bfd_elf_generic_reloc,
161 HOWTO (R_PRU_S10_PCREL,
167 complain_overflow_bitfield,
168 pru_elf32_s10_pcrel_relocate,
175 HOWTO (R_PRU_U8_PCREL,
181 complain_overflow_unsigned,
182 pru_elf32_u8_pcrel_relocate,
191 4, /* size (4 = 8bytes) */
193 FALSE, /* pc_relative */
195 complain_overflow_unsigned, /* complain on overflow */
196 pru_elf32_ldi32_relocate, /* special function */
197 "R_PRU_LDI32", /* name */
198 FALSE, /* partial_inplace */
200 0xffffffff, /* dest_mask */
201 FALSE), /* pcrel_offset */
203 /* GNU-specific relocations. */
204 HOWTO (R_PRU_GNU_BFD_RELOC_8,
210 complain_overflow_bitfield,
211 bfd_elf_generic_reloc,
218 HOWTO (R_PRU_GNU_DIFF8, /* type */
220 0, /* size (0 = byte, 1 = short, 2 = long) */
222 FALSE, /* pc_relative */
224 complain_overflow_bitfield, /* complain_on_overflow */
225 bfd_elf_pru_diff_relocate, /* special_function */
226 "R_PRU_DIFF8", /* name */
227 FALSE, /* partial_inplace */
230 FALSE), /* pcrel_offset */
232 HOWTO (R_PRU_GNU_DIFF16, /* type */
234 1, /* size (0 = byte, 1 = short, 2 = long) */
236 FALSE, /* pc_relative */
238 complain_overflow_bitfield, /* complain_on_overflow */
239 bfd_elf_pru_diff_relocate,/* special_function */
240 "R_PRU_DIFF16", /* name */
241 FALSE, /* partial_inplace */
243 0xffff, /* dst_mask */
244 FALSE), /* pcrel_offset */
246 HOWTO (R_PRU_GNU_DIFF32, /* type */
248 2, /* size (0 = byte, 1 = short, 2 = long) */
250 FALSE, /* pc_relative */
252 complain_overflow_bitfield, /* complain_on_overflow */
253 bfd_elf_pru_diff_relocate,/* special_function */
254 "R_PRU_DIFF32", /* name */
255 FALSE, /* partial_inplace */
257 0xffffffff, /* dst_mask */
258 FALSE), /* pcrel_offset */
260 HOWTO (R_PRU_GNU_DIFF16_PMEM, /* type */
262 1, /* size (0 = byte, 1 = short, 2 = long) */
264 FALSE, /* pc_relative */
266 complain_overflow_bitfield, /* complain_on_overflow */
267 bfd_elf_pru_diff_relocate,/* special_function */
268 "R_PRU_DIFF16_PMEM", /* name */
269 FALSE, /* partial_inplace */
271 0xffff, /* dst_mask */
272 FALSE), /* pcrel_offset */
274 HOWTO (R_PRU_GNU_DIFF32_PMEM, /* type */
276 2, /* size (0 = byte, 1 = short, 2 = long) */
278 FALSE, /* pc_relative */
280 complain_overflow_bitfield, /* complain_on_overflow */
281 bfd_elf_pru_diff_relocate,/* special_function */
282 "R_PRU_DIFF32_PMEM", /* name */
283 FALSE, /* partial_inplace */
285 0xffffffff, /* dst_mask */
286 FALSE), /* pcrel_offset */
288 /* Add other relocations here. */
291 static unsigned char elf_code_to_howto_index[R_PRU_ILLEGAL + 1];
293 /* Return the howto for relocation RTYPE. */
294 static reloc_howto_type *
295 lookup_howto (unsigned int rtype)
297 static int initialized = 0;
299 int howto_tbl_size = (int) (sizeof (elf_pru_howto_table_rel)
300 / sizeof (elf_pru_howto_table_rel[0]));
305 memset (elf_code_to_howto_index, 0xff,
306 sizeof (elf_code_to_howto_index));
307 for (i = 0; i < howto_tbl_size; i++)
308 elf_code_to_howto_index[elf_pru_howto_table_rel[i].type] = i;
311 BFD_ASSERT (rtype <= R_PRU_ILLEGAL);
312 i = elf_code_to_howto_index[rtype];
313 if (i >= howto_tbl_size)
315 return elf_pru_howto_table_rel + i;
318 /* Map for converting BFD reloc types to PRU reloc types. */
321 bfd_reloc_code_real_type bfd_val;
322 enum elf_pru_reloc_type elf_val;
325 static const struct elf_reloc_map pru_reloc_map[] = {
326 {BFD_RELOC_NONE, R_PRU_NONE},
327 {BFD_RELOC_PRU_16_PMEM, R_PRU_16_PMEM},
328 {BFD_RELOC_PRU_U16_PMEMIMM, R_PRU_U16_PMEMIMM},
329 {BFD_RELOC_16, R_PRU_BFD_RELOC_16},
330 {BFD_RELOC_PRU_U16, R_PRU_U16},
331 {BFD_RELOC_PRU_32_PMEM, R_PRU_32_PMEM},
332 {BFD_RELOC_32, R_PRU_BFD_RELOC_32},
333 {BFD_RELOC_PRU_S10_PCREL, R_PRU_S10_PCREL},
334 {BFD_RELOC_PRU_U8_PCREL, R_PRU_U8_PCREL},
335 {BFD_RELOC_PRU_LDI32, R_PRU_LDI32},
337 {BFD_RELOC_8, R_PRU_GNU_BFD_RELOC_8},
338 {BFD_RELOC_PRU_GNU_DIFF8, R_PRU_GNU_DIFF8},
339 {BFD_RELOC_PRU_GNU_DIFF16, R_PRU_GNU_DIFF16},
340 {BFD_RELOC_PRU_GNU_DIFF32, R_PRU_GNU_DIFF32},
341 {BFD_RELOC_PRU_GNU_DIFF16_PMEM, R_PRU_GNU_DIFF16_PMEM},
342 {BFD_RELOC_PRU_GNU_DIFF32_PMEM, R_PRU_GNU_DIFF32_PMEM},
346 /* Assorted hash table functions. */
348 /* Create an entry in a PRU ELF linker hash table. */
349 static struct bfd_hash_entry *
350 link_hash_newfunc (struct bfd_hash_entry *entry,
351 struct bfd_hash_table *table, const char *string)
353 /* Allocate the structure if it has not already been allocated by a
357 entry = bfd_hash_allocate (table,
358 sizeof (struct elf_link_hash_entry));
363 /* Call the allocation method of the superclass. */
364 entry = _bfd_elf_link_hash_newfunc (entry, table, string);
369 /* Implement bfd_elf32_bfd_reloc_type_lookup:
370 Given a BFD reloc type, return a howto structure. */
371 static reloc_howto_type *
372 pru_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
373 bfd_reloc_code_real_type code)
377 i < (int) (sizeof (pru_reloc_map) / sizeof (struct elf_reloc_map));
379 if (pru_reloc_map[i].bfd_val == code)
380 return lookup_howto ((unsigned int) pru_reloc_map[i].elf_val);
384 /* Implement bfd_elf32_bfd_reloc_name_lookup:
385 Given a reloc name, return a howto structure. */
386 static reloc_howto_type *
387 pru_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
392 i < (sizeof (elf_pru_howto_table_rel)
393 / sizeof (elf_pru_howto_table_rel[0]));
395 if (elf_pru_howto_table_rel[i].name
396 && strcasecmp (elf_pru_howto_table_rel[i].name, r_name) == 0)
397 return &elf_pru_howto_table_rel[i];
402 /* Implement elf_info_to_howto:
403 Given a ELF32 relocation, fill in a arelent structure. */
405 pru_elf32_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
406 Elf_Internal_Rela *dst)
410 r_type = ELF32_R_TYPE (dst->r_info);
411 BFD_ASSERT (r_type < R_PRU_ILLEGAL);
412 cache_ptr->howto = lookup_howto (r_type);
415 /* Do the relocations that require special handling. */
416 /* Produce a word address for program memory. Linker scripts will put .text
417 at a high offset in order to differentiate it from .data. So here we also
418 mask the high bits of PMEM address.
420 But why 1MB when internal Program Memory much smaller? We want to catch
421 unintended overflows.
423 Why not use (1<<31) as an offset and a mask? Sitara DDRAM usually resides
424 there, and users might want to put some shared carveout memory region in
425 their linker scripts. So 0x80000000 might be a valid .data address.
427 Note that we still keep and pass down the original howto. This way we
428 can reuse this function for several different relocations. */
429 static bfd_reloc_status_type
430 pru_elf32_do_pmem_relocate (bfd *abfd, reloc_howto_type *howto,
431 asection *input_section,
432 bfd_byte *data, bfd_vma offset,
433 bfd_vma symbol_value, bfd_vma addend)
435 symbol_value = symbol_value + addend;
437 symbol_value &= 0x3fffff;
438 return _bfd_final_link_relocate (howto, abfd, input_section,
439 data, offset, symbol_value, addend);
442 /* Direct copy of _bfd_final_link_relocate, but with special
443 "fill-in". This copy-paste mumbo jumbo is only needed because BFD
444 cannot deal correctly with non-contiguous bit fields. */
445 static bfd_reloc_status_type
446 pru_elf32_do_s10_pcrel_relocate (bfd *input_bfd, reloc_howto_type *howto,
447 asection *input_section,
448 bfd_byte *contents, bfd_vma address,
449 bfd_vma relocation, bfd_vma addend)
454 bfd_reloc_status_type flag = bfd_reloc_ok;
456 /* Sanity check the address. */
457 if (address > bfd_get_section_limit (input_bfd, input_section))
458 return bfd_reloc_outofrange;
460 BFD_ASSERT (howto->pc_relative);
461 BFD_ASSERT (howto->pcrel_offset);
463 relocation = relocation + addend - (input_section->output_section->vma
464 + input_section->output_offset) - address;
466 location = contents + address;
468 /* Get the value we are going to relocate. */
469 BFD_ASSERT (bfd_get_reloc_size (howto) == 4);
470 x = bfd_get_32 (input_bfd, location);
472 qboff = GET_BROFF_SIGNED (x) << howto->rightshift;
475 BFD_ASSERT (howto->complain_on_overflow == complain_overflow_bitfield);
477 if (relocation > 2047 && relocation < (bfd_vma)-2048l)
478 flag = bfd_reloc_overflow;
480 /* Check that target address is word-aligned. */
481 if (relocation & ((1 << howto->rightshift) - 1))
482 flag = bfd_reloc_outofrange;
484 relocation >>= (bfd_vma) howto->rightshift;
486 /* Fill-in the RELOCATION to the right bits of X. */
487 SET_BROFF_URAW (x, relocation);
489 bfd_put_32 (input_bfd, x, location);
494 static bfd_reloc_status_type
495 pru_elf32_do_u8_pcrel_relocate (bfd *abfd, reloc_howto_type *howto,
496 asection *input_section,
497 bfd_byte *data, bfd_vma offset,
498 bfd_vma symbol_value, bfd_vma addend)
502 BFD_ASSERT (howto->pc_relative);
503 BFD_ASSERT (howto->pcrel_offset);
505 relocation = symbol_value + addend - (input_section->output_section->vma
506 + input_section->output_offset) - offset;
507 relocation >>= howto->rightshift;
509 /* 0 and 1 are invalid target labels for LOOP. We cannot
510 encode this info in HOWTO, so catch such cases here. */
512 return bfd_reloc_outofrange;
514 return _bfd_final_link_relocate (howto, abfd, input_section,
515 data, offset, symbol_value, addend);
518 /* Idea and code taken from elf32-d30v. */
519 static bfd_reloc_status_type
520 pru_elf32_do_ldi32_relocate (bfd *abfd, reloc_howto_type *howto,
521 asection *input_section,
522 bfd_byte *data, bfd_vma offset,
523 bfd_vma symbol_value, bfd_vma addend)
525 bfd_signed_vma relocation;
526 bfd_size_type octets = offset * bfd_octets_per_byte (abfd);
528 unsigned long in1, in2, num;
530 /* A hacked-up version of _bfd_final_link_relocate() follows. */
532 /* Sanity check the address. */
533 if (octets + bfd_get_reloc_size (howto)
534 > bfd_get_section_limit_octets (abfd, input_section))
535 return bfd_reloc_outofrange;
537 /* This function assumes that we are dealing with a basic relocation
538 against a symbol. We want to compute the value of the symbol to
539 relocate to. This is just VALUE, the value of the symbol, plus
540 ADDEND, any addend associated with the reloc. */
541 relocation = symbol_value + addend;
543 BFD_ASSERT (!howto->pc_relative);
545 /* A hacked-up version of _bfd_relocate_contents() follows. */
546 location = data + offset * bfd_octets_per_byte (abfd);
548 BFD_ASSERT (!howto->pc_relative);
550 in1 = bfd_get_32 (abfd, location);
551 in2 = bfd_get_32 (abfd, location + 4);
553 /* Extract the addend - should be zero per my understanding. */
554 num = GET_INSN_FIELD (IMM16, in1) | (GET_INSN_FIELD (IMM16, in2) << 16);
559 SET_INSN_FIELD (IMM16, in1, relocation & 0xffff);
560 SET_INSN_FIELD (IMM16, in2, relocation >> 16);
562 bfd_put_32 (abfd, in1, location);
563 bfd_put_32 (abfd, in2, location + 4);
568 /* HOWTO handlers for relocations that require special handling. */
570 static bfd_reloc_status_type
571 pru_elf32_pmem_relocate (bfd *abfd, arelent *reloc_entry,
572 asymbol *symbol, void *data,
573 asection *input_section, bfd *output_bfd,
574 char **error_message)
576 /* If this is a relocatable link (output_bfd test tells us), just
577 call the generic function. Any adjustment will be done at final
579 if (output_bfd != NULL)
580 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
581 input_section, output_bfd, error_message);
583 return pru_elf32_do_pmem_relocate (abfd, reloc_entry->howto,
585 data, reloc_entry->address,
587 + symbol->section->output_section->vma
588 + symbol->section->output_offset),
589 reloc_entry->addend);
592 static bfd_reloc_status_type
593 pru_elf32_s10_pcrel_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
601 if (output_bfd != NULL)
602 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
603 input_section, output_bfd, error_message);
605 return pru_elf32_do_s10_pcrel_relocate (abfd, reloc_entry->howto,
607 reloc_entry->address,
609 + symbol->section->output_section->vma
610 + symbol->section->output_offset),
611 reloc_entry->addend);
614 static bfd_reloc_status_type
615 pru_elf32_u8_pcrel_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
616 void *data, asection *input_section,
618 char **error_message)
620 /* If this is a relocatable link (output_bfd test tells us), just
621 call the generic function. Any adjustment will be done at final
623 if (output_bfd != NULL)
624 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
625 input_section, output_bfd, error_message);
627 return pru_elf32_do_u8_pcrel_relocate (abfd, reloc_entry->howto,
629 data, reloc_entry->address,
631 + symbol->section->output_section->vma
632 + symbol->section->output_offset),
633 reloc_entry->addend);
636 static bfd_reloc_status_type
637 pru_elf32_ldi32_relocate (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
638 void *data, asection *input_section,
640 char **error_message)
642 /* If this is a relocatable link (output_bfd test tells us), just
643 call the generic function. Any adjustment will be done at final
645 if (output_bfd != NULL)
646 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
647 input_section, output_bfd, error_message);
649 return pru_elf32_do_ldi32_relocate (abfd, reloc_entry->howto,
651 data, reloc_entry->address,
653 + symbol->section->output_section->vma
654 + symbol->section->output_offset),
655 reloc_entry->addend);
659 /* Implement elf_backend_relocate_section. */
661 pru_elf32_relocate_section (bfd *output_bfd,
662 struct bfd_link_info *info,
664 asection *input_section,
666 Elf_Internal_Rela *relocs,
667 Elf_Internal_Sym *local_syms,
668 asection **local_sections)
670 Elf_Internal_Shdr *symtab_hdr;
671 struct elf_link_hash_entry **sym_hashes;
672 Elf_Internal_Rela *rel;
673 Elf_Internal_Rela *relend;
675 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
676 sym_hashes = elf_sym_hashes (input_bfd);
677 relend = relocs + input_section->reloc_count;
679 for (rel = relocs; rel < relend; rel++)
681 reloc_howto_type *howto;
682 unsigned long r_symndx;
683 Elf_Internal_Sym *sym;
685 struct elf_link_hash_entry *h;
687 bfd_reloc_status_type r = bfd_reloc_ok;
688 const char *name = NULL;
689 const char* msg = (const char*) NULL;
690 bfd_boolean unresolved_reloc;
692 r_symndx = ELF32_R_SYM (rel->r_info);
694 howto = lookup_howto ((unsigned) ELF32_R_TYPE (rel->r_info));
699 if (r_symndx < symtab_hdr->sh_info)
701 sym = local_syms + r_symndx;
702 sec = local_sections[r_symndx];
703 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
707 bfd_boolean warned, ignored;
709 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
710 r_symndx, symtab_hdr, sym_hashes,
712 unresolved_reloc, warned, ignored);
715 if (sec && discarded_section (sec))
716 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
717 rel, 1, relend, howto, 0, contents);
719 /* Nothing more to do unless this is a final link. */
720 if (bfd_link_relocatable (info))
728 /* We don't need to find a value for this symbol. It's just a
733 case R_PRU_U16_PMEMIMM:
736 r = pru_elf32_do_pmem_relocate (input_bfd, howto,
738 contents, rel->r_offset,
739 relocation, rel->r_addend);
741 case R_PRU_S10_PCREL:
742 r = pru_elf32_do_s10_pcrel_relocate (input_bfd, howto,
750 r = pru_elf32_do_u8_pcrel_relocate (input_bfd, howto,
758 r = pru_elf32_do_ldi32_relocate (input_bfd, howto,
765 case R_PRU_GNU_DIFF8:
766 case R_PRU_GNU_DIFF16:
767 case R_PRU_GNU_DIFF32:
768 case R_PRU_GNU_DIFF16_PMEM:
769 case R_PRU_GNU_DIFF32_PMEM:
770 /* Nothing to do here, as contents already contain the
776 r = _bfd_final_link_relocate (howto, input_bfd,
777 input_section, contents,
778 rel->r_offset, relocation,
784 r = bfd_reloc_notsupported;
786 if (r != bfd_reloc_ok)
789 name = h->root.root.string;
792 name = bfd_elf_string_from_elf_section (input_bfd,
795 if (name == NULL || *name == '\0')
796 name = bfd_section_name (input_bfd, sec);
801 case bfd_reloc_overflow:
802 (*info->callbacks->reloc_overflow) (info, NULL, name,
803 howto->name, (bfd_vma) 0,
804 input_bfd, input_section,
808 case bfd_reloc_undefined:
809 (*info->callbacks->undefined_symbol) (info, name, input_bfd,
811 rel->r_offset, TRUE);
814 case bfd_reloc_outofrange:
816 msg = _("relocation out of range");
819 case bfd_reloc_notsupported:
821 msg = _("unsupported relocation");
824 case bfd_reloc_dangerous:
826 msg = _("dangerous relocation");
831 msg = _("unknown error");
837 (*info->callbacks->warning) (info, msg, name, input_bfd,
838 input_section, rel->r_offset);
847 /* Perform a diff relocation. Nothing to do, as the difference value is
848 already written into the section's contents. */
850 static bfd_reloc_status_type
851 bfd_elf_pru_diff_relocate (bfd *abfd ATTRIBUTE_UNUSED,
852 arelent *reloc_entry ATTRIBUTE_UNUSED,
853 asymbol *symbol ATTRIBUTE_UNUSED,
854 void *data ATTRIBUTE_UNUSED,
855 asection *input_section ATTRIBUTE_UNUSED,
856 bfd *output_bfd ATTRIBUTE_UNUSED,
857 char **error_message ATTRIBUTE_UNUSED)
863 /* Returns whether the relocation type passed is a diff reloc. */
866 elf32_pru_is_diff_reloc (Elf_Internal_Rela *irel)
868 return (ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF8
869 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16
870 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32
871 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF16_PMEM
872 || ELF32_R_TYPE (irel->r_info) == R_PRU_GNU_DIFF32_PMEM);
875 /* Reduce the diff value written in the section by count if the shrinked
876 insn address happens to fall between the two symbols for which this
877 diff reloc was emitted. */
880 elf32_pru_adjust_diff_reloc_value (bfd *abfd,
881 struct bfd_section *isec,
882 Elf_Internal_Rela *irel,
884 bfd_vma shrinked_insn_address,
887 unsigned char *reloc_contents = NULL;
888 unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
889 if (isec_contents == NULL)
891 if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
894 elf_section_data (isec)->this_hdr.contents = isec_contents;
897 reloc_contents = isec_contents + irel->r_offset;
899 /* Read value written in object file. */
900 bfd_signed_vma x = 0;
901 switch (ELF32_R_TYPE (irel->r_info))
903 case R_PRU_GNU_DIFF8:
905 x = bfd_get_signed_8 (abfd, reloc_contents);
908 case R_PRU_GNU_DIFF16:
910 x = bfd_get_signed_16 (abfd, reloc_contents);
913 case R_PRU_GNU_DIFF32:
915 x = bfd_get_signed_32 (abfd, reloc_contents);
918 case R_PRU_GNU_DIFF16_PMEM:
920 x = bfd_get_signed_16 (abfd, reloc_contents) * 4;
923 case R_PRU_GNU_DIFF32_PMEM:
925 x = bfd_get_signed_32 (abfd, reloc_contents) * 4;
934 /* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
935 into the object file at the reloc offset. sym2's logical value is
936 symval (<start_of_section>) + reloc addend. Compute the start and end
937 addresses and check if the shrinked insn falls between sym1 and sym2. */
939 bfd_vma end_address = symval + irel->r_addend;
940 bfd_vma start_address = end_address - x;
942 /* Shrink the absolute DIFF value (get the to labels "closer"
943 together), because we have removed data between labels. */
947 /* In case the signed x is negative, restore order. */
948 SWAP_VALS (end_address, start_address);
955 /* Reduce the diff value by count bytes and write it back into section
958 if (shrinked_insn_address >= start_address
959 && shrinked_insn_address <= end_address)
961 switch (ELF32_R_TYPE (irel->r_info))
963 case R_PRU_GNU_DIFF8:
965 bfd_put_signed_8 (abfd, x & 0xFF, reloc_contents);
968 case R_PRU_GNU_DIFF16:
970 bfd_put_signed_16 (abfd, x & 0xFFFF, reloc_contents);
973 case R_PRU_GNU_DIFF32:
975 bfd_put_signed_32 (abfd, x & 0xFFFFFFFF, reloc_contents);
978 case R_PRU_GNU_DIFF16_PMEM:
980 bfd_put_signed_16 (abfd, (x / 4) & 0xFFFF, reloc_contents);
983 case R_PRU_GNU_DIFF32_PMEM:
985 bfd_put_signed_32 (abfd, (x / 4) & 0xFFFFFFFF, reloc_contents);
997 /* Delete some bytes from a section while changing the size of an instruction.
998 The parameter "addr" denotes the section-relative offset pointing just
999 behind the shrinked instruction. "addr+count" point at the first
1000 byte just behind the original unshrinked instruction.
1002 Idea copied from the AVR port. */
1005 pru_elf_relax_delete_bytes (bfd *abfd,
1010 Elf_Internal_Shdr *symtab_hdr;
1011 unsigned int sec_shndx;
1013 Elf_Internal_Rela *irel, *irelend;
1014 Elf_Internal_Sym *isym;
1015 Elf_Internal_Sym *isymbuf = NULL;
1017 struct elf_link_hash_entry **sym_hashes;
1018 struct elf_link_hash_entry **end_hashes;
1019 unsigned int symcount;
1021 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
1022 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
1023 contents = elf_section_data (sec)->this_hdr.contents;
1027 irel = elf_section_data (sec)->relocs;
1028 irelend = irel + sec->reloc_count;
1030 /* Actually delete the bytes. */
1031 if (toaddr - addr - count > 0)
1032 memmove (contents + addr, contents + addr + count,
1033 (size_t) (toaddr - addr - count));
1036 /* Adjust all the reloc addresses. */
1037 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
1039 bfd_vma old_reloc_address;
1041 old_reloc_address = (sec->output_section->vma
1042 + sec->output_offset + irel->r_offset);
1044 /* Get the new reloc address. */
1045 if ((irel->r_offset > addr
1046 && irel->r_offset < toaddr))
1049 printf ("Relocation at address 0x%x needs to be moved.\n"
1050 "Old section offset: 0x%x, New section offset: 0x%x \n",
1051 (unsigned int) old_reloc_address,
1052 (unsigned int) irel->r_offset,
1053 (unsigned int) ((irel->r_offset) - count));
1055 irel->r_offset -= count;
1060 /* The reloc's own addresses are now ok. However, we need to readjust
1061 the reloc's addend, i.e. the reloc's value if two conditions are met:
1062 1.) the reloc is relative to a symbol in this section that
1063 is located in front of the shrinked instruction
1064 2.) symbol plus addend end up behind the shrinked instruction.
1066 The most common case where this happens are relocs relative to
1067 the section-start symbol.
1069 This step needs to be done for all of the sections of the bfd. */
1072 struct bfd_section *isec;
1074 for (isec = abfd->sections; isec; isec = isec->next)
1077 bfd_vma shrinked_insn_address;
1079 if (isec->reloc_count == 0)
1082 shrinked_insn_address = (sec->output_section->vma
1083 + sec->output_offset + addr - count);
1085 irel = elf_section_data (isec)->relocs;
1086 /* PR 12161: Read in the relocs for this section if necessary. */
1088 irel = _bfd_elf_link_read_relocs (abfd, isec, NULL, NULL, TRUE);
1090 for (irelend = irel + isec->reloc_count;
1094 /* Read this BFD's local symbols if we haven't done
1096 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1098 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1099 if (isymbuf == NULL)
1100 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1101 symtab_hdr->sh_info, 0,
1103 if (isymbuf == NULL)
1107 /* Get the value of the symbol referred to by the reloc. */
1108 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1110 /* A local symbol. */
1113 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1114 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1115 symval = isym->st_value;
1116 /* If the reloc is absolute, it will not have
1117 a symbol or section associated with it. */
1120 symval += sym_sec->output_section->vma
1121 + sym_sec->output_offset;
1124 printf ("Checking if the relocation's "
1125 "addend needs corrections.\n"
1126 "Address of anchor symbol: 0x%x \n"
1127 "Address of relocation target: 0x%x \n"
1128 "Address of relaxed insn: 0x%x \n",
1129 (unsigned int) symval,
1130 (unsigned int) (symval + irel->r_addend),
1131 (unsigned int) shrinked_insn_address);
1133 /* Shrink the special DIFF relocations. */
1134 if (elf32_pru_is_diff_reloc (irel))
1136 elf32_pru_adjust_diff_reloc_value (abfd, isec, irel,
1138 shrinked_insn_address,
1142 /* Fix the addend, if it is affected. */
1143 if (symval <= shrinked_insn_address
1144 && (symval + irel->r_addend) > shrinked_insn_address)
1147 irel->r_addend -= count;
1150 printf ("Relocation's addend needed to be fixed \n");
1153 /* else...Reference symbol is absolute.
1154 No adjustment needed. */
1156 /* else...Reference symbol is extern. No need for adjusting
1162 /* Adjust the local symbols defined in this section. */
1163 isym = (Elf_Internal_Sym *) symtab_hdr->contents;
1164 /* Fix PR 9841, there may be no local symbols. */
1167 Elf_Internal_Sym *isymend;
1169 isymend = isym + symtab_hdr->sh_info;
1170 for (; isym < isymend; isym++)
1172 if (isym->st_shndx == sec_shndx)
1174 if (isym->st_value > addr
1175 && isym->st_value <= toaddr)
1176 isym->st_value -= count;
1178 if (isym->st_value <= addr
1179 && isym->st_value + isym->st_size > addr)
1181 /* If this assert fires then we have a symbol that ends
1182 part way through an instruction. Does that make
1184 BFD_ASSERT (isym->st_value + isym->st_size >= addr + count);
1185 isym->st_size -= count;
1191 /* Now adjust the global symbols defined in this section. */
1192 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
1193 - symtab_hdr->sh_info);
1194 sym_hashes = elf_sym_hashes (abfd);
1195 end_hashes = sym_hashes + symcount;
1196 for (; sym_hashes < end_hashes; sym_hashes++)
1198 struct elf_link_hash_entry *sym_hash = *sym_hashes;
1199 if ((sym_hash->root.type == bfd_link_hash_defined
1200 || sym_hash->root.type == bfd_link_hash_defweak)
1201 && sym_hash->root.u.def.section == sec)
1203 if (sym_hash->root.u.def.value > addr
1204 && sym_hash->root.u.def.value <= toaddr)
1205 sym_hash->root.u.def.value -= count;
1207 if (sym_hash->root.u.def.value <= addr
1208 && (sym_hash->root.u.def.value + sym_hash->size > addr))
1210 /* If this assert fires then we have a symbol that ends
1211 part way through an instruction. Does that make
1213 BFD_ASSERT (sym_hash->root.u.def.value + sym_hash->size
1215 sym_hash->size -= count;
1224 pru_elf32_relax_section (bfd * abfd, asection * sec,
1225 struct bfd_link_info * link_info,
1226 bfd_boolean * again)
1228 Elf_Internal_Shdr * symtab_hdr;
1229 Elf_Internal_Rela * internal_relocs;
1230 Elf_Internal_Rela * irel;
1231 Elf_Internal_Rela * irelend;
1232 bfd_byte * contents = NULL;
1233 Elf_Internal_Sym * isymbuf = NULL;
1235 /* Assume nothing changes. */
1238 /* We don't have to do anything for a relocatable link, if
1239 this section does not have relocs, or if this is not a
1241 if (bfd_link_relocatable (link_info)
1242 || (sec->flags & SEC_RELOC) == 0
1243 || sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
1246 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
1248 /* Get a copy of the native relocations. */
1249 internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
1250 link_info->keep_memory);
1251 if (internal_relocs == NULL)
1254 /* Walk through them looking for relaxing opportunities. */
1255 irelend = internal_relocs + sec->reloc_count;
1257 for (irel = internal_relocs; irel < irelend; irel++)
1261 /* Get the section contents if we haven't done so already. */
1262 if (contents == NULL)
1264 /* Get cached copy if it exists. */
1265 if (elf_section_data (sec)->this_hdr.contents != NULL)
1266 contents = elf_section_data (sec)->this_hdr.contents;
1267 else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
1271 /* Read this BFD's local symbols if we haven't done so already. */
1272 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
1274 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
1275 if (isymbuf == NULL)
1276 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
1277 symtab_hdr->sh_info, 0,
1279 if (isymbuf == NULL)
1283 /* Get the value of the symbol referred to by the reloc. */
1284 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
1286 /* A local symbol. */
1287 Elf_Internal_Sym *isym;
1290 isym = isymbuf + ELF32_R_SYM (irel->r_info);
1291 if (isym->st_shndx == SHN_UNDEF)
1292 sym_sec = bfd_und_section_ptr;
1293 else if (isym->st_shndx == SHN_ABS)
1294 sym_sec = bfd_abs_section_ptr;
1295 else if (isym->st_shndx == SHN_COMMON)
1296 sym_sec = bfd_com_section_ptr;
1298 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
1299 symval = (isym->st_value
1300 + sym_sec->output_section->vma + sym_sec->output_offset);
1305 struct elf_link_hash_entry *h;
1307 /* An external symbol. */
1308 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
1309 h = elf_sym_hashes (abfd)[indx];
1310 BFD_ASSERT (h != NULL);
1312 if (h->root.type != bfd_link_hash_defined
1313 && h->root.type != bfd_link_hash_defweak)
1314 /* This appears to be a reference to an undefined
1315 symbol. Just ignore it--it will be caught by the
1316 regular reloc processing. */
1319 symval = (h->root.u.def.value
1320 + h->root.u.def.section->output_section->vma
1321 + h->root.u.def.section->output_offset);
1324 /* For simplicity of coding, we are going to modify the section
1325 contents, the section relocs, and the BFD symbol table. We
1326 must tell the rest of the code not to free up this
1327 information. It would be possible to instead create a table
1328 of changes which have to be made, as is done in coff-mips.c;
1329 that would be more work, but would require less memory when
1330 the linker is run. */
1332 /* Check if we can remove an LDI instruction from the LDI32
1333 pseudo instruction if the upper 16 operand bits are zero. */
1334 if (ELF32_R_TYPE (irel->r_info) == (int) R_PRU_LDI32)
1336 bfd_vma value = symval + irel->r_addend;
1339 printf ("R_PRU_LDI32 with value=0x%lx\n", (long) value);
1341 if ((long) value >> 16 == 0)
1343 /* Note that we've changed the relocs, section contents. */
1344 elf_section_data (sec)->relocs = internal_relocs;
1345 elf_section_data (sec)->this_hdr.contents = contents;
1346 symtab_hdr->contents = (unsigned char *) isymbuf;
1349 if (!pru_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 4, 4))
1352 /* We're done with deletion of the second instruction.
1353 Set a regular LDI relocation for the first instruction
1354 we left to load the 16-bit value into the 32-bit
1356 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
1359 /* That will change things, so, we should relax again.
1360 Note that this is not required, and it may be slow. */
1366 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1368 if (!link_info->keep_memory)
1372 /* Cache the symbols for elf_link_input_bfd. */
1373 symtab_hdr->contents = (unsigned char *) isymbuf;
1377 if (contents != NULL
1378 && elf_section_data (sec)->this_hdr.contents != contents)
1380 if (!link_info->keep_memory)
1384 /* Cache the section contents for elf_link_input_bfd. */
1385 elf_section_data (sec)->this_hdr.contents = contents;
1389 if (internal_relocs != NULL
1390 && elf_section_data (sec)->relocs != internal_relocs)
1391 free (internal_relocs);
1396 if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
1398 if (contents != NULL
1399 && elf_section_data (sec)->this_hdr.contents != contents)
1401 if (internal_relocs != NULL
1402 && elf_section_data (sec)->relocs != internal_relocs)
1403 free (internal_relocs);
1408 /* Free the derived linker hash table. */
1410 pru_elf32_link_hash_table_free (bfd *obfd)
1412 _bfd_elf_link_hash_table_free (obfd);
1415 /* Implement bfd_elf32_bfd_link_hash_table_create. */
1416 static struct bfd_link_hash_table *
1417 pru_elf32_link_hash_table_create (bfd *abfd)
1419 struct elf_link_hash_table *ret;
1420 bfd_size_type amt = sizeof (struct elf_link_hash_table);
1422 ret = bfd_zmalloc (amt);
1426 if (!_bfd_elf_link_hash_table_init (ret, abfd,
1429 elf_link_hash_entry),
1436 ret->root.hash_table_free = pru_elf32_link_hash_table_free;
1441 #define ELF_ARCH bfd_arch_pru
1442 #define ELF_TARGET_ID PRU_ELF_DATA
1443 #define ELF_MACHINE_CODE EM_TI_PRU
1445 #define ELF_MAXPAGESIZE 1
1447 #define bfd_elf32_bfd_link_hash_table_create \
1448 pru_elf32_link_hash_table_create
1450 /* Relocation table lookup macros. */
1452 #define bfd_elf32_bfd_reloc_type_lookup pru_elf32_bfd_reloc_type_lookup
1453 #define bfd_elf32_bfd_reloc_name_lookup pru_elf32_bfd_reloc_name_lookup
1455 /* elf_info_to_howto (using RELA relocations). */
1457 #define elf_info_to_howto pru_elf32_info_to_howto
1459 /* elf backend functions. */
1461 #define elf_backend_rela_normal 1
1463 #define elf_backend_relocate_section pru_elf32_relocate_section
1464 #define bfd_elf32_bfd_relax_section pru_elf32_relax_section
1466 #define TARGET_LITTLE_SYM pru_elf32_vec
1467 #define TARGET_LITTLE_NAME "elf32-pru"
1469 #include "elf32-target.h"