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