1 /* moxie-specific support for 32-bit ELF.
2 Copyright 2009, 2010 Free Software Foundation, Inc.
4 Copied from elf32-fr30.c which is..
5 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
6 Free Software Foundation, Inc.
8 This file is part of BFD, the Binary File Descriptor library.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23 MA 02110-1301, USA. */
29 #include "elf/moxie.h"
31 /* Forward declarations. */
33 static reloc_howto_type moxie_elf_howto_table
[] =
35 /* This reloc does nothing. */
36 HOWTO (R_MOXIE_NONE
, /* type */
38 2, /* size (0 = byte, 1 = short, 2 = long) */
40 FALSE
, /* pc_relative */
42 complain_overflow_bitfield
, /* complain_on_overflow */
43 bfd_elf_generic_reloc
, /* special_function */
44 "R_MOXIE_NONE", /* name */
45 FALSE
, /* partial_inplace */
48 FALSE
), /* pcrel_offset */
50 /* A 32 bit absolute relocation. */
51 HOWTO (R_MOXIE_32
, /* 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_MOXIE_32", /* name */
60 FALSE
, /* partial_inplace */
61 0x00000000, /* src_mask */
62 0xffffffff, /* dst_mask */
63 FALSE
), /* pcrel_offset */
65 /* A 10 bit PC-relative relocation. */
66 HOWTO (R_MOXIE_PCREL10
, /* type. */
68 1, /* 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_MOXIE_PCREL10", /* name. */
75 FALSE
, /* partial_inplace. */
77 0x000003FF, /* dst_mask. */
78 TRUE
), /* pcrel_offset. */
81 /* Map BFD reloc types to MOXIE ELF reloc types. */
83 struct moxie_reloc_map
85 bfd_reloc_code_real_type bfd_reloc_val
;
86 unsigned int moxie_reloc_val
;
89 static const struct moxie_reloc_map moxie_reloc_map
[] =
91 { BFD_RELOC_NONE
, R_MOXIE_NONE
},
92 { BFD_RELOC_32
, R_MOXIE_32
},
93 { BFD_RELOC_MOXIE_10_PCREL
, R_MOXIE_PCREL10
},
96 static reloc_howto_type
*
97 moxie_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
98 bfd_reloc_code_real_type code
)
102 for (i
= sizeof (moxie_reloc_map
) / sizeof (moxie_reloc_map
[0]);
104 if (moxie_reloc_map
[i
].bfd_reloc_val
== code
)
105 return & moxie_elf_howto_table
[moxie_reloc_map
[i
].moxie_reloc_val
];
110 static reloc_howto_type
*
111 moxie_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
, const char *r_name
)
116 i
< sizeof (moxie_elf_howto_table
) / sizeof (moxie_elf_howto_table
[0]);
118 if (moxie_elf_howto_table
[i
].name
!= NULL
119 && strcasecmp (moxie_elf_howto_table
[i
].name
, r_name
) == 0)
120 return &moxie_elf_howto_table
[i
];
125 /* Set the howto pointer for an MOXIE ELF reloc. */
128 moxie_info_to_howto_rela (bfd
*abfd ATTRIBUTE_UNUSED
,
130 Elf_Internal_Rela
*dst
)
134 r_type
= ELF32_R_TYPE (dst
->r_info
);
135 BFD_ASSERT (r_type
< (unsigned int) R_MOXIE_max
);
136 cache_ptr
->howto
= & moxie_elf_howto_table
[r_type
];
139 /* Perform a single relocation. By default we use the standard BFD
140 routines, but a few relocs, we have to do them ourselves. */
142 static bfd_reloc_status_type
143 moxie_final_link_relocate (reloc_howto_type
*howto
,
145 asection
*input_section
,
147 Elf_Internal_Rela
*rel
,
150 bfd_reloc_status_type r
= bfd_reloc_ok
;
155 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
156 contents
, rel
->r_offset
,
157 relocation
, rel
->r_addend
);
163 /* Relocate an MOXIE ELF section.
165 The RELOCATE_SECTION function is called by the new ELF backend linker
166 to handle the relocations for a section.
168 The relocs are always passed as Rela structures; if the section
169 actually uses Rel structures, the r_addend field will always be
172 This function is responsible for adjusting the section contents as
173 necessary, and (if using Rela relocs and generating a relocatable
174 output file) adjusting the reloc addend as necessary.
176 This function does not have to worry about setting the reloc
177 address or the reloc symbol index.
179 LOCAL_SYMS is a pointer to the swapped in local symbols.
181 LOCAL_SECTIONS is an array giving the section in the input file
182 corresponding to the st_shndx field of each local symbol.
184 The global hash table entry for the global symbols can be found
185 via elf_sym_hashes (input_bfd).
187 When generating relocatable output, this function must handle
188 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
189 going to be the section symbol corresponding to the output
190 section, which means that the addend must be adjusted
194 moxie_elf_relocate_section (bfd
*output_bfd
,
195 struct bfd_link_info
*info
,
197 asection
*input_section
,
199 Elf_Internal_Rela
*relocs
,
200 Elf_Internal_Sym
*local_syms
,
201 asection
**local_sections
)
203 Elf_Internal_Shdr
*symtab_hdr
;
204 struct elf_link_hash_entry
**sym_hashes
;
205 Elf_Internal_Rela
*rel
;
206 Elf_Internal_Rela
*relend
;
208 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
209 sym_hashes
= elf_sym_hashes (input_bfd
);
210 relend
= relocs
+ input_section
->reloc_count
;
212 for (rel
= relocs
; rel
< relend
; rel
++)
214 reloc_howto_type
*howto
;
215 unsigned long r_symndx
;
216 Elf_Internal_Sym
*sym
;
218 struct elf_link_hash_entry
*h
;
220 bfd_reloc_status_type r
;
224 r_type
= ELF32_R_TYPE (rel
->r_info
);
225 r_symndx
= ELF32_R_SYM (rel
->r_info
);
226 howto
= moxie_elf_howto_table
+ r_type
;
231 if (r_symndx
< symtab_hdr
->sh_info
)
233 sym
= local_syms
+ r_symndx
;
234 sec
= local_sections
[r_symndx
];
235 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
237 name
= bfd_elf_string_from_elf_section
238 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
239 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
243 bfd_boolean unresolved_reloc
, warned
;
245 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
246 r_symndx
, symtab_hdr
, sym_hashes
,
248 unresolved_reloc
, warned
);
250 name
= h
->root
.root
.string
;
253 if (sec
!= NULL
&& elf_discarded_section (sec
))
255 /* For relocs against symbols from removed linkonce sections,
256 or sections discarded by a linker script, we just want the
257 section contents zeroed. Avoid any special processing. */
258 _bfd_clear_contents (howto
, input_bfd
, contents
+ rel
->r_offset
);
264 if (info
->relocatable
)
267 r
= moxie_final_link_relocate (howto
, input_bfd
, input_section
,
268 contents
, rel
, relocation
);
270 if (r
!= bfd_reloc_ok
)
272 const char * msg
= NULL
;
276 case bfd_reloc_overflow
:
277 r
= info
->callbacks
->reloc_overflow
278 (info
, (h
? &h
->root
: NULL
), name
, howto
->name
,
279 (bfd_vma
) 0, input_bfd
, input_section
, rel
->r_offset
);
282 case bfd_reloc_undefined
:
283 r
= info
->callbacks
->undefined_symbol
284 (info
, name
, input_bfd
, input_section
, rel
->r_offset
,
288 case bfd_reloc_outofrange
:
289 msg
= _("internal error: out of range error");
292 case bfd_reloc_notsupported
:
293 msg
= _("internal error: unsupported relocation error");
296 case bfd_reloc_dangerous
:
297 msg
= _("internal error: dangerous relocation");
301 msg
= _("internal error: unknown error");
306 r
= info
->callbacks
->warning
307 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
317 /* Return the section that should be marked against GC for a given
321 moxie_elf_gc_mark_hook (asection
*sec
,
322 struct bfd_link_info
*info
,
323 Elf_Internal_Rela
*rel
,
324 struct elf_link_hash_entry
*h
,
325 Elf_Internal_Sym
*sym
)
327 return _bfd_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
);
330 /* Look through the relocs for a section during the first phase.
331 Since we don't do .gots or .plts, we just need to consider the
332 virtual table relocs for gc. */
335 moxie_elf_check_relocs (bfd
*abfd
,
336 struct bfd_link_info
*info
,
338 const Elf_Internal_Rela
*relocs
)
340 Elf_Internal_Shdr
*symtab_hdr
;
341 struct elf_link_hash_entry
**sym_hashes
;
342 const Elf_Internal_Rela
*rel
;
343 const Elf_Internal_Rela
*rel_end
;
345 if (info
->relocatable
)
348 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
349 sym_hashes
= elf_sym_hashes (abfd
);
351 rel_end
= relocs
+ sec
->reloc_count
;
352 for (rel
= relocs
; rel
< rel_end
; rel
++)
354 struct elf_link_hash_entry
*h
;
355 unsigned long r_symndx
;
357 r_symndx
= ELF32_R_SYM (rel
->r_info
);
358 if (r_symndx
< symtab_hdr
->sh_info
)
362 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
363 while (h
->root
.type
== bfd_link_hash_indirect
364 || h
->root
.type
== bfd_link_hash_warning
)
365 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
372 #define ELF_ARCH bfd_arch_moxie
373 #define ELF_MACHINE_CODE EM_MOXIE
374 #define ELF_MAXPAGESIZE 0x1
376 #define TARGET_BIG_SYM bfd_elf32_moxie_vec
377 #define TARGET_BIG_NAME "elf32-moxie"
379 #define elf_info_to_howto_rel NULL
380 #define elf_info_to_howto moxie_info_to_howto_rela
381 #define elf_backend_relocate_section moxie_elf_relocate_section
382 #define elf_backend_gc_mark_hook moxie_elf_gc_mark_hook
383 #define elf_backend_check_relocs moxie_elf_check_relocs
385 #define elf_backend_can_gc_sections 1
386 #define elf_backend_rela_normal 1
388 #define bfd_elf32_bfd_reloc_type_lookup moxie_reloc_type_lookup
389 #define bfd_elf32_bfd_reloc_name_lookup moxie_reloc_name_lookup
391 #include "elf32-target.h"