Add new binutils target: moxie
[deliverable/binutils-gdb.git] / bfd / elf32-moxie.c
1 /* moxie-specific support for 32-bit ELF.
2 Copyright 2008 Anthony Green.
3 Copyright 2009 Free Software Foundation, Inc.
4
5 Copied from elf32-fr30.c which is..
6 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
7 Free Software Foundation, Inc.
8
9 This file is part of BFD, the Binary File Descriptor library.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
24 MA 02110-1301, USA. */
25
26 #include "sysdep.h"
27 #include "bfd.h"
28 #include "libbfd.h"
29 #include "elf-bfd.h"
30 #include "elf/moxie.h"
31
32 /* Forward declarations. */
33
34 static reloc_howto_type moxie_elf_howto_table [] =
35 {
36 /* This reloc does nothing. */
37 HOWTO (R_MOXIE_NONE, /* type */
38 0, /* rightshift */
39 2, /* size (0 = byte, 1 = short, 2 = long) */
40 32, /* bitsize */
41 FALSE, /* pc_relative */
42 0, /* bitpos */
43 complain_overflow_bitfield, /* complain_on_overflow */
44 bfd_elf_generic_reloc, /* special_function */
45 "R_MOXIE_NONE", /* name */
46 FALSE, /* partial_inplace */
47 0, /* src_mask */
48 0, /* dst_mask */
49 FALSE), /* pcrel_offset */
50
51 /* A 32 bit absolute relocation. */
52 HOWTO (R_MOXIE_32, /* type */
53 0, /* rightshift */
54 2, /* size (0 = byte, 1 = short, 2 = long) */
55 32, /* bitsize */
56 FALSE, /* pc_relative */
57 0, /* bitpos */
58 complain_overflow_bitfield, /* complain_on_overflow */
59 bfd_elf_generic_reloc, /* special_function */
60 "R_MOXIE_32", /* name */
61 FALSE, /* partial_inplace */
62 0x00000000, /* src_mask */
63 0xffffffff, /* dst_mask */
64 FALSE), /* pcrel_offset */
65 };
66 \f
67 /* Map BFD reloc types to MOXIE ELF reloc types. */
68
69 struct moxie_reloc_map
70 {
71 bfd_reloc_code_real_type bfd_reloc_val;
72 unsigned int moxie_reloc_val;
73 };
74
75 static const struct moxie_reloc_map moxie_reloc_map [] =
76 {
77 { BFD_RELOC_NONE, R_MOXIE_NONE },
78 { BFD_RELOC_32, R_MOXIE_32 },
79 };
80
81 static reloc_howto_type *
82 moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
83 bfd_reloc_code_real_type code)
84 {
85 unsigned int i;
86
87 for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
88 --i;)
89 if (moxie_reloc_map [i].bfd_reloc_val == code)
90 return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
91
92 return NULL;
93 }
94
95 static reloc_howto_type *
96 moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
97 {
98 unsigned int i;
99
100 for (i = 0;
101 i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]);
102 i++)
103 if (moxie_elf_howto_table[i].name != NULL
104 && strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0)
105 return &moxie_elf_howto_table[i];
106
107 return NULL;
108 }
109
110 /* Set the howto pointer for an MOXIE ELF reloc. */
111
112 static void
113 moxie_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
114 arelent *cache_ptr,
115 Elf_Internal_Rela *dst)
116 {
117 unsigned int r_type;
118
119 r_type = ELF32_R_TYPE (dst->r_info);
120 BFD_ASSERT (r_type < (unsigned int) R_MOXIE_max);
121 cache_ptr->howto = & moxie_elf_howto_table [r_type];
122 }
123 \f
124 /* Perform a single relocation. By default we use the standard BFD
125 routines, but a few relocs, we have to do them ourselves. */
126
127 static bfd_reloc_status_type
128 moxie_final_link_relocate (reloc_howto_type *howto,
129 bfd *input_bfd,
130 asection *input_section,
131 bfd_byte *contents,
132 Elf_Internal_Rela *rel,
133 bfd_vma relocation)
134 {
135 bfd_reloc_status_type r = bfd_reloc_ok;
136
137 switch (howto->type)
138 {
139 default:
140 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
141 contents, rel->r_offset,
142 relocation, rel->r_addend);
143 }
144
145 return r;
146 }
147 \f
148 /* Relocate an MOXIE ELF section.
149
150 The RELOCATE_SECTION function is called by the new ELF backend linker
151 to handle the relocations for a section.
152
153 The relocs are always passed as Rela structures; if the section
154 actually uses Rel structures, the r_addend field will always be
155 zero.
156
157 This function is responsible for adjusting the section contents as
158 necessary, and (if using Rela relocs and generating a relocatable
159 output file) adjusting the reloc addend as necessary.
160
161 This function does not have to worry about setting the reloc
162 address or the reloc symbol index.
163
164 LOCAL_SYMS is a pointer to the swapped in local symbols.
165
166 LOCAL_SECTIONS is an array giving the section in the input file
167 corresponding to the st_shndx field of each local symbol.
168
169 The global hash table entry for the global symbols can be found
170 via elf_sym_hashes (input_bfd).
171
172 When generating relocatable output, this function must handle
173 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
174 going to be the section symbol corresponding to the output
175 section, which means that the addend must be adjusted
176 accordingly. */
177
178 static bfd_boolean
179 moxie_elf_relocate_section (bfd *output_bfd,
180 struct bfd_link_info *info,
181 bfd *input_bfd,
182 asection *input_section,
183 bfd_byte *contents,
184 Elf_Internal_Rela *relocs,
185 Elf_Internal_Sym *local_syms,
186 asection **local_sections)
187 {
188 Elf_Internal_Shdr *symtab_hdr;
189 struct elf_link_hash_entry **sym_hashes;
190 Elf_Internal_Rela *rel;
191 Elf_Internal_Rela *relend;
192
193 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
194 sym_hashes = elf_sym_hashes (input_bfd);
195 relend = relocs + input_section->reloc_count;
196
197 for (rel = relocs; rel < relend; rel ++)
198 {
199 reloc_howto_type *howto;
200 unsigned long r_symndx;
201 Elf_Internal_Sym *sym;
202 asection *sec;
203 struct elf_link_hash_entry *h;
204 bfd_vma relocation;
205 bfd_reloc_status_type r;
206 const char *name;
207 int r_type;
208
209 r_type = ELF32_R_TYPE (rel->r_info);
210
211 r_symndx = ELF32_R_SYM (rel->r_info);
212
213 howto = moxie_elf_howto_table + ELF32_R_TYPE (rel->r_info);
214 h = NULL;
215 sym = NULL;
216 sec = NULL;
217
218 if (r_symndx < symtab_hdr->sh_info)
219 {
220 sym = local_syms + r_symndx;
221 sec = local_sections [r_symndx];
222 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
223
224 name = bfd_elf_string_from_elf_section
225 (input_bfd, symtab_hdr->sh_link, sym->st_name);
226 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
227 }
228 else
229 {
230 bfd_boolean unresolved_reloc, warned;
231
232 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
233 r_symndx, symtab_hdr, sym_hashes,
234 h, sec, relocation,
235 unresolved_reloc, warned);
236
237 name = h->root.root.string;
238 }
239
240 if (sec != NULL && elf_discarded_section (sec))
241 {
242 /* For relocs against symbols from removed linkonce sections,
243 or sections discarded by a linker script, we just want the
244 section contents zeroed. Avoid any special processing. */
245 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
246 rel->r_info = 0;
247 rel->r_addend = 0;
248 continue;
249 }
250
251 if (info->relocatable)
252 continue;
253
254 r = moxie_final_link_relocate (howto, input_bfd, input_section,
255 contents, rel, relocation);
256
257 if (r != bfd_reloc_ok)
258 {
259 const char * msg = NULL;
260
261 switch (r)
262 {
263 case bfd_reloc_overflow:
264 r = info->callbacks->reloc_overflow
265 (info, (h ? &h->root : NULL), name, howto->name,
266 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
267 break;
268
269 case bfd_reloc_undefined:
270 r = info->callbacks->undefined_symbol
271 (info, name, input_bfd, input_section, rel->r_offset,
272 TRUE);
273 break;
274
275 case bfd_reloc_outofrange:
276 msg = _("internal error: out of range error");
277 break;
278
279 case bfd_reloc_notsupported:
280 msg = _("internal error: unsupported relocation error");
281 break;
282
283 case bfd_reloc_dangerous:
284 msg = _("internal error: dangerous relocation");
285 break;
286
287 default:
288 msg = _("internal error: unknown error");
289 break;
290 }
291
292 if (msg)
293 r = info->callbacks->warning
294 (info, msg, name, input_bfd, input_section, rel->r_offset);
295
296 if (! r)
297 return FALSE;
298 }
299 }
300
301 return TRUE;
302 }
303 \f
304 /* Return the section that should be marked against GC for a given
305 relocation. */
306
307 static asection *
308 moxie_elf_gc_mark_hook (asection *sec,
309 struct bfd_link_info *info,
310 Elf_Internal_Rela *rel,
311 struct elf_link_hash_entry *h,
312 Elf_Internal_Sym *sym)
313 {
314 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
315 }
316
317 /* Look through the relocs for a section during the first phase.
318 Since we don't do .gots or .plts, we just need to consider the
319 virtual table relocs for gc. */
320
321 static bfd_boolean
322 moxie_elf_check_relocs (bfd *abfd,
323 struct bfd_link_info *info,
324 asection *sec,
325 const Elf_Internal_Rela *relocs)
326 {
327 Elf_Internal_Shdr *symtab_hdr;
328 struct elf_link_hash_entry **sym_hashes;
329 const Elf_Internal_Rela *rel;
330 const Elf_Internal_Rela *rel_end;
331
332 if (info->relocatable)
333 return TRUE;
334
335 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
336 sym_hashes = elf_sym_hashes (abfd);
337
338 rel_end = relocs + sec->reloc_count;
339 for (rel = relocs; rel < rel_end; rel++)
340 {
341 struct elf_link_hash_entry *h;
342 unsigned long r_symndx;
343
344 r_symndx = ELF32_R_SYM (rel->r_info);
345 if (r_symndx < symtab_hdr->sh_info)
346 h = NULL;
347 else
348 {
349 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
350 while (h->root.type == bfd_link_hash_indirect
351 || h->root.type == bfd_link_hash_warning)
352 h = (struct elf_link_hash_entry *) h->root.u.i.link;
353 }
354 }
355
356 return TRUE;
357 }
358 \f
359 #define ELF_ARCH bfd_arch_moxie
360 #define ELF_MACHINE_CODE EM_MOXIE
361 #define ELF_MAXPAGESIZE 0x1
362
363 #define TARGET_BIG_SYM bfd_elf32_moxie_vec
364 #define TARGET_BIG_NAME "elf32-moxie"
365
366 #define elf_info_to_howto_rel NULL
367 #define elf_info_to_howto moxie_info_to_howto_rela
368 #define elf_backend_relocate_section moxie_elf_relocate_section
369 #define elf_backend_gc_mark_hook moxie_elf_gc_mark_hook
370 #define elf_backend_check_relocs moxie_elf_check_relocs
371
372 #define elf_backend_can_gc_sections 1
373 #define elf_backend_rela_normal 1
374
375 #define bfd_elf32_bfd_reloc_type_lookup moxie_reloc_type_lookup
376 #define bfd_elf32_bfd_reloc_name_lookup moxie_reloc_name_lookup
377
378 #include "elf32-target.h"
This page took 0.045474 seconds and 4 git commands to generate.