1 /* OpenRISC-specific support for 32-bit ELF.
2 Copyright (C) 2001 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 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. */
25 #include "elf/openrisc.h"
26 #include "libiberty.h"
28 /* Forward declarations. */
30 static reloc_howto_type
*openrisc_reloc_type_lookup
31 PARAMS ((bfd
* , bfd_reloc_code_real_type
));
32 static void openrisc_info_to_howto_rela
33 PARAMS ((bfd
*, arelent
*, Elf32_Internal_Rela
*));
34 static boolean openrisc_elf_relocate_section
35 PARAMS ((bfd
*, struct bfd_link_info
*, bfd
*, asection
*, bfd_byte
*,
36 Elf_Internal_Rela
*, Elf_Internal_Sym
*, asection
**));
37 static bfd_reloc_status_type openrisc_final_link_relocate
38 PARAMS ((reloc_howto_type
*, bfd
*, asection
*, bfd_byte
*,
39 Elf_Internal_Rela
*, bfd_vma
));
40 static boolean openrisc_elf_gc_sweep_hook
41 PARAMS ((bfd
*, struct bfd_link_info
*, asection
*,
42 const Elf_Internal_Rela
*));
43 static asection
*openrisc_elf_gc_mark_hook
44 PARAMS ((bfd
*, struct bfd_link_info
*, Elf_Internal_Rela
*,
45 struct elf_link_hash_entry
*, Elf_Internal_Sym
*));
48 static reloc_howto_type openrisc_elf_howto_table
[] =
50 /* This reloc does nothing. */
51 HOWTO (R_OPENRISC_NONE
, /* type */
53 2, /* size (0 = byte, 1 = short, 2 = long) */
55 false, /* pc_relative */
57 complain_overflow_bitfield
, /* complain_on_overflow */
58 bfd_elf_generic_reloc
, /* special_function */
59 "R_OPENRISC_NONE", /* name */
60 false, /* partial_inplace */
63 false), /* pcrel_offset */
65 /* A PC relative 26 bit relocation, right shifted by 2. */
66 HOWTO (R_OPENRISC_INSN_REL_26
, /* type */
68 2, /* size (0 = byte, 1 = short, 2 = long) */
70 true, /* pc_relative */
72 complain_overflow_signed
, /* complain_on_overflow */
73 bfd_elf_generic_reloc
, /* special_function */
74 "R_OPENRISC_INSN_REL_26", /* name */
75 false, /* partial_inplace */
76 0x00000000, /* src_mask */
77 0x03ffffff, /* dst_mask */
78 false), /* pcrel_offset */
80 /* A absolute 26 bit relocation, right shifted by 2. */
81 HOWTO (R_OPENRISC_INSN_ABS_26
, /* type */
83 2, /* size (0 = byte, 1 = short, 2 = long) */
85 false, /* pc_relative */
87 complain_overflow_signed
, /* complain_on_overflow */
88 bfd_elf_generic_reloc
, /* special_function */
89 "R_OPENRISC_INSN_ABS_26", /* name */
90 false, /* partial_inplace */
91 0x00000000, /* src_mask */
92 0x03ffffff, /* dst_mask */
93 false), /* pcrel_offset */
95 HOWTO (R_OPENRISC_LO_16_IN_INSN
, /* type */
97 1, /* size (0 = byte, 1 = short, 2 = long) */
99 false, /* pc_relative */
101 complain_overflow_dont
, /* complain_on_overflow */
102 bfd_elf_generic_reloc
, /* special_function */
103 "R_OPENRISC_LO_16_IN_INSN", /* name */
104 false, /* partial_inplace */
106 0x0000ffff, /* dst_mask */
107 false), /* pcrel_offset */
109 HOWTO (R_OPENRISC_HI_16_IN_INSN
, /* type */
111 1, /* size (0 = byte, 1 = short, 2 = long) */
113 false, /* pc_relative */
115 complain_overflow_dont
, /* complain_on_overflow */
116 bfd_elf_generic_reloc
, /* special_function */
117 "R_OPENRISC_HI_16_IN_INSN", /* name */
118 false, /* partial_inplace */
120 0x0000ffff, /* dst_mask */
121 false), /* pcrel_offset */
123 /* An 8 bit absolute relocation. */
124 HOWTO (R_OPENRISC_8
, /* type */
126 0, /* size (0 = byte, 1 = short, 2 = long) */
128 false, /* pc_relative */
130 complain_overflow_bitfield
, /* complain_on_overflow */
131 bfd_elf_generic_reloc
, /* special_function */
132 "R_OPENRISC_8", /* name */
133 true, /* partial_inplace */
134 0x0000, /* src_mask */
135 0x00ff, /* dst_mask */
136 false), /* pcrel_offset */
138 /* A 16 bit absolute relocation. */
139 HOWTO (R_OPENRISC_16
, /* type */
141 1, /* size (0 = byte, 1 = short, 2 = long) */
143 false, /* pc_relative */
145 complain_overflow_bitfield
, /* complain_on_overflow */
146 bfd_elf_generic_reloc
, /* special_function */
147 "R_OPENRISC_16", /* name */
148 true, /* partial_inplace */
149 0x00000000, /* src_mask */
150 0x0000ffff, /* dst_mask */
151 false), /* pcrel_offset */
153 /* A 32 bit absolute relocation. */
154 HOWTO (R_OPENRISC_32
, /* type */
156 2, /* size (0 = byte, 1 = short, 2 = long) */
158 false, /* pc_relative */
160 complain_overflow_bitfield
, /* complain_on_overflow */
161 bfd_elf_generic_reloc
, /* special_function */
162 "R_OPENRISC_32", /* name */
163 true, /* partial_inplace */
164 0x00000000, /* src_mask */
165 0xffffffff, /* dst_mask */
166 false), /* pcrel_offset */
168 /* GNU extension to record C++ vtable hierarchy */
169 HOWTO (R_OPENRISC_GNU_VTINHERIT
, /* type */
171 2, /* size (0 = byte, 1 = short, 2 = long) */
173 false, /* pc_relative */
175 complain_overflow_dont
, /* complain_on_overflow */
176 NULL
, /* special_function */
177 "R_OPENRISC_GNU_VTINHERIT", /* name */
178 false, /* partial_inplace */
181 false), /* pcrel_offset */
183 /* GNU extension to record C++ vtable member usage */
184 HOWTO (R_OPENRISC_GNU_VTENTRY
, /* type */
186 2, /* size (0 = byte, 1 = short, 2 = long) */
188 false, /* pc_relative */
190 complain_overflow_dont
, /* complain_on_overflow */
191 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
192 "R_OPENRISC_GNU_VTENTRY", /* name */
193 false, /* partial_inplace */
196 false), /* pcrel_offset */
199 /* Map BFD reloc types to OpenRISC ELF reloc types. */
201 struct openrisc_reloc_map
203 bfd_reloc_code_real_type bfd_reloc_val
;
204 unsigned int openrisc_reloc_val
;
207 static const struct openrisc_reloc_map openrisc_reloc_map
[] =
209 { BFD_RELOC_NONE
, R_OPENRISC_NONE
},
210 { BFD_RELOC_32
, R_OPENRISC_32
},
211 { BFD_RELOC_16
, R_OPENRISC_16
},
212 { BFD_RELOC_8
, R_OPENRISC_8
},
213 { BFD_RELOC_OPENRISC_REL_26
,R_OPENRISC_INSN_REL_26
},
214 { BFD_RELOC_OPENRISC_ABS_26
,R_OPENRISC_INSN_ABS_26
},
215 { BFD_RELOC_HI16
, R_OPENRISC_HI_16_IN_INSN
},
216 { BFD_RELOC_LO16
, R_OPENRISC_LO_16_IN_INSN
},
217 { BFD_RELOC_VTABLE_INHERIT
, R_OPENRISC_GNU_VTINHERIT
},
218 { BFD_RELOC_VTABLE_ENTRY
, R_OPENRISC_GNU_VTENTRY
}
221 static reloc_howto_type
*
222 openrisc_reloc_type_lookup (abfd
, code
)
223 bfd
* abfd ATTRIBUTE_UNUSED
;
224 bfd_reloc_code_real_type code
;
228 for (i
= ARRAY_SIZE (openrisc_reloc_map
); --i
;)
229 if (openrisc_reloc_map
[i
].bfd_reloc_val
== code
)
230 return & openrisc_elf_howto_table
[openrisc_reloc_map
[i
].
236 /* Set the howto pointer for an OpenRISC ELF reloc. */
239 openrisc_info_to_howto_rela (abfd
, cache_ptr
, dst
)
240 bfd
* abfd ATTRIBUTE_UNUSED
;
242 Elf32_Internal_Rela
* dst
;
246 r_type
= ELF32_R_TYPE (dst
->r_info
);
247 BFD_ASSERT (r_type
< (unsigned int) R_OPENRISC_max
);
248 cache_ptr
->howto
= & openrisc_elf_howto_table
[r_type
];
251 /* Perform a single relocation. By default we use the standard BFD
252 routines, but a few relocs, we have to do them ourselves. */
254 static bfd_reloc_status_type
255 openrisc_final_link_relocate (howto
, input_bfd
, input_section
, contents
, rel
,
257 reloc_howto_type
*howto
;
259 asection
*input_section
;
261 Elf_Internal_Rela
*rel
;
264 bfd_reloc_status_type r
= bfd_reloc_ok
;
268 case R_OPENRISC_LO_16_IN_INSN
:
269 relocation
&= 0xffff;
270 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
271 contents
, rel
->r_offset
,
272 relocation
, rel
->r_addend
);
276 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
277 contents
, rel
->r_offset
,
278 relocation
, rel
->r_addend
);
284 /* Relocate an OpenRISC ELF section.
285 There is some attempt to make this function usable for many architectures,
286 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
287 if only to serve as a learning tool.
289 The RELOCATE_SECTION function is called by the new ELF backend linker
290 to handle the relocations for a section.
292 The relocs are always passed as Rela structures; if the section
293 actually uses Rel structures, the r_addend field will always be
296 This function is responsible for adjusting the section contents as
297 necessary, and (if using Rela relocs and generating a relocateable
298 output file) adjusting the reloc addend as necessary.
300 This function does not have to worry about setting the reloc
301 address or the reloc symbol index.
303 LOCAL_SYMS is a pointer to the swapped in local symbols.
305 LOCAL_SECTIONS is an array giving the section in the input file
306 corresponding to the st_shndx field of each local symbol.
308 The global hash table entry for the global symbols can be found
309 via elf_sym_hashes (input_bfd).
311 When generating relocateable output, this function must handle
312 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
313 going to be the section symbol corresponding to the output
314 section, which means that the addend must be adjusted
318 openrisc_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
319 contents
, relocs
, local_syms
, local_sections
)
320 bfd
*output_bfd ATTRIBUTE_UNUSED
;
321 struct bfd_link_info
*info
;
323 asection
*input_section
;
325 Elf_Internal_Rela
*relocs
;
326 Elf_Internal_Sym
*local_syms
;
327 asection
**local_sections
;
329 Elf_Internal_Shdr
*symtab_hdr
;
330 struct elf_link_hash_entry
**sym_hashes
;
331 Elf_Internal_Rela
*rel
;
332 Elf_Internal_Rela
*relend
;
334 symtab_hdr
= &elf_tdata (input_bfd
)->symtab_hdr
;
335 sym_hashes
= elf_sym_hashes (input_bfd
);
336 relend
= relocs
+ input_section
->reloc_count
;
338 for (rel
= relocs
; rel
< relend
; rel
++)
340 reloc_howto_type
*howto
;
341 unsigned long r_symndx
;
342 Elf_Internal_Sym
*sym
;
344 struct elf_link_hash_entry
*h
;
346 bfd_reloc_status_type r
;
347 const char *name
= NULL
;
350 r_type
= ELF32_R_TYPE (rel
->r_info
);
351 r_symndx
= ELF32_R_SYM (rel
->r_info
);
353 if (r_type
== R_OPENRISC_GNU_VTINHERIT
354 || r_type
== R_OPENRISC_GNU_VTENTRY
)
357 if (info
->relocateable
)
359 /* This is a relocateable link. We don't have to change
360 anything, unless the reloc is against a section symbol,
361 in which case we have to adjust according to where the
362 section symbol winds up in the output section. */
363 if (r_symndx
< symtab_hdr
->sh_info
)
365 sym
= local_syms
+ r_symndx
;
367 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
369 sec
= local_sections
[r_symndx
];
370 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
376 if ((unsigned int) r_type
>
377 (sizeof openrisc_elf_howto_table
/ sizeof (reloc_howto_type
)))
380 /* This is a final link. */
381 howto
= openrisc_elf_howto_table
+ ELF32_R_TYPE (rel
->r_info
);
386 if (r_symndx
< symtab_hdr
->sh_info
)
388 sym
= local_syms
+ r_symndx
;
389 sec
= local_sections
[r_symndx
];
390 relocation
= (sec
->output_section
->vma
391 + sec
->output_offset
+ sym
->st_value
);
393 name
= bfd_elf_string_from_elf_section
394 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
395 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
399 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
401 while (h
->root
.type
== bfd_link_hash_indirect
402 || h
->root
.type
== bfd_link_hash_warning
)
403 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
405 name
= h
->root
.root
.string
;
407 if (h
->root
.type
== bfd_link_hash_defined
408 || h
->root
.type
== bfd_link_hash_defweak
)
410 sec
= h
->root
.u
.def
.section
;
411 relocation
= (h
->root
.u
.def
.value
412 + sec
->output_section
->vma
+ sec
->output_offset
);
414 else if (h
->root
.type
== bfd_link_hash_undefweak
)
420 if (!((*info
->callbacks
->undefined_symbol
)
421 (info
, h
->root
.root
.string
, input_bfd
,
422 input_section
, rel
->r_offset
, true)))
428 r
= openrisc_final_link_relocate (howto
, input_bfd
, input_section
,
429 contents
, rel
, relocation
);
431 if (r
!= bfd_reloc_ok
)
433 const char *msg
= (const char *) NULL
;
437 case bfd_reloc_overflow
:
438 r
= info
->callbacks
->reloc_overflow
439 (info
, name
, howto
->name
, (bfd_vma
) 0,
440 input_bfd
, input_section
, rel
->r_offset
);
443 case bfd_reloc_undefined
:
444 r
= info
->callbacks
->undefined_symbol
445 (info
, name
, input_bfd
, input_section
, rel
->r_offset
, true);
448 case bfd_reloc_outofrange
:
449 msg
= _("internal error: out of range error");
452 case bfd_reloc_notsupported
:
453 msg
= _("internal error: unsupported relocation error");
456 case bfd_reloc_dangerous
:
457 msg
= _("internal error: dangerous relocation");
461 msg
= _("internal error: unknown error");
466 r
= info
->callbacks
->warning
467 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
477 /* Return the section that should be marked against GC for a given
481 openrisc_elf_gc_mark_hook (abfd
, info
, rel
, h
, sym
)
482 bfd
*abfd ATTRIBUTE_UNUSED
;
483 struct bfd_link_info
*info ATTRIBUTE_UNUSED
;
484 Elf_Internal_Rela
*rel ATTRIBUTE_UNUSED
;
485 struct elf_link_hash_entry
*h ATTRIBUTE_UNUSED
;
486 Elf_Internal_Sym
*sym ATTRIBUTE_UNUSED
;
490 switch (ELF32_R_TYPE (rel
->r_info
))
492 case R_OPENRISC_GNU_VTINHERIT
:
493 case R_OPENRISC_GNU_VTENTRY
:
497 switch (h
->root
.type
)
499 case bfd_link_hash_defined
:
500 case bfd_link_hash_defweak
:
501 return h
->root
.u
.def
.section
;
503 case bfd_link_hash_common
:
504 return h
->root
.u
.c
.p
->section
;
513 if (!(elf_bad_symtab (abfd
)
514 && ELF_ST_BIND (sym
->st_info
) != STB_LOCAL
)
515 && !((sym
->st_shndx
<= 0 || sym
->st_shndx
>= SHN_LORESERVE
)
516 && sym
->st_shndx
!= SHN_COMMON
))
518 return bfd_section_from_elf_index (abfd
, sym
->st_shndx
);
525 /* Update the got entry reference counts for the section being removed. */
528 openrisc_elf_gc_sweep_hook (abfd
, info
, sec
, relocs
)
529 bfd
*abfd ATTRIBUTE_UNUSED
;
530 struct bfd_link_info
*info ATTRIBUTE_UNUSED
;
531 asection
*sec ATTRIBUTE_UNUSED
;
532 const Elf_Internal_Rela
*relocs ATTRIBUTE_UNUSED
;
537 /* Look through the relocs for a section during the first phase.
538 Since we don't do .gots or .plts, we just need to consider the
539 virtual table relocs for gc. */
542 openrisc_elf_check_relocs (abfd
, info
, sec
, relocs
)
544 struct bfd_link_info
*info
;
546 const Elf_Internal_Rela
*relocs
;
548 Elf_Internal_Shdr
*symtab_hdr
;
549 struct elf_link_hash_entry
**sym_hashes
, **sym_hashes_end
;
550 const Elf_Internal_Rela
*rel
;
551 const Elf_Internal_Rela
*rel_end
;
553 if (info
->relocateable
)
556 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
557 sym_hashes
= elf_sym_hashes (abfd
);
559 sym_hashes
+ symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
);
560 if (!elf_bad_symtab (abfd
))
561 sym_hashes_end
-= symtab_hdr
->sh_info
;
563 rel_end
= relocs
+ sec
->reloc_count
;
564 for (rel
= relocs
; rel
< rel_end
; rel
++)
566 struct elf_link_hash_entry
*h
;
567 unsigned long r_symndx
;
569 r_symndx
= ELF32_R_SYM (rel
->r_info
);
570 if (r_symndx
< symtab_hdr
->sh_info
)
573 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
575 switch (ELF32_R_TYPE (rel
->r_info
))
577 /* This relocation describes the C++ object vtable hierarchy.
578 Reconstruct it for later use during GC. */
579 case R_OPENRISC_GNU_VTINHERIT
:
580 if (!_bfd_elf32_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
584 /* This relocation describes which C++ vtable entries are actually
585 used. Record for later use during GC. */
586 case R_OPENRISC_GNU_VTENTRY
:
587 if (!_bfd_elf32_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
596 /* Set the right machine number. */
599 openrisc_elf_object_p (abfd
)
602 switch (elf_elfheader (abfd
)->e_flags
& 0xf)
605 (void) bfd_default_set_arch_mach (abfd
, bfd_arch_openrisc
, 0);
611 /* Store the machine number in the flags field. */
614 openrisc_elf_final_write_processing (abfd
, linker
)
616 boolean linker ATTRIBUTE_UNUSED
;
620 switch (bfd_get_mach (abfd
))
627 elf_elfheader (abfd
)->e_flags
&= ~0xf;
628 elf_elfheader (abfd
)->e_flags
|= val
;
632 #define ELF_ARCH bfd_arch_openrisc
633 #define ELF_MACHINE_CODE EM_OPENRISC
634 #define ELF_MAXPAGESIZE 0x1000
636 #define TARGET_BIG_SYM bfd_elf32_openrisc_vec
637 #define TARGET_BIG_NAME "elf32-openrisc"
639 #define elf_info_to_howto_rel NULL
640 #define elf_info_to_howto openrisc_info_to_howto_rela
641 #define elf_backend_relocate_section openrisc_elf_relocate_section
642 #define elf_backend_gc_mark_hook openrisc_elf_gc_mark_hook
643 #define elf_backend_gc_sweep_hook openrisc_elf_gc_sweep_hook
644 #define elf_backend_check_relocs openrisc_elf_check_relocs
646 #define elf_backend_can_gc_sections 1
648 #define bfd_elf32_bfd_reloc_type_lookup openrisc_reloc_type_lookup
650 #define elf_backend_object_p openrisc_elf_object_p
651 #define elf_backend_final_write_processing openrisc_elf_final_write_processing
653 #include "elf32-target.h"