elf32-moxie.c revision 1.1.1.1 1 /* moxie-specific support for 32-bit ELF.
2 Copyright 2009, 2010, 2012 Free Software Foundation, Inc.
3
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.
7
8 This file is part of BFD, the Binary File Descriptor library.
9
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.
14
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.
19
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. */
24
25 #include "sysdep.h"
26 #include "bfd.h"
27 #include "libbfd.h"
28 #include "elf-bfd.h"
29 #include "elf/moxie.h"
30
31 /* Forward declarations. */
32
33 static reloc_howto_type moxie_elf_howto_table [] =
34 {
35 /* This reloc does nothing. */
36 HOWTO (R_MOXIE_NONE, /* type */
37 0, /* rightshift */
38 2, /* size (0 = byte, 1 = short, 2 = long) */
39 32, /* bitsize */
40 FALSE, /* pc_relative */
41 0, /* bitpos */
42 complain_overflow_bitfield, /* complain_on_overflow */
43 bfd_elf_generic_reloc, /* special_function */
44 "R_MOXIE_NONE", /* name */
45 FALSE, /* partial_inplace */
46 0, /* src_mask */
47 0, /* dst_mask */
48 FALSE), /* pcrel_offset */
49
50 /* A 32 bit absolute relocation. */
51 HOWTO (R_MOXIE_32, /* type */
52 0, /* rightshift */
53 2, /* size (0 = byte, 1 = short, 2 = long) */
54 32, /* bitsize */
55 FALSE, /* pc_relative */
56 0, /* bitpos */
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 */
64
65 /* A 10 bit PC-relative relocation. */
66 HOWTO (R_MOXIE_PCREL10, /* type. */
67 1, /* rightshift. */
68 1, /* size (0 = byte, 1 = short, 2 = long). */
69 10, /* bitsize. */
70 TRUE, /* pc_relative. */
71 0, /* bitpos. */
72 complain_overflow_signed, /* complain_on_overflow. */
73 bfd_elf_generic_reloc, /* special_function. */
74 "R_MOXIE_PCREL10", /* name. */
75 FALSE, /* partial_inplace. */
76 0, /* src_mask. */
77 0x000003FF, /* dst_mask. */
78 TRUE), /* pcrel_offset. */
79 };
80
81 /* Map BFD reloc types to MOXIE ELF reloc types. */
83
84 struct moxie_reloc_map
85 {
86 bfd_reloc_code_real_type bfd_reloc_val;
87 unsigned int moxie_reloc_val;
88 };
89
90 static const struct moxie_reloc_map moxie_reloc_map [] =
91 {
92 { BFD_RELOC_NONE, R_MOXIE_NONE },
93 { BFD_RELOC_32, R_MOXIE_32 },
94 { BFD_RELOC_MOXIE_10_PCREL, R_MOXIE_PCREL10 },
95 };
96
97 static reloc_howto_type *
98 moxie_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
99 bfd_reloc_code_real_type code)
100 {
101 unsigned int i;
102
103 for (i = sizeof (moxie_reloc_map) / sizeof (moxie_reloc_map[0]);
104 --i;)
105 if (moxie_reloc_map [i].bfd_reloc_val == code)
106 return & moxie_elf_howto_table [moxie_reloc_map[i].moxie_reloc_val];
107
108 return NULL;
109 }
110
111 static reloc_howto_type *
112 moxie_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
113 {
114 unsigned int i;
115
116 for (i = 0;
117 i < sizeof (moxie_elf_howto_table) / sizeof (moxie_elf_howto_table[0]);
118 i++)
119 if (moxie_elf_howto_table[i].name != NULL
120 && strcasecmp (moxie_elf_howto_table[i].name, r_name) == 0)
121 return &moxie_elf_howto_table[i];
122
123 return NULL;
124 }
125
126 /* Set the howto pointer for an MOXIE ELF reloc. */
127
128 static void
129 moxie_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED,
130 arelent *cache_ptr,
131 Elf_Internal_Rela *dst)
132 {
133 unsigned int r_type;
134
135 r_type = ELF32_R_TYPE (dst->r_info);
136 BFD_ASSERT (r_type < (unsigned int) R_MOXIE_max);
137 cache_ptr->howto = & moxie_elf_howto_table [r_type];
138 }
139
140 /* Perform a single relocation. By default we use the standard BFD
142 routines, but a few relocs, we have to do them ourselves. */
143
144 static bfd_reloc_status_type
145 moxie_final_link_relocate (reloc_howto_type *howto,
146 bfd *input_bfd,
147 asection *input_section,
148 bfd_byte *contents,
149 Elf_Internal_Rela *rel,
150 bfd_vma relocation)
151 {
152 bfd_reloc_status_type r = bfd_reloc_ok;
153
154 switch (howto->type)
155 {
156 default:
157 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
158 contents, rel->r_offset,
159 relocation, rel->r_addend);
160 }
161
162 return r;
163 }
164
165 /* Relocate an MOXIE ELF section.
167
168 The RELOCATE_SECTION function is called by the new ELF backend linker
169 to handle the relocations for a section.
170
171 The relocs are always passed as Rela structures; if the section
172 actually uses Rel structures, the r_addend field will always be
173 zero.
174
175 This function is responsible for adjusting the section contents as
176 necessary, and (if using Rela relocs and generating a relocatable
177 output file) adjusting the reloc addend as necessary.
178
179 This function does not have to worry about setting the reloc
180 address or the reloc symbol index.
181
182 LOCAL_SYMS is a pointer to the swapped in local symbols.
183
184 LOCAL_SECTIONS is an array giving the section in the input file
185 corresponding to the st_shndx field of each local symbol.
186
187 The global hash table entry for the global symbols can be found
188 via elf_sym_hashes (input_bfd).
189
190 When generating relocatable output, this function must handle
191 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
192 going to be the section symbol corresponding to the output
193 section, which means that the addend must be adjusted
194 accordingly. */
195
196 static bfd_boolean
197 moxie_elf_relocate_section (bfd *output_bfd,
198 struct bfd_link_info *info,
199 bfd *input_bfd,
200 asection *input_section,
201 bfd_byte *contents,
202 Elf_Internal_Rela *relocs,
203 Elf_Internal_Sym *local_syms,
204 asection **local_sections)
205 {
206 Elf_Internal_Shdr *symtab_hdr;
207 struct elf_link_hash_entry **sym_hashes;
208 Elf_Internal_Rela *rel;
209 Elf_Internal_Rela *relend;
210
211 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
212 sym_hashes = elf_sym_hashes (input_bfd);
213 relend = relocs + input_section->reloc_count;
214
215 for (rel = relocs; rel < relend; rel ++)
216 {
217 reloc_howto_type *howto;
218 unsigned long r_symndx;
219 Elf_Internal_Sym *sym;
220 asection *sec;
221 struct elf_link_hash_entry *h;
222 bfd_vma relocation;
223 bfd_reloc_status_type r;
224 const char *name;
225 int r_type;
226
227 r_type = ELF32_R_TYPE (rel->r_info);
228 r_symndx = ELF32_R_SYM (rel->r_info);
229 howto = moxie_elf_howto_table + r_type;
230 h = NULL;
231 sym = NULL;
232 sec = NULL;
233
234 if (r_symndx < symtab_hdr->sh_info)
235 {
236 sym = local_syms + r_symndx;
237 sec = local_sections [r_symndx];
238 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
239
240 name = bfd_elf_string_from_elf_section
241 (input_bfd, symtab_hdr->sh_link, sym->st_name);
242 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
243 }
244 else
245 {
246 bfd_boolean unresolved_reloc, warned, ignored;
247
248 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
249 r_symndx, symtab_hdr, sym_hashes,
250 h, sec, relocation,
251 unresolved_reloc, warned, ignored);
252
253 name = h->root.root.string;
254 }
255
256 if (sec != NULL && discarded_section (sec))
257 RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
258 rel, 1, relend, howto, 0, contents);
259
260 if (info->relocatable)
261 continue;
262
263 r = moxie_final_link_relocate (howto, input_bfd, input_section,
264 contents, rel, relocation);
265
266 if (r != bfd_reloc_ok)
267 {
268 const char * msg = NULL;
269
270 switch (r)
271 {
272 case bfd_reloc_overflow:
273 r = info->callbacks->reloc_overflow
274 (info, (h ? &h->root : NULL), name, howto->name,
275 (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
276 break;
277
278 case bfd_reloc_undefined:
279 r = info->callbacks->undefined_symbol
280 (info, name, input_bfd, input_section, rel->r_offset,
281 TRUE);
282 break;
283
284 case bfd_reloc_outofrange:
285 msg = _("internal error: out of range error");
286 break;
287
288 case bfd_reloc_notsupported:
289 msg = _("internal error: unsupported relocation error");
290 break;
291
292 case bfd_reloc_dangerous:
293 msg = _("internal error: dangerous relocation");
294 break;
295
296 default:
297 msg = _("internal error: unknown error");
298 break;
299 }
300
301 if (msg)
302 r = info->callbacks->warning
303 (info, msg, name, input_bfd, input_section, rel->r_offset);
304
305 if (! r)
306 return FALSE;
307 }
308 }
309
310 return TRUE;
311 }
312
313 /* Return the section that should be marked against GC for a given
315 relocation. */
316
317 static asection *
318 moxie_elf_gc_mark_hook (asection *sec,
319 struct bfd_link_info *info,
320 Elf_Internal_Rela *rel,
321 struct elf_link_hash_entry *h,
322 Elf_Internal_Sym *sym)
323 {
324 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
325 }
326
327 /* Look through the relocs for a section during the first phase.
328 Since we don't do .gots or .plts, we just need to consider the
329 virtual table relocs for gc. */
330
331 static bfd_boolean
332 moxie_elf_check_relocs (bfd *abfd,
333 struct bfd_link_info *info,
334 asection *sec,
335 const Elf_Internal_Rela *relocs)
336 {
337 Elf_Internal_Shdr *symtab_hdr;
338 struct elf_link_hash_entry **sym_hashes;
339 const Elf_Internal_Rela *rel;
340 const Elf_Internal_Rela *rel_end;
341
342 if (info->relocatable)
343 return TRUE;
344
345 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
346 sym_hashes = elf_sym_hashes (abfd);
347
348 rel_end = relocs + sec->reloc_count;
349 for (rel = relocs; rel < rel_end; rel++)
350 {
351 struct elf_link_hash_entry *h;
352 unsigned long r_symndx;
353
354 r_symndx = ELF32_R_SYM (rel->r_info);
355 if (r_symndx < symtab_hdr->sh_info)
356 h = NULL;
357 else
358 {
359 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
360 while (h->root.type == bfd_link_hash_indirect
361 || h->root.type == bfd_link_hash_warning)
362 h = (struct elf_link_hash_entry *) h->root.u.i.link;
363
364 /* PR15323, ref flags aren't set for references in the same
365 object. */
366 h->root.non_ir_ref = 1;
367 }
368 }
369
370 return TRUE;
371 }
372
373 #define ELF_ARCH bfd_arch_moxie
375 #define ELF_MACHINE_CODE EM_MOXIE
376 #define ELF_MAXPAGESIZE 0x1
377
378 #define TARGET_BIG_SYM bfd_elf32_bigmoxie_vec
379 #define TARGET_BIG_NAME "elf32-bigmoxie"
380 #define TARGET_LITTLE_SYM bfd_elf32_littlemoxie_vec
381 #define TARGET_LITTLE_NAME "elf32-littlemoxie"
382
383 #define elf_info_to_howto_rel NULL
384 #define elf_info_to_howto moxie_info_to_howto_rela
385 #define elf_backend_relocate_section moxie_elf_relocate_section
386 #define elf_backend_gc_mark_hook moxie_elf_gc_mark_hook
387 #define elf_backend_check_relocs moxie_elf_check_relocs
388
389 #define elf_backend_can_gc_sections 1
390 #define elf_backend_rela_normal 1
391
392 #define bfd_elf32_bfd_reloc_type_lookup moxie_reloc_type_lookup
393 #define bfd_elf32_bfd_reloc_name_lookup moxie_reloc_name_lookup
394
395 #include "elf32-target.h"
396