1 /* XSTORMY16-specific support for 32-bit ELF.
2 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
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 2 of the License, or
9 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #include "elf/xstormy16.h"
25 #include "libiberty.h"
27 /* Forward declarations. */
28 static reloc_howto_type * xstormy16_reloc_type_lookup
29 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
30 static void xstormy16_info_to_howto_rela
31 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
32 static bfd_reloc_status_type xstormy16_elf_24_reloc
33 PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol,
34 PTR data, asection *input_section, bfd *output_bfd,
35 char **error_message));
36 static bfd_boolean xstormy16_elf_check_relocs
37 PARAMS ((bfd *, struct bfd_link_info *, asection *,
38 const Elf_Internal_Rela *));
39 static bfd_boolean xstormy16_relax_plt_check
40 PARAMS ((struct elf_link_hash_entry *, PTR));
41 static bfd_boolean xstormy16_relax_plt_realloc
42 PARAMS ((struct elf_link_hash_entry *, PTR));
43 static bfd_boolean xstormy16_elf_relax_section
44 PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
46 static bfd_boolean xstormy16_elf_always_size_sections
47 PARAMS ((bfd *, struct bfd_link_info *));
48 static bfd_boolean xstormy16_elf_relocate_section
49 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
51 static bfd_boolean xstormy16_elf_finish_dynamic_sections
52 PARAMS((bfd *, struct bfd_link_info *));
53 static bfd_boolean xstormy16_elf_gc_sweep_hook
54 PARAMS ((bfd *, struct bfd_link_info *, asection *,
55 const Elf_Internal_Rela *));
56 static asection * xstormy16_elf_gc_mark_hook
57 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
58 struct elf_link_hash_entry *, Elf_Internal_Sym *));
60 static reloc_howto_type xstormy16_elf_howto_table [] =
62 /* This reloc does nothing. */
63 HOWTO (R_XSTORMY16_NONE, /* type */
65 2, /* size (0 = byte, 1 = short, 2 = long) */
67 FALSE, /* pc_relative */
69 complain_overflow_bitfield, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_XSTORMY16_NONE", /* name */
72 FALSE, /* partial_inplace */
75 FALSE), /* pcrel_offset */
77 /* A 32 bit absolute relocation. */
78 HOWTO (R_XSTORMY16_32, /* type */
80 2, /* size (0 = byte, 1 = short, 2 = long) */
82 FALSE, /* pc_relative */
84 complain_overflow_dont, /* complain_on_overflow */
85 bfd_elf_generic_reloc, /* special_function */
86 "R_XSTORMY16_32", /* name */
87 FALSE, /* partial_inplace */
89 0xffffffff, /* dst_mask */
90 FALSE), /* pcrel_offset */
92 /* A 16 bit absolute relocation. */
93 HOWTO (R_XSTORMY16_16, /* type */
95 1, /* size (0 = byte, 1 = short, 2 = long) */
97 FALSE, /* pc_relative */
99 complain_overflow_bitfield, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_XSTORMY16_16", /* name */
102 FALSE, /* partial_inplace */
104 0xffffffff, /* dst_mask */
105 FALSE), /* pcrel_offset */
107 /* An 8 bit absolute relocation. */
108 HOWTO (R_XSTORMY16_8, /* type */
110 0, /* size (0 = byte, 1 = short, 2 = long) */
112 FALSE, /* pc_relative */
114 complain_overflow_bitfield, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_XSTORMY16_8", /* name */
117 FALSE, /* partial_inplace */
119 0xffffffff, /* dst_mask */
120 FALSE), /* pcrel_offset */
122 /* A 32 bit pc-relative relocation. */
123 HOWTO (R_XSTORMY16_PC32, /* type */
125 2, /* size (0 = byte, 1 = short, 2 = long) */
127 TRUE, /* pc_relative */
129 complain_overflow_dont, /* complain_on_overflow */
130 bfd_elf_generic_reloc, /* special_function */
131 "R_XSTORMY16_PC32", /* name */
132 FALSE, /* partial_inplace */
134 0xffffffff, /* dst_mask */
135 TRUE), /* pcrel_offset */
137 /* A 16 bit pc-relative relocation. */
138 HOWTO (R_XSTORMY16_PC16, /* type */
140 1, /* size (0 = byte, 1 = short, 2 = long) */
142 TRUE, /* pc_relative */
144 complain_overflow_signed, /* complain_on_overflow */
145 bfd_elf_generic_reloc, /* special_function */
146 "R_XSTORMY16_PC16", /* name */
147 FALSE, /* partial_inplace */
149 0xffffffff, /* dst_mask */
150 TRUE), /* pcrel_offset */
152 /* An 8 bit pc-relative relocation. */
153 HOWTO (R_XSTORMY16_PC8, /* type */
155 0, /* size (0 = byte, 1 = short, 2 = long) */
157 TRUE, /* pc_relative */
159 complain_overflow_signed, /* complain_on_overflow */
160 bfd_elf_generic_reloc, /* special_function */
161 "R_XSTORMY16_PC8", /* name */
162 FALSE, /* partial_inplace */
164 0xffffffff, /* dst_mask */
165 TRUE), /* pcrel_offset */
167 /* A 12-bit pc-relative relocation suitable for the branch instructions. */
168 HOWTO (R_XSTORMY16_REL_12, /* type */
170 1, /* size (0 = byte, 1 = short, 2 = long) */
172 TRUE, /* pc_relative */
174 complain_overflow_signed, /* complain_on_overflow */
175 bfd_elf_generic_reloc, /* special_function */
176 "R_XSTORMY16_REL_12", /* name */
177 TRUE, /* partial_inplace */
179 0x0fff, /* dst_mask */
180 TRUE), /* pcrel_offset */
182 /* A 24-bit absolute relocation suitable for the jump instructions. */
183 HOWTO (R_XSTORMY16_24, /* type */
185 2, /* size (0 = byte, 1 = short, 2 = long) */
187 FALSE, /* pc_relative */
189 complain_overflow_unsigned, /* complain_on_overflow */
190 xstormy16_elf_24_reloc, /* special_function */
191 "R_XSTORMY16_24", /* name */
192 TRUE, /* partial_inplace */
194 0xffff00ff, /* dst_mask */
195 TRUE), /* pcrel_offset */
197 /* A 16 bit absolute relocation to a function pointer. */
198 HOWTO (R_XSTORMY16_FPTR16, /* type */
200 1, /* size (0 = byte, 1 = short, 2 = long) */
202 FALSE, /* pc_relative */
204 complain_overflow_bitfield, /* complain_on_overflow */
205 bfd_elf_generic_reloc, /* special_function */
206 "R_XSTORMY16_FPTR16", /* name */
207 FALSE, /* partial_inplace */
209 0xffffffff, /* dst_mask */
210 FALSE), /* pcrel_offset */
212 /* Low order 16 bit value of a high memory address. */
213 HOWTO (R_XSTORMY16_LO16, /* type */
215 1, /* size (0 = byte, 1 = short, 2 = long) */
217 FALSE, /* pc_relative */
219 complain_overflow_dont, /* complain_on_overflow */
220 bfd_elf_generic_reloc, /* special_function */
221 "R_XSTORMY16_LO16", /* name */
222 FALSE, /* partial_inplace */
224 0xffff, /* dst_mask */
225 FALSE), /* pcrel_offset */
227 /* High order 16 bit value of a high memory address. */
228 HOWTO (R_XSTORMY16_HI16, /* type */
230 1, /* size (0 = byte, 1 = short, 2 = long) */
232 FALSE, /* pc_relative */
234 complain_overflow_dont, /* complain_on_overflow */
235 bfd_elf_generic_reloc, /* special_function */
236 "R_XSTORMY16_HI16", /* name */
237 FALSE, /* partial_inplace */
239 0xffff, /* dst_mask */
240 FALSE), /* pcrel_offset */
243 static reloc_howto_type xstormy16_elf_howto_table2 [] =
245 /* GNU extension to record C++ vtable hierarchy */
246 HOWTO (R_XSTORMY16_GNU_VTINHERIT, /* type */
248 2, /* size (0 = byte, 1 = short, 2 = long) */
250 FALSE, /* pc_relative */
252 complain_overflow_dont, /* complain_on_overflow */
253 NULL, /* special_function */
254 "R_XSTORMY16_GNU_VTINHERIT", /* name */
255 FALSE, /* partial_inplace */
258 FALSE), /* pcrel_offset */
260 /* GNU extension to record C++ vtable member usage */
261 HOWTO (R_XSTORMY16_GNU_VTENTRY, /* type */
263 2, /* size (0 = byte, 1 = short, 2 = long) */
265 FALSE, /* pc_relative */
267 complain_overflow_dont, /* complain_on_overflow */
268 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
269 "R_XSTORMY16_GNU_VTENTRY", /* name */
270 FALSE, /* partial_inplace */
273 FALSE), /* pcrel_offset */
277 /* Map BFD reloc types to XSTORMY16 ELF reloc types. */
279 typedef struct xstormy16_reloc_map
281 bfd_reloc_code_real_type bfd_reloc_val;
282 unsigned int xstormy16_reloc_val;
283 reloc_howto_type * table;
286 static const reloc_map xstormy16_reloc_map [] =
288 { BFD_RELOC_NONE, R_XSTORMY16_NONE, xstormy16_elf_howto_table },
289 { BFD_RELOC_32, R_XSTORMY16_32, xstormy16_elf_howto_table },
290 { BFD_RELOC_16, R_XSTORMY16_16, xstormy16_elf_howto_table },
291 { BFD_RELOC_8, R_XSTORMY16_8, xstormy16_elf_howto_table },
292 { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32, xstormy16_elf_howto_table },
293 { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16, xstormy16_elf_howto_table },
294 { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8, xstormy16_elf_howto_table },
295 { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12, xstormy16_elf_howto_table },
296 { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24, xstormy16_elf_howto_table },
297 { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16, xstormy16_elf_howto_table },
298 { BFD_RELOC_LO16, R_XSTORMY16_LO16, xstormy16_elf_howto_table },
299 { BFD_RELOC_HI16, R_XSTORMY16_HI16, xstormy16_elf_howto_table },
300 { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 },
301 { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY, xstormy16_elf_howto_table2 },
304 static reloc_howto_type *
305 xstormy16_reloc_type_lookup (abfd, code)
306 bfd * abfd ATTRIBUTE_UNUSED;
307 bfd_reloc_code_real_type code;
311 for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
313 const reloc_map * entry;
315 entry = xstormy16_reloc_map + i;
317 if (entry->bfd_reloc_val == code)
318 return entry->table + (entry->xstormy16_reloc_val
319 - entry->table[0].type);
325 /* Set the howto pointer for an XSTORMY16 ELF reloc. */
328 xstormy16_info_to_howto_rela (abfd, cache_ptr, dst)
329 bfd * abfd ATTRIBUTE_UNUSED;
331 Elf_Internal_Rela * dst;
333 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
335 if (r_type <= (unsigned int) R_XSTORMY16_HI16)
336 cache_ptr->howto = &xstormy16_elf_howto_table [r_type];
337 else if (r_type - R_XSTORMY16_GNU_VTINHERIT
338 <= (unsigned int) R_XSTORMY16_GNU_VTENTRY)
340 = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
345 /* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */
347 static bfd_reloc_status_type
348 xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section,
349 output_bfd, error_message)
351 arelent *reloc_entry;
354 asection *input_section;
356 char **error_message ATTRIBUTE_UNUSED;
358 bfd_vma relocation, x;
360 if (output_bfd != NULL)
362 reloc_entry->address += input_section->output_offset;
366 if (reloc_entry->address > input_section->_cooked_size)
367 return bfd_reloc_outofrange;
369 if (bfd_is_com_section (symbol->section))
372 relocation = symbol->value;
374 relocation += symbol->section->output_section->vma;
375 relocation += symbol->section->output_offset;
376 relocation += reloc_entry->addend;
378 x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
380 x |= relocation & 0xff;
381 x |= (relocation << 8) & 0xffff0000;
382 bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
384 if (relocation & ~ (bfd_vma) 0xffffff)
385 return bfd_reloc_overflow;
390 /* We support 16-bit pointers to code above 64k by generating a thunk
391 below 64k containing a JMPF instruction to the final address. We
392 cannot, unfortunately, minimize the number of thunks unless the
393 -relax switch is given, as otherwise we have no idea where the
394 sections will fall in the address space. */
397 xstormy16_elf_check_relocs (abfd, info, sec, relocs)
399 struct bfd_link_info *info;
401 const Elf_Internal_Rela *relocs;
403 const Elf_Internal_Rela *rel, *relend;
404 struct elf_link_hash_entry **sym_hashes;
405 Elf_Internal_Shdr *symtab_hdr;
406 bfd_vma *local_plt_offsets;
410 if (info->relocateable)
413 symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
414 sym_hashes = elf_sym_hashes (abfd);
415 local_plt_offsets = elf_local_got_offsets (abfd);
417 dynobj = elf_hash_table(info)->dynobj;
419 relend = relocs + sec->reloc_count;
420 for (rel = relocs; rel < relend; ++rel)
422 unsigned long r_symndx;
423 struct elf_link_hash_entry *h;
426 r_symndx = ELF32_R_SYM (rel->r_info);
427 if (r_symndx < symtab_hdr->sh_info)
431 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
432 while (h->root.type == bfd_link_hash_indirect
433 || h->root.type == bfd_link_hash_warning)
434 h = (struct elf_link_hash_entry *) h->root.u.i.link;
437 switch (ELF32_R_TYPE (rel->r_info))
439 /* This relocation describes a 16-bit pointer to a function.
440 We may need to allocate a thunk in low memory; reserve memory
442 case R_XSTORMY16_FPTR16:
443 if (rel->r_addend != 0)
445 (*info->callbacks->warning)
446 (info, _("non-zero addend in @fptr reloc"), 0,
451 elf_hash_table (info)->dynobj = dynobj = abfd;
454 splt = bfd_get_section_by_name (dynobj, ".plt");
457 splt = bfd_make_section (dynobj, ".plt");
459 || ! bfd_set_section_flags (dynobj, splt,
467 || ! bfd_set_section_alignment (dynobj, splt, 1))
473 offset = &h->plt.offset;
476 if (local_plt_offsets == NULL)
481 size = symtab_hdr->sh_info * sizeof (bfd_vma);
482 local_plt_offsets = (bfd_vma *) bfd_alloc (abfd, size);
483 if (local_plt_offsets == NULL)
485 elf_local_got_offsets (abfd) = local_plt_offsets;
487 for (i = 0; i < symtab_hdr->sh_info; i++)
488 local_plt_offsets[i] = (bfd_vma) -1;
490 offset = &local_plt_offsets[r_symndx];
493 if (*offset == (bfd_vma) -1)
495 *offset = splt->_raw_size;
496 splt->_raw_size += 4;
500 /* This relocation describes the C++ object vtable hierarchy.
501 Reconstruct it for later use during GC. */
502 case R_XSTORMY16_GNU_VTINHERIT:
503 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
507 /* This relocation describes which C++ vtable entries are actually
508 used. Record for later use during GC. */
509 case R_XSTORMY16_GNU_VTENTRY:
510 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
519 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
520 is within the low 64k, remove any entry for it in the plt. */
522 struct relax_plt_data
529 xstormy16_relax_plt_check (h, xdata)
530 struct elf_link_hash_entry *h;
533 struct relax_plt_data *data = (struct relax_plt_data *) xdata;
535 if (h->root.type == bfd_link_hash_warning)
536 h = (struct elf_link_hash_entry *) h->root.u.i.link;
538 if (h->plt.offset != (bfd_vma) -1)
542 if (h->root.type == bfd_link_hash_undefined
543 || h->root.type == bfd_link_hash_undefweak)
546 address = (h->root.u.def.section->output_section->vma
547 + h->root.u.def.section->output_offset
548 + h->root.u.def.value);
550 if (address <= 0xffff)
553 data->splt->_cooked_size -= 4;
561 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
562 previously had a plt entry, give it a new entry offset. */
565 xstormy16_relax_plt_realloc (h, xdata)
566 struct elf_link_hash_entry *h;
569 bfd_vma *entry = (bfd_vma *) xdata;
571 if (h->root.type == bfd_link_hash_warning)
572 h = (struct elf_link_hash_entry *) h->root.u.i.link;
574 if (h->plt.offset != (bfd_vma) -1)
576 h->plt.offset = *entry;
584 xstormy16_elf_relax_section (dynobj, splt, info, again)
587 struct bfd_link_info *info;
590 struct relax_plt_data relax_plt_data;
593 /* Assume nothing changes. */
596 if (info->relocateable)
599 /* We only relax the .plt section at the moment. */
600 if (dynobj != elf_hash_table (info)->dynobj
601 || strcmp (splt->name, ".plt") != 0)
604 /* Quick check for an empty plt. */
605 if (splt->_raw_size == 0)
608 /* If this is the first time we have been called for this section,
609 initialize the cooked size. */
610 if (splt->_cooked_size == 0)
611 splt->_cooked_size = splt->_raw_size;
613 /* Map across all global symbols; see which ones happen to
614 fall in the low 64k. */
615 relax_plt_data.splt = splt;
616 relax_plt_data.again = again;
617 elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
620 /* Likewise for local symbols, though that's somewhat less convenient
621 as we have to walk the list of input bfds and swap in symbol data. */
622 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
624 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
625 Elf_Internal_Shdr *symtab_hdr;
626 Elf_Internal_Sym *isymbuf = NULL;
629 if (! local_plt_offsets)
632 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
633 if (symtab_hdr->sh_info != 0)
635 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
637 isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
638 symtab_hdr->sh_info, 0,
644 for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
646 Elf_Internal_Sym *isym;
650 if (local_plt_offsets[idx] == (bfd_vma) -1)
653 isym = &isymbuf[idx];
654 if (isym->st_shndx == SHN_UNDEF)
656 else if (isym->st_shndx == SHN_ABS)
657 tsec = bfd_abs_section_ptr;
658 else if (isym->st_shndx == SHN_COMMON)
659 tsec = bfd_com_section_ptr;
661 tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
663 address = (tsec->output_section->vma
664 + tsec->output_offset
666 if (address <= 0xffff)
668 local_plt_offsets[idx] = -1;
669 splt->_cooked_size -= 4;
675 && symtab_hdr->contents != (unsigned char *) isymbuf)
677 if (! info->keep_memory)
681 /* Cache the symbols for elf_link_input_bfd. */
682 symtab_hdr->contents = (unsigned char *) isymbuf;
687 /* If we changed anything, walk the symbols again to reallocate
688 .plt entry addresses. */
689 if (*again && splt->_cooked_size > 0)
693 elf_link_hash_traverse (elf_hash_table (info),
694 xstormy16_relax_plt_realloc, &entry);
696 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
698 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
699 unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
702 if (! local_plt_offsets)
705 for (idx = 0; idx < nlocals; ++idx)
706 if (local_plt_offsets[idx] != (bfd_vma) -1)
708 local_plt_offsets[idx] = entry;
714 splt->_raw_size = splt->_cooked_size;
719 xstormy16_elf_always_size_sections (output_bfd, info)
720 bfd *output_bfd ATTRIBUTE_UNUSED;
721 struct bfd_link_info *info;
726 if (info->relocateable)
729 dynobj = elf_hash_table (info)->dynobj;
733 splt = bfd_get_section_by_name (dynobj, ".plt");
734 BFD_ASSERT (splt != NULL);
736 splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->_raw_size);
737 if (splt->contents == NULL)
743 /* Relocate an XSTORMY16 ELF section.
745 The RELOCATE_SECTION function is called by the new ELF backend linker
746 to handle the relocations for a section.
748 The relocs are always passed as Rela structures; if the section
749 actually uses Rel structures, the r_addend field will always be
752 This function is responsible for adjusting the section contents as
753 necessary, and (if using Rela relocs and generating a relocateable
754 output file) adjusting the reloc addend as necessary.
756 This function does not have to worry about setting the reloc
757 address or the reloc symbol index.
759 LOCAL_SYMS is a pointer to the swapped in local symbols.
761 LOCAL_SECTIONS is an array giving the section in the input file
762 corresponding to the st_shndx field of each local symbol.
764 The global hash table entry for the global symbols can be found
765 via elf_sym_hashes (input_bfd).
767 When generating relocateable output, this function must handle
768 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
769 going to be the section symbol corresponding to the output
770 section, which means that the addend must be adjusted
774 xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
775 contents, relocs, local_syms, local_sections)
776 bfd * output_bfd ATTRIBUTE_UNUSED;
777 struct bfd_link_info * info;
779 asection * input_section;
781 Elf_Internal_Rela * relocs;
782 Elf_Internal_Sym * local_syms;
783 asection ** local_sections;
785 Elf_Internal_Shdr * symtab_hdr;
786 struct elf_link_hash_entry ** sym_hashes;
787 Elf_Internal_Rela * rel;
788 Elf_Internal_Rela * relend;
792 if (info->relocateable)
795 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
796 sym_hashes = elf_sym_hashes (input_bfd);
797 relend = relocs + input_section->reloc_count;
799 dynobj = elf_hash_table (info)->dynobj;
802 splt = bfd_get_section_by_name (dynobj, ".plt");
804 for (rel = relocs; rel < relend; rel ++)
806 reloc_howto_type * howto;
807 unsigned long r_symndx;
808 Elf_Internal_Sym * sym;
810 struct elf_link_hash_entry * h;
812 bfd_reloc_status_type r;
813 const char * name = NULL;
816 r_type = ELF32_R_TYPE (rel->r_info);
818 if ( r_type == R_XSTORMY16_GNU_VTINHERIT
819 || r_type == R_XSTORMY16_GNU_VTENTRY)
822 r_symndx = ELF32_R_SYM (rel->r_info);
823 howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
828 if (r_symndx < symtab_hdr->sh_info)
830 sym = local_syms + r_symndx;
831 sec = local_sections [r_symndx];
832 relocation = (sec->output_section->vma
836 name = bfd_elf_string_from_elf_section
837 (input_bfd, symtab_hdr->sh_link, sym->st_name);
838 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
842 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
844 while (h->root.type == bfd_link_hash_indirect
845 || h->root.type == bfd_link_hash_warning)
846 h = (struct elf_link_hash_entry *) h->root.u.i.link;
848 name = h->root.root.string;
850 if (h->root.type == bfd_link_hash_defined
851 || h->root.type == bfd_link_hash_defweak)
853 sec = h->root.u.def.section;
854 relocation = (h->root.u.def.value
855 + sec->output_section->vma
856 + sec->output_offset);
858 else if (h->root.type == bfd_link_hash_undefweak)
864 if (! ((*info->callbacks->undefined_symbol)
865 (info, h->root.root.string, input_bfd,
866 input_section, rel->r_offset, TRUE)))
872 switch (ELF32_R_TYPE (rel->r_info))
876 bfd_vma reloc = relocation + rel->r_addend;
879 x = bfd_get_32 (input_bfd, contents + rel->r_offset);
882 x |= (reloc << 8) & 0xffff0000;
883 bfd_put_32 (input_bfd, x, contents + rel->r_offset);
885 if (reloc & ~0xffffff)
886 r = bfd_reloc_overflow;
892 case R_XSTORMY16_FPTR16:
897 plt_offset = &h->plt.offset;
899 plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
901 if (relocation <= 0xffff)
903 /* If the symbol is in range for a 16-bit address, we should
904 have deallocated the plt entry in relax_section. */
905 BFD_ASSERT (*plt_offset == (bfd_vma) -1);
909 /* If the symbol is out of range for a 16-bit address,
910 we must have allocated a plt entry. */
911 BFD_ASSERT (*plt_offset != (bfd_vma) -1);
913 /* If this is the first time we've processed this symbol,
914 fill in the plt entry with the correct symbol address. */
915 if ((*plt_offset & 1) == 0)
919 x = 0x00000200; /* jmpf */
920 x |= relocation & 0xff;
921 x |= (relocation << 8) & 0xffff0000;
922 bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
926 relocation = (splt->output_section->vma
927 + splt->output_offset
928 + (*plt_offset & -2));
930 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
931 contents, rel->r_offset,
937 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
938 contents, rel->r_offset,
939 relocation, rel->r_addend);
943 if (r != bfd_reloc_ok)
945 const char * msg = (const char *) NULL;
949 case bfd_reloc_overflow:
950 r = info->callbacks->reloc_overflow
951 (info, name, howto->name, (bfd_vma) 0,
952 input_bfd, input_section, rel->r_offset);
955 case bfd_reloc_undefined:
956 r = info->callbacks->undefined_symbol
957 (info, name, input_bfd, input_section, rel->r_offset,
961 case bfd_reloc_outofrange:
962 msg = _("internal error: out of range error");
965 case bfd_reloc_notsupported:
966 msg = _("internal error: unsupported relocation error");
969 case bfd_reloc_dangerous:
970 msg = _("internal error: dangerous relocation");
974 msg = _("internal error: unknown error");
979 r = info->callbacks->warning
980 (info, msg, name, input_bfd, input_section, rel->r_offset);
990 /* This must exist if dynobj is ever set. */
993 xstormy16_elf_finish_dynamic_sections (abfd, info)
994 bfd *abfd ATTRIBUTE_UNUSED;
995 struct bfd_link_info *info;
1000 /* As an extra sanity check, verify that all plt entries have
1003 if ((dynobj = elf_hash_table (info)->dynobj) != NULL
1004 && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
1006 bfd_byte *contents = splt->contents;
1007 unsigned int i, size = splt->_raw_size;
1008 for (i = 0; i < size; i += 4)
1010 unsigned int x = bfd_get_32 (dynobj, contents + i);
1011 BFD_ASSERT (x != 0);
1018 /* Return the section that should be marked against GC for a given
1022 xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
1024 struct bfd_link_info * info ATTRIBUTE_UNUSED;
1025 Elf_Internal_Rela * rel;
1026 struct elf_link_hash_entry * h;
1027 Elf_Internal_Sym * sym;
1031 switch (ELF32_R_TYPE (rel->r_info))
1033 case R_XSTORMY16_GNU_VTINHERIT:
1034 case R_XSTORMY16_GNU_VTENTRY:
1038 switch (h->root.type)
1040 case bfd_link_hash_defined:
1041 case bfd_link_hash_defweak:
1042 return h->root.u.def.section;
1044 case bfd_link_hash_common:
1045 return h->root.u.c.p->section;
1053 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1058 /* Update the got entry reference counts for the section being removed. */
1061 xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs)
1062 bfd * abfd ATTRIBUTE_UNUSED;
1063 struct bfd_link_info * info ATTRIBUTE_UNUSED;
1064 asection * sec ATTRIBUTE_UNUSED;
1065 const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
1070 #define ELF_ARCH bfd_arch_xstormy16
1071 #define ELF_MACHINE_CODE EM_XSTORMY16
1072 #define ELF_MAXPAGESIZE 0x100
1074 #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1075 #define TARGET_LITTLE_NAME "elf32-xstormy16"
1077 #define elf_info_to_howto_rel NULL
1078 #define elf_info_to_howto xstormy16_info_to_howto_rela
1079 #define elf_backend_relocate_section xstormy16_elf_relocate_section
1080 #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1081 #define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
1082 #define elf_backend_check_relocs xstormy16_elf_check_relocs
1083 #define elf_backend_always_size_sections \
1084 xstormy16_elf_always_size_sections
1085 #define elf_backend_finish_dynamic_sections \
1086 xstormy16_elf_finish_dynamic_sections
1088 #define elf_backend_can_gc_sections 1
1089 #define elf_backend_rela_normal 1
1091 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1092 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1094 #include "elf32-target.h"