elf32-moxie.c revision 1.1.1.9 1 1.1 christos /* moxie-specific support for 32-bit ELF.
2 1.1.1.9 christos Copyright (C) 2009-2020 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos Copied from elf32-fr30.c which is..
5 1.1.1.9 christos Copyright (C) 1998-2020 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.1.8 christos {
91 1.1.1.8 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.1.8 christos
127 1.1.1.8 christos static bfd_boolean
128 1.1 christos moxie_info_to_howto_rela (bfd *abfd,
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.7 christos {
137 1.1.1.8 christos /* xgettext:c-format */
138 1.1.1.8 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
139 1.1.1.8 christos abfd, r_type);
140 1.1.1.8 christos bfd_set_error (bfd_error_bad_value);
141 1.1.1.4 christos return FALSE;
142 1.1 christos }
143 1.1.1.8 christos cache_ptr->howto = & moxie_elf_howto_table [r_type];
144 1.1 christos return TRUE;
145 1.1 christos }
146 1.1 christos
147 1.1 christos /* Perform a single relocation. By default we use the standard BFD
149 1.1 christos routines, but a few relocs, we have to do them ourselves. */
150 1.1 christos
151 1.1 christos static bfd_reloc_status_type
152 1.1 christos moxie_final_link_relocate (reloc_howto_type *howto,
153 1.1 christos bfd *input_bfd,
154 1.1 christos asection *input_section,
155 1.1 christos bfd_byte *contents,
156 1.1 christos Elf_Internal_Rela *rel,
157 1.1 christos bfd_vma relocation)
158 1.1 christos {
159 1.1 christos bfd_reloc_status_type r = bfd_reloc_ok;
160 1.1 christos
161 1.1 christos switch (howto->type)
162 1.1 christos {
163 1.1 christos default:
164 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
165 1.1 christos contents, rel->r_offset,
166 1.1 christos relocation, rel->r_addend);
167 1.1 christos }
168 1.1 christos
169 1.1 christos return r;
170 1.1 christos }
171 1.1 christos
172 1.1 christos /* Relocate an MOXIE ELF section.
174 1.1 christos
175 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
176 1.1 christos to handle the relocations for a section.
177 1.1 christos
178 1.1 christos The relocs are always passed as Rela structures; if the section
179 1.1 christos actually uses Rel structures, the r_addend field will always be
180 1.1 christos zero.
181 1.1 christos
182 1.1 christos This function is responsible for adjusting the section contents as
183 1.1 christos necessary, and (if using Rela relocs and generating a relocatable
184 1.1 christos output file) adjusting the reloc addend as necessary.
185 1.1 christos
186 1.1 christos This function does not have to worry about setting the reloc
187 1.1 christos address or the reloc symbol index.
188 1.1 christos
189 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
190 1.1 christos
191 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
192 1.1 christos corresponding to the st_shndx field of each local symbol.
193 1.1 christos
194 1.1 christos The global hash table entry for the global symbols can be found
195 1.1 christos via elf_sym_hashes (input_bfd).
196 1.1 christos
197 1.1 christos When generating relocatable output, this function must handle
198 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
199 1.1 christos going to be the section symbol corresponding to the output
200 1.1 christos section, which means that the addend must be adjusted
201 1.1 christos accordingly. */
202 1.1 christos
203 1.1 christos static bfd_boolean
204 1.1 christos moxie_elf_relocate_section (bfd *output_bfd,
205 1.1 christos struct bfd_link_info *info,
206 1.1 christos bfd *input_bfd,
207 1.1 christos asection *input_section,
208 1.1 christos bfd_byte *contents,
209 1.1 christos Elf_Internal_Rela *relocs,
210 1.1 christos Elf_Internal_Sym *local_syms,
211 1.1 christos asection **local_sections)
212 1.1 christos {
213 1.1 christos Elf_Internal_Shdr *symtab_hdr;
214 1.1 christos struct elf_link_hash_entry **sym_hashes;
215 1.1 christos Elf_Internal_Rela *rel;
216 1.1 christos Elf_Internal_Rela *relend;
217 1.1 christos
218 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
219 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
220 1.1 christos relend = relocs + input_section->reloc_count;
221 1.1 christos
222 1.1 christos for (rel = relocs; rel < relend; rel ++)
223 1.1 christos {
224 1.1 christos reloc_howto_type *howto;
225 1.1 christos unsigned long r_symndx;
226 1.1 christos Elf_Internal_Sym *sym;
227 1.1 christos asection *sec;
228 1.1 christos struct elf_link_hash_entry *h;
229 1.1 christos bfd_vma relocation;
230 1.1 christos bfd_reloc_status_type r;
231 1.1 christos const char *name;
232 1.1 christos int r_type;
233 1.1 christos
234 1.1 christos r_type = ELF32_R_TYPE (rel->r_info);
235 1.1 christos r_symndx = ELF32_R_SYM (rel->r_info);
236 1.1 christos howto = moxie_elf_howto_table + r_type;
237 1.1 christos h = NULL;
238 1.1 christos sym = NULL;
239 1.1 christos sec = NULL;
240 1.1 christos
241 1.1 christos if (r_symndx < symtab_hdr->sh_info)
242 1.1 christos {
243 1.1 christos sym = local_syms + r_symndx;
244 1.1 christos sec = local_sections [r_symndx];
245 1.1 christos relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
246 1.1.1.9 christos
247 1.1 christos name = bfd_elf_string_from_elf_section
248 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
249 1.1 christos name = name == NULL ? bfd_section_name (sec) : name;
250 1.1.1.3 christos }
251 1.1 christos else
252 1.1 christos {
253 1.1 christos bfd_boolean unresolved_reloc, warned, ignored;
254 1.1 christos
255 1.1.1.3 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
256 1.1 christos r_symndx, symtab_hdr, sym_hashes,
257 1.1 christos h, sec, relocation,
258 1.1 christos unresolved_reloc, warned, ignored);
259 1.1 christos
260 1.1.1.2 christos name = h->root.root.string;
261 1.1 christos }
262 1.1.1.2 christos
263 1.1 christos if (sec != NULL && discarded_section (sec))
264 1.1.1.6 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
265 1.1 christos rel, 1, relend, howto, 0, contents);
266 1.1 christos
267 1.1 christos if (bfd_link_relocatable (info))
268 1.1 christos continue;
269 1.1 christos
270 1.1 christos r = moxie_final_link_relocate (howto, input_bfd, input_section,
271 1.1 christos contents, rel, relocation);
272 1.1 christos
273 1.1 christos if (r != bfd_reloc_ok)
274 1.1 christos {
275 1.1 christos const char * msg = NULL;
276 1.1 christos
277 1.1.1.6 christos switch (r)
278 1.1 christos {
279 1.1 christos case bfd_reloc_overflow:
280 1.1 christos (*info->callbacks->reloc_overflow)
281 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
282 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
283 1.1.1.6 christos break;
284 1.1.1.6 christos
285 1.1 christos case bfd_reloc_undefined:
286 1.1 christos (*info->callbacks->undefined_symbol)
287 1.1 christos (info, name, input_bfd, input_section, rel->r_offset, TRUE);
288 1.1 christos break;
289 1.1 christos
290 1.1 christos case bfd_reloc_outofrange:
291 1.1 christos msg = _("internal error: out of range error");
292 1.1 christos break;
293 1.1 christos
294 1.1 christos case bfd_reloc_notsupported:
295 1.1 christos msg = _("internal error: unsupported relocation error");
296 1.1 christos break;
297 1.1 christos
298 1.1 christos case bfd_reloc_dangerous:
299 1.1 christos msg = _("internal error: dangerous relocation");
300 1.1 christos break;
301 1.1 christos
302 1.1 christos default:
303 1.1 christos msg = _("internal error: unknown error");
304 1.1 christos break;
305 1.1.1.6 christos }
306 1.1.1.6 christos
307 1.1 christos if (msg)
308 1.1 christos (*info->callbacks->warning) (info, msg, name, input_bfd,
309 1.1 christos input_section, rel->r_offset);
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.1.6 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 (bfd_link_relocatable (info))
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.1.8 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 christos h = sym_hashes[r_symndx - symtab_hdr->sh_info];
363 1.1 christos while (h->root.type == bfd_link_hash_indirect
364 1.1 christos || h->root.type == bfd_link_hash_warning)
365 1.1 christos h = (struct elf_link_hash_entry *) h->root.u.i.link;
366 1.1 christos }
367 1.1 christos }
368 1.1 christos
369 1.1 christos return TRUE;
370 1.1.1.8 christos }
371 1.1 christos
372 1.1 christos #define ELF_ARCH bfd_arch_moxie
374 1.1.1.2 christos #define ELF_MACHINE_CODE EM_MOXIE
375 1.1.1.8 christos #define ELF_MACHINE_ALT1 EM_MOXIE_OLD
376 1.1.1.2 christos #define ELF_MAXPAGESIZE 0x1
377 1.1 christos
378 1.1 christos #define TARGET_BIG_SYM moxie_elf32_be_vec
379 1.1 christos #define TARGET_BIG_NAME "elf32-bigmoxie"
380 1.1 christos #define TARGET_LITTLE_SYM moxie_elf32_le_vec
381 1.1 christos #define TARGET_LITTLE_NAME "elf32-littlemoxie"
382 1.1.1.8 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