Correct spelling of "relocatable".
[deliverable/binutils-gdb.git] / bfd / elf32-fr30.c
CommitLineData
252b5132 1/* FR30-specific support for 32-bit ELF.
1049f94e
AM
2 Copyright 1998, 1999, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
252b5132
RH
4
5This file is part of BFD, the Binary File Descriptor library.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "bfd.h"
22#include "sysdep.h"
23#include "libbfd.h"
24#include "elf-bfd.h"
25#include "elf/fr30.h"
26
27/* Forward declarations. */
28static bfd_reloc_status_type fr30_elf_i20_reloc
29 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
30static bfd_reloc_status_type fr30_elf_i32_reloc
31 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
32static reloc_howto_type * fr30_reloc_type_lookup
33 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
6609fa74 34static void fr30_info_to_howto_rela
947216bf 35 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
b34976b6 36static bfd_boolean fr30_elf_relocate_section
dc810e39
AM
37 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
38 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
252b5132 39static bfd_reloc_status_type fr30_final_link_relocate
dc810e39
AM
40 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
41 Elf_Internal_Rela *, bfd_vma));
b34976b6 42static bfd_boolean fr30_elf_gc_sweep_hook
dc810e39
AM
43 PARAMS ((bfd *, struct bfd_link_info *, asection *,
44 const Elf_Internal_Rela *));
252b5132 45static asection * fr30_elf_gc_mark_hook
1e2f5b6e 46 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
dc810e39 47 struct elf_link_hash_entry *, Elf_Internal_Sym *));
b34976b6 48static bfd_boolean fr30_elf_check_relocs
dc810e39
AM
49 PARAMS ((bfd *, struct bfd_link_info *, asection *,
50 const Elf_Internal_Rela *));
252b5132
RH
51
52static reloc_howto_type fr30_elf_howto_table [] =
53{
54 /* This reloc does nothing. */
55 HOWTO (R_FR30_NONE, /* type */
56 0, /* rightshift */
57 2, /* size (0 = byte, 1 = short, 2 = long) */
58 32, /* bitsize */
b34976b6 59 FALSE, /* pc_relative */
252b5132
RH
60 0, /* bitpos */
61 complain_overflow_bitfield, /* complain_on_overflow */
62 bfd_elf_generic_reloc, /* special_function */
63 "R_FR30_NONE", /* name */
b34976b6 64 FALSE, /* partial_inplace */
252b5132
RH
65 0, /* src_mask */
66 0, /* dst_mask */
b34976b6 67 FALSE), /* pcrel_offset */
252b5132
RH
68
69 /* An 8 bit absolute relocation. */
70 HOWTO (R_FR30_8, /* type */
71 0, /* rightshift */
72 1, /* size (0 = byte, 1 = short, 2 = long) */
73 8, /* bitsize */
b34976b6 74 FALSE, /* pc_relative */
252b5132
RH
75 4, /* bitpos */
76 complain_overflow_bitfield, /* complain_on_overflow */
77 bfd_elf_generic_reloc, /* special_function */
78 "R_FR30_8", /* name */
b34976b6 79 TRUE, /* partial_inplace */
252b5132
RH
80 0x0000, /* src_mask */
81 0x0ff0, /* dst_mask */
b34976b6 82 FALSE), /* pcrel_offset */
252b5132
RH
83
84 /* A 20 bit absolute relocation. */
85 HOWTO (R_FR30_20, /* type */
86 0, /* rightshift */
87 2, /* size (0 = byte, 1 = short, 2 = long) */
88 20, /* bitsize */
b34976b6 89 FALSE, /* pc_relative */
252b5132
RH
90 0, /* bitpos */
91 complain_overflow_bitfield, /* complain_on_overflow */
92 fr30_elf_i20_reloc, /* special_function */
93 "R_FR30_20", /* name */
b34976b6 94 TRUE, /* partial_inplace */
252b5132
RH
95 0x00000000, /* src_mask */
96 0x00f0ffff, /* dst_mask */
b34976b6 97 FALSE), /* pcrel_offset */
252b5132
RH
98
99 /* A 32 bit absolute relocation. */
100 HOWTO (R_FR30_32, /* type */
101 0, /* rightshift */
102 2, /* size (0 = byte, 1 = short, 2 = long) */
103 32, /* bitsize */
b34976b6 104 FALSE, /* pc_relative */
252b5132
RH
105 0, /* bitpos */
106 complain_overflow_bitfield, /* complain_on_overflow */
107 bfd_elf_generic_reloc, /* special_function */
108 "R_FR30_32", /* name */
b34976b6 109 TRUE, /* partial_inplace */
252b5132
RH
110 0x00000000, /* src_mask */
111 0xffffffff, /* dst_mask */
b34976b6 112 FALSE), /* pcrel_offset */
252b5132
RH
113
114 /* A 32 bit into 48 bits absolute relocation. */
115 HOWTO (R_FR30_48, /* type */
116 0, /* rightshift */
117 2, /* size (0 = byte, 1 = short, 2 = long) */
118 32, /* bitsize */
b34976b6 119 FALSE, /* pc_relative */
252b5132
RH
120 0, /* bitpos */
121 complain_overflow_bitfield, /* complain_on_overflow */
122 fr30_elf_i32_reloc, /* special_function */
123 "R_FR30_48", /* name */
b34976b6 124 TRUE, /* partial_inplace */
252b5132
RH
125 0x00000000, /* src_mask */
126 0xffffffff, /* dst_mask */
b34976b6 127 FALSE), /* pcrel_offset */
252b5132
RH
128
129 /* A 6 bit absolute relocation. */
130 HOWTO (R_FR30_6_IN_4, /* type */
131 2, /* rightshift */
132 1, /* size (0 = byte, 1 = short, 2 = long) */
133 6, /* bitsize */
b34976b6 134 FALSE, /* pc_relative */
252b5132
RH
135 4, /* bitpos */
136 complain_overflow_unsigned, /* complain_on_overflow */
137 bfd_elf_generic_reloc, /* special_function */
138 "R_FR30_6_IN_4", /* name */
b34976b6 139 TRUE, /* partial_inplace */
252b5132
RH
140 0x0000, /* src_mask */
141 0x00f0, /* dst_mask */
b34976b6 142 FALSE), /* pcrel_offset */
6609fa74 143
252b5132
RH
144 /* An 8 bit absolute relocation. */
145 HOWTO (R_FR30_8_IN_8, /* type */
146 0, /* rightshift */
147 1, /* size (0 = byte, 1 = short, 2 = long) */
148 8, /* bitsize */
b34976b6 149 FALSE, /* pc_relative */
252b5132
RH
150 4, /* bitpos */
151 complain_overflow_signed, /* complain_on_overflow */
152 bfd_elf_generic_reloc,/* special_function */
153 "R_FR30_8_IN_8", /* name */
b34976b6 154 TRUE, /* partial_inplace */
252b5132
RH
155 0x0000, /* src_mask */
156 0x0ff0, /* dst_mask */
b34976b6 157 FALSE), /* pcrel_offset */
6609fa74 158
252b5132
RH
159 /* A 9 bit absolute relocation. */
160 HOWTO (R_FR30_9_IN_8, /* type */
161 1, /* rightshift */
162 1, /* size (0 = byte, 1 = short, 2 = long) */
163 9, /* bitsize */
b34976b6 164 FALSE, /* pc_relative */
252b5132
RH
165 4, /* bitpos */
166 complain_overflow_signed, /* complain_on_overflow */
167 bfd_elf_generic_reloc,/* special_function */
168 "R_FR30_9_IN_8", /* name */
b34976b6 169 TRUE, /* partial_inplace */
252b5132
RH
170 0x0000, /* src_mask */
171 0x0ff0, /* dst_mask */
b34976b6 172 FALSE), /* pcrel_offset */
6609fa74 173
252b5132
RH
174 /* A 10 bit absolute relocation. */
175 HOWTO (R_FR30_10_IN_8, /* type */
176 2, /* rightshift */
177 1, /* size (0 = byte, 1 = short, 2 = long) */
178 10, /* bitsize */
b34976b6 179 FALSE, /* pc_relative */
252b5132
RH
180 4, /* bitpos */
181 complain_overflow_signed, /* complain_on_overflow */
182 bfd_elf_generic_reloc,/* special_function */
183 "R_FR30_10_IN_8", /* name */
b34976b6 184 TRUE, /* partial_inplace */
252b5132
RH
185 0x0000, /* src_mask */
186 0x0ff0, /* dst_mask */
b34976b6 187 FALSE), /* pcrel_offset */
252b5132
RH
188
189 /* A PC relative 9 bit relocation, right shifted by 1. */
190 HOWTO (R_FR30_9_PCREL, /* type */
191 1, /* rightshift */
192 1, /* size (0 = byte, 1 = short, 2 = long) */
193 9, /* bitsize */
b34976b6 194 TRUE, /* pc_relative */
252b5132
RH
195 0, /* bitpos */
196 complain_overflow_signed, /* complain_on_overflow */
197 bfd_elf_generic_reloc, /* special_function */
198 "R_FR30_9_PCREL", /* name */
b34976b6 199 FALSE, /* partial_inplace */
252b5132
RH
200 0x0000, /* src_mask */
201 0x00ff, /* dst_mask */
b34976b6 202 FALSE), /* pcrel_offset */
252b5132
RH
203
204 /* A PC relative 12 bit relocation, right shifted by 1. */
205 HOWTO (R_FR30_12_PCREL, /* type */
206 1, /* rightshift */
207 1, /* size (0 = byte, 1 = short, 2 = long) */
208 12, /* bitsize */
b34976b6 209 TRUE, /* pc_relative */
252b5132
RH
210 0, /* bitpos */
211 complain_overflow_signed, /* complain_on_overflow */
212 bfd_elf_generic_reloc, /* special_function */
213 "R_FR30_12_PCREL", /* name */
b34976b6 214 FALSE, /* partial_inplace */
252b5132
RH
215 0x0000, /* src_mask */
216 0x07ff, /* dst_mask */
b34976b6 217 FALSE), /* pcrel_offset */
252b5132
RH
218 /* GNU extension to record C++ vtable hierarchy */
219 HOWTO (R_FR30_GNU_VTINHERIT, /* type */
220 0, /* rightshift */
221 2, /* size (0 = byte, 1 = short, 2 = long) */
222 0, /* bitsize */
b34976b6 223 FALSE, /* pc_relative */
252b5132
RH
224 0, /* bitpos */
225 complain_overflow_dont, /* complain_on_overflow */
226 NULL, /* special_function */
227 "R_FR30_GNU_VTINHERIT", /* name */
b34976b6 228 FALSE, /* partial_inplace */
252b5132
RH
229 0, /* src_mask */
230 0, /* dst_mask */
b34976b6 231 FALSE), /* pcrel_offset */
252b5132
RH
232
233 /* GNU extension to record C++ vtable member usage */
234 HOWTO (R_FR30_GNU_VTENTRY, /* type */
235 0, /* rightshift */
236 2, /* size (0 = byte, 1 = short, 2 = long) */
237 0, /* bitsize */
b34976b6 238 FALSE, /* pc_relative */
252b5132
RH
239 0, /* bitpos */
240 complain_overflow_dont, /* complain_on_overflow */
241 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
242 "R_FR30_GNU_VTENTRY", /* name */
b34976b6 243 FALSE, /* partial_inplace */
252b5132
RH
244 0, /* src_mask */
245 0, /* dst_mask */
b34976b6 246 FALSE), /* pcrel_offset */
252b5132
RH
247};
248\f
249/* Utility to actually perform an R_FR30_20 reloc. */
250
251static bfd_reloc_status_type
252fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
253 input_section, output_bfd, error_message)
b34976b6
AM
254 bfd *abfd;
255 arelent *reloc_entry;
256 asymbol *symbol;
257 PTR data;
258 asection *input_section;
259 bfd *output_bfd;
260 char **error_message ATTRIBUTE_UNUSED;
252b5132 261{
b34976b6 262 bfd_vma relocation;
252b5132 263 unsigned long x;
6609fa74 264
252b5132
RH
265 /* This part is from bfd_elf_generic_reloc. */
266 if (output_bfd != (bfd *) NULL
267 && (symbol->flags & BSF_SECTION_SYM) == 0
268 && (! reloc_entry->howto->partial_inplace
269 || reloc_entry->addend == 0))
270 {
271 reloc_entry->address += input_section->output_offset;
272 return bfd_reloc_ok;
273 }
274
275 if (output_bfd != NULL)
276 /* FIXME: See bfd_perform_relocation. Is this right? */
277 return bfd_reloc_ok;
278
279 relocation =
280 symbol->value
281 + symbol->section->output_section->vma
282 + symbol->section->output_offset
283 + reloc_entry->addend;
284
fc633e5b 285 if (relocation > (((bfd_vma) 1 << 20) - 1))
252b5132
RH
286 return bfd_reloc_overflow;
287
23ccc829 288 x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
252b5132 289 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
dc810e39 290 bfd_put_32 (abfd, (bfd_vma) x, (char *) data + reloc_entry->address);
252b5132
RH
291
292 return bfd_reloc_ok;
293}
252b5132
RH
294\f
295/* Utility to actually perform a R_FR30_48 reloc. */
296
297static bfd_reloc_status_type
298fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data,
299 input_section, output_bfd, error_message)
b34976b6
AM
300 bfd *abfd;
301 arelent *reloc_entry;
302 asymbol *symbol;
303 PTR data;
304 asection *input_section;
305 bfd *output_bfd;
306 char **error_message ATTRIBUTE_UNUSED;
252b5132 307{
b34976b6 308 bfd_vma relocation;
252b5132
RH
309
310 /* This part is from bfd_elf_generic_reloc. */
311 if (output_bfd != (bfd *) NULL
312 && (symbol->flags & BSF_SECTION_SYM) == 0
313 && (! reloc_entry->howto->partial_inplace
314 || reloc_entry->addend == 0))
315 {
316 reloc_entry->address += input_section->output_offset;
317 return bfd_reloc_ok;
318 }
319
320 if (output_bfd != NULL)
321 /* FIXME: See bfd_perform_relocation. Is this right? */
322 return bfd_reloc_ok;
323
324 relocation =
325 symbol->value
326 + symbol->section->output_section->vma
327 + symbol->section->output_offset
328 + reloc_entry->addend;
329
23ccc829 330 bfd_put_32 (abfd, relocation, (char *) data + reloc_entry->address + 2);
252b5132
RH
331
332 return bfd_reloc_ok;
333}
334\f
335/* Map BFD reloc types to FR30 ELF reloc types. */
336
337struct fr30_reloc_map
338{
339 bfd_reloc_code_real_type bfd_reloc_val;
340 unsigned int fr30_reloc_val;
341};
342
343static const struct fr30_reloc_map fr30_reloc_map [] =
344{
345 { BFD_RELOC_NONE, R_FR30_NONE },
346 { BFD_RELOC_8, R_FR30_8 },
347 { BFD_RELOC_FR30_20, R_FR30_20 },
348 { BFD_RELOC_32, R_FR30_32 },
349 { BFD_RELOC_FR30_48, R_FR30_48 },
350 { BFD_RELOC_FR30_6_IN_4, R_FR30_6_IN_4 },
351 { BFD_RELOC_FR30_8_IN_8, R_FR30_8_IN_8 },
352 { BFD_RELOC_FR30_9_IN_8, R_FR30_9_IN_8 },
353 { BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 },
354 { BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL },
355 { BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL },
356 { BFD_RELOC_VTABLE_INHERIT, R_FR30_GNU_VTINHERIT },
357 { BFD_RELOC_VTABLE_ENTRY, R_FR30_GNU_VTENTRY },
358};
359
360static reloc_howto_type *
361fr30_reloc_type_lookup (abfd, code)
b34976b6 362 bfd *abfd ATTRIBUTE_UNUSED;
252b5132
RH
363 bfd_reloc_code_real_type code;
364{
365 unsigned int i;
366
367 for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
368 --i;)
369 if (fr30_reloc_map [i].bfd_reloc_val == code)
370 return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
6609fa74 371
252b5132
RH
372 return NULL;
373}
374
375/* Set the howto pointer for an FR30 ELF reloc. */
376
377static void
378fr30_info_to_howto_rela (abfd, cache_ptr, dst)
b34976b6
AM
379 bfd *abfd ATTRIBUTE_UNUSED;
380 arelent *cache_ptr;
381 Elf_Internal_Rela *dst;
252b5132
RH
382{
383 unsigned int r_type;
384
385 r_type = ELF32_R_TYPE (dst->r_info);
386 BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
387 cache_ptr->howto = & fr30_elf_howto_table [r_type];
388}
389\f
390/* Perform a single relocation. By default we use the standard BFD
391 routines, but a few relocs, we have to do them ourselves. */
392
393static bfd_reloc_status_type
b34976b6
AM
394fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel,
395 relocation)
396 reloc_howto_type *howto;
397 bfd *input_bfd;
398 asection *input_section;
399 bfd_byte *contents;
400 Elf_Internal_Rela *rel;
401 bfd_vma relocation;
252b5132
RH
402{
403 bfd_reloc_status_type r = bfd_reloc_ok;
b34976b6
AM
404 bfd_vma x;
405 bfd_signed_vma srel;
6609fa74 406
252b5132
RH
407 switch (howto->type)
408 {
409 case R_FR30_20:
410 contents += rel->r_offset;
411 relocation += rel->r_addend;
412
413 if (relocation > ((1 << 20) - 1))
414 return bfd_reloc_overflow;
6609fa74 415
252b5132
RH
416 x = bfd_get_32 (input_bfd, contents);
417 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
418 bfd_put_32 (input_bfd, x, contents);
419 break;
6609fa74 420
252b5132
RH
421 case R_FR30_48:
422 contents += rel->r_offset + 2;
423 relocation += rel->r_addend;
424 bfd_put_32 (input_bfd, relocation, contents);
425 break;
426
427 case R_FR30_9_PCREL:
428 contents += rel->r_offset + 1;
429 srel = (bfd_signed_vma) relocation;
430 srel += rel->r_addend;
431 srel -= rel->r_offset;
6609fa74 432 srel -= 2; /* Branch instructions add 2 to the PC... */
252b5132
RH
433 srel -= (input_section->output_section->vma +
434 input_section->output_offset);
6609fa74 435
252b5132
RH
436 if (srel & 1)
437 return bfd_reloc_outofrange;
438 if (srel > ((1 << 8) - 1) || (srel < - (1 << 8)))
439 return bfd_reloc_overflow;
440
441 bfd_put_8 (input_bfd, srel >> 1, contents);
442 break;
443
444 case R_FR30_12_PCREL:
445 contents += rel->r_offset;
446 srel = (bfd_signed_vma) relocation;
447 srel += rel->r_addend;
448 srel -= rel->r_offset;
6609fa74 449 srel -= 2; /* Branch instructions add 2 to the PC... */
252b5132
RH
450 srel -= (input_section->output_section->vma +
451 input_section->output_offset);
6609fa74 452
252b5132
RH
453 if (srel & 1)
454 return bfd_reloc_outofrange;
455 if (srel > ((1 << 11) - 1) || (srel < - (1 << 11)))
456 return bfd_reloc_overflow;
6609fa74 457
252b5132
RH
458 x = bfd_get_16 (input_bfd, contents);
459 x = (x & 0xf800) | ((srel >> 1) & 0x7ff);
460 bfd_put_16 (input_bfd, x, contents);
461 break;
462
463 default:
464 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
465 contents, rel->r_offset,
466 relocation, rel->r_addend);
467 }
468
469 return r;
470}
252b5132
RH
471\f
472/* Relocate an FR30 ELF section.
252b5132
RH
473
474 The RELOCATE_SECTION function is called by the new ELF backend linker
475 to handle the relocations for a section.
476
477 The relocs are always passed as Rela structures; if the section
478 actually uses Rel structures, the r_addend field will always be
479 zero.
480
481 This function is responsible for adjusting the section contents as
1049f94e 482 necessary, and (if using Rela relocs and generating a relocatable
252b5132
RH
483 output file) adjusting the reloc addend as necessary.
484
485 This function does not have to worry about setting the reloc
486 address or the reloc symbol index.
487
488 LOCAL_SYMS is a pointer to the swapped in local symbols.
489
490 LOCAL_SECTIONS is an array giving the section in the input file
491 corresponding to the st_shndx field of each local symbol.
492
493 The global hash table entry for the global symbols can be found
494 via elf_sym_hashes (input_bfd).
495
1049f94e 496 When generating relocatable output, this function must handle
252b5132
RH
497 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
498 going to be the section symbol corresponding to the output
499 section, which means that the addend must be adjusted
500 accordingly. */
501
b34976b6 502static bfd_boolean
252b5132
RH
503fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
504 contents, relocs, local_syms, local_sections)
b34976b6
AM
505 bfd *output_bfd;
506 struct bfd_link_info *info;
507 bfd *input_bfd;
508 asection *input_section;
509 bfd_byte *contents;
510 Elf_Internal_Rela *relocs;
511 Elf_Internal_Sym *local_syms;
512 asection **local_sections;
252b5132 513{
b34976b6
AM
514 Elf_Internal_Shdr *symtab_hdr;
515 struct elf_link_hash_entry **sym_hashes;
516 Elf_Internal_Rela *rel;
517 Elf_Internal_Rela *relend;
252b5132 518
1049f94e 519 if (info->relocatable)
b34976b6 520 return TRUE;
b491616a 521
252b5132
RH
522 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
523 sym_hashes = elf_sym_hashes (input_bfd);
524 relend = relocs + input_section->reloc_count;
525
526 for (rel = relocs; rel < relend; rel ++)
527 {
b34976b6
AM
528 reloc_howto_type *howto;
529 unsigned long r_symndx;
530 Elf_Internal_Sym *sym;
531 asection *sec;
532 struct elf_link_hash_entry *h;
533 bfd_vma relocation;
534 bfd_reloc_status_type r;
535 const char *name = NULL;
536 int r_type;
6609fa74 537
252b5132 538 r_type = ELF32_R_TYPE (rel->r_info);
6609fa74 539
252b5132
RH
540 if ( r_type == R_FR30_GNU_VTINHERIT
541 || r_type == R_FR30_GNU_VTENTRY)
542 continue;
6609fa74 543
252b5132
RH
544 r_symndx = ELF32_R_SYM (rel->r_info);
545
252b5132
RH
546 howto = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
547 h = NULL;
548 sym = NULL;
549 sec = NULL;
6609fa74 550
252b5132
RH
551 if (r_symndx < symtab_hdr->sh_info)
552 {
553 sym = local_syms + r_symndx;
554 sec = local_sections [r_symndx];
f8df10f4 555 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
6609fa74 556
252b5132
RH
557 name = bfd_elf_string_from_elf_section
558 (input_bfd, symtab_hdr->sh_link, sym->st_name);
559 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
560#if 0
561 fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
562 sec->name, name, sym->st_name,
563 sec->output_section->vma, sec->output_offset,
564 sym->st_value, rel->r_addend);
565#endif
566 }
567 else
568 {
569 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
6609fa74 570
252b5132
RH
571 while (h->root.type == bfd_link_hash_indirect
572 || h->root.type == bfd_link_hash_warning)
573 h = (struct elf_link_hash_entry *) h->root.u.i.link;
574
575 name = h->root.root.string;
6609fa74 576
252b5132
RH
577 if (h->root.type == bfd_link_hash_defined
578 || h->root.type == bfd_link_hash_defweak)
579 {
580 sec = h->root.u.def.section;
581 relocation = (h->root.u.def.value
582 + sec->output_section->vma
583 + sec->output_offset);
584#if 0
585 fprintf (stderr,
586 "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
587 sec->name, name, h->root.u.def.value,
588 sec->output_section->vma, sec->output_offset, relocation);
589#endif
590 }
591 else if (h->root.type == bfd_link_hash_undefweak)
592 {
593#if 0
594 fprintf (stderr, "undefined: sec: %s, name: %s\n",
595 sec->name, name);
596#endif
597 relocation = 0;
598 }
599 else
600 {
601 if (! ((*info->callbacks->undefined_symbol)
602 (info, h->root.root.string, input_bfd,
b34976b6
AM
603 input_section, rel->r_offset, TRUE)))
604 return FALSE;
252b5132
RH
605#if 0
606 fprintf (stderr, "unknown: name: %s\n", name);
607#endif
608 relocation = 0;
609 }
610 }
6609fa74 611
252b5132
RH
612 r = fr30_final_link_relocate (howto, input_bfd, input_section,
613 contents, rel, relocation);
614
615 if (r != bfd_reloc_ok)
616 {
617 const char * msg = (const char *) NULL;
618
619 switch (r)
620 {
621 case bfd_reloc_overflow:
622 r = info->callbacks->reloc_overflow
623 (info, name, howto->name, (bfd_vma) 0,
624 input_bfd, input_section, rel->r_offset);
625 break;
6609fa74 626
252b5132
RH
627 case bfd_reloc_undefined:
628 r = info->callbacks->undefined_symbol
5cc7c785 629 (info, name, input_bfd, input_section, rel->r_offset,
b34976b6 630 TRUE);
252b5132 631 break;
6609fa74 632
252b5132
RH
633 case bfd_reloc_outofrange:
634 msg = _("internal error: out of range error");
635 break;
636
637 case bfd_reloc_notsupported:
638 msg = _("internal error: unsupported relocation error");
639 break;
640
641 case bfd_reloc_dangerous:
642 msg = _("internal error: dangerous relocation");
643 break;
644
645 default:
646 msg = _("internal error: unknown error");
647 break;
648 }
649
650 if (msg)
651 r = info->callbacks->warning
652 (info, msg, name, input_bfd, input_section, rel->r_offset);
653
654 if (! r)
b34976b6 655 return FALSE;
252b5132
RH
656 }
657 }
658
b34976b6 659 return TRUE;
252b5132
RH
660}
661\f
662/* Return the section that should be marked against GC for a given
663 relocation. */
664
665static asection *
1e2f5b6e 666fr30_elf_gc_mark_hook (sec, info, rel, h, sym)
b34976b6
AM
667 asection *sec;
668 struct bfd_link_info *info ATTRIBUTE_UNUSED;
669 Elf_Internal_Rela *rel;
670 struct elf_link_hash_entry *h;
671 Elf_Internal_Sym * sym;
252b5132
RH
672{
673 if (h != NULL)
674 {
675 switch (ELF32_R_TYPE (rel->r_info))
676 {
677 case R_FR30_GNU_VTINHERIT:
678 case R_FR30_GNU_VTENTRY:
679 break;
680
681 default:
682 switch (h->root.type)
683 {
684 case bfd_link_hash_defined:
685 case bfd_link_hash_defweak:
686 return h->root.u.def.section;
687
688 case bfd_link_hash_common:
689 return h->root.u.c.p->section;
e049a0de
ILT
690
691 default:
692 break;
252b5132
RH
693 }
694 }
695 }
696 else
1e2f5b6e 697 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
252b5132
RH
698
699 return NULL;
700}
701
702/* Update the got entry reference counts for the section being removed. */
703
b34976b6 704static bfd_boolean
252b5132 705fr30_elf_gc_sweep_hook (abfd, info, sec, relocs)
b34976b6
AM
706 bfd *abfd ATTRIBUTE_UNUSED;
707 struct bfd_link_info *info ATTRIBUTE_UNUSED;
708 asection *sec ATTRIBUTE_UNUSED;
709 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
252b5132 710{
b34976b6 711 return TRUE;
252b5132
RH
712}
713
714/* Look through the relocs for a section during the first phase.
715 Since we don't do .gots or .plts, we just need to consider the
716 virtual table relocs for gc. */
6609fa74 717
b34976b6 718static bfd_boolean
252b5132
RH
719fr30_elf_check_relocs (abfd, info, sec, relocs)
720 bfd *abfd;
721 struct bfd_link_info *info;
722 asection *sec;
723 const Elf_Internal_Rela *relocs;
724{
725 Elf_Internal_Shdr *symtab_hdr;
726 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
727 const Elf_Internal_Rela *rel;
728 const Elf_Internal_Rela *rel_end;
6609fa74 729
1049f94e 730 if (info->relocatable)
b34976b6 731 return TRUE;
6609fa74 732
252b5132
RH
733 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
734 sym_hashes = elf_sym_hashes (abfd);
6609fa74 735 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
252b5132
RH
736 if (!elf_bad_symtab (abfd))
737 sym_hashes_end -= symtab_hdr->sh_info;
6609fa74 738
252b5132
RH
739 rel_end = relocs + sec->reloc_count;
740 for (rel = relocs; rel < rel_end; rel++)
741 {
742 struct elf_link_hash_entry *h;
743 unsigned long r_symndx;
6609fa74 744
252b5132
RH
745 r_symndx = ELF32_R_SYM (rel->r_info);
746 if (r_symndx < symtab_hdr->sh_info)
747 h = NULL;
748 else
749 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
6609fa74 750
252b5132
RH
751 switch (ELF32_R_TYPE (rel->r_info))
752 {
753 /* This relocation describes the C++ object vtable hierarchy.
754 Reconstruct it for later use during GC. */
755 case R_FR30_GNU_VTINHERIT:
756 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
b34976b6 757 return FALSE;
252b5132 758 break;
6609fa74 759
252b5132
RH
760 /* This relocation describes which C++ vtable entries are actually
761 used. Record for later use during GC. */
762 case R_FR30_GNU_VTENTRY:
763 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
b34976b6 764 return FALSE;
252b5132
RH
765 break;
766 }
767 }
6609fa74 768
b34976b6 769 return TRUE;
252b5132
RH
770}
771\f
772#define ELF_ARCH bfd_arch_fr30
aa4f99bb
AO
773#define ELF_MACHINE_CODE EM_FR30
774#define ELF_MACHINE_ALT1 EM_CYGNUS_FR30
252b5132
RH
775#define ELF_MAXPAGESIZE 0x1000
776
777#define TARGET_BIG_SYM bfd_elf32_fr30_vec
778#define TARGET_BIG_NAME "elf32-fr30"
779
780#define elf_info_to_howto_rel NULL
781#define elf_info_to_howto fr30_info_to_howto_rela
782#define elf_backend_relocate_section fr30_elf_relocate_section
783#define elf_backend_gc_mark_hook fr30_elf_gc_mark_hook
784#define elf_backend_gc_sweep_hook fr30_elf_gc_sweep_hook
785#define elf_backend_check_relocs fr30_elf_check_relocs
786
787#define elf_backend_can_gc_sections 1
b491616a 788#define elf_backend_rela_normal 1
252b5132
RH
789
790#define bfd_elf32_bfd_reloc_type_lookup fr30_reloc_type_lookup
791
792#include "elf32-target.h"
This page took 0.282146 seconds and 4 git commands to generate.