1
/* Adapteva epiphany specific support for 32-bit ELF
2
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2011, 2012
3
Free Software Foundation, Inc.
4
Contributed by Embecosm on behalf of Adapteva, Inc.
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. */
27
#include "elf/epiphany.h"
28
#include "libiberty.h"
30
/* Struct used to pass miscellaneous paramaters which
31
helps to avoid overly long parameter lists. */
34
Elf_Internal_Shdr * symtab_hdr;
35
Elf_Internal_Rela * irelbase;
37
Elf_Internal_Sym * isymbuf;
40
struct epiphany_opcode
42
unsigned short opcode;
46
static bfd_boolean epiphany_relaxed = FALSE;
48
/* Relocation tables. */
49
static reloc_howto_type epiphany_elf_howto_table [] =
51
#define AHOW(t,rs,s,bs,pr,bp,co,name,sm,dm) \
53
rs, /* rightshift */ \
54
s, /* size (0 = byte, 1 = short, 2 = long) */ \
56
pr, /* pc_relative */ \
58
co, /* complain_on_overflow */ \
59
bfd_elf_generic_reloc,/* special_function */ \
61
FALSE, /* partial_inplace */ \
64
pr) /* pcrel_offset */
66
/* This reloc does nothing. */
67
AHOW (R_EPIPHANY_NONE, 0, 0,32, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_NONE", 0, 0),
69
/* 8 bit absolute (not likely) */
70
AHOW (R_EPIPHANY_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_8", 0x000000ff, 0x000000ff),
72
AHOW (R_EPIPHANY_16, 0, 1,16, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_16", 0x0000ffff, 0x00ff1fe0),
73
/* A 32 bit absolute relocation. */
74
AHOW (R_EPIPHANY_32, 0, 2,32, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_32", 0xffffffff, 0xffffffff),
76
/* 8 bit relative relocation */
77
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),
78
/* 16 bit relative relocation */
79
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),
80
/* 32 bit relative relocation */
81
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),
83
/* 8 bit pc-relative relocation */
84
AHOW (R_EPIPHANY_SIMM8, 1, 0, 8, TRUE, 8, complain_overflow_signed, "R_EPIPHANY_SIMM8", 0x000000ff, 0x0000ff00),
85
/* 24 bit pc-relative relocation */
86
AHOW (R_EPIPHANY_SIMM24, 1, 2,24, TRUE, 8, complain_overflow_signed, "R_EPIPHANY_SIMM24", 0x00ffffff, 0xffffff00),
89
AHOW (R_EPIPHANY_HIGH, 0, 2,16, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_HIGH", 0x0ff01fe0, 0x0ff01fe0),
92
AHOW (R_EPIPHANY_LOW, 0, 2,16, FALSE, 0, complain_overflow_dont, "R_EPIPHANY_LOW", 0x0ff01fe0, 0x0ff01fe0),
95
AHOW (R_EPIPHANY_SIMM11, 0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_SIMM11", 0x00ff0380, 0x00ff0380),
96
/* imm12 - sign-magnitude */
97
AHOW (R_EPIPHANY_IMM11, 0, 2,11, FALSE, 0, complain_overflow_bitfield, "R_EPIPHANY_IMM12", 0x00ff0380, 0x00ff0380),
99
AHOW (R_EPIPHANY_IMM8, 0, 1, 8, FALSE, 8, complain_overflow_signed, "R_EPIPHANY_IMM8", 0x0000ff00, 0x0000ff00)
105
/* Map BFD reloc types to EPIPHANY ELF reloc types. */
107
static reloc_howto_type *
108
epiphany_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
109
bfd_reloc_code_real_type code)
111
/* Note that the epiphany_elf_howto_table is indxed by the R_
112
constants. Thus, the order that the howto records appear in the
113
table *must* match the order of the relocation types defined in
114
include/elf/epiphany.h. */
119
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_NONE];
121
case BFD_RELOC_EPIPHANY_SIMM8:
122
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM8];
123
case BFD_RELOC_EPIPHANY_SIMM24:
124
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM24];
126
case BFD_RELOC_8_PCREL:
127
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8_PCREL];
128
case BFD_RELOC_16_PCREL:
129
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16_PCREL];
130
case BFD_RELOC_32_PCREL:
131
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32_PCREL];
134
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_8];
136
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_16];
138
return &epiphany_elf_howto_table[ (int) R_EPIPHANY_32];
140
case BFD_RELOC_EPIPHANY_HIGH:
141
return & epiphany_elf_howto_table[ (int) R_EPIPHANY_HIGH];
142
case BFD_RELOC_EPIPHANY_LOW:
143
return & epiphany_elf_howto_table[ (int) R_EPIPHANY_LOW];
145
case BFD_RELOC_EPIPHANY_SIMM11:
146
return & epiphany_elf_howto_table[ (int) R_EPIPHANY_SIMM11];
147
case BFD_RELOC_EPIPHANY_IMM11:
148
return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM11];
150
case BFD_RELOC_EPIPHANY_IMM8:
151
return & epiphany_elf_howto_table[ (int) R_EPIPHANY_IMM8];
154
/* Pacify gcc -Wall. */
160
static reloc_howto_type *
161
epiphany_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
165
for (i = 0; i < ARRAY_SIZE (epiphany_elf_howto_table); i++)
166
if (epiphany_elf_howto_table[i].name != NULL
167
&& strcasecmp (epiphany_elf_howto_table[i].name, r_name) == 0)
168
return &epiphany_elf_howto_table[i];
173
#define PAGENO(ABSADDR) ((ABSADDR) & 0xFFFFC000)
174
#define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset)
176
/* This function handles relaxing for the epiphany.
177
Dummy placeholder for future optimizations. */
180
epiphany_elf_relax_section (bfd *abfd, asection *sec,
181
struct bfd_link_info *link_info,
184
Elf_Internal_Shdr *symtab_hdr;
185
Elf_Internal_Rela *internal_relocs;
186
bfd_byte *contents = NULL;
187
Elf_Internal_Sym *isymbuf = NULL;
188
static asection * first_section = NULL;
189
static unsigned long search_addr;
190
static unsigned long page_start = 0;
191
static unsigned long page_end = 0;
192
static unsigned int pass = 0;
193
static bfd_boolean new_pass = FALSE;
194
static bfd_boolean changed = FALSE;
195
struct misc misc ATTRIBUTE_UNUSED;
198
/* Assume nothing changes. */
201
if (first_section == NULL)
203
epiphany_relaxed = TRUE;
207
if (first_section == sec)
213
/* We don't have to do anything for a relocatable link,
214
if this section does not have relocs, or if this is
215
not a code section. */
216
if (link_info->relocatable
217
|| (sec->flags & SEC_RELOC) == 0
218
|| sec->reloc_count == 0
219
|| (sec->flags & SEC_CODE) == 0)
222
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
224
internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
225
link_info->keep_memory);
226
if (internal_relocs == NULL)
229
/* Make sure the stac.rela stuff gets read in. */
230
stab = bfd_get_section_by_name (abfd, ".stab");
234
/* So stab does exits. */
235
Elf_Internal_Rela * irelbase ATTRIBUTE_UNUSED;
237
irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
238
link_info->keep_memory);
241
/* Get section contents cached copy if it exists. */
242
if (contents == NULL)
244
/* Get cached copy if it exists. */
245
if (elf_section_data (sec)->this_hdr.contents != NULL)
246
contents = elf_section_data (sec)->this_hdr.contents;
249
/* Go get them off disk. */
250
if (!bfd_malloc_and_get_section (abfd, sec, &contents))
255
/* Read this BFD's symbols cached copy if it exists. */
256
if (isymbuf == NULL && symtab_hdr->sh_info != 0)
258
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
260
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
261
symtab_hdr->sh_info, 0,
267
misc.symtab_hdr = symtab_hdr;
268
misc.isymbuf = isymbuf;
269
misc.irelbase = internal_relocs;
270
misc.contents = contents;
272
/* This is where all the relaxation actually get done. */
273
if ((pass == 1) || (new_pass && !changed))
275
/* On the first pass we simply search for the lowest page that
276
we havn't relaxed yet. Note that the pass count is reset
277
each time a page is complete in order to move on to the next page.
278
If we can't find any more pages then we are finished. */
283
changed = TRUE; /* Pre-initialize to break out of pass 1. */
284
search_addr = 0xFFFFFFFF;
287
if ((BASEADDR (sec) + sec->size < search_addr)
288
&& (BASEADDR (sec) + sec->size > page_end))
290
if (BASEADDR (sec) <= page_end)
291
search_addr = page_end + 1;
293
search_addr = BASEADDR (sec);
295
/* Found a page => more work to do. */
305
page_start = PAGENO (search_addr);
306
page_end = page_start | 0x00003FFF;
309
/* Only process sections in range. */
310
if ((BASEADDR (sec) + sec->size >= page_start)
311
&& (BASEADDR (sec) <= page_end))
314
if (!epiphany_elf_relax_section_page (abfd, sec, &changed, &misc,
315
page_start, page_end))
322
/* Perform some house keeping after relaxing the section. */
325
&& symtab_hdr->contents != (unsigned char *) isymbuf)
327
if (! link_info->keep_memory)
330
symtab_hdr->contents = (unsigned char *) isymbuf;
334
&& elf_section_data (sec)->this_hdr.contents != contents)
336
if (! link_info->keep_memory)
340
/* Cache the section contents for elf_link_input_bfd. */
341
elf_section_data (sec)->this_hdr.contents = contents;
345
if (internal_relocs != NULL
346
&& elf_section_data (sec)->relocs != internal_relocs)
347
free (internal_relocs);
353
&& symtab_hdr->contents != (unsigned char *) isymbuf)
356
&& elf_section_data (sec)->this_hdr.contents != contents)
358
if (internal_relocs != NULL
359
&& elf_section_data (sec)->relocs != internal_relocs)
360
free (internal_relocs);
364
/* Set the howto pointer for a EPIPHANY ELF reloc. */
367
epiphany_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
369
Elf_Internal_Rela * dst)
373
r_type = ELF32_R_TYPE (dst->r_info);
374
cache_ptr->howto = & epiphany_elf_howto_table [r_type];
377
/* Perform a single relocation.
378
By default we use the standard BFD routines. */
380
static bfd_reloc_status_type
381
epiphany_final_link_relocate (reloc_howto_type * howto,
383
asection * input_section,
385
Elf_Internal_Rela * rel,
390
/* Handle 16 bit immediates. */
391
case R_EPIPHANY_HIGH:
392
relocation += rel->r_addend;
397
relocation += rel->r_addend;
399
relocation = ((relocation & 0xff00L) << 12)
400
| ((relocation & 0x00ffL) << 5);
401
/* Sanity check the address. */
402
if (rel->r_offset > bfd_get_section_limit (input_bfd, input_section))
403
return bfd_reloc_outofrange;
405
return _bfd_relocate_contents (howto, input_bfd, relocation,
406
contents + rel->r_offset);
408
case R_EPIPHANY_SIMM11:
409
relocation += rel->r_addend;
410
/* Check signed overflow. */
411
if ((int)relocation > 1023 || (int)relocation < -1024)
412
return bfd_reloc_outofrange;
415
case R_EPIPHANY_IMM11:
416
relocation += rel->r_addend;
417
if ((unsigned int) relocation > 0x7ff)
418
return bfd_reloc_outofrange;
420
relocation = ((relocation & 7) << 5)
421
|| ((relocation & 0x7f8 ) << 13);
422
return _bfd_relocate_contents (howto, input_bfd, relocation,
423
contents + rel->r_offset);
425
/* Pass others through. */
430
/* Only install relocation if above tests did not disqualify it. */
431
return _bfd_final_link_relocate (howto, input_bfd, input_section,
432
contents, rel->r_offset,
433
relocation, rel->r_addend);
436
/* Relocate an EPIPHANY ELF section.
438
The RELOCATE_SECTION function is called by the new ELF backend linker
439
to handle the relocations for a section.
441
The relocs are always passed as Rela structures; if the section
442
actually uses Rel structures, the r_addend field will always be
445
This function is responsible for adjusting the section contents as
446
necessary, and (if using Rela relocs and generating a relocatable
447
output file) adjusting the reloc addend as necessary.
449
This function does not have to worry about setting the reloc
450
address or the reloc symbol index.
452
LOCAL_SYMS is a pointer to the swapped in local symbols.
454
LOCAL_SECTIONS is an array giving the section in the input file
455
corresponding to the st_shndx field of each local symbol.
457
The global hash table entry for the global symbols can be found
458
via elf_sym_hashes (input_bfd).
460
When generating relocatable output, this function must handle
461
STB_LOCAL/STT_SECTION symbols specially. The output symbol is
462
going to be the section symbol corresponding to the output
463
section, which means that the addend must be adjusted
467
epiphany_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
468
struct bfd_link_info *info,
470
asection *input_section,
472
Elf_Internal_Rela *relocs,
473
Elf_Internal_Sym *local_syms,
474
asection **local_sections)
476
Elf_Internal_Shdr *symtab_hdr;
477
struct elf_link_hash_entry **sym_hashes;
478
Elf_Internal_Rela *rel;
479
Elf_Internal_Rela *relend;
481
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
482
sym_hashes = elf_sym_hashes (input_bfd);
483
relend = relocs + input_section->reloc_count;
485
for (rel = relocs; rel < relend; rel ++)
487
reloc_howto_type * howto;
488
unsigned long r_symndx;
489
Elf_Internal_Sym * sym;
491
struct elf_link_hash_entry * h;
493
bfd_reloc_status_type r;
494
const char * name = NULL;
495
int r_type ATTRIBUTE_UNUSED;
497
r_type = ELF32_R_TYPE (rel->r_info);
498
r_symndx = ELF32_R_SYM (rel->r_info);
499
howto = epiphany_elf_howto_table + ELF32_R_TYPE (rel->r_info);
504
if (r_symndx < symtab_hdr->sh_info)
506
sym = local_syms + r_symndx;
507
sec = local_sections [r_symndx];
508
relocation = BASEADDR (sec) + sym->st_value;
510
name = bfd_elf_string_from_elf_section
511
(input_bfd, symtab_hdr->sh_link, sym->st_name);
512
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
516
bfd_boolean warned ATTRIBUTE_UNUSED;
517
bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
519
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
520
r_symndx, symtab_hdr, sym_hashes,
522
unresolved_reloc, warned);
524
name = h->root.root.string;
527
if (sec != NULL && discarded_section (sec))
528
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
529
rel, 1, relend, howto, 0, contents);
531
if (info->relocatable)
534
/* Finally, the sole EPIPHANY-specific part. */
535
r = epiphany_final_link_relocate (howto, input_bfd, input_section,
536
contents, rel, relocation);
538
if (r != bfd_reloc_ok)
540
const char * msg = NULL;
544
case bfd_reloc_overflow:
545
r = info->callbacks->reloc_overflow
546
(info, (h ? &h->root : NULL), name, howto->name,
547
(bfd_vma) 0, input_bfd, input_section, rel->r_offset);
550
case bfd_reloc_undefined:
551
r = info->callbacks->undefined_symbol
552
(info, name, input_bfd, input_section, rel->r_offset, TRUE);
555
case bfd_reloc_outofrange:
556
msg = _("internal error: out of range error");
559
/* This is how epiphany_final_link_relocate tells us of a
560
non-kosher reference between insn & data address spaces. */
561
case bfd_reloc_notsupported:
562
if (sym != NULL) /* Only if it's not an unresolved symbol. */
563
msg = _("unsupported relocation between data/insn address spaces");
566
case bfd_reloc_dangerous:
567
msg = _("internal error: dangerous relocation");
571
msg = _("internal error: unknown error");
576
r = info->callbacks->warning
577
(info, msg, name, input_bfd, input_section, rel->r_offset);
587
/* We only have a little-endian target. */
588
#define TARGET_LITTLE_SYM bfd_elf32_epiphany_vec
589
#define TARGET_LITTLE_NAME "elf32-epiphany"
591
#define ELF_ARCH bfd_arch_epiphany
592
#define ELF_MACHINE_CODE EM_ADAPTEVA_EPIPHANY
594
#define ELF_MAXPAGESIZE 0x8000 /* No pages on the EPIPHANY. */
596
#define elf_info_to_howto_rel NULL
597
#define elf_info_to_howto epiphany_info_to_howto_rela
599
#define elf_backend_can_gc_sections 1
600
#define elf_backend_rela_normal 1
601
#define elf_backend_relocate_section epiphany_elf_relocate_section
603
#define elf_symbol_leading_char '_'
604
#define bfd_elf32_bfd_reloc_type_lookup epiphany_reloc_type_lookup
605
#define bfd_elf32_bfd_reloc_name_lookup epiphany_reloc_name_lookup
606
#define bfd_elf32_bfd_relax_section epiphany_elf_relax_section
608
#include "elf32-target.h"