/src/binutils-gdb/bfd/elf32-mcore.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Motorola MCore specific support for 32-bit ELF |
2 | | Copyright (C) 1994-2025 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of BFD, the Binary File Descriptor library. |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program; if not, write to the Free Software |
18 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | | MA 02110-1301, USA. */ |
20 | | |
21 | | |
22 | | /* This file is based on a preliminary RCE ELF ABI. The |
23 | | information may not match the final RCE ELF ABI. */ |
24 | | |
25 | | #include "sysdep.h" |
26 | | #include "bfd.h" |
27 | | #include "bfdlink.h" |
28 | | #include "libbfd.h" |
29 | | #include "elf-bfd.h" |
30 | | #include "elf/mcore.h" |
31 | | #include <assert.h> |
32 | | |
33 | | /* RELA relocs are used here... */ |
34 | | |
35 | | /* Function to set whether a module needs the -mrelocatable bit set. */ |
36 | | |
37 | | static bool |
38 | | mcore_elf_set_private_flags (bfd * abfd, flagword flags) |
39 | 0 | { |
40 | 0 | BFD_ASSERT (! elf_flags_init (abfd) |
41 | 0 | || elf_elfheader (abfd)->e_flags == flags); |
42 | |
|
43 | 0 | elf_elfheader (abfd)->e_flags = flags; |
44 | 0 | elf_flags_init (abfd) = true; |
45 | 0 | return true; |
46 | 0 | } |
47 | | |
48 | | /* Merge backend specific data from an object file to the output |
49 | | object file when linking. */ |
50 | | |
51 | | static bool |
52 | | mcore_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) |
53 | 0 | { |
54 | 0 | bfd *obfd = info->output_bfd; |
55 | 0 | flagword old_flags; |
56 | 0 | flagword new_flags; |
57 | | |
58 | | /* Check if we have the same endianness. */ |
59 | 0 | if (! _bfd_generic_verify_endian_match (ibfd, info)) |
60 | 0 | return false; |
61 | | |
62 | 0 | if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
63 | 0 | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
64 | 0 | return true; |
65 | | |
66 | 0 | new_flags = elf_elfheader (ibfd)->e_flags; |
67 | 0 | old_flags = elf_elfheader (obfd)->e_flags; |
68 | |
|
69 | 0 | if (! elf_flags_init (obfd)) |
70 | 0 | { |
71 | | /* First call, no flags set. */ |
72 | 0 | elf_flags_init (obfd) = true; |
73 | 0 | elf_elfheader (obfd)->e_flags = new_flags; |
74 | 0 | } |
75 | 0 | else if (new_flags == old_flags) |
76 | | /* Compatible flags are OK. */ |
77 | 0 | ; |
78 | 0 | else |
79 | 0 | { |
80 | | /* FIXME */ |
81 | 0 | } |
82 | |
|
83 | 0 | return true; |
84 | 0 | } |
85 | | |
86 | | /* Don't pretend we can deal with unsupported relocs. */ |
87 | | |
88 | | static bfd_reloc_status_type |
89 | | mcore_elf_unsupported_reloc (bfd * abfd, |
90 | | arelent * reloc_entry, |
91 | | asymbol * symbol ATTRIBUTE_UNUSED, |
92 | | void * data ATTRIBUTE_UNUSED, |
93 | | asection * input_section ATTRIBUTE_UNUSED, |
94 | | bfd * output_bfd ATTRIBUTE_UNUSED, |
95 | | char ** error_message ATTRIBUTE_UNUSED) |
96 | 0 | { |
97 | 0 | BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0); |
98 | | |
99 | | /* xgettext:c-format */ |
100 | 0 | _bfd_error_handler (_("%pB: %s unsupported"), |
101 | 0 | abfd, |
102 | 0 | reloc_entry->howto->name); |
103 | |
|
104 | 0 | return bfd_reloc_notsupported; |
105 | 0 | } |
106 | | |
107 | | static reloc_howto_type * mcore_elf_howto_table [(int) R_MCORE_max]; |
108 | | |
109 | | static reloc_howto_type mcore_elf_howto_raw[] = |
110 | | { |
111 | | /* This reloc does nothing. */ |
112 | | HOWTO (R_MCORE_NONE, /* type */ |
113 | | 0, /* rightshift */ |
114 | | 0, /* size */ |
115 | | 0, /* bitsize */ |
116 | | false, /* pc_relative */ |
117 | | 0, /* bitpos */ |
118 | | complain_overflow_dont, /* complain_on_overflow */ |
119 | | NULL, /* special_function */ |
120 | | "R_MCORE_NONE", /* name */ |
121 | | false, /* partial_inplace */ |
122 | | 0, /* src_mask */ |
123 | | 0, /* dst_mask */ |
124 | | false), /* pcrel_offset */ |
125 | | |
126 | | /* A standard 32 bit relocation. */ |
127 | | HOWTO (R_MCORE_ADDR32, /* type */ |
128 | | 0, /* rightshift */ |
129 | | 4, /* size */ |
130 | | 32, /* bitsize */ |
131 | | false, /* pc_relative */ |
132 | | 0, /* bitpos */ |
133 | | complain_overflow_bitfield, /* complain_on_overflow */ |
134 | | bfd_elf_generic_reloc, /* special_function */ |
135 | | "ADDR32", /* name *//* For compatibility with coff/pe port. */ |
136 | | false, /* partial_inplace */ |
137 | | 0x0, /* src_mask */ |
138 | | 0xffffffff, /* dst_mask */ |
139 | | false), /* pcrel_offset */ |
140 | | |
141 | | /* 8 bits + 2 zero bits; jmpi/jsri/lrw instructions. |
142 | | Should not appear in object files. */ |
143 | | HOWTO (R_MCORE_PCRELIMM8BY4, /* type */ |
144 | | 2, /* rightshift */ |
145 | | 2, /* size */ |
146 | | 8, /* bitsize */ |
147 | | true, /* pc_relative */ |
148 | | 0, /* bitpos */ |
149 | | complain_overflow_bitfield, /* complain_on_overflow */ |
150 | | mcore_elf_unsupported_reloc, /* special_function */ |
151 | | "R_MCORE_PCRELIMM8BY4",/* name */ |
152 | | false, /* partial_inplace */ |
153 | | 0, /* src_mask */ |
154 | | 0, /* dst_mask */ |
155 | | true), /* pcrel_offset */ |
156 | | |
157 | | /* bsr/bt/bf/br instructions; 11 bits + 1 zero bit |
158 | | Span 2k instructions == 4k bytes. |
159 | | Only useful pieces at the relocated address are the opcode (5 bits) */ |
160 | | HOWTO (R_MCORE_PCRELIMM11BY2,/* type */ |
161 | | 1, /* rightshift */ |
162 | | 2, /* size */ |
163 | | 11, /* bitsize */ |
164 | | true, /* pc_relative */ |
165 | | 0, /* bitpos */ |
166 | | complain_overflow_signed, /* complain_on_overflow */ |
167 | | bfd_elf_generic_reloc, /* special_function */ |
168 | | "R_MCORE_PCRELIMM11BY2",/* name */ |
169 | | false, /* partial_inplace */ |
170 | | 0x0, /* src_mask */ |
171 | | 0x7ff, /* dst_mask */ |
172 | | true), /* pcrel_offset */ |
173 | | |
174 | | /* 4 bits + 1 zero bit; 'loopt' instruction only; unsupported. */ |
175 | | HOWTO (R_MCORE_PCRELIMM4BY2, /* type */ |
176 | | 1, /* rightshift */ |
177 | | 2, /* size */ |
178 | | 4, /* bitsize */ |
179 | | true, /* pc_relative */ |
180 | | 0, /* bitpos */ |
181 | | complain_overflow_bitfield, /* complain_on_overflow */ |
182 | | mcore_elf_unsupported_reloc,/* special_function */ |
183 | | "R_MCORE_PCRELIMM4BY2",/* name */ |
184 | | false, /* partial_inplace */ |
185 | | 0, /* src_mask */ |
186 | | 0, /* dst_mask */ |
187 | | true), /* pcrel_offset */ |
188 | | |
189 | | /* 32-bit pc-relative. Eventually this will help support PIC code. */ |
190 | | HOWTO (R_MCORE_PCREL32, /* type */ |
191 | | 0, /* rightshift */ |
192 | | 4, /* size */ |
193 | | 32, /* bitsize */ |
194 | | true, /* pc_relative */ |
195 | | 0, /* bitpos */ |
196 | | complain_overflow_bitfield, /* complain_on_overflow */ |
197 | | bfd_elf_generic_reloc, /* special_function */ |
198 | | "R_MCORE_PCREL32", /* name */ |
199 | | false, /* partial_inplace */ |
200 | | 0x0, /* src_mask */ |
201 | | 0xffffffff, /* dst_mask */ |
202 | | true), /* pcrel_offset */ |
203 | | |
204 | | /* Like PCRELIMM11BY2, this relocation indicates that there is a |
205 | | 'jsri' at the specified address. There is a separate relocation |
206 | | entry for the literal pool entry that it references, but we |
207 | | might be able to change the jsri to a bsr if the target turns out |
208 | | to be close enough [even though we won't reclaim the literal pool |
209 | | entry, we'll get some runtime efficiency back]. Note that this |
210 | | is a relocation that we are allowed to safely ignore. */ |
211 | | HOWTO (R_MCORE_PCRELJSR_IMM11BY2,/* type */ |
212 | | 1, /* rightshift */ |
213 | | 2, /* size */ |
214 | | 11, /* bitsize */ |
215 | | true, /* pc_relative */ |
216 | | 0, /* bitpos */ |
217 | | complain_overflow_signed, /* complain_on_overflow */ |
218 | | bfd_elf_generic_reloc, /* special_function */ |
219 | | "R_MCORE_PCRELJSR_IMM11BY2", /* name */ |
220 | | false, /* partial_inplace */ |
221 | | 0x0, /* src_mask */ |
222 | | 0x7ff, /* dst_mask */ |
223 | | true), /* pcrel_offset */ |
224 | | |
225 | | /* GNU extension to record C++ vtable hierarchy. */ |
226 | | HOWTO (R_MCORE_GNU_VTINHERIT, /* type */ |
227 | | 0, /* rightshift */ |
228 | | 4, /* size */ |
229 | | 0, /* bitsize */ |
230 | | false, /* pc_relative */ |
231 | | 0, /* bitpos */ |
232 | | complain_overflow_dont, /* complain_on_overflow */ |
233 | | NULL, /* special_function */ |
234 | | "R_MCORE_GNU_VTINHERIT", /* name */ |
235 | | false, /* partial_inplace */ |
236 | | 0, /* src_mask */ |
237 | | 0, /* dst_mask */ |
238 | | false), /* pcrel_offset */ |
239 | | |
240 | | /* GNU extension to record C++ vtable member usage. */ |
241 | | HOWTO (R_MCORE_GNU_VTENTRY, /* type */ |
242 | | 0, /* rightshift */ |
243 | | 4, /* size */ |
244 | | 0, /* bitsize */ |
245 | | false, /* pc_relative */ |
246 | | 0, /* bitpos */ |
247 | | complain_overflow_dont,/* complain_on_overflow */ |
248 | | _bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
249 | | "R_MCORE_GNU_VTENTRY", /* name */ |
250 | | false, /* partial_inplace */ |
251 | | 0, /* src_mask */ |
252 | | 0, /* dst_mask */ |
253 | | false), /* pcrel_offset */ |
254 | | |
255 | | HOWTO (R_MCORE_RELATIVE, /* type */ |
256 | | 0, /* rightshift */ |
257 | | 4, /* size */ |
258 | | 32, /* bitsize */ |
259 | | false, /* pc_relative */ |
260 | | 0, /* bitpos */ |
261 | | complain_overflow_signed, /* complain_on_overflow */ |
262 | | NULL, /* special_function */ |
263 | | "R_MCORE_RELATIVE", /* name */ |
264 | | true, /* partial_inplace */ |
265 | | 0xffffffff, /* src_mask */ |
266 | | 0xffffffff, /* dst_mask */ |
267 | | false) /* pcrel_offset */ |
268 | | }; |
269 | | |
270 | | #ifndef NUM_ELEM |
271 | 0 | #define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) |
272 | | #endif |
273 | | |
274 | | /* Initialize the mcore_elf_howto_table, so that linear accesses can be done. */ |
275 | | static void |
276 | | mcore_elf_howto_init (void) |
277 | 0 | { |
278 | 0 | unsigned int i; |
279 | |
|
280 | 0 | for (i = NUM_ELEM (mcore_elf_howto_raw); i--;) |
281 | 0 | { |
282 | 0 | unsigned int type; |
283 | |
|
284 | 0 | type = mcore_elf_howto_raw[i].type; |
285 | |
|
286 | 0 | BFD_ASSERT (type < NUM_ELEM (mcore_elf_howto_table)); |
287 | |
|
288 | 0 | mcore_elf_howto_table [type] = & mcore_elf_howto_raw [i]; |
289 | 0 | } |
290 | 0 | } |
291 | | |
292 | | static reloc_howto_type * |
293 | | mcore_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, |
294 | | bfd_reloc_code_real_type code) |
295 | 0 | { |
296 | 0 | enum elf_mcore_reloc_type mcore_reloc = R_MCORE_NONE; |
297 | |
|
298 | 0 | switch (code) |
299 | 0 | { |
300 | 0 | case BFD_RELOC_NONE: mcore_reloc = R_MCORE_NONE; break; |
301 | 0 | case BFD_RELOC_32: mcore_reloc = R_MCORE_ADDR32; break; |
302 | 0 | case BFD_RELOC_MCORE_PCREL_IMM8BY4: mcore_reloc = R_MCORE_PCRELIMM8BY4; break; |
303 | 0 | case BFD_RELOC_MCORE_PCREL_IMM11BY2: mcore_reloc = R_MCORE_PCRELIMM11BY2; break; |
304 | 0 | case BFD_RELOC_MCORE_PCREL_IMM4BY2: mcore_reloc = R_MCORE_PCRELIMM4BY2; break; |
305 | 0 | case BFD_RELOC_32_PCREL: mcore_reloc = R_MCORE_PCREL32; break; |
306 | 0 | case BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2: mcore_reloc = R_MCORE_PCRELJSR_IMM11BY2; break; |
307 | 0 | case BFD_RELOC_VTABLE_INHERIT: mcore_reloc = R_MCORE_GNU_VTINHERIT; break; |
308 | 0 | case BFD_RELOC_VTABLE_ENTRY: mcore_reloc = R_MCORE_GNU_VTENTRY; break; |
309 | 0 | case BFD_RELOC_RVA: mcore_reloc = R_MCORE_RELATIVE; break; |
310 | 0 | default: |
311 | 0 | return NULL; |
312 | 0 | } |
313 | | |
314 | 0 | if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4]) |
315 | | /* Initialize howto table if needed. */ |
316 | 0 | mcore_elf_howto_init (); |
317 | |
|
318 | 0 | return mcore_elf_howto_table [(int) mcore_reloc]; |
319 | 0 | }; |
320 | | |
321 | | static reloc_howto_type * |
322 | | mcore_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, |
323 | | const char *r_name) |
324 | 0 | { |
325 | 0 | unsigned int i; |
326 | |
|
327 | 0 | for (i = 0; |
328 | 0 | i < sizeof (mcore_elf_howto_raw) / sizeof (mcore_elf_howto_raw[0]); |
329 | 0 | i++) |
330 | 0 | if (mcore_elf_howto_raw[i].name != NULL |
331 | 0 | && strcasecmp (mcore_elf_howto_raw[i].name, r_name) == 0) |
332 | 0 | return &mcore_elf_howto_raw[i]; |
333 | | |
334 | 0 | return NULL; |
335 | 0 | } |
336 | | |
337 | | /* Set the howto pointer for a RCE ELF reloc. */ |
338 | | |
339 | | static bool |
340 | | mcore_elf_info_to_howto (bfd * abfd, |
341 | | arelent * cache_ptr, |
342 | | Elf_Internal_Rela * dst) |
343 | 0 | { |
344 | 0 | unsigned int r_type; |
345 | |
|
346 | 0 | if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4]) |
347 | | /* Initialize howto table if needed. */ |
348 | 0 | mcore_elf_howto_init (); |
349 | |
|
350 | 0 | r_type = ELF32_R_TYPE (dst->r_info); |
351 | 0 | if (r_type >= R_MCORE_max) |
352 | 0 | { |
353 | | /* xgettext:c-format */ |
354 | 0 | _bfd_error_handler (_("%pB: unsupported relocation type %#x"), |
355 | 0 | abfd, r_type); |
356 | 0 | bfd_set_error (bfd_error_bad_value); |
357 | 0 | return false; |
358 | 0 | } |
359 | | |
360 | 0 | cache_ptr->howto = mcore_elf_howto_table [r_type]; |
361 | 0 | return true; |
362 | 0 | } |
363 | | |
364 | | /* The RELOCATE_SECTION function is called by the ELF backend linker |
365 | | to handle the relocations for a section. |
366 | | |
367 | | The relocs are always passed as Rela structures; if the section |
368 | | actually uses Rel structures, the r_addend field will always be |
369 | | zero. |
370 | | |
371 | | This function is responsible for adjust the section contents as |
372 | | necessary, and (if using Rela relocs and generating a |
373 | | relocatable output file) adjusting the reloc addend as |
374 | | necessary. |
375 | | |
376 | | This function does not have to worry about setting the reloc |
377 | | address or the reloc symbol index. |
378 | | |
379 | | LOCAL_SYMS is a pointer to the swapped in local symbols. |
380 | | |
381 | | LOCAL_SECTIONS is an array giving the section in the input file |
382 | | corresponding to the st_shndx field of each local symbol. |
383 | | |
384 | | The global hash table entry for the global symbols can be found |
385 | | via elf_sym_hashes (input_bfd). |
386 | | |
387 | | When generating relocatable output, this function must handle |
388 | | STB_LOCAL/STT_SECTION symbols specially. The output symbol is |
389 | | going to be the section symbol corresponding to the output |
390 | | section, which means that the addend must be adjusted |
391 | | accordingly. */ |
392 | | |
393 | | static int |
394 | | mcore_elf_relocate_section (bfd * output_bfd, |
395 | | struct bfd_link_info * info, |
396 | | bfd * input_bfd, |
397 | | asection * input_section, |
398 | | bfd_byte * contents, |
399 | | Elf_Internal_Rela * relocs, |
400 | | Elf_Internal_Sym * local_syms, |
401 | | asection ** local_sections) |
402 | 0 | { |
403 | 0 | Elf_Internal_Shdr * symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
404 | 0 | struct elf_link_hash_entry ** sym_hashes = elf_sym_hashes (input_bfd); |
405 | 0 | Elf_Internal_Rela * rel = relocs; |
406 | 0 | Elf_Internal_Rela * relend = relocs + input_section->reloc_count; |
407 | 0 | bool ret = true; |
408 | |
|
409 | | #ifdef DEBUG |
410 | | _bfd_error_handler |
411 | | ("mcore_elf_relocate_section called for %pB section %pA, %u relocations%s", |
412 | | input_bfd, |
413 | | input_section, |
414 | | input_section->reloc_count, |
415 | | (bfd_link_relocatable (info)) ? " (relocatable)" : ""); |
416 | | #endif |
417 | |
|
418 | 0 | if (! mcore_elf_howto_table [R_MCORE_PCRELIMM8BY4]) /* Initialize howto table if needed */ |
419 | 0 | mcore_elf_howto_init (); |
420 | |
|
421 | 0 | for (; rel < relend; rel++) |
422 | 0 | { |
423 | 0 | enum elf_mcore_reloc_type r_type = (enum elf_mcore_reloc_type) ELF32_R_TYPE (rel->r_info); |
424 | 0 | bfd_vma offset = rel->r_offset; |
425 | 0 | bfd_vma addend = rel->r_addend; |
426 | 0 | bfd_reloc_status_type r = bfd_reloc_other; |
427 | 0 | asection * sec = NULL; |
428 | 0 | reloc_howto_type * howto; |
429 | 0 | bfd_vma relocation; |
430 | 0 | Elf_Internal_Sym * sym = NULL; |
431 | 0 | unsigned long r_symndx; |
432 | 0 | struct elf_link_hash_entry * h = NULL; |
433 | 0 | unsigned short oldinst = 0; |
434 | | |
435 | | /* Unknown relocation handling. */ |
436 | 0 | if ((unsigned) r_type >= (unsigned) R_MCORE_max |
437 | 0 | || ! mcore_elf_howto_table [(int)r_type]) |
438 | 0 | { |
439 | | /* xgettext:c-format */ |
440 | 0 | _bfd_error_handler (_("%pB: unsupported relocation type %#x"), |
441 | 0 | input_bfd, (int) r_type); |
442 | |
|
443 | 0 | bfd_set_error (bfd_error_bad_value); |
444 | 0 | ret = false; |
445 | 0 | continue; |
446 | 0 | } |
447 | | |
448 | 0 | howto = mcore_elf_howto_table [(int) r_type]; |
449 | 0 | r_symndx = ELF32_R_SYM (rel->r_info); |
450 | | |
451 | | /* Complain about known relocation that are not yet supported. */ |
452 | 0 | if (howto->special_function == mcore_elf_unsupported_reloc) |
453 | 0 | { |
454 | | /* xgettext:c-format */ |
455 | 0 | _bfd_error_handler (_("%pB: %s unsupported"), |
456 | 0 | input_bfd, |
457 | 0 | howto->name); |
458 | |
|
459 | 0 | bfd_set_error (bfd_error_bad_value); |
460 | 0 | ret = false; |
461 | 0 | continue; |
462 | 0 | } |
463 | | |
464 | 0 | if (r_symndx < symtab_hdr->sh_info) |
465 | 0 | { |
466 | 0 | sym = local_syms + r_symndx; |
467 | 0 | sec = local_sections [r_symndx]; |
468 | 0 | relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
469 | 0 | addend = rel->r_addend; |
470 | 0 | } |
471 | 0 | else |
472 | 0 | { |
473 | 0 | bool unresolved_reloc, warned, ignored; |
474 | |
|
475 | 0 | RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
476 | 0 | r_symndx, symtab_hdr, sym_hashes, |
477 | 0 | h, sec, relocation, |
478 | 0 | unresolved_reloc, warned, ignored); |
479 | 0 | } |
480 | | |
481 | 0 | if (sec != NULL && discarded_section (sec)) |
482 | 0 | RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, |
483 | 0 | rel, 1, relend, howto, 0, contents); |
484 | |
|
485 | 0 | if (bfd_link_relocatable (info)) |
486 | 0 | continue; |
487 | | |
488 | 0 | switch (r_type) |
489 | 0 | { |
490 | 0 | default: |
491 | 0 | break; |
492 | | |
493 | 0 | case R_MCORE_PCRELJSR_IMM11BY2: |
494 | 0 | oldinst = bfd_get_16 (input_bfd, contents + offset); |
495 | 0 | #define MCORE_INST_BSR 0xF800 |
496 | 0 | bfd_put_16 (input_bfd, (bfd_vma) MCORE_INST_BSR, contents + offset); |
497 | 0 | break; |
498 | 0 | } |
499 | | |
500 | | #ifdef DEBUG |
501 | | fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n", |
502 | | howto->name, r_type, r_symndx, (long) offset, (long) addend); |
503 | | #endif |
504 | | |
505 | 0 | r = _bfd_final_link_relocate |
506 | 0 | (howto, input_bfd, input_section, contents, offset, relocation, addend); |
507 | |
|
508 | 0 | if (r != bfd_reloc_ok && r_type == R_MCORE_PCRELJSR_IMM11BY2) |
509 | 0 | { |
510 | | /* Wasn't ok, back it out and give up. */ |
511 | 0 | bfd_put_16 (input_bfd, (bfd_vma) oldinst, contents + offset); |
512 | 0 | r = bfd_reloc_ok; |
513 | 0 | } |
514 | |
|
515 | 0 | if (r != bfd_reloc_ok) |
516 | 0 | { |
517 | 0 | ret = false; |
518 | |
|
519 | 0 | switch (r) |
520 | 0 | { |
521 | 0 | default: |
522 | 0 | break; |
523 | | |
524 | 0 | case bfd_reloc_overflow: |
525 | 0 | { |
526 | 0 | const char * name; |
527 | |
|
528 | 0 | if (h != NULL) |
529 | 0 | name = NULL; |
530 | 0 | else |
531 | 0 | { |
532 | 0 | name = bfd_elf_string_from_elf_section |
533 | 0 | (input_bfd, symtab_hdr->sh_link, sym->st_name); |
534 | |
|
535 | 0 | if (name == NULL) |
536 | 0 | break; |
537 | | |
538 | 0 | if (* name == '\0') |
539 | 0 | name = bfd_section_name (sec); |
540 | 0 | } |
541 | | |
542 | 0 | (*info->callbacks->reloc_overflow) |
543 | 0 | (info, (h ? &h->root : NULL), name, howto->name, |
544 | 0 | (bfd_vma) 0, input_bfd, input_section, offset); |
545 | 0 | } |
546 | 0 | break; |
547 | 0 | } |
548 | 0 | } |
549 | 0 | } |
550 | | |
551 | | #ifdef DEBUG |
552 | | fprintf (stderr, "\n"); |
553 | | #endif |
554 | | |
555 | 0 | return ret; |
556 | 0 | } |
557 | | |
558 | | /* Return the section that should be marked against GC for a given |
559 | | relocation. */ |
560 | | |
561 | | static asection * |
562 | | mcore_elf_gc_mark_hook (asection *sec, |
563 | | struct bfd_link_info *info, |
564 | | Elf_Internal_Rela *rel, |
565 | | struct elf_link_hash_entry *h, |
566 | | Elf_Internal_Sym *sym) |
567 | 0 | { |
568 | 0 | if (h != NULL) |
569 | 0 | switch (ELF32_R_TYPE (rel->r_info)) |
570 | 0 | { |
571 | 0 | case R_MCORE_GNU_VTINHERIT: |
572 | 0 | case R_MCORE_GNU_VTENTRY: |
573 | 0 | return NULL; |
574 | 0 | } |
575 | | |
576 | 0 | return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); |
577 | 0 | } |
578 | | |
579 | | /* Look through the relocs for a section during the first phase. |
580 | | Since we don't do .gots or .plts, we just need to consider the |
581 | | virtual table relocs for gc. */ |
582 | | |
583 | | static bool |
584 | | mcore_elf_check_relocs (bfd * abfd, |
585 | | struct bfd_link_info * info, |
586 | | asection * sec, |
587 | | const Elf_Internal_Rela * relocs) |
588 | 0 | { |
589 | 0 | Elf_Internal_Shdr * symtab_hdr; |
590 | 0 | struct elf_link_hash_entry ** sym_hashes; |
591 | 0 | const Elf_Internal_Rela * rel; |
592 | 0 | const Elf_Internal_Rela * rel_end; |
593 | |
|
594 | 0 | if (bfd_link_relocatable (info)) |
595 | 0 | return true; |
596 | | |
597 | 0 | symtab_hdr = & elf_tdata (abfd)->symtab_hdr; |
598 | 0 | sym_hashes = elf_sym_hashes (abfd); |
599 | |
|
600 | 0 | rel_end = relocs + sec->reloc_count; |
601 | |
|
602 | 0 | for (rel = relocs; rel < rel_end; rel++) |
603 | 0 | { |
604 | 0 | struct elf_link_hash_entry * h; |
605 | 0 | unsigned long r_symndx; |
606 | |
|
607 | 0 | r_symndx = ELF32_R_SYM (rel->r_info); |
608 | |
|
609 | 0 | if (r_symndx < symtab_hdr->sh_info) |
610 | 0 | h = NULL; |
611 | 0 | else |
612 | 0 | { |
613 | 0 | h = sym_hashes [r_symndx - symtab_hdr->sh_info]; |
614 | 0 | while (h->root.type == bfd_link_hash_indirect |
615 | 0 | || h->root.type == bfd_link_hash_warning) |
616 | 0 | h = (struct elf_link_hash_entry *) h->root.u.i.link; |
617 | 0 | } |
618 | |
|
619 | 0 | switch (ELF32_R_TYPE (rel->r_info)) |
620 | 0 | { |
621 | | /* This relocation describes the C++ object vtable hierarchy. |
622 | | Reconstruct it for later use during GC. */ |
623 | 0 | case R_MCORE_GNU_VTINHERIT: |
624 | 0 | if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
625 | 0 | return false; |
626 | 0 | break; |
627 | | |
628 | | /* This relocation describes which C++ vtable entries are actually |
629 | | used. Record for later use during GC. */ |
630 | 0 | case R_MCORE_GNU_VTENTRY: |
631 | 0 | if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
632 | 0 | return false; |
633 | 0 | break; |
634 | 0 | } |
635 | 0 | } |
636 | | |
637 | 0 | return true; |
638 | 0 | } |
639 | | |
640 | | static const struct bfd_elf_special_section mcore_elf_special_sections[]= |
641 | | { |
642 | | { STRING_COMMA_LEN (".ctors"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, |
643 | | { STRING_COMMA_LEN (".dtors"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, |
644 | | { NULL, 0, 0, 0, 0 } |
645 | | }; |
646 | | |
647 | | #define TARGET_BIG_SYM mcore_elf32_be_vec |
648 | | #define TARGET_BIG_NAME "elf32-mcore-big" |
649 | | #define TARGET_LITTLE_SYM mcore_elf32_le_vec |
650 | | #define TARGET_LITTLE_NAME "elf32-mcore-little" |
651 | | |
652 | | #define ELF_ARCH bfd_arch_mcore |
653 | | #define ELF_MACHINE_CODE EM_MCORE |
654 | | #define ELF_MAXPAGESIZE 0x1000 /* 4k, if we ever have 'em */ |
655 | | #define elf_info_to_howto mcore_elf_info_to_howto |
656 | | #define elf_info_to_howto_rel NULL |
657 | | |
658 | | #define bfd_elf32_bfd_merge_private_bfd_data mcore_elf_merge_private_bfd_data |
659 | | #define bfd_elf32_bfd_set_private_flags mcore_elf_set_private_flags |
660 | | #define bfd_elf32_bfd_reloc_type_lookup mcore_elf_reloc_type_lookup |
661 | | #define bfd_elf32_bfd_reloc_name_lookup mcore_elf_reloc_name_lookup |
662 | | #define elf_backend_relocate_section mcore_elf_relocate_section |
663 | | #define elf_backend_gc_mark_hook mcore_elf_gc_mark_hook |
664 | | #define elf_backend_check_relocs mcore_elf_check_relocs |
665 | | #define elf_backend_special_sections mcore_elf_special_sections |
666 | | |
667 | | #define elf_backend_can_gc_sections 1 |
668 | | #define elf_backend_rela_normal 1 |
669 | | |
670 | | #include "elf32-target.h" |