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