1 /* OpenRISC-specific support for 32-bit ELF.
2 Copyright (C) 2001-2014 Free Software Foundation, Inc.
3 Contributed by Johan Rydberg, jrydberg@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 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/openrisc.h"
27 #include "libiberty.h"
29 static reloc_howto_type openrisc_elf_howto_table
[] =
31 /* This reloc does nothing. */
32 HOWTO (R_OPENRISC_NONE
, /* type */
34 2, /* size (0 = byte, 1 = short, 2 = long) */
36 FALSE
, /* pc_relative */
38 complain_overflow_bitfield
, /* complain_on_overflow */
39 bfd_elf_generic_reloc
, /* special_function */
40 "R_OPENRISC_NONE", /* name */
41 FALSE
, /* partial_inplace */
44 FALSE
), /* pcrel_offset */
46 /* A PC relative 26 bit relocation, right shifted by 2. */
47 HOWTO (R_OPENRISC_INSN_REL_26
, /* type */
49 2, /* size (0 = byte, 1 = short, 2 = long) */
51 TRUE
, /* pc_relative */
53 complain_overflow_signed
, /* complain_on_overflow */
54 bfd_elf_generic_reloc
, /* special_function */
55 "R_OPENRISC_INSN_REL_26", /* name */
56 FALSE
, /* partial_inplace */
57 0x00000000, /* src_mask */
58 0x03ffffff, /* dst_mask */
59 FALSE
), /* pcrel_offset */
61 /* A absolute 26 bit relocation, right shifted by 2. */
62 HOWTO (R_OPENRISC_INSN_ABS_26
, /* type */
64 2, /* size (0 = byte, 1 = short, 2 = long) */
66 FALSE
, /* pc_relative */
68 complain_overflow_signed
, /* complain_on_overflow */
69 bfd_elf_generic_reloc
, /* special_function */
70 "R_OPENRISC_INSN_ABS_26", /* name */
71 FALSE
, /* partial_inplace */
72 0x00000000, /* src_mask */
73 0x03ffffff, /* dst_mask */
74 FALSE
), /* pcrel_offset */
76 HOWTO (R_OPENRISC_LO_16_IN_INSN
, /* type */
78 1, /* size (0 = byte, 1 = short, 2 = long) */
80 FALSE
, /* pc_relative */
82 complain_overflow_dont
, /* complain_on_overflow */
83 bfd_elf_generic_reloc
, /* special_function */
84 "R_OPENRISC_LO_16_IN_INSN", /* name */
85 FALSE
, /* partial_inplace */
87 0x0000ffff, /* dst_mask */
88 FALSE
), /* pcrel_offset */
90 HOWTO (R_OPENRISC_HI_16_IN_INSN
, /* type */
92 1, /* size (0 = byte, 1 = short, 2 = long) */
94 FALSE
, /* pc_relative */
96 complain_overflow_dont
, /* complain_on_overflow */
97 bfd_elf_generic_reloc
, /* special_function */
98 "R_OPENRISC_HI_16_IN_INSN", /* name */
99 FALSE
, /* partial_inplace */
101 0x0000ffff, /* dst_mask */
102 FALSE
), /* pcrel_offset */
104 /* An 8 bit absolute relocation. */
105 HOWTO (R_OPENRISC_8
, /* type */
107 0, /* size (0 = byte, 1 = short, 2 = long) */
109 FALSE
, /* pc_relative */
111 complain_overflow_bitfield
, /* complain_on_overflow */
112 bfd_elf_generic_reloc
, /* special_function */
113 "R_OPENRISC_8", /* name */
114 TRUE
, /* partial_inplace */
115 0x0000, /* src_mask */
116 0x00ff, /* dst_mask */
117 FALSE
), /* pcrel_offset */
119 /* A 16 bit absolute relocation. */
120 HOWTO (R_OPENRISC_16
, /* type */
122 1, /* size (0 = byte, 1 = short, 2 = long) */
124 FALSE
, /* pc_relative */
126 complain_overflow_bitfield
, /* complain_on_overflow */
127 bfd_elf_generic_reloc
, /* special_function */
128 "R_OPENRISC_16", /* name */
129 TRUE
, /* partial_inplace */
130 0x00000000, /* src_mask */
131 0x0000ffff, /* dst_mask */
132 FALSE
), /* pcrel_offset */
134 /* A 32 bit absolute relocation. */
135 HOWTO (R_OPENRISC_32
, /* type */
137 2, /* size (0 = byte, 1 = short, 2 = long) */
139 FALSE
, /* pc_relative */
141 complain_overflow_bitfield
, /* complain_on_overflow */
142 bfd_elf_generic_reloc
, /* special_function */
143 "R_OPENRISC_32", /* name */
144 TRUE
, /* partial_inplace */
145 0x00000000, /* src_mask */
146 0xffffffff, /* dst_mask */
147 FALSE
), /* pcrel_offset */
149 /* GNU extension to record C++ vtable hierarchy. */
150 HOWTO (R_OPENRISC_GNU_VTINHERIT
, /* type */
152 2, /* size (0 = byte, 1 = short, 2 = long) */
154 FALSE
, /* pc_relative */
156 complain_overflow_dont
, /* complain_on_overflow */
157 NULL
, /* special_function */
158 "R_OPENRISC_GNU_VTINHERIT", /* name */
159 FALSE
, /* partial_inplace */
162 FALSE
), /* pcrel_offset */
164 /* GNU extension to record C++ vtable member usage. */
165 HOWTO (R_OPENRISC_GNU_VTENTRY
, /* type */
167 2, /* size (0 = byte, 1 = short, 2 = long) */
169 FALSE
, /* pc_relative */
171 complain_overflow_dont
, /* complain_on_overflow */
172 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
173 "R_OPENRISC_GNU_VTENTRY", /* name */
174 FALSE
, /* partial_inplace */
177 FALSE
), /* pcrel_offset */
180 /* Map BFD reloc types to OpenRISC ELF reloc types. */
182 struct openrisc_reloc_map
184 bfd_reloc_code_real_type bfd_reloc_val
;
185 unsigned int openrisc_reloc_val
;
188 static const struct openrisc_reloc_map openrisc_reloc_map
[] =
190 { BFD_RELOC_NONE
, R_OPENRISC_NONE
},
191 { BFD_RELOC_32
, R_OPENRISC_32
},
192 { BFD_RELOC_16
, R_OPENRISC_16
},
193 { BFD_RELOC_8
, R_OPENRISC_8
},
194 { BFD_RELOC_OPENRISC_REL_26
, R_OPENRISC_INSN_REL_26
},
195 { BFD_RELOC_OPENRISC_ABS_26
, R_OPENRISC_INSN_ABS_26
},
196 { BFD_RELOC_HI16
, R_OPENRISC_HI_16_IN_INSN
},
197 { BFD_RELOC_LO16
, R_OPENRISC_LO_16_IN_INSN
},
198 { BFD_RELOC_VTABLE_INHERIT
, R_OPENRISC_GNU_VTINHERIT
},
199 { BFD_RELOC_VTABLE_ENTRY
, R_OPENRISC_GNU_VTENTRY
}
202 static reloc_howto_type
*
203 openrisc_reloc_type_lookup (bfd
* abfd ATTRIBUTE_UNUSED
,
204 bfd_reloc_code_real_type code
)
208 for (i
= ARRAY_SIZE (openrisc_reloc_map
); --i
;)
209 if (openrisc_reloc_map
[i
].bfd_reloc_val
== code
)
210 return & openrisc_elf_howto_table
[openrisc_reloc_map
[i
].
216 static reloc_howto_type
*
217 openrisc_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
223 i
< (sizeof (openrisc_elf_howto_table
)
224 / sizeof (openrisc_elf_howto_table
[0]));
226 if (openrisc_elf_howto_table
[i
].name
!= NULL
227 && strcasecmp (openrisc_elf_howto_table
[i
].name
, r_name
) == 0)
228 return &openrisc_elf_howto_table
[i
];
233 /* Set the howto pointer for an OpenRISC ELF reloc. */
236 openrisc_info_to_howto_rela (bfd
* abfd ATTRIBUTE_UNUSED
,
238 Elf_Internal_Rela
* dst
)
242 r_type
= ELF32_R_TYPE (dst
->r_info
);
243 BFD_ASSERT (r_type
< (unsigned int) R_OPENRISC_max
);
244 cache_ptr
->howto
= & openrisc_elf_howto_table
[r_type
];
247 /* Perform a single relocation. By default we use the standard BFD
248 routines, but a few relocs, we have to do them ourselves. */
250 static bfd_reloc_status_type
251 openrisc_final_link_relocate (reloc_howto_type
*howto
,
253 asection
*input_section
,
255 Elf_Internal_Rela
*rel
,
258 bfd_reloc_status_type r
= bfd_reloc_ok
;
262 case R_OPENRISC_LO_16_IN_INSN
:
263 relocation
&= 0xffff;
264 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
265 contents
, rel
->r_offset
,
266 relocation
, rel
->r_addend
);
270 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
271 contents
, rel
->r_offset
,
272 relocation
, rel
->r_addend
);
278 /* Relocate an OpenRISC ELF section.
280 The RELOCATE_SECTION function is called by the new ELF backend linker
281 to handle the relocations for a section.
283 The relocs are always passed as Rela structures; if the section
284 actually uses Rel structures, the r_addend field will always be
287 This function is responsible for adjusting the section contents as
288 necessary, and (if using Rela relocs and generating a relocatable
289 output file) adjusting the reloc addend as necessary.
291 This function does not have to worry about setting the reloc
292 address or the reloc symbol index.
294 LOCAL_SYMS is a pointer to the swapped in local symbols.
296 LOCAL_SECTIONS is an array giving the section in the input file
297 corresponding to the st_shndx field of each local symbol.
299 The global hash table entry for the global symbols can be found
300 via elf_sym_hashes (input_bfd).
302 When generating relocatable output, this function must handle
303 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
304 going to be the section symbol corresponding to the output
305 section, which means that the addend must be adjusted
309 openrisc_elf_relocate_section (bfd
*output_bfd
,
310 struct bfd_link_info
*info
,
312 asection
*input_section
,
314 Elf_Internal_Rela
*relocs
,
315 Elf_Internal_Sym
*local_syms
,
316 asection
**local_sections
)
318 Elf_Internal_Shdr
*symtab_hdr
;
319 struct elf_link_hash_entry
**sym_hashes
;
320 Elf_Internal_Rela
*rel
;
321 Elf_Internal_Rela
*relend
;
323 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
324 sym_hashes
= elf_sym_hashes (input_bfd
);
325 relend
= relocs
+ input_section
->reloc_count
;
327 for (rel
= relocs
; rel
< relend
; rel
++)
329 reloc_howto_type
*howto
;
330 unsigned long r_symndx
;
331 Elf_Internal_Sym
*sym
;
333 struct elf_link_hash_entry
*h
;
335 bfd_reloc_status_type r
;
336 const char *name
= NULL
;
339 r_type
= ELF32_R_TYPE (rel
->r_info
);
340 r_symndx
= ELF32_R_SYM (rel
->r_info
);
342 if (r_type
== R_OPENRISC_GNU_VTINHERIT
343 || r_type
== R_OPENRISC_GNU_VTENTRY
)
346 if ((unsigned int) r_type
>
347 (sizeof openrisc_elf_howto_table
/ sizeof (reloc_howto_type
)))
350 howto
= openrisc_elf_howto_table
+ ELF32_R_TYPE (rel
->r_info
);
355 if (r_symndx
< symtab_hdr
->sh_info
)
357 sym
= local_syms
+ r_symndx
;
358 sec
= local_sections
[r_symndx
];
359 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
361 name
= bfd_elf_string_from_elf_section
362 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
363 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
367 bfd_boolean unresolved_reloc
, warned
, ignored
;
369 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
370 r_symndx
, symtab_hdr
, sym_hashes
,
372 unresolved_reloc
, warned
, ignored
);
375 if (sec
!= NULL
&& discarded_section (sec
))
376 RELOC_AGAINST_DISCARDED_SECTION (info
, input_bfd
, input_section
,
377 rel
, 1, relend
, howto
, 0, contents
);
379 if (info
->relocatable
)
382 r
= openrisc_final_link_relocate (howto
, input_bfd
, input_section
,
383 contents
, rel
, relocation
);
385 if (r
!= bfd_reloc_ok
)
387 const char *msg
= NULL
;
391 case bfd_reloc_overflow
:
392 r
= info
->callbacks
->reloc_overflow
393 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
394 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
397 case bfd_reloc_undefined
:
398 r
= info
->callbacks
->undefined_symbol
399 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, TRUE
);
402 case bfd_reloc_outofrange
:
403 msg
= _("internal error: out of range error");
406 case bfd_reloc_notsupported
:
407 msg
= _("internal error: unsupported relocation error");
410 case bfd_reloc_dangerous
:
411 msg
= _("internal error: dangerous relocation");
415 msg
= _("internal error: unknown error");
420 r
= info
->callbacks
->warning
421 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
431 /* Return the section that should be marked against GC for a given
435 openrisc_elf_gc_mark_hook (asection
*sec
,
436 struct bfd_link_info
*info
,
437 Elf_Internal_Rela
*rel
,
438 struct elf_link_hash_entry
*h
,
439 Elf_Internal_Sym
*sym
)
442 switch (ELF32_R_TYPE (rel
->r_info
))
444 case R_OPENRISC_GNU_VTINHERIT
:
445 case R_OPENRISC_GNU_VTENTRY
:
449 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
452 /* Look through the relocs for a section during the first phase.
453 Since we don't do .gots or .plts, we just need to consider the
454 virtual table relocs for gc. */
457 openrisc_elf_check_relocs (bfd
*abfd
,
458 struct bfd_link_info
*info
,
460 const Elf_Internal_Rela
*relocs
)
462 Elf_Internal_Shdr
*symtab_hdr
;
463 struct elf_link_hash_entry
**sym_hashes
;
464 const Elf_Internal_Rela
*rel
;
465 const Elf_Internal_Rela
*rel_end
;
467 if (info
->relocatable
)
470 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
471 sym_hashes
= elf_sym_hashes (abfd
);
473 rel_end
= relocs
+ sec
->reloc_count
;
474 for (rel
= relocs
; rel
< rel_end
; rel
++)
476 struct elf_link_hash_entry
*h
;
477 unsigned long r_symndx
;
479 r_symndx
= ELF32_R_SYM (rel
->r_info
);
480 if (r_symndx
< symtab_hdr
->sh_info
)
484 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
485 while (h
->root
.type
== bfd_link_hash_indirect
486 || h
->root
.type
== bfd_link_hash_warning
)
487 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
489 /* PR15323, ref flags aren't set for references in the same
491 h
->root
.non_ir_ref
= 1;
494 switch (ELF32_R_TYPE (rel
->r_info
))
496 /* This relocation describes the C++ object vtable hierarchy.
497 Reconstruct it for later use during GC. */
498 case R_OPENRISC_GNU_VTINHERIT
:
499 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
503 /* This relocation describes which C++ vtable entries are actually
504 used. Record for later use during GC. */
505 case R_OPENRISC_GNU_VTENTRY
:
506 BFD_ASSERT (h
!= NULL
);
508 && !bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
517 /* Set the right machine number. */
520 openrisc_elf_object_p (bfd
*abfd
)
522 bfd_default_set_arch_mach (abfd
, bfd_arch_openrisc
, 0);
526 /* Store the machine number in the flags field. */
529 openrisc_elf_final_write_processing (bfd
*abfd
,
530 bfd_boolean linker ATTRIBUTE_UNUSED
)
534 switch (bfd_get_mach (abfd
))
541 elf_elfheader (abfd
)->e_flags
&= ~0xf;
542 elf_elfheader (abfd
)->e_flags
|= val
;
546 #define ELF_ARCH bfd_arch_openrisc
547 #define ELF_MACHINE_CODE EM_OPENRISC
548 #define ELF_MACHINE_ALT1 EM_OPENRISC_OLD
549 #define ELF_MAXPAGESIZE 0x1000
551 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
552 #define TARGET_BIG_NAME "elf32-openrisc"
554 #define elf_info_to_howto_rel NULL
555 #define elf_info_to_howto openrisc_info_to_howto_rela
556 #define elf_backend_relocate_section openrisc_elf_relocate_section
557 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
558 #define elf_backend_check_relocs openrisc_elf_check_relocs
560 #define elf_backend_can_gc_sections 1
561 #define elf_backend_rela_normal 1
563 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
564 #define bfd_elf32_bfd_reloc_name_lookup openrisc_reloc_name_lookup
566 #define elf_backend_object_p openrisc_elf_object_p
567 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
569 #include "elf32-target.h"