1 /* Adapteva epiphany specific support for 32-bit ELF
2 Copyright (C) 2000-2018 Free Software Foundation, Inc.
3 Contributed by Embecosm on behalf of Adapteva, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
26 #include "elf/epiphany.h"
27 #include "libiberty.h"
29 /* Struct used to pass miscellaneous paramaters which
30 helps to avoid overly long parameter lists. */
33 Elf_Internal_Shdr
* symtab_hdr
;
34 Elf_Internal_Rela
* irelbase
;
36 Elf_Internal_Sym
* isymbuf
;
39 struct epiphany_opcode
41 unsigned short opcode
;
45 static bfd_boolean epiphany_relaxed
= FALSE
;
47 /* Relocation tables. */
48 static reloc_howto_type epiphany_elf_howto_table
[] =
50 #define AHOW(t,rs,s,bs,pr,bp,co,name,sm,dm) \
52 rs, /* rightshift */ \
53 s, /* size (0 = byte, 1 = short, 2 = long) */ \
55 pr, /* pc_relative */ \
57 co, /* complain_on_overflow */ \
58 bfd_elf_generic_reloc,/* special_function */ \
60 FALSE, /* partial_inplace */ \
63 pr) /* pcrel_offset */
65 /* This reloc does nothing. */
66 AHOW (R_EPIPHANY_NONE
, 0, 3,0, FALSE
, 0, complain_overflow_dont
, "R_EPIPHANY_NONE", 0, 0),
68 /* 8 bit absolute (not likely) */
69 AHOW (R_EPIPHANY_8
, 0, 0, 8, FALSE
, 0, complain_overflow_bitfield
, "R_EPIPHANY_8", 0x000000ff, 0x000000ff),
71 AHOW (R_EPIPHANY_16
, 0, 1,16, FALSE
, 0, complain_overflow_bitfield
, "R_EPIPHANY_16", 0x0000ffff, 0x00ff1fe0),
72 /* A 32 bit absolute relocation. */
73 AHOW (R_EPIPHANY_32
, 0, 2,32, FALSE
, 0, complain_overflow_dont
, "R_EPIPHANY_32", 0xffffffff, 0xffffffff),
75 /* 8 bit relative relocation */
76 HOWTO ( R_EPIPHANY_8_PCREL
, 0, 0, 8, TRUE
, 0, complain_overflow_bitfield
, bfd_elf_generic_reloc
, "R_EPIPHANY_8_PCREL", FALSE
, 0x000000ff, 0x000000ff, FALSE
),
77 /* 16 bit relative relocation */
78 HOWTO ( R_EPIPHANY_16_PCREL
, 0, 1, 16, TRUE
, 0, complain_overflow_bitfield
, bfd_elf_generic_reloc
, "R_EPIPHANY_8_PCREL", FALSE
, 0x000000ff, 0x000000ff, FALSE
),
79 /* 32 bit relative relocation */
80 HOWTO ( R_EPIPHANY_32_PCREL
, 0, 2, 32, TRUE
, 0, complain_overflow_bitfield
, bfd_elf_generic_reloc
, "R_EPIPHANY_8_PCREL", FALSE
, 0x000000ff, 0x000000ff, FALSE
),
82 /* 8 bit pc-relative relocation */
83 AHOW (R_EPIPHANY_SIMM8
, 1, 0, 8, TRUE
, 8, complain_overflow_signed
, "R_EPIPHANY_SIMM8", 0x000000ff, 0x0000ff00),
84 /* 24 bit pc-relative relocation */
85 AHOW (R_EPIPHANY_SIMM24
, 1, 2,24, TRUE
, 8, complain_overflow_signed
, "R_EPIPHANY_SIMM24", 0x00ffffff, 0xffffff00),
88 AHOW (R_EPIPHANY_HIGH
, 0, 2,16, FALSE
, 0, complain_overflow_dont
, "R_EPIPHANY_HIGH", 0x0ff01fe0, 0x0ff01fe0),
91 AHOW (R_EPIPHANY_LOW
, 0, 2,16, FALSE
, 0, complain_overflow_dont
, "R_EPIPHANY_LOW", 0x0ff01fe0, 0x0ff01fe0),
94 AHOW (R_EPIPHANY_SIMM11
, 0, 2,11, FALSE
, 0, complain_overflow_bitfield
, "R_EPIPHANY_SIMM11", 0x00ff0380, 0x00ff0380),
95 /* imm12 - sign-magnitude */
96 AHOW (R_EPIPHANY_IMM11
, 0, 2,11, FALSE
, 0, complain_overflow_bitfield
, "R_EPIPHANY_IMM12", 0x00ff0380, 0x00ff0380),
98 AHOW (R_EPIPHANY_IMM8
, 0, 1, 8, FALSE
, 8, complain_overflow_signed
, "R_EPIPHANY_IMM8", 0x0000ff00, 0x0000ff00)
104 /* Map BFD reloc types to EPIPHANY ELF reloc types. */
106 static reloc_howto_type
*
107 epiphany_reloc_type_lookup (bfd
* abfd ATTRIBUTE_UNUSED
,
108 bfd_reloc_code_real_type code
)
110 /* Note that the epiphany_elf_howto_table is indxed by the R_
111 constants. Thus, the order that the howto records appear in the
112 table *must* match the order of the relocation types defined in
113 include/elf/epiphany.h. */
118 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_NONE
];
120 case BFD_RELOC_EPIPHANY_SIMM8
:
121 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_SIMM8
];
122 case BFD_RELOC_EPIPHANY_SIMM24
:
123 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_SIMM24
];
125 case BFD_RELOC_8_PCREL
:
126 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_8_PCREL
];
127 case BFD_RELOC_16_PCREL
:
128 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_16_PCREL
];
129 case BFD_RELOC_32_PCREL
:
130 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_32_PCREL
];
133 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_8
];
135 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_16
];
137 return &epiphany_elf_howto_table
[ (int) R_EPIPHANY_32
];
139 case BFD_RELOC_EPIPHANY_HIGH
:
140 return & epiphany_elf_howto_table
[ (int) R_EPIPHANY_HIGH
];
141 case BFD_RELOC_EPIPHANY_LOW
:
142 return & epiphany_elf_howto_table
[ (int) R_EPIPHANY_LOW
];
144 case BFD_RELOC_EPIPHANY_SIMM11
:
145 return & epiphany_elf_howto_table
[ (int) R_EPIPHANY_SIMM11
];
146 case BFD_RELOC_EPIPHANY_IMM11
:
147 return & epiphany_elf_howto_table
[ (int) R_EPIPHANY_IMM11
];
149 case BFD_RELOC_EPIPHANY_IMM8
:
150 return & epiphany_elf_howto_table
[ (int) R_EPIPHANY_IMM8
];
153 /* Pacify gcc -Wall. */
159 static reloc_howto_type
*
160 epiphany_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
164 for (i
= 0; i
< ARRAY_SIZE (epiphany_elf_howto_table
); i
++)
165 if (epiphany_elf_howto_table
[i
].name
!= NULL
166 && strcasecmp (epiphany_elf_howto_table
[i
].name
, r_name
) == 0)
167 return &epiphany_elf_howto_table
[i
];
172 #define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
173 #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset)
175 /* This function handles relaxing for the epiphany.
176 Dummy placeholder for future optimizations. */
179 epiphany_elf_relax_section (bfd
*abfd
, asection
*sec
,
180 struct bfd_link_info
*link_info
,
183 Elf_Internal_Shdr
*symtab_hdr
;
184 Elf_Internal_Rela
*internal_relocs
;
185 bfd_byte
*contents
= NULL
;
186 Elf_Internal_Sym
*isymbuf
= NULL
;
187 static asection
* first_section
= NULL
;
188 static unsigned long search_addr
;
189 static unsigned long page_start
= 0;
190 static unsigned long page_end
= 0;
191 static unsigned int pass
= 0;
192 static bfd_boolean new_pass
= FALSE
;
193 static bfd_boolean changed
= FALSE
;
194 struct misc misc ATTRIBUTE_UNUSED
;
197 /* Assume nothing changes. */
200 if (first_section
== NULL
)
202 epiphany_relaxed
= TRUE
;
206 if (first_section
== sec
)
212 /* We don't have to do anything for a relocatable link,
213 if this section does not have relocs, or if this is
214 not a code section. */
215 if (bfd_link_relocatable (link_info
)
216 || (sec
->flags
& SEC_RELOC
) == 0
217 || sec
->reloc_count
== 0
218 || (sec
->flags
& SEC_CODE
) == 0)
221 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
223 internal_relocs
= _bfd_elf_link_read_relocs (abfd
, sec
, NULL
, NULL
,
224 link_info
->keep_memory
);
225 if (internal_relocs
== NULL
)
228 /* Make sure the stac.rela stuff gets read in. */
229 stab
= bfd_get_section_by_name (abfd
, ".stab");
233 /* So stab does exits. */
234 Elf_Internal_Rela
* irelbase ATTRIBUTE_UNUSED
;
236 irelbase
= _bfd_elf_link_read_relocs (abfd
, stab
, NULL
, NULL
,
237 link_info
->keep_memory
);
240 /* Get section contents cached copy if it exists. */
241 if (contents
== NULL
)
243 /* Get cached copy if it exists. */
244 if (elf_section_data (sec
)->this_hdr
.contents
!= NULL
)
245 contents
= elf_section_data (sec
)->this_hdr
.contents
;
248 /* Go get them off disk. */
249 if (!bfd_malloc_and_get_section (abfd
, sec
, &contents
))
254 /* Read this BFD's symbols cached copy if it exists. */
255 if (isymbuf
== NULL
&& symtab_hdr
->sh_info
!= 0)
257 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
259 isymbuf
= bfd_elf_get_elf_syms (abfd
, symtab_hdr
,
260 symtab_hdr
->sh_info
, 0,
266 misc
.symtab_hdr
= symtab_hdr
;
267 misc
.isymbuf
= isymbuf
;
268 misc
.irelbase
= internal_relocs
;
269 misc
.contents
= contents
;
271 /* This is where all the relaxation actually get done. */
272 if ((pass
== 1) || (new_pass
&& !changed
))
274 /* On the first pass we simply search for the lowest page that
275 we havn't relaxed yet. Note that the pass count is reset
276 each time a page is complete in order to move on to the next page.
277 If we can't find any more pages then we are finished. */
282 changed
= TRUE
; /* Pre-initialize to break out of pass 1. */
283 search_addr
= 0xFFFFFFFF;
286 if ((BASEADDR (sec
) + sec
->size
< search_addr
)
287 && (BASEADDR (sec
) + sec
->size
> page_end
))
289 if (BASEADDR (sec
) <= page_end
)
290 search_addr
= page_end
+ 1;
292 search_addr
= BASEADDR (sec
);
294 /* Found a page => more work to do. */
304 page_start
= PAGENO (search_addr
);
305 page_end
= page_start
| 0x00003FFF;
308 /* Only process sections in range. */
309 if ((BASEADDR (sec
) + sec
->size
>= page_start
)
310 && (BASEADDR (sec
) <= page_end
))
313 if (!epiphany_elf_relax_section_page (abfd
, sec
, &changed
, &misc
,
314 page_start
, page_end
))
321 /* Perform some house keeping after relaxing the section. */
324 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
326 if (! link_info
->keep_memory
)
329 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
333 && elf_section_data (sec
)->this_hdr
.contents
!= contents
)
335 if (! link_info
->keep_memory
)
339 /* Cache the section contents for elf_link_input_bfd. */
340 elf_section_data (sec
)->this_hdr
.contents
= contents
;
344 if (internal_relocs
!= NULL
345 && elf_section_data (sec
)->relocs
!= internal_relocs
)
346 free (internal_relocs
);
352 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
355 && elf_section_data (sec
)->this_hdr
.contents
!= contents
)
357 if (internal_relocs
!= NULL
358 && elf_section_data (sec
)->relocs
!= internal_relocs
)
359 free (internal_relocs
);
363 /* Set the howto pointer for a EPIPHANY ELF reloc. */
366 epiphany_info_to_howto_rela (bfd
* abfd
,
368 Elf_Internal_Rela
* dst
)
372 r_type
= ELF32_R_TYPE (dst
->r_info
);
373 if (r_type
>= (unsigned int) R_EPIPHANY_max
)
375 /* xgettext:c-format */
376 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
380 cache_ptr
->howto
= & epiphany_elf_howto_table
[r_type
];
383 /* Perform a single relocation.
384 By default we use the standard BFD routines. */
386 static bfd_reloc_status_type
387 epiphany_final_link_relocate (reloc_howto_type
* howto
,
389 asection
* input_section
,
391 Elf_Internal_Rela
* rel
,
396 /* Handle 16 bit immediates. */
397 case R_EPIPHANY_HIGH
:
398 relocation
+= rel
->r_addend
;
403 relocation
+= rel
->r_addend
;
405 relocation
= ((relocation
& 0xff00L
) << 12)
406 | ((relocation
& 0x00ffL
) << 5);
407 /* Sanity check the address. */
408 if (rel
->r_offset
> bfd_get_section_limit (input_bfd
, input_section
))
409 return bfd_reloc_outofrange
;
411 return _bfd_relocate_contents (howto
, input_bfd
, relocation
,
412 contents
+ rel
->r_offset
);
414 case R_EPIPHANY_SIMM11
:
415 relocation
+= rel
->r_addend
;
416 /* Check signed overflow. */
417 if ((int)relocation
> 1023 || (int)relocation
< -1024)
418 return bfd_reloc_outofrange
;
421 case R_EPIPHANY_IMM11
:
422 relocation
+= rel
->r_addend
;
423 if ((unsigned int) relocation
> 0x7ff)
424 return bfd_reloc_outofrange
;
427 relocation
= (((relocation
& 7) << 5)
428 | ((relocation
& 0x7f8 ) << 13));
429 return _bfd_relocate_contents (howto
, input_bfd
, relocation
,
430 contents
+ rel
->r_offset
);
432 /* Pass others through. */
437 /* Only install relocation if above tests did not disqualify it. */
438 return _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
439 contents
, rel
->r_offset
,
440 relocation
, rel
->r_addend
);
443 /* Relocate an EPIPHANY ELF section.
445 The RELOCATE_SECTION function is called by the new ELF backend linker
446 to handle the relocations for a section.
448 The relocs are always passed as Rela structures; if the section
449 actually uses Rel structures, the r_addend field will always be
452 This function is responsible for adjusting the section contents as
453 necessary, and (if using Rela relocs and generating a relocatable
454 output file) adjusting the reloc addend as necessary.
456 This function does not have to worry about setting the reloc
457 address or the reloc symbol index.
459 LOCAL_SYMS is a pointer to the swapped in local symbols.
461 LOCAL_SECTIONS is an array giving the section in the input file
462 corresponding to the st_shndx field of each local symbol.
464 The global hash table entry for the global symbols can be found
465 via elf_sym_hashes (input_bfd).
467 When generating relocatable output, this function must handle
468 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
469 going to be the section symbol corresponding to the output
470 section, which means that the addend must be adjusted
474 epiphany_elf_relocate_section (bfd
*output_bfd ATTRIBUTE_UNUSED
,
475 struct bfd_link_info
*info
,
477 asection
*input_section
,
479 Elf_Internal_Rela
*relocs
,
480 Elf_Internal_Sym
*local_syms
,
481 asection
**local_sections
)
483 Elf_Internal_Shdr
*symtab_hdr
;
484 struct elf_link_hash_entry
**sym_hashes
;
485 Elf_Internal_Rela
*rel
;
486 Elf_Internal_Rela
*relend
;
488 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
489 sym_hashes
= elf_sym_hashes (input_bfd
);
490 relend
= relocs
+ input_section
->reloc_count
;
492 for (rel
= relocs
; rel
< relend
; rel
++)
494 reloc_howto_type
* howto
;
495 unsigned long r_symndx
;
496 Elf_Internal_Sym
* sym
;
498 struct elf_link_hash_entry
* h
;
500 bfd_reloc_status_type r
;
501 const char * name
= NULL
;
502 int r_type ATTRIBUTE_UNUSED
;
504 r_type
= ELF32_R_TYPE (rel
->r_info
);
505 r_symndx
= ELF32_R_SYM (rel
->r_info
);
506 howto
= epiphany_elf_howto_table
+ ELF32_R_TYPE (rel
->r_info
);
511 if (r_symndx
< symtab_hdr
->sh_info
)
513 sym
= local_syms
+ r_symndx
;
514 sec
= local_sections
[r_symndx
];
515 relocation
= BASEADDR (sec
) + sym
->st_value
;
517 name
= bfd_elf_string_from_elf_section
518 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
519 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
523 bfd_boolean warned ATTRIBUTE_UNUSED
;
524 bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED
;
525 bfd_boolean ignored ATTRIBUTE_UNUSED
;
527 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
528 r_symndx
, symtab_hdr
, sym_hashes
,
530 unresolved_reloc
, warned
, ignored
);
532 name
= h
->root
.root
.string
;
535 if (sec
!= NULL
&& discarded_section (sec
))
536 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
537 rel
, 1, relend
, howto
, 0, contents
);
539 if (bfd_link_relocatable (info
))
542 /* Finally, the sole EPIPHANY-specific part. */
543 r
= epiphany_final_link_relocate (howto
, input_bfd
, input_section
,
544 contents
, rel
, relocation
);
546 if (r
!= bfd_reloc_ok
)
548 const char * msg
= NULL
;
552 case bfd_reloc_overflow
:
553 (*info
->callbacks
->reloc_overflow
)
554 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
555 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
558 case bfd_reloc_undefined
:
559 (*info
->callbacks
->undefined_symbol
)
560 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
563 case bfd_reloc_outofrange
:
564 msg
= _("internal error: out of range error");
567 /* This is how epiphany_final_link_relocate tells us of a
568 non-kosher reference between insn & data address spaces. */
569 case bfd_reloc_notsupported
:
570 if (sym
!= NULL
) /* Only if it's not an unresolved symbol. */
571 msg
= _("unsupported relocation between data/insn address spaces");
574 case bfd_reloc_dangerous
:
575 msg
= _("internal error: dangerous relocation");
579 msg
= _("internal error: unknown error");
584 (*info
->callbacks
->warning
) (info
, msg
, name
, input_bfd
,
585 input_section
, rel
->r_offset
);
592 /* We only have a little-endian target. */
593 #define TARGET_LITTLE_SYM epiphany_elf32_vec
594 #define TARGET_LITTLE_NAME "elf32-epiphany"
596 #define ELF_ARCH bfd_arch_epiphany
597 #define ELF_MACHINE_CODE EM_ADAPTEVA_EPIPHANY
599 #define ELF_MAXPAGESIZE 0x8000 /* No pages on the EPIPHANY. */
601 #define elf_info_to_howto_rel NULL
602 #define elf_info_to_howto epiphany_info_to_howto_rela
604 #define elf_backend_can_gc_sections 1
605 #define elf_backend_rela_normal 1
606 #define elf_backend_relocate_section epiphany_elf_relocate_section
608 #define elf_symbol_leading_char '_'
609 #define bfd_elf32_bfd_reloc_type_lookup epiphany_reloc_type_lookup
610 #define bfd_elf32_bfd_reloc_name_lookup epiphany_reloc_name_lookup
611 #define bfd_elf32_bfd_relax_section epiphany_elf_relax_section
613 #include "elf32-target.h"