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