1
/* OR32-specific support for 32-bit ELF
2
Copyright 2002 Free Software Foundation, Inc.
3
Contributed by Ivan Guzvinec <ivang@opencores.org>
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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26
#include "libiberty.h"
28
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29
PARAMS ((bfd *, bfd_reloc_code_real_type));
30
static void or32_info_to_howto_rel
31
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
32
static bfd_boolean or32_elf_object_p
34
static void or32_elf_final_write_processing
35
PARAMS ((bfd *, bfd_boolean));
36
static bfd_reloc_status_type or32_elf_32_reloc
37
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
38
static bfd_reloc_status_type or32_elf_16_reloc
39
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
40
static bfd_reloc_status_type or32_elf_8_reloc
41
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
42
static bfd_reloc_status_type or32_elf_const_reloc
43
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
44
static bfd_reloc_status_type or32_elf_consth_reloc
45
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
46
static bfd_reloc_status_type or32_elf_jumptarg_reloc
47
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
49
/* Try to minimize the amount of space occupied by relocation tables
50
on the ROM (not that the ROM won't be swamped by other ELF overhead). */
53
static reloc_howto_type elf_or32_howto_table[] =
55
/* This reloc does nothing. */
56
HOWTO (R_OR32_NONE, /* type */
58
2, /* size (0 = byte, 1 = short, 2 = long) */
60
FALSE, /* pc_relative */
62
complain_overflow_bitfield, /* complain_on_overflow */
63
bfd_elf_generic_reloc, /* special_function */
64
"R_OR32_NONE", /* name */
65
FALSE, /* partial_inplace */
68
FALSE), /* pcrel_offset */
70
/* A standard 32 bit relocation. */
71
HOWTO (R_OR32_32, /* type */
73
2, /* size (0 = byte, 1 = short, 2 = long) */
75
FALSE, /* pc_relative */
77
complain_overflow_bitfield, /* complain_on_overflow */
78
or32_elf_32_reloc, /* special_function */
79
"R_OR32_32", /* name */
80
FALSE, /* partial_inplace */
81
0xffffffff, /* src_mask */
82
0xffffffff, /* dst_mask */
83
FALSE), /* pcrel_offset */
85
/* A standard 16 bit relocation. */
86
HOWTO (R_OR32_16, /* type */
88
1, /* size (0 = byte, 1 = short, 2 = long) */
90
FALSE, /* pc_relative */
92
complain_overflow_bitfield, /* complain_on_overflow */
93
or32_elf_16_reloc, /* special_function */
94
"R_OR32_16", /* name */
95
FALSE, /* partial_inplace */
96
0x0000ffff, /* src_mask */
97
0x0000ffff, /* dst_mask */
98
FALSE), /* pcrel_offset */
100
/* A standard 8 bit relocation. */
101
HOWTO (R_OR32_8, /* type */
103
0, /* size (0 = byte, 1 = short, 2 = long) */
105
FALSE, /* pc_relative */
107
complain_overflow_bitfield, /* complain_on_overflow */
108
or32_elf_8_reloc, /* special_function */
109
"R_OR32_8", /* name */
110
FALSE, /* partial_inplace */
111
0x000000ff, /* src_mask */
112
0x000000ff, /* dst_mask */
113
FALSE), /* pcrel_offset */
115
/* A standard low 16 bit relocation. */
116
HOWTO (R_OR32_CONST, /* type */
118
2, /* size (0 = byte, 1 = short, 2 = long) */
120
FALSE, /* pc_relative */
122
complain_overflow_dont, /* complain_on_overflow */
123
or32_elf_const_reloc, /* special_function */
124
"R_OR32_CONST", /* name */
125
FALSE, /* partial_inplace */
126
0x0000ffff, /* src_mask */
127
0x0000ffff, /* dst_mask */
128
FALSE), /* pcrel_offset */
130
/* A standard high 16 bit relocation. */
131
HOWTO (R_OR32_CONSTH, /* type */
133
2, /* size (0 = byte, 1 = short, 2 = long) */
135
TRUE, /* pc_relative */
137
complain_overflow_dont, /* complain_on_overflow */
138
or32_elf_consth_reloc, /* special_function */
139
"R_OR32_CONSTH", /* name */
140
FALSE, /* partial_inplace */
141
0xffff0000, /* src_mask */
142
0x0000ffff, /* dst_mask */
143
FALSE), /* pcrel_offset */
145
/* A standard branch relocation. */
146
HOWTO (R_OR32_JUMPTARG, /* type */
148
2, /* size (0 = byte, 1 = short, 2 = long) */
150
TRUE, /* pc_relative */
152
complain_overflow_signed, /* complain_on_overflow */
153
or32_elf_jumptarg_reloc,/* special_function */
154
"R_OR32_JUMPTARG", /* name */
155
FALSE, /* partial_inplace */
157
0x03ffffff, /* dst_mask */
158
TRUE), /* pcrel_offset */
160
/* GNU extension to record C++ vtable hierarchy. */
161
HOWTO (R_OR32_GNU_VTINHERIT, /* type */
163
2, /* size (0 = byte, 1 = short, 2 = long) */
165
FALSE, /* pc_relative */
167
complain_overflow_dont, /* complain_on_overflow */
168
NULL, /* special_function */
169
"R_OR32_GNU_VTINHERIT", /* name */
170
FALSE, /* partial_inplace */
173
FALSE), /* pcrel_offset */
175
/* GNU extension to record C++ vtable member usage. */
176
HOWTO (R_OR32_GNU_VTENTRY, /* type */
178
2, /* size (0 = byte, 1 = short, 2 = long) */
180
FALSE, /* pc_relative */
182
complain_overflow_dont, /* complain_on_overflow */
183
_bfd_elf_rel_vtable_reloc_fn, /* special_function */
184
"R_OR32_GNU_VTENTRY", /* name */
185
FALSE, /* partial_inplace */
188
FALSE), /* pcrel_offset */
191
/* Map BFD reloc types to OR32 ELF reloc types. */
193
struct or32_reloc_map
195
bfd_reloc_code_real_type bfd_reloc_val;
196
unsigned char elf_reloc_val;
199
static const struct or32_reloc_map or32_reloc_map[] =
201
{ BFD_RELOC_NONE, R_OR32_NONE },
202
{ BFD_RELOC_32, R_OR32_32 },
203
{ BFD_RELOC_16, R_OR32_16 },
204
{ BFD_RELOC_8, R_OR32_8 },
205
{ BFD_RELOC_LO16, R_OR32_CONST },
206
{ BFD_RELOC_HI16, R_OR32_CONSTH },
207
{ BFD_RELOC_32_GOT_PCREL, R_OR32_JUMPTARG },
208
{ BFD_RELOC_VTABLE_INHERIT, R_OR32_GNU_VTINHERIT },
209
{ BFD_RELOC_VTABLE_ENTRY, R_OR32_GNU_VTENTRY },
212
static reloc_howto_type *
213
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
214
bfd *abfd ATTRIBUTE_UNUSED;
215
bfd_reloc_code_real_type code;
219
for (i = ARRAY_SIZE (or32_reloc_map); i--;)
221
if (or32_reloc_map[i].bfd_reloc_val == code)
222
return &elf_or32_howto_table[or32_reloc_map[i].elf_reloc_val];
228
/* Set the howto pointer for an OR32 ELF reloc. */
231
or32_info_to_howto_rel (abfd, cache_ptr, dst)
232
bfd *abfd ATTRIBUTE_UNUSED;
234
Elf_Internal_Rela *dst;
238
r_type = ELF32_R_TYPE (dst->r_info);
239
BFD_ASSERT (r_type < (unsigned int) R_OR32_max);
240
cache_ptr->howto = &elf_or32_howto_table[r_type];
243
/* Set the right machine number for an OR32 ELF file. */
246
or32_elf_object_p (abfd)
249
(void) bfd_default_set_arch_mach (abfd, bfd_arch_or32, 0);
253
/* The final processing done just before writing out an OR32 ELF object file.
254
This gets the OR32 architecture right based on the machine number. */
257
or32_elf_final_write_processing (abfd, linker)
259
bfd_boolean linker ATTRIBUTE_UNUSED;
264
switch (mach = bfd_get_mach (abfd))
267
case bfd_mach_arc_base:
268
val = E_OR32_MACH_BASE;
276
elf_elfheader (abfd)->e_flags &=~ EF_OR32_MACH;
277
elf_elfheader (abfd)->e_flags |= val;
280
bfd_reloc_status_type
281
or32_elf_32_reloc (abfd, reloc_entry, symbol, data, input_section,
282
output_bfd, error_message)
284
arelent *reloc_entry;
287
asection *input_section;
289
char **error_message ATTRIBUTE_UNUSED;
291
if (output_bfd != (bfd *) NULL)
294
bfd_size_type addr = reloc_entry->address;
296
reloc_entry->address += input_section->output_offset;
298
insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
299
insn += symbol->section->output_section->vma;
300
insn += symbol->section->output_offset;
301
insn += symbol->value;
302
bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
307
return bfd_reloc_continue;
310
bfd_reloc_status_type
311
or32_elf_16_reloc (abfd, reloc_entry, symbol, data, input_section,
312
output_bfd, error_message)
314
arelent *reloc_entry;
317
asection *input_section;
319
char **error_message ATTRIBUTE_UNUSED;
321
if (output_bfd != (bfd *) NULL)
324
bfd_size_type addr = reloc_entry->address;
326
reloc_entry->address += input_section->output_offset;
328
insn = bfd_get_16 (abfd, (bfd_byte *) data + addr);
329
insn += symbol->section->output_section->vma;
330
insn += symbol->section->output_offset;
331
insn += symbol->value;
332
bfd_put_16 (abfd, insn, (bfd_byte *) data + addr);
337
return bfd_reloc_continue;
340
bfd_reloc_status_type
341
or32_elf_8_reloc (abfd, reloc_entry, symbol, data, input_section,
342
output_bfd, error_message)
343
bfd *abfd ATTRIBUTE_UNUSED;
344
arelent *reloc_entry;
347
asection *input_section;
349
char **error_message ATTRIBUTE_UNUSED;
351
if (output_bfd != (bfd *) NULL)
354
bfd_size_type addr = reloc_entry->address;
356
reloc_entry->address += input_section->output_offset;
358
insn = bfd_get_8 (abfd, (bfd_byte *) data + addr);
359
insn += symbol->section->output_section->vma;
360
insn += symbol->section->output_offset;
361
insn += symbol->value;
362
bfd_put_8 (abfd, insn, (bfd_byte *) data + addr);
367
return bfd_reloc_continue;
370
/* Do a R_OR32_CONSTH relocation. This has to be done in combination
371
with a R_OR32_CONST reloc, because there is a carry from the LO16 to
372
the HI16. Here we just save the information we need; we do the
373
actual relocation when we see the LO16. OR32 ELF requires that the
374
LO16 immediately follow the HI16. As a GNU extension, we permit an
375
arbitrary number of HI16 relocs to be associated with a single LO16
376
reloc. This extension permits gcc to output the HI and LO relocs
377
itself. This code is copied from the elf32-mips.c. */
381
struct or32_consth *next;
386
/* FIXME: This should not be a static variable. */
388
static struct or32_consth *or32_consth_list;
390
bfd_reloc_status_type
391
or32_elf_consth_reloc (abfd, reloc_entry, symbol, data, input_section,
392
output_bfd, error_message)
393
bfd *abfd ATTRIBUTE_UNUSED;
394
arelent *reloc_entry;
397
asection *input_section;
399
char **error_message ATTRIBUTE_UNUSED;
401
bfd_reloc_status_type ret;
403
struct or32_consth *n;
407
if (bfd_is_und_section (symbol->section)
408
&& output_bfd == (bfd *) NULL)
409
ret = bfd_reloc_undefined;
411
if (bfd_is_com_section (symbol->section))
414
relocation = symbol->value;
416
relocation += symbol->section->output_section->vma;
417
relocation += symbol->section->output_offset;
418
relocation += reloc_entry->addend;
420
if (reloc_entry->address > input_section->_cooked_size)
421
return bfd_reloc_outofrange;
423
/* Save the information, and let LO16 do the actual relocation. */
424
n = (struct or32_consth *) bfd_malloc (sizeof *n);
426
return bfd_reloc_outofrange;
427
n->addr = (bfd_byte *) data + reloc_entry->address;
428
n->addend = relocation;
429
n->next = or32_consth_list;
430
or32_consth_list = n;
432
if (output_bfd != (bfd *) NULL)
433
reloc_entry->address += input_section->output_offset;
438
/* Do a R_OR32_CONST relocation. This is a straightforward 16 bit
439
inplace relocation; this function exists in order to do the
440
R_OR32_CONSTH relocation described above. */
442
bfd_reloc_status_type
443
or32_elf_const_reloc (abfd, reloc_entry, symbol, data, input_section,
444
output_bfd, error_message)
446
arelent *reloc_entry;
449
asection *input_section;
451
char **error_message;
453
if (or32_consth_list != NULL)
455
struct or32_consth *l;
457
l = or32_consth_list;
463
struct or32_consth *next;
465
/* Do the HI16 relocation. Note that we actually don't need
466
to know anything about the LO16 itself, except where to
467
find the low 16 bits of the addend needed by the LO16. */
468
insn = bfd_get_32 (abfd, l->addr);
469
vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
471
val = ((insn & 0xffff) << 16) + vallo;
474
insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
475
bfd_put_32 (abfd, insn, l->addr);
482
or32_consth_list = NULL;
485
if (output_bfd != (bfd *) NULL)
487
unsigned long insn, tmp;
488
bfd_size_type addr = reloc_entry->address;
490
reloc_entry->address += input_section->output_offset;
492
insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
493
tmp = insn & 0x0000ffff;
494
tmp += symbol->section->output_section->vma;
495
tmp += symbol->section->output_offset;
496
tmp += symbol->value;
497
insn = (insn & 0xffff0000) | (tmp & 0x0000ffff);
498
bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
503
/* Now do the LO16 reloc in the usual way. */
504
return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
505
input_section, output_bfd, error_message);
508
bfd_reloc_status_type
509
or32_elf_jumptarg_reloc (abfd, reloc_entry, symbol, data, input_section,
510
output_bfd, error_message)
512
arelent *reloc_entry;
513
asymbol *symbol ATTRIBUTE_UNUSED;
515
asection *input_section;
517
char **error_message ATTRIBUTE_UNUSED;
519
if (output_bfd != (bfd *) NULL)
521
unsigned long insn, tmp;
522
bfd_size_type addr = reloc_entry->address;
524
reloc_entry->address += input_section->output_offset;
526
insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
527
tmp = insn | 0xfc000000;
528
tmp -= (input_section->output_offset >> 2);
529
insn = (insn & 0xfc000000) | (tmp & 0x03ffffff);
530
bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
535
return bfd_reloc_continue;
538
#define TARGET_LITTLE_SYM bfd_elf32_or32_little_vec
539
#define TARGET_LITTLE_NAME "elf32-littleor32"
540
#define TARGET_BIG_SYM bfd_elf32_or32_big_vec
541
#define TARGET_BIG_NAME "elf32-or32"
542
#define ELF_ARCH bfd_arch_or32
543
#define ELF_MACHINE_CODE EM_OR32
544
#define ELF_MAXPAGESIZE 0x1000
546
#define elf_info_to_howto 0
547
#define elf_info_to_howto_rel or32_info_to_howto_rel
548
#define elf_backend_object_p or32_elf_object_p
549
#define elf_backend_final_write_processing \
550
or32_elf_final_write_processing
552
#include "elf32-target.h"