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