1
/* D10V-specific support for 32-bit ELF
2
Copyright 1996, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3
Contributed by Martin Hunt (hunt@cygnus.com).
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. */
27
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
28
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
29
static void d10v_info_to_howto_rel
30
PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
31
static asection * elf32_d10v_gc_mark_hook
32
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
33
struct elf_link_hash_entry *, Elf_Internal_Sym *));
34
static boolean elf32_d10v_gc_sweep_hook
35
PARAMS ((bfd *, struct bfd_link_info *, asection *,
36
const Elf_Internal_Rela *));
37
static boolean elf32_d10v_check_relocs
38
PARAMS ((bfd *, struct bfd_link_info *, asection *,
39
const Elf_Internal_Rela *));
40
static boolean elf32_d10v_relocate_section
41
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
42
bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *,
45
/* Use REL instead of RELA to save space. */
48
static reloc_howto_type elf_d10v_howto_table[] =
50
/* This reloc does nothing. */
51
HOWTO (R_D10V_NONE, /* type */
53
2, /* size (0 = byte, 1 = short, 2 = long) */
55
false, /* pc_relative */
57
complain_overflow_dont, /* complain_on_overflow */
58
bfd_elf_generic_reloc, /* special_function */
59
"R_D10V_NONE", /* name */
60
false, /* partial_inplace */
63
false), /* pcrel_offset */
65
/* An PC Relative 10-bit relocation, shifted by 2 */
67
HOWTO (R_D10V_10_PCREL_R, /* type */
69
2, /* size (0 = byte, 1 = short, 2 = long) */
71
true, /* pc_relative */
73
complain_overflow_bitfield, /* complain_on_overflow */
74
bfd_elf_generic_reloc, /* special_function */
75
"R_D10V_10_PCREL_R", /* name */
76
false, /* partial_inplace */
79
true), /* pcrel_offset */
81
/* An PC Relative 10-bit relocation, shifted by 2 */
83
HOWTO (R_D10V_10_PCREL_L, /* type */
85
2, /* size (0 = byte, 1 = short, 2 = long) */
87
true, /* pc_relative */
89
complain_overflow_bitfield, /* complain_on_overflow */
90
bfd_elf_generic_reloc, /* special_function */
91
"R_D10V_10_PCREL_L", /* name */
92
false, /* partial_inplace */
93
0x07f8000, /* src_mask */
94
0x07f8000, /* dst_mask */
95
true), /* pcrel_offset */
97
/* A 16 bit absolute relocation */
98
HOWTO (R_D10V_16, /* type */
100
1, /* size (0 = byte, 1 = short, 2 = long) */
102
false, /* pc_relative */
104
complain_overflow_dont, /* complain_on_overflow */
105
bfd_elf_generic_reloc, /* special_function */
106
"R_D10V_16", /* name */
107
false, /* partial_inplace */
108
0xffff, /* src_mask */
109
0xffff, /* dst_mask */
110
false), /* pcrel_offset */
112
/* An 18 bit absolute relocation, right shifted 2 */
113
HOWTO (R_D10V_18, /* type */
115
1, /* size (0 = byte, 1 = short, 2 = long) */
117
false, /* pc_relative */
119
complain_overflow_dont, /* complain_on_overflow */
120
bfd_elf_generic_reloc, /* special_function */
121
"R_D10V_18", /* name */
122
false, /* partial_inplace */
123
0xffff, /* src_mask */
124
0xffff, /* dst_mask */
125
false), /* pcrel_offset */
127
/* A relative 18 bit relocation, right shifted by 2 */
128
HOWTO (R_D10V_18_PCREL, /* type */
130
2, /* size (0 = byte, 1 = short, 2 = long) */
132
true, /* pc_relative */
134
complain_overflow_bitfield, /* complain_on_overflow */
135
bfd_elf_generic_reloc, /* special_function */
136
"R_D10V_18_PCREL", /* name */
137
false, /* partial_inplace */
138
0xffff, /* src_mask */
139
0xffff, /* dst_mask */
140
true), /* pcrel_offset */
142
/* A 32 bit absolute relocation */
143
HOWTO (R_D10V_32, /* type */
145
2, /* size (0 = byte, 1 = short, 2 = long) */
147
false, /* pc_relative */
149
complain_overflow_dont, /* complain_on_overflow */
150
bfd_elf_generic_reloc, /* special_function */
151
"R_D10V_32", /* name */
152
false, /* partial_inplace */
153
0xffffffff, /* src_mask */
154
0xffffffff, /* dst_mask */
155
false), /* pcrel_offset */
157
/* GNU extension to record C++ vtable hierarchy */
158
HOWTO (R_D10V_GNU_VTINHERIT, /* type */
160
2, /* size (0 = byte, 1 = short, 2 = long) */
162
false, /* pc_relative */
164
complain_overflow_dont, /* complain_on_overflow */
165
NULL, /* special_function */
166
"R_D10V_GNU_VTINHERIT", /* name */
167
false, /* partial_inplace */
170
false), /* pcrel_offset */
172
/* GNU extension to record C++ vtable member usage */
173
HOWTO (R_D10V_GNU_VTENTRY, /* type */
175
2, /* size (0 = byte, 1 = short, 2 = long) */
177
false, /* pc_relative */
179
complain_overflow_dont, /* complain_on_overflow */
180
_bfd_elf_rel_vtable_reloc_fn, /* special_function */
181
"R_D10V_GNU_VTENTRY", /* name */
182
false, /* partial_inplace */
185
false), /* pcrel_offset */
188
/* Map BFD reloc types to D10V ELF reloc types. */
190
struct d10v_reloc_map
192
bfd_reloc_code_real_type bfd_reloc_val;
193
unsigned char elf_reloc_val;
196
static const struct d10v_reloc_map d10v_reloc_map[] =
198
{ BFD_RELOC_NONE, R_D10V_NONE, },
199
{ BFD_RELOC_D10V_10_PCREL_R, R_D10V_10_PCREL_R },
200
{ BFD_RELOC_D10V_10_PCREL_L, R_D10V_10_PCREL_L },
201
{ BFD_RELOC_16, R_D10V_16 },
202
{ BFD_RELOC_D10V_18, R_D10V_18 },
203
{ BFD_RELOC_D10V_18_PCREL, R_D10V_18_PCREL },
204
{ BFD_RELOC_32, R_D10V_32 },
205
{ BFD_RELOC_VTABLE_INHERIT, R_D10V_GNU_VTINHERIT },
206
{ BFD_RELOC_VTABLE_ENTRY, R_D10V_GNU_VTENTRY },
209
static reloc_howto_type *
210
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
211
bfd *abfd ATTRIBUTE_UNUSED;
212
bfd_reloc_code_real_type code;
217
i < sizeof (d10v_reloc_map) / sizeof (struct d10v_reloc_map);
220
if (d10v_reloc_map[i].bfd_reloc_val == code)
221
return &elf_d10v_howto_table[d10v_reloc_map[i].elf_reloc_val];
227
/* Set the howto pointer for an D10V ELF reloc. */
230
d10v_info_to_howto_rel (abfd, cache_ptr, dst)
231
bfd *abfd ATTRIBUTE_UNUSED;
233
Elf32_Internal_Rel *dst;
237
r_type = ELF32_R_TYPE (dst->r_info);
238
BFD_ASSERT (r_type < (unsigned int) R_D10V_max);
239
cache_ptr->howto = &elf_d10v_howto_table[r_type];
243
elf32_d10v_gc_mark_hook (sec, info, rel, h, sym)
245
struct bfd_link_info *info ATTRIBUTE_UNUSED;
246
Elf_Internal_Rela *rel;
247
struct elf_link_hash_entry *h;
248
Elf_Internal_Sym *sym;
252
switch (ELF32_R_TYPE (rel->r_info))
254
case R_D10V_GNU_VTINHERIT:
255
case R_D10V_GNU_VTENTRY:
259
switch (h->root.type)
261
case bfd_link_hash_defined:
262
case bfd_link_hash_defweak:
263
return h->root.u.def.section;
265
case bfd_link_hash_common:
266
return h->root.u.c.p->section;
274
return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
280
elf32_d10v_gc_sweep_hook (abfd, info, sec, relocs)
281
bfd *abfd ATTRIBUTE_UNUSED;
282
struct bfd_link_info *info ATTRIBUTE_UNUSED;
283
asection *sec ATTRIBUTE_UNUSED;
284
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
286
/* we don't use got and plt entries for d10v */
290
/* Look through the relocs for a section during the first phase.
291
Since we don't do .gots or .plts, we just need to consider the
292
virtual table relocs for gc. */
295
elf32_d10v_check_relocs (abfd, info, sec, relocs)
297
struct bfd_link_info *info;
299
const Elf_Internal_Rela *relocs;
301
Elf_Internal_Shdr *symtab_hdr;
302
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
303
const Elf_Internal_Rela *rel;
304
const Elf_Internal_Rela *rel_end;
306
if (info->relocateable)
309
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
310
sym_hashes = elf_sym_hashes (abfd);
311
sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
312
if (!elf_bad_symtab (abfd))
313
sym_hashes_end -= symtab_hdr->sh_info;
315
rel_end = relocs + sec->reloc_count;
316
for (rel = relocs; rel < rel_end; rel++)
318
struct elf_link_hash_entry *h;
319
unsigned long r_symndx;
321
r_symndx = ELF32_R_SYM (rel->r_info);
322
if (r_symndx < symtab_hdr->sh_info)
325
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
327
switch (ELF32_R_TYPE (rel->r_info))
329
/* This relocation describes the C++ object vtable hierarchy.
330
Reconstruct it for later use during GC. */
331
case R_D10V_GNU_VTINHERIT:
332
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
336
/* This relocation describes which C++ vtable entries are actually
337
used. Record for later use during GC. */
338
case R_D10V_GNU_VTENTRY:
339
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_offset))
348
/* Relocate a D10V ELF section. */
350
elf32_d10v_relocate_section (output_bfd, info, input_bfd, input_section,
351
contents, relocs, local_syms, local_sections)
353
struct bfd_link_info *info;
355
asection *input_section;
357
Elf_Internal_Rela *relocs;
358
Elf_Internal_Sym *local_syms;
359
asection **local_sections;
361
Elf_Internal_Shdr *symtab_hdr;
362
struct elf_link_hash_entry **sym_hashes;
363
Elf_Internal_Rela *rel, *relend;
366
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
367
sym_hashes = elf_sym_hashes (input_bfd);
370
relend = relocs + input_section->reloc_count;
371
for (; rel < relend; rel++)
374
reloc_howto_type *howto;
375
unsigned long r_symndx;
376
Elf_Internal_Sym *sym;
378
struct elf_link_hash_entry *h;
380
bfd_reloc_status_type r;
382
r_symndx = ELF32_R_SYM (rel->r_info);
383
r_type = ELF32_R_TYPE (rel->r_info);
385
if (r_type == R_D10V_GNU_VTENTRY
386
|| r_type == R_D10V_GNU_VTINHERIT )
389
howto = elf_d10v_howto_table + r_type;
391
if (info->relocateable)
393
/* This is a relocateable link. We don't have to change
394
anything, unless the reloc is against a section symbol,
395
in which case we have to adjust according to where the
396
section symbol winds up in the output section. */
397
if (r_symndx < symtab_hdr->sh_info)
399
sym = local_syms + r_symndx;
400
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
402
sec = local_sections[r_symndx];
403
rel->r_addend += sec->output_offset + sym->st_value;
410
/* This is a final link. */
414
if (r_symndx < symtab_hdr->sh_info)
416
sym = local_syms + r_symndx;
417
sec = local_sections[r_symndx];
418
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
422
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
423
while (h->root.type == bfd_link_hash_indirect
424
|| h->root.type == bfd_link_hash_warning)
425
h = (struct elf_link_hash_entry *) h->root.u.i.link;
426
if (h->root.type == bfd_link_hash_defined
427
|| h->root.type == bfd_link_hash_defweak)
429
sec = h->root.u.def.section;
430
relocation = (h->root.u.def.value
431
+ sec->output_section->vma
432
+ sec->output_offset);
434
else if (h->root.type == bfd_link_hash_undefweak)
438
if (!((*info->callbacks->undefined_symbol)
439
(info, h->root.root.string, input_bfd,
440
input_section, rel->r_offset, true)))
447
name = h->root.root.string;
450
name = (bfd_elf_string_from_elf_section
451
(input_bfd, symtab_hdr->sh_link, sym->st_name));
452
if (name == NULL || *name == '\0')
453
name = bfd_section_name (input_bfd, sec);
456
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
457
contents, rel->r_offset,
458
relocation, rel->r_addend);
460
if (r != bfd_reloc_ok)
462
const char * msg = (const char *) 0;
466
case bfd_reloc_overflow:
467
if (!((*info->callbacks->reloc_overflow)
468
(info, name, howto->name, (bfd_vma) 0,
469
input_bfd, input_section, rel->r_offset)))
473
case bfd_reloc_undefined:
474
if (!((*info->callbacks->undefined_symbol)
475
(info, name, input_bfd, input_section,
476
rel->r_offset, true)))
480
case bfd_reloc_outofrange:
481
msg = _("internal error: out of range error");
484
case bfd_reloc_notsupported:
485
msg = _("internal error: unsupported relocation error");
488
case bfd_reloc_dangerous:
489
msg = _("internal error: dangerous error");
493
msg = _("internal error: unknown error");
497
if (!((*info->callbacks->warning)
498
(info, msg, name, input_bfd, input_section,
508
#define ELF_ARCH bfd_arch_d10v
509
#define ELF_MACHINE_CODE EM_D10V
510
#define ELF_MACHINE_ALT1 EM_CYGNUS_D10V
511
#define ELF_MAXPAGESIZE 0x1000
513
#define TARGET_BIG_SYM bfd_elf32_d10v_vec
514
#define TARGET_BIG_NAME "elf32-d10v"
516
#define elf_info_to_howto 0
517
#define elf_info_to_howto_rel d10v_info_to_howto_rel
518
#define elf_backend_object_p 0
519
#define elf_backend_final_write_processing 0
520
#define elf_backend_gc_mark_hook elf32_d10v_gc_mark_hook
521
#define elf_backend_gc_sweep_hook elf32_d10v_gc_sweep_hook
522
#define elf_backend_check_relocs elf32_d10v_check_relocs
523
#define elf_backend_relocate_section elf32_d10v_relocate_section
524
#define elf_backend_can_gc_sections 1
526
#include "elf32-target.h"