1 /* XSTORMY16-specific support for 32-bit ELF.
2 Copyright (C) 2000, 2001 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"
26 /* Forward declarations. */
27 static reloc_howto_type
* xstormy16_reloc_type_lookup
28 PARAMS ((bfd
*abfd
, bfd_reloc_code_real_type code
));
29 static void xstormy16_info_to_howto_rela
30 PARAMS ((bfd
*, arelent
*, Elf32_Internal_Rela
*));
31 static bfd_reloc_status_type xstormy16_elf_24_reloc
32 PARAMS ((bfd
*abfd
, arelent
*reloc_entry
, asymbol
*symbol
,
33 PTR data
, asection
*input_section
, bfd
*output_bfd
,
34 char **error_message
));
35 static boolean xstormy16_elf_check_relocs
36 PARAMS ((bfd
*, struct bfd_link_info
*, asection
*,
37 const Elf_Internal_Rela
*));
38 static boolean xstormy16_relax_plt_check
39 PARAMS ((struct elf_link_hash_entry
*, PTR
));
40 static boolean xstormy16_relax_plt_realloc
41 PARAMS ((struct elf_link_hash_entry
*, PTR
));
42 static boolean xstormy16_elf_relax_section
43 PARAMS ((bfd
*abfd
, asection
*sec
, struct bfd_link_info
*link_info
,
45 static boolean xstormy16_elf_always_size_sections
46 PARAMS ((bfd
*, struct bfd_link_info
*));
47 static boolean xstormy16_elf_relocate_section
48 PARAMS ((bfd
*, struct bfd_link_info
*, bfd
*, asection
*, bfd_byte
*,
49 Elf_Internal_Rela
*, Elf_Internal_Sym
*, asection
**));
50 static boolean xstormy16_elf_finish_dynamic_sections
51 PARAMS((bfd
*, struct bfd_link_info
*));
52 static boolean xstormy16_elf_gc_sweep_hook
53 PARAMS ((bfd
*, struct bfd_link_info
*, asection
*,
54 const Elf_Internal_Rela
*));
55 static asection
* xstormy16_elf_gc_mark_hook
56 PARAMS ((bfd
*, struct bfd_link_info
*, Elf_Internal_Rela
*,
57 struct elf_link_hash_entry
*, Elf_Internal_Sym
*));
59 static reloc_howto_type xstormy16_elf_howto_table
[] =
61 /* This reloc does nothing. */
62 HOWTO (R_XSTORMY16_NONE
, /* type */
64 2, /* size (0 = byte, 1 = short, 2 = long) */
66 false, /* pc_relative */
68 complain_overflow_bitfield
, /* complain_on_overflow */
69 bfd_elf_generic_reloc
, /* special_function */
70 "R_XSTORMY16_NONE", /* name */
71 false, /* partial_inplace */
74 false), /* pcrel_offset */
76 /* A 32 bit absolute relocation. */
77 HOWTO (R_XSTORMY16_32
, /* type */
79 2, /* size (0 = byte, 1 = short, 2 = long) */
81 false, /* pc_relative */
83 complain_overflow_dont
, /* complain_on_overflow */
84 bfd_elf_generic_reloc
, /* special_function */
85 "R_XSTORMY16_32", /* name */
86 false, /* partial_inplace */
88 0xffffffff, /* dst_mask */
89 false), /* pcrel_offset */
91 /* A 16 bit absolute relocation. */
92 HOWTO (R_XSTORMY16_16
, /* type */
94 1, /* size (0 = byte, 1 = short, 2 = long) */
96 false, /* pc_relative */
98 complain_overflow_bitfield
, /* complain_on_overflow */
99 bfd_elf_generic_reloc
, /* special_function */
100 "R_XSTORMY16_16", /* name */
101 false, /* partial_inplace */
103 0xffffffff, /* dst_mask */
104 false), /* pcrel_offset */
106 /* An 8 bit absolute relocation. */
107 HOWTO (R_XSTORMY16_8
, /* type */
109 0, /* size (0 = byte, 1 = short, 2 = long) */
111 false, /* pc_relative */
113 complain_overflow_bitfield
, /* complain_on_overflow */
114 bfd_elf_generic_reloc
, /* special_function */
115 "R_XSTORMY16_8", /* name */
116 false, /* partial_inplace */
118 0xffffffff, /* dst_mask */
119 false), /* pcrel_offset */
121 /* A 32 bit pc-relative relocation. */
122 HOWTO (R_XSTORMY16_PC32
, /* type */
124 2, /* size (0 = byte, 1 = short, 2 = long) */
126 true, /* pc_relative */
128 complain_overflow_dont
, /* complain_on_overflow */
129 bfd_elf_generic_reloc
, /* special_function */
130 "R_XSTORMY16_PC32", /* name */
131 false, /* partial_inplace */
133 0xffffffff, /* dst_mask */
134 true), /* pcrel_offset */
136 /* A 16 bit pc-relative relocation. */
137 HOWTO (R_XSTORMY16_PC16
, /* type */
139 1, /* size (0 = byte, 1 = short, 2 = long) */
141 true, /* pc_relative */
143 complain_overflow_signed
, /* complain_on_overflow */
144 bfd_elf_generic_reloc
, /* special_function */
145 "R_XSTORMY16_PC16", /* name */
146 false, /* partial_inplace */
148 0xffffffff, /* dst_mask */
149 true), /* pcrel_offset */
151 /* An 8 bit pc-relative relocation. */
152 HOWTO (R_XSTORMY16_PC8
, /* type */
154 0, /* size (0 = byte, 1 = short, 2 = long) */
156 true, /* pc_relative */
158 complain_overflow_signed
, /* complain_on_overflow */
159 bfd_elf_generic_reloc
, /* special_function */
160 "R_XSTORMY16_PC8", /* name */
161 false, /* partial_inplace */
163 0xffffffff, /* dst_mask */
164 true), /* pcrel_offset */
166 /* A 12-bit pc-relative relocation suitable for the branch instructions. */
167 HOWTO (R_XSTORMY16_REL_12
, /* type */
169 1, /* size (0 = byte, 1 = short, 2 = long) */
171 true, /* pc_relative */
173 complain_overflow_signed
, /* complain_on_overflow */
174 bfd_elf_generic_reloc
, /* special_function */
175 "R_XSTORMY16_REL_12", /* name */
176 true, /* partial_inplace */
178 0x0fff, /* dst_mask */
179 true), /* pcrel_offset */
181 /* A 24-bit absolute relocation suitable for the jump instructions. */
182 HOWTO (R_XSTORMY16_24
, /* type */
184 2, /* size (0 = byte, 1 = short, 2 = long) */
186 false, /* pc_relative */
188 complain_overflow_unsigned
, /* complain_on_overflow */
189 xstormy16_elf_24_reloc
, /* special_function */
190 "R_XSTORMY16_24", /* name */
191 true, /* partial_inplace */
193 0xffff00ff, /* dst_mask */
194 true), /* pcrel_offset */
196 /* A 16 bit absolute relocation to a function pointer. */
197 HOWTO (R_XSTORMY16_FPTR16
, /* type */
199 1, /* size (0 = byte, 1 = short, 2 = long) */
201 false, /* pc_relative */
203 complain_overflow_bitfield
, /* complain_on_overflow */
204 bfd_elf_generic_reloc
, /* special_function */
205 "R_XSTORMY16_FPTR16", /* name */
206 false, /* partial_inplace */
208 0xffffffff, /* dst_mask */
209 false), /* pcrel_offset */
212 static reloc_howto_type xstormy16_elf_howto_table2
[] =
214 /* GNU extension to record C++ vtable hierarchy */
215 HOWTO (R_XSTORMY16_GNU_VTINHERIT
, /* type */
217 2, /* size (0 = byte, 1 = short, 2 = long) */
219 false, /* pc_relative */
221 complain_overflow_dont
, /* complain_on_overflow */
222 NULL
, /* special_function */
223 "R_XSTORMY16_GNU_VTINHERIT", /* name */
224 false, /* partial_inplace */
227 false), /* pcrel_offset */
229 /* GNU extension to record C++ vtable member usage */
230 HOWTO (R_XSTORMY16_GNU_VTENTRY
, /* type */
232 2, /* size (0 = byte, 1 = short, 2 = long) */
234 false, /* pc_relative */
236 complain_overflow_dont
, /* complain_on_overflow */
237 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
238 "R_XSTORMY16_GNU_VTENTRY", /* name */
239 false, /* partial_inplace */
242 false), /* pcrel_offset */
246 /* Map BFD reloc types to XSTORMY16 ELF reloc types. */
248 struct xstormy16_reloc_map
250 bfd_reloc_code_real_type bfd_reloc_val
;
251 unsigned int xstormy16_reloc_val
;
254 static const struct xstormy16_reloc_map xstormy16_reloc_map
[] =
256 { BFD_RELOC_NONE
, R_XSTORMY16_NONE
},
257 { BFD_RELOC_32
, R_XSTORMY16_32
},
258 { BFD_RELOC_16
, R_XSTORMY16_16
},
259 { BFD_RELOC_8
, R_XSTORMY16_8
},
260 { BFD_RELOC_32_PCREL
, R_XSTORMY16_PC32
},
261 { BFD_RELOC_16_PCREL
, R_XSTORMY16_PC16
},
262 { BFD_RELOC_8_PCREL
, R_XSTORMY16_PC8
},
263 { BFD_RELOC_XSTORMY16_REL_12
, R_XSTORMY16_REL_12
},
264 { BFD_RELOC_XSTORMY16_24
, R_XSTORMY16_24
},
265 { BFD_RELOC_XSTORMY16_FPTR16
, R_XSTORMY16_FPTR16
},
266 { BFD_RELOC_VTABLE_INHERIT
, R_XSTORMY16_GNU_VTINHERIT
},
267 { BFD_RELOC_VTABLE_ENTRY
, R_XSTORMY16_GNU_VTENTRY
},
270 static reloc_howto_type
*
271 xstormy16_reloc_type_lookup (abfd
, code
)
272 bfd
* abfd ATTRIBUTE_UNUSED
;
273 bfd_reloc_code_real_type code
;
277 for (i
= sizeof (xstormy16_reloc_map
) / sizeof (xstormy16_reloc_map
[0]);
279 if (xstormy16_reloc_map
[i
].bfd_reloc_val
== code
)
280 return & xstormy16_elf_howto_table
[xstormy16_reloc_map
[i
].xstormy16_reloc_val
];
285 /* Set the howto pointer for an XSTORMY16 ELF reloc. */
288 xstormy16_info_to_howto_rela (abfd
, cache_ptr
, dst
)
289 bfd
* abfd ATTRIBUTE_UNUSED
;
291 Elf32_Internal_Rela
* dst
;
293 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
295 if (r_type
<= (unsigned int) R_XSTORMY16_FPTR16
)
296 cache_ptr
->howto
= &xstormy16_elf_howto_table
[r_type
];
297 else if (r_type
- R_XSTORMY16_GNU_VTINHERIT
298 <= (unsigned int) R_XSTORMY16_GNU_VTENTRY
)
300 = &xstormy16_elf_howto_table2
[r_type
- R_XSTORMY16_GNU_VTINHERIT
];
305 /* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */
307 static bfd_reloc_status_type
308 xstormy16_elf_24_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
309 output_bfd
, error_message
)
311 arelent
*reloc_entry
;
314 asection
*input_section
;
316 char **error_message ATTRIBUTE_UNUSED
;
318 bfd_vma relocation
, x
;
320 if (output_bfd
!= NULL
)
322 reloc_entry
->address
+= input_section
->output_offset
;
326 if (reloc_entry
->address
> input_section
->_cooked_size
)
327 return bfd_reloc_outofrange
;
329 if (bfd_is_com_section (symbol
->section
))
332 relocation
= symbol
->value
;
334 relocation
+= symbol
->section
->output_section
->vma
;
335 relocation
+= symbol
->section
->output_offset
;
336 relocation
+= reloc_entry
->addend
;
338 x
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ reloc_entry
->address
);
340 x
|= relocation
& 0xff;
341 x
|= (relocation
<< 8) & 0xffff0000;
342 bfd_put_32 (abfd
, x
, (bfd_byte
*) data
+ reloc_entry
->address
);
344 if (relocation
& ~ (bfd_vma
) 0xffffff)
345 return bfd_reloc_overflow
;
350 /* We support 16-bit pointers to code above 64k by generating a thunk
351 below 64k containing a JMPF instruction to the final address. We
352 cannot, unfortunately, minimize the number of thunks unless the
353 -relax switch is given, as otherwise we have no idea where the
354 sections will fall in the address space. */
357 xstormy16_elf_check_relocs (abfd
, info
, sec
, relocs
)
359 struct bfd_link_info
*info
;
361 const Elf_Internal_Rela
*relocs
;
363 const Elf_Internal_Rela
*rel
, *relend
;
364 struct elf_link_hash_entry
**sym_hashes
;
365 Elf_Internal_Shdr
*symtab_hdr
;
366 bfd_vma
*local_plt_offsets
;
370 if (info
->relocateable
)
373 symtab_hdr
= &elf_tdata(abfd
)->symtab_hdr
;
374 sym_hashes
= elf_sym_hashes (abfd
);
375 local_plt_offsets
= elf_local_got_offsets (abfd
);
377 dynobj
= elf_hash_table(info
)->dynobj
;
379 relend
= relocs
+ sec
->reloc_count
;
380 for (rel
= relocs
; rel
< relend
; ++rel
)
382 unsigned long r_symndx
;
383 struct elf_link_hash_entry
*h
;
386 r_symndx
= ELF32_R_SYM (rel
->r_info
);
387 if (r_symndx
< symtab_hdr
->sh_info
)
391 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
392 while (h
->root
.type
== bfd_link_hash_indirect
393 || h
->root
.type
== bfd_link_hash_warning
)
394 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
397 switch (ELF32_R_TYPE (rel
->r_info
))
399 /* This relocation describes a 16-bit pointer to a function.
400 We may need to allocate a thunk in low memory; reserve memory
402 case R_XSTORMY16_FPTR16
:
403 if (rel
->r_addend
!= 0)
405 (*info
->callbacks
->warning
)
406 (info
, _("non-zero addend in @fptr reloc"), 0,
411 elf_hash_table (info
)->dynobj
= dynobj
= abfd
;
414 splt
= bfd_get_section_by_name (dynobj
, ".plt");
417 splt
= bfd_make_section (dynobj
, ".plt");
419 || ! bfd_set_section_flags (dynobj
, splt
,
427 || ! bfd_set_section_alignment (dynobj
, splt
, 1))
433 offset
= &h
->plt
.offset
;
436 if (local_plt_offsets
== NULL
)
441 size
= symtab_hdr
->sh_info
* sizeof (bfd_vma
);
442 local_plt_offsets
= (bfd_vma
*) bfd_alloc (abfd
, size
);
443 if (local_plt_offsets
== NULL
)
445 elf_local_got_offsets (abfd
) = local_plt_offsets
;
447 for (i
= 0; i
< symtab_hdr
->sh_info
; i
++)
448 local_plt_offsets
[i
] = (bfd_vma
) -1;
450 offset
= &local_plt_offsets
[r_symndx
];
453 if (*offset
== (bfd_vma
) -1)
455 *offset
= splt
->_raw_size
;
456 splt
->_raw_size
+= 4;
460 /* This relocation describes the C++ object vtable hierarchy.
461 Reconstruct it for later use during GC. */
462 case R_XSTORMY16_GNU_VTINHERIT
:
463 if (!_bfd_elf32_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
467 /* This relocation describes which C++ vtable entries are actually
468 used. Record for later use during GC. */
469 case R_XSTORMY16_GNU_VTENTRY
:
470 if (!_bfd_elf32_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
479 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
480 is within the low 64k, remove any entry for it in the plt. */
482 struct relax_plt_data
489 xstormy16_relax_plt_check (h
, xdata
)
490 struct elf_link_hash_entry
*h
;
493 struct relax_plt_data
*data
= (struct relax_plt_data
*) xdata
;
495 if (h
->plt
.offset
!= (bfd_vma
) -1)
499 if (h
->root
.type
== bfd_link_hash_undefined
500 || h
->root
.type
== bfd_link_hash_undefweak
)
503 address
= (h
->root
.u
.def
.section
->output_section
->vma
504 + h
->root
.u
.def
.section
->output_offset
505 + h
->root
.u
.def
.value
);
507 if (address
<= 0xffff)
510 data
->splt
->_cooked_size
-= 4;
518 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
519 previously had a plt entry, give it a new entry offset. */
522 xstormy16_relax_plt_realloc (h
, xdata
)
523 struct elf_link_hash_entry
*h
;
526 bfd_vma
*entry
= (bfd_vma
*) xdata
;
528 if (h
->plt
.offset
!= (bfd_vma
) -1)
530 h
->plt
.offset
= *entry
;
538 xstormy16_elf_relax_section (dynobj
, splt
, info
, again
)
541 struct bfd_link_info
*info
;
544 struct relax_plt_data relax_plt_data
;
547 /* Assume nothing changes. */
550 if (info
->relocateable
)
553 /* We only relax the .plt section at the moment. */
554 if (dynobj
!= elf_hash_table (info
)->dynobj
555 || strcmp (splt
->name
, ".plt") != 0)
558 /* Quick check for an empty plt. */
559 if (splt
->_raw_size
== 0)
562 /* If this is the first time we have been called for this section,
563 initialize the cooked size. */
564 if (splt
->_cooked_size
== 0)
565 splt
->_cooked_size
= splt
->_raw_size
;
567 /* Map across all global symbols; see which ones happen to
568 fall in the low 64k. */
569 relax_plt_data
.splt
= splt
;
570 relax_plt_data
.again
= again
;
571 elf_link_hash_traverse (elf_hash_table (info
), xstormy16_relax_plt_check
,
574 /* Likewise for local symbols, though that's somewhat less convenient
575 as we have walk the list of input bfds and swap in symbol data. */
576 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
578 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
579 Elf_Internal_Shdr
*symtab_hdr
;
580 Elf32_External_Sym
*extsyms
;
583 if (! local_plt_offsets
)
586 symtab_hdr
= &elf_tdata (ibfd
)->symtab_hdr
;
588 if (symtab_hdr
->contents
!= NULL
)
589 extsyms
= (Elf32_External_Sym
*) symtab_hdr
->contents
;
592 extsyms
= (Elf32_External_Sym
*) bfd_malloc (symtab_hdr
->sh_size
);
595 if (bfd_seek (ibfd
, symtab_hdr
->sh_offset
, SEEK_SET
) != 0
596 || (bfd_bread (extsyms
, symtab_hdr
->sh_size
, ibfd
)
597 != symtab_hdr
->sh_size
))
604 for (idx
= 0; idx
< symtab_hdr
->sh_info
; ++idx
)
606 Elf_Internal_Sym isym
;
610 if (local_plt_offsets
[idx
] == (bfd_vma
) -1)
613 bfd_elf32_swap_symbol_in (ibfd
, extsyms
+ idx
, &isym
);
614 if (isym
.st_shndx
== SHN_UNDEF
)
616 else if (isym
.st_shndx
> 0 && isym
.st_shndx
< SHN_LORESERVE
)
617 tsec
= bfd_section_from_elf_index (ibfd
, isym
.st_shndx
);
618 else if (isym
.st_shndx
== SHN_ABS
)
619 tsec
= bfd_abs_section_ptr
;
623 address
= (tsec
->output_section
->vma
624 + tsec
->output_offset
626 if (address
<= 0xffff)
628 local_plt_offsets
[idx
] = -1;
629 splt
->_cooked_size
-= 4;
634 if (symtab_hdr
->contents
!= extsyms
)
638 /* If we changed anything, walk the symbols again to reallocate
639 .plt entry addresses. */
640 if (*again
&& splt
->_cooked_size
> 0)
644 elf_link_hash_traverse (elf_hash_table (info
),
645 xstormy16_relax_plt_realloc
, &entry
);
647 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
649 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
650 unsigned int nlocals
= elf_tdata (ibfd
)->symtab_hdr
.sh_info
;
653 if (! local_plt_offsets
)
656 for (idx
= 0; idx
< nlocals
; ++idx
)
657 if (local_plt_offsets
[idx
] != (bfd_vma
) -1)
659 local_plt_offsets
[idx
] = entry
;
665 splt
->_raw_size
= splt
->_cooked_size
;
670 xstormy16_elf_always_size_sections (output_bfd
, info
)
671 bfd
*output_bfd ATTRIBUTE_UNUSED
;
672 struct bfd_link_info
*info
;
677 if (info
->relocateable
)
680 dynobj
= elf_hash_table (info
)->dynobj
;
684 splt
= bfd_get_section_by_name (dynobj
, ".plt");
685 BFD_ASSERT (splt
!= NULL
);
687 splt
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, splt
->_raw_size
);
688 if (splt
->contents
== NULL
)
694 /* Relocate an XSTORMY16 ELF section.
695 There is some attempt to make this function usable for many architectures,
696 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
697 if only to serve as a learning tool.
699 The RELOCATE_SECTION function is called by the new ELF backend linker
700 to handle the relocations for a section.
702 The relocs are always passed as Rela structures; if the section
703 actually uses Rel structures, the r_addend field will always be
706 This function is responsible for adjusting the section contents as
707 necessary, and (if using Rela relocs and generating a relocateable
708 output file) adjusting the reloc addend as necessary.
710 This function does not have to worry about setting the reloc
711 address or the reloc symbol index.
713 LOCAL_SYMS is a pointer to the swapped in local symbols.
715 LOCAL_SECTIONS is an array giving the section in the input file
716 corresponding to the st_shndx field of each local symbol.
718 The global hash table entry for the global symbols can be found
719 via elf_sym_hashes (input_bfd).
721 When generating relocateable output, this function must handle
722 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
723 going to be the section symbol corresponding to the output
724 section, which means that the addend must be adjusted
728 xstormy16_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
729 contents
, relocs
, local_syms
, local_sections
)
730 bfd
* output_bfd ATTRIBUTE_UNUSED
;
731 struct bfd_link_info
* info
;
733 asection
* input_section
;
735 Elf_Internal_Rela
* relocs
;
736 Elf_Internal_Sym
* local_syms
;
737 asection
** local_sections
;
739 Elf_Internal_Shdr
* symtab_hdr
;
740 struct elf_link_hash_entry
** sym_hashes
;
741 Elf_Internal_Rela
* rel
;
742 Elf_Internal_Rela
* relend
;
746 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
747 sym_hashes
= elf_sym_hashes (input_bfd
);
748 relend
= relocs
+ input_section
->reloc_count
;
750 dynobj
= elf_hash_table (info
)->dynobj
;
753 splt
= bfd_get_section_by_name (dynobj
, ".plt");
755 for (rel
= relocs
; rel
< relend
; rel
++)
757 reloc_howto_type
* howto
;
758 unsigned long r_symndx
;
759 Elf_Internal_Sym
* sym
;
761 struct elf_link_hash_entry
* h
;
763 bfd_reloc_status_type r
;
764 const char * name
= NULL
;
767 r_type
= ELF32_R_TYPE (rel
->r_info
);
769 if ( r_type
== R_XSTORMY16_GNU_VTINHERIT
770 || r_type
== R_XSTORMY16_GNU_VTENTRY
)
773 r_symndx
= ELF32_R_SYM (rel
->r_info
);
775 if (info
->relocateable
)
777 /* This is a relocateable link. We don't have to change
778 anything, unless the reloc is against a section symbol,
779 in which case we have to adjust according to where the
780 section symbol winds up in the output section. */
781 if (r_symndx
< symtab_hdr
->sh_info
)
783 sym
= local_syms
+ r_symndx
;
785 if (ELF_ST_TYPE (sym
->st_info
) == STT_SECTION
)
787 sec
= local_sections
[r_symndx
];
788 rel
->r_addend
+= sec
->output_offset
+ sym
->st_value
;
795 /* This is a final link. */
796 howto
= xstormy16_elf_howto_table
+ ELF32_R_TYPE (rel
->r_info
);
801 if (r_symndx
< symtab_hdr
->sh_info
)
803 sym
= local_syms
+ r_symndx
;
804 sec
= local_sections
[r_symndx
];
805 relocation
= (sec
->output_section
->vma
809 name
= bfd_elf_string_from_elf_section
810 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
811 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
815 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
817 while (h
->root
.type
== bfd_link_hash_indirect
818 || h
->root
.type
== bfd_link_hash_warning
)
819 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
821 name
= h
->root
.root
.string
;
823 if (h
->root
.type
== bfd_link_hash_defined
824 || h
->root
.type
== bfd_link_hash_defweak
)
826 sec
= h
->root
.u
.def
.section
;
827 relocation
= (h
->root
.u
.def
.value
828 + sec
->output_section
->vma
829 + sec
->output_offset
);
831 else if (h
->root
.type
== bfd_link_hash_undefweak
)
837 if (! ((*info
->callbacks
->undefined_symbol
)
838 (info
, h
->root
.root
.string
, input_bfd
,
839 input_section
, rel
->r_offset
, true)))
845 switch (ELF32_R_TYPE (rel
->r_info
))
849 bfd_vma reloc
= relocation
+ rel
->r_addend
;
852 x
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
855 x
|= (reloc
<< 8) & 0xffff0000;
856 bfd_put_32 (input_bfd
, x
, contents
+ rel
->r_offset
);
858 if (reloc
& ~0xffffff)
859 r
= bfd_reloc_overflow
;
865 case R_XSTORMY16_FPTR16
:
870 plt_offset
= &h
->plt
.offset
;
872 plt_offset
= elf_local_got_offsets (input_bfd
) + r_symndx
;
874 if (relocation
<= 0xffff)
876 /* If the symbol is in range for a 16-bit address, we should
877 have deallocated the plt entry in relax_section. */
878 BFD_ASSERT (*plt_offset
== (bfd_vma
) -1);
882 /* If the symbol is out of range for a 16-bit address,
883 we must have allocated a plt entry. */
884 BFD_ASSERT (*plt_offset
!= (bfd_vma
) -1);
886 /* If this is the first time we've processed this symbol,
887 fill in the plt entry with the correct symbol address. */
888 if ((*plt_offset
& 1) == 0)
892 x
= 0x00000200; /* jmpf */
893 x
|= relocation
& 0xff;
894 x
|= (relocation
<< 8) & 0xffff0000;
895 bfd_put_32 (input_bfd
, x
, splt
->contents
+ *plt_offset
);
899 relocation
= (splt
->output_section
->vma
900 + splt
->output_offset
901 + (*plt_offset
& -2));
903 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
904 contents
, rel
->r_offset
,
910 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
911 contents
, rel
->r_offset
,
912 relocation
, rel
->r_addend
);
916 if (r
!= bfd_reloc_ok
)
918 const char * msg
= (const char *) NULL
;
922 case bfd_reloc_overflow
:
923 r
= info
->callbacks
->reloc_overflow
924 (info
, name
, howto
->name
, (bfd_vma
) 0,
925 input_bfd
, input_section
, rel
->r_offset
);
928 case bfd_reloc_undefined
:
929 r
= info
->callbacks
->undefined_symbol
930 (info
, name
, input_bfd
, input_section
, rel
->r_offset
,
934 case bfd_reloc_outofrange
:
935 msg
= _("internal error: out of range error");
938 case bfd_reloc_notsupported
:
939 msg
= _("internal error: unsupported relocation error");
942 case bfd_reloc_dangerous
:
943 msg
= _("internal error: dangerous relocation");
947 msg
= _("internal error: unknown error");
952 r
= info
->callbacks
->warning
953 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
963 /* This must exist if dynobj is ever set. */
966 xstormy16_elf_finish_dynamic_sections (abfd
, info
)
967 bfd
*abfd ATTRIBUTE_UNUSED
;
968 struct bfd_link_info
*info
;
973 /* As an extra sanity check, verify that all plt entries have
976 if ((dynobj
= elf_hash_table (info
)->dynobj
) != NULL
977 && (splt
= bfd_get_section_by_name (dynobj
, ".plt")) != NULL
)
979 bfd_byte
*contents
= splt
->contents
;
980 unsigned int i
, size
= splt
->_raw_size
;
981 for (i
= 0; i
< size
; i
+= 4)
983 unsigned int x
= bfd_get_32 (dynobj
, contents
+ i
);
991 /* Return the section that should be marked against GC for a given
995 xstormy16_elf_gc_mark_hook (abfd
, info
, rel
, h
, sym
)
997 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
998 Elf_Internal_Rela
* rel
;
999 struct elf_link_hash_entry
* h
;
1000 Elf_Internal_Sym
* sym
;
1004 switch (ELF32_R_TYPE (rel
->r_info
))
1006 case R_XSTORMY16_GNU_VTINHERIT
:
1007 case R_XSTORMY16_GNU_VTENTRY
:
1011 switch (h
->root
.type
)
1013 case bfd_link_hash_defined
:
1014 case bfd_link_hash_defweak
:
1015 return h
->root
.u
.def
.section
;
1017 case bfd_link_hash_common
:
1018 return h
->root
.u
.c
.p
->section
;
1027 if (!(elf_bad_symtab (abfd
)
1028 && ELF_ST_BIND (sym
->st_info
) != STB_LOCAL
)
1029 && ! ((sym
->st_shndx
<= 0 || sym
->st_shndx
>= SHN_LORESERVE
)
1030 && sym
->st_shndx
!= SHN_COMMON
))
1032 return bfd_section_from_elf_index (abfd
, sym
->st_shndx
);
1039 /* Update the got entry reference counts for the section being removed. */
1042 xstormy16_elf_gc_sweep_hook (abfd
, info
, sec
, relocs
)
1043 bfd
* abfd ATTRIBUTE_UNUSED
;
1044 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
1045 asection
* sec ATTRIBUTE_UNUSED
;
1046 const Elf_Internal_Rela
* relocs ATTRIBUTE_UNUSED
;
1051 #define ELF_ARCH bfd_arch_xstormy16
1052 #define ELF_MACHINE_CODE EM_XSTORMY16
1053 #define ELF_MAXPAGESIZE 0x100
1055 #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1056 #define TARGET_LITTLE_NAME "elf32-xstormy16"
1058 #define elf_info_to_howto_rel NULL
1059 #define elf_info_to_howto xstormy16_info_to_howto_rela
1060 #define elf_backend_relocate_section xstormy16_elf_relocate_section
1061 #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1062 #define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
1063 #define elf_backend_check_relocs xstormy16_elf_check_relocs
1064 #define elf_backend_always_size_sections \
1065 xstormy16_elf_always_size_sections
1066 #define elf_backend_finish_dynamic_sections \
1067 xstormy16_elf_finish_dynamic_sections
1069 #define elf_backend_can_gc_sections 1
1071 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1072 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1074 #include "elf32-target.h"