1 /* XSTORMY16-specific support for 32-bit ELF.
2 Copyright (C) 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
*, Elf32_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 boolean xstormy16_elf_check_relocs
37 PARAMS ((bfd
*, struct bfd_link_info
*, asection
*,
38 const Elf_Internal_Rela
*));
39 static boolean xstormy16_relax_plt_check
40 PARAMS ((struct elf_link_hash_entry
*, PTR
));
41 static boolean xstormy16_relax_plt_realloc
42 PARAMS ((struct elf_link_hash_entry
*, PTR
));
43 static boolean xstormy16_elf_relax_section
44 PARAMS ((bfd
*abfd
, asection
*sec
, struct bfd_link_info
*link_info
,
46 static boolean xstormy16_elf_always_size_sections
47 PARAMS ((bfd
*, struct bfd_link_info
*));
48 static 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 boolean xstormy16_elf_finish_dynamic_sections
52 PARAMS((bfd
*, struct bfd_link_info
*));
53 static 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 */
213 static reloc_howto_type xstormy16_elf_howto_table2
[] =
215 /* GNU extension to record C++ vtable hierarchy */
216 HOWTO (R_XSTORMY16_GNU_VTINHERIT
, /* type */
218 2, /* size (0 = byte, 1 = short, 2 = long) */
220 false, /* pc_relative */
222 complain_overflow_dont
, /* complain_on_overflow */
223 NULL
, /* special_function */
224 "R_XSTORMY16_GNU_VTINHERIT", /* name */
225 false, /* partial_inplace */
228 false), /* pcrel_offset */
230 /* GNU extension to record C++ vtable member usage */
231 HOWTO (R_XSTORMY16_GNU_VTENTRY
, /* type */
233 2, /* size (0 = byte, 1 = short, 2 = long) */
235 false, /* pc_relative */
237 complain_overflow_dont
, /* complain_on_overflow */
238 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
239 "R_XSTORMY16_GNU_VTENTRY", /* name */
240 false, /* partial_inplace */
243 false), /* pcrel_offset */
247 /* Map BFD reloc types to XSTORMY16 ELF reloc types. */
249 typedef struct xstormy16_reloc_map
251 bfd_reloc_code_real_type bfd_reloc_val
;
252 unsigned int xstormy16_reloc_val
;
253 reloc_howto_type
* table
;
256 static const reloc_map xstormy16_reloc_map
[] =
258 { BFD_RELOC_NONE
, R_XSTORMY16_NONE
, xstormy16_elf_howto_table
},
259 { BFD_RELOC_32
, R_XSTORMY16_32
, xstormy16_elf_howto_table
},
260 { BFD_RELOC_16
, R_XSTORMY16_16
, xstormy16_elf_howto_table
},
261 { BFD_RELOC_8
, R_XSTORMY16_8
, xstormy16_elf_howto_table
},
262 { BFD_RELOC_32_PCREL
, R_XSTORMY16_PC32
, xstormy16_elf_howto_table
},
263 { BFD_RELOC_16_PCREL
, R_XSTORMY16_PC16
, xstormy16_elf_howto_table
},
264 { BFD_RELOC_8_PCREL
, R_XSTORMY16_PC8
, xstormy16_elf_howto_table
},
265 { BFD_RELOC_XSTORMY16_REL_12
, R_XSTORMY16_REL_12
, xstormy16_elf_howto_table
},
266 { BFD_RELOC_XSTORMY16_24
, R_XSTORMY16_24
, xstormy16_elf_howto_table
},
267 { BFD_RELOC_XSTORMY16_FPTR16
, R_XSTORMY16_FPTR16
, xstormy16_elf_howto_table
},
268 { BFD_RELOC_VTABLE_INHERIT
, R_XSTORMY16_GNU_VTINHERIT
, xstormy16_elf_howto_table2
},
269 { BFD_RELOC_VTABLE_ENTRY
, R_XSTORMY16_GNU_VTENTRY
, xstormy16_elf_howto_table2
},
272 static reloc_howto_type
*
273 xstormy16_reloc_type_lookup (abfd
, code
)
274 bfd
* abfd ATTRIBUTE_UNUSED
;
275 bfd_reloc_code_real_type code
;
279 for (i
= ARRAY_SIZE (xstormy16_reloc_map
); --i
;)
281 const reloc_map
* entry
;
283 entry
= xstormy16_reloc_map
+ i
;
285 if (entry
->bfd_reloc_val
== code
)
286 return entry
->table
+ (entry
->xstormy16_reloc_val
287 - entry
->table
[0].type
);
293 /* Set the howto pointer for an XSTORMY16 ELF reloc. */
296 xstormy16_info_to_howto_rela (abfd
, cache_ptr
, dst
)
297 bfd
* abfd ATTRIBUTE_UNUSED
;
299 Elf32_Internal_Rela
* dst
;
301 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
303 if (r_type
<= (unsigned int) R_XSTORMY16_FPTR16
)
304 cache_ptr
->howto
= &xstormy16_elf_howto_table
[r_type
];
305 else if (r_type
- R_XSTORMY16_GNU_VTINHERIT
306 <= (unsigned int) R_XSTORMY16_GNU_VTENTRY
)
308 = &xstormy16_elf_howto_table2
[r_type
- R_XSTORMY16_GNU_VTINHERIT
];
313 /* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */
315 static bfd_reloc_status_type
316 xstormy16_elf_24_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
317 output_bfd
, error_message
)
319 arelent
*reloc_entry
;
322 asection
*input_section
;
324 char **error_message ATTRIBUTE_UNUSED
;
326 bfd_vma relocation
, x
;
328 if (output_bfd
!= NULL
)
330 reloc_entry
->address
+= input_section
->output_offset
;
334 if (reloc_entry
->address
> input_section
->_cooked_size
)
335 return bfd_reloc_outofrange
;
337 if (bfd_is_com_section (symbol
->section
))
340 relocation
= symbol
->value
;
342 relocation
+= symbol
->section
->output_section
->vma
;
343 relocation
+= symbol
->section
->output_offset
;
344 relocation
+= reloc_entry
->addend
;
346 x
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ reloc_entry
->address
);
348 x
|= relocation
& 0xff;
349 x
|= (relocation
<< 8) & 0xffff0000;
350 bfd_put_32 (abfd
, x
, (bfd_byte
*) data
+ reloc_entry
->address
);
352 if (relocation
& ~ (bfd_vma
) 0xffffff)
353 return bfd_reloc_overflow
;
358 /* We support 16-bit pointers to code above 64k by generating a thunk
359 below 64k containing a JMPF instruction to the final address. We
360 cannot, unfortunately, minimize the number of thunks unless the
361 -relax switch is given, as otherwise we have no idea where the
362 sections will fall in the address space. */
365 xstormy16_elf_check_relocs (abfd
, info
, sec
, relocs
)
367 struct bfd_link_info
*info
;
369 const Elf_Internal_Rela
*relocs
;
371 const Elf_Internal_Rela
*rel
, *relend
;
372 struct elf_link_hash_entry
**sym_hashes
;
373 Elf_Internal_Shdr
*symtab_hdr
;
374 bfd_vma
*local_plt_offsets
;
378 if (info
->relocateable
)
381 symtab_hdr
= &elf_tdata(abfd
)->symtab_hdr
;
382 sym_hashes
= elf_sym_hashes (abfd
);
383 local_plt_offsets
= elf_local_got_offsets (abfd
);
385 dynobj
= elf_hash_table(info
)->dynobj
;
387 relend
= relocs
+ sec
->reloc_count
;
388 for (rel
= relocs
; rel
< relend
; ++rel
)
390 unsigned long r_symndx
;
391 struct elf_link_hash_entry
*h
;
394 r_symndx
= ELF32_R_SYM (rel
->r_info
);
395 if (r_symndx
< symtab_hdr
->sh_info
)
399 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
400 while (h
->root
.type
== bfd_link_hash_indirect
401 || h
->root
.type
== bfd_link_hash_warning
)
402 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
405 switch (ELF32_R_TYPE (rel
->r_info
))
407 /* This relocation describes a 16-bit pointer to a function.
408 We may need to allocate a thunk in low memory; reserve memory
410 case R_XSTORMY16_FPTR16
:
411 if (rel
->r_addend
!= 0)
413 (*info
->callbacks
->warning
)
414 (info
, _("non-zero addend in @fptr reloc"), 0,
419 elf_hash_table (info
)->dynobj
= dynobj
= abfd
;
422 splt
= bfd_get_section_by_name (dynobj
, ".plt");
425 splt
= bfd_make_section (dynobj
, ".plt");
427 || ! bfd_set_section_flags (dynobj
, splt
,
435 || ! bfd_set_section_alignment (dynobj
, splt
, 1))
441 offset
= &h
->plt
.offset
;
444 if (local_plt_offsets
== NULL
)
449 size
= symtab_hdr
->sh_info
* sizeof (bfd_vma
);
450 local_plt_offsets
= (bfd_vma
*) bfd_alloc (abfd
, size
);
451 if (local_plt_offsets
== NULL
)
453 elf_local_got_offsets (abfd
) = local_plt_offsets
;
455 for (i
= 0; i
< symtab_hdr
->sh_info
; i
++)
456 local_plt_offsets
[i
] = (bfd_vma
) -1;
458 offset
= &local_plt_offsets
[r_symndx
];
461 if (*offset
== (bfd_vma
) -1)
463 *offset
= splt
->_raw_size
;
464 splt
->_raw_size
+= 4;
468 /* This relocation describes the C++ object vtable hierarchy.
469 Reconstruct it for later use during GC. */
470 case R_XSTORMY16_GNU_VTINHERIT
:
471 if (!_bfd_elf32_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
475 /* This relocation describes which C++ vtable entries are actually
476 used. Record for later use during GC. */
477 case R_XSTORMY16_GNU_VTENTRY
:
478 if (!_bfd_elf32_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
487 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
488 is within the low 64k, remove any entry for it in the plt. */
490 struct relax_plt_data
497 xstormy16_relax_plt_check (h
, xdata
)
498 struct elf_link_hash_entry
*h
;
501 struct relax_plt_data
*data
= (struct relax_plt_data
*) xdata
;
503 if (h
->root
.type
== bfd_link_hash_warning
)
504 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
506 if (h
->plt
.offset
!= (bfd_vma
) -1)
510 if (h
->root
.type
== bfd_link_hash_undefined
511 || h
->root
.type
== bfd_link_hash_undefweak
)
514 address
= (h
->root
.u
.def
.section
->output_section
->vma
515 + h
->root
.u
.def
.section
->output_offset
516 + h
->root
.u
.def
.value
);
518 if (address
<= 0xffff)
521 data
->splt
->_cooked_size
-= 4;
529 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
530 previously had a plt entry, give it a new entry offset. */
533 xstormy16_relax_plt_realloc (h
, xdata
)
534 struct elf_link_hash_entry
*h
;
537 bfd_vma
*entry
= (bfd_vma
*) xdata
;
539 if (h
->root
.type
== bfd_link_hash_warning
)
540 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
542 if (h
->plt
.offset
!= (bfd_vma
) -1)
544 h
->plt
.offset
= *entry
;
552 xstormy16_elf_relax_section (dynobj
, splt
, info
, again
)
555 struct bfd_link_info
*info
;
558 struct relax_plt_data relax_plt_data
;
561 /* Assume nothing changes. */
564 if (info
->relocateable
)
567 /* We only relax the .plt section at the moment. */
568 if (dynobj
!= elf_hash_table (info
)->dynobj
569 || strcmp (splt
->name
, ".plt") != 0)
572 /* Quick check for an empty plt. */
573 if (splt
->_raw_size
== 0)
576 /* If this is the first time we have been called for this section,
577 initialize the cooked size. */
578 if (splt
->_cooked_size
== 0)
579 splt
->_cooked_size
= splt
->_raw_size
;
581 /* Map across all global symbols; see which ones happen to
582 fall in the low 64k. */
583 relax_plt_data
.splt
= splt
;
584 relax_plt_data
.again
= again
;
585 elf_link_hash_traverse (elf_hash_table (info
), xstormy16_relax_plt_check
,
588 /* Likewise for local symbols, though that's somewhat less convenient
589 as we have to walk the list of input bfds and swap in symbol data. */
590 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
592 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
593 Elf_Internal_Shdr
*symtab_hdr
;
594 Elf_Internal_Sym
*isymbuf
= NULL
;
597 if (! local_plt_offsets
)
600 symtab_hdr
= &elf_tdata (ibfd
)->symtab_hdr
;
601 if (symtab_hdr
->sh_info
!= 0)
603 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
605 isymbuf
= bfd_elf_get_elf_syms (ibfd
, symtab_hdr
,
606 symtab_hdr
->sh_info
, 0,
612 for (idx
= 0; idx
< symtab_hdr
->sh_info
; ++idx
)
614 Elf_Internal_Sym
*isym
;
618 if (local_plt_offsets
[idx
] == (bfd_vma
) -1)
621 isym
= &isymbuf
[idx
];
622 if (isym
->st_shndx
== SHN_UNDEF
)
624 else if (isym
->st_shndx
== SHN_ABS
)
625 tsec
= bfd_abs_section_ptr
;
626 else if (isym
->st_shndx
== SHN_COMMON
)
627 tsec
= bfd_com_section_ptr
;
629 tsec
= bfd_section_from_elf_index (ibfd
, isym
->st_shndx
);
631 address
= (tsec
->output_section
->vma
632 + tsec
->output_offset
634 if (address
<= 0xffff)
636 local_plt_offsets
[idx
] = -1;
637 splt
->_cooked_size
-= 4;
643 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
645 if (! info
->keep_memory
)
649 /* Cache the symbols for elf_link_input_bfd. */
650 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
655 /* If we changed anything, walk the symbols again to reallocate
656 .plt entry addresses. */
657 if (*again
&& splt
->_cooked_size
> 0)
661 elf_link_hash_traverse (elf_hash_table (info
),
662 xstormy16_relax_plt_realloc
, &entry
);
664 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
666 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
667 unsigned int nlocals
= elf_tdata (ibfd
)->symtab_hdr
.sh_info
;
670 if (! local_plt_offsets
)
673 for (idx
= 0; idx
< nlocals
; ++idx
)
674 if (local_plt_offsets
[idx
] != (bfd_vma
) -1)
676 local_plt_offsets
[idx
] = entry
;
682 splt
->_raw_size
= splt
->_cooked_size
;
687 xstormy16_elf_always_size_sections (output_bfd
, info
)
688 bfd
*output_bfd ATTRIBUTE_UNUSED
;
689 struct bfd_link_info
*info
;
694 if (info
->relocateable
)
697 dynobj
= elf_hash_table (info
)->dynobj
;
701 splt
= bfd_get_section_by_name (dynobj
, ".plt");
702 BFD_ASSERT (splt
!= NULL
);
704 splt
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, splt
->_raw_size
);
705 if (splt
->contents
== NULL
)
711 /* Relocate an XSTORMY16 ELF section.
713 The RELOCATE_SECTION function is called by the new ELF backend linker
714 to handle the relocations for a section.
716 The relocs are always passed as Rela structures; if the section
717 actually uses Rel structures, the r_addend field will always be
720 This function is responsible for adjusting the section contents as
721 necessary, and (if using Rela relocs and generating a relocateable
722 output file) adjusting the reloc addend as necessary.
724 This function does not have to worry about setting the reloc
725 address or the reloc symbol index.
727 LOCAL_SYMS is a pointer to the swapped in local symbols.
729 LOCAL_SECTIONS is an array giving the section in the input file
730 corresponding to the st_shndx field of each local symbol.
732 The global hash table entry for the global symbols can be found
733 via elf_sym_hashes (input_bfd).
735 When generating relocateable output, this function must handle
736 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
737 going to be the section symbol corresponding to the output
738 section, which means that the addend must be adjusted
742 xstormy16_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
743 contents
, relocs
, local_syms
, local_sections
)
744 bfd
* output_bfd ATTRIBUTE_UNUSED
;
745 struct bfd_link_info
* info
;
747 asection
* input_section
;
749 Elf_Internal_Rela
* relocs
;
750 Elf_Internal_Sym
* local_syms
;
751 asection
** local_sections
;
753 Elf_Internal_Shdr
* symtab_hdr
;
754 struct elf_link_hash_entry
** sym_hashes
;
755 Elf_Internal_Rela
* rel
;
756 Elf_Internal_Rela
* relend
;
760 if (info
->relocateable
)
763 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
764 sym_hashes
= elf_sym_hashes (input_bfd
);
765 relend
= relocs
+ input_section
->reloc_count
;
767 dynobj
= elf_hash_table (info
)->dynobj
;
770 splt
= bfd_get_section_by_name (dynobj
, ".plt");
772 for (rel
= relocs
; rel
< relend
; rel
++)
774 reloc_howto_type
* howto
;
775 unsigned long r_symndx
;
776 Elf_Internal_Sym
* sym
;
778 struct elf_link_hash_entry
* h
;
780 bfd_reloc_status_type r
;
781 const char * name
= NULL
;
784 r_type
= ELF32_R_TYPE (rel
->r_info
);
786 if ( r_type
== R_XSTORMY16_GNU_VTINHERIT
787 || r_type
== R_XSTORMY16_GNU_VTENTRY
)
790 r_symndx
= ELF32_R_SYM (rel
->r_info
);
791 howto
= xstormy16_elf_howto_table
+ ELF32_R_TYPE (rel
->r_info
);
796 if (r_symndx
< symtab_hdr
->sh_info
)
798 sym
= local_syms
+ r_symndx
;
799 sec
= local_sections
[r_symndx
];
800 relocation
= (sec
->output_section
->vma
804 name
= bfd_elf_string_from_elf_section
805 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
806 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
810 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
812 while (h
->root
.type
== bfd_link_hash_indirect
813 || h
->root
.type
== bfd_link_hash_warning
)
814 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
816 name
= h
->root
.root
.string
;
818 if (h
->root
.type
== bfd_link_hash_defined
819 || h
->root
.type
== bfd_link_hash_defweak
)
821 sec
= h
->root
.u
.def
.section
;
822 relocation
= (h
->root
.u
.def
.value
823 + sec
->output_section
->vma
824 + sec
->output_offset
);
826 else if (h
->root
.type
== bfd_link_hash_undefweak
)
832 if (! ((*info
->callbacks
->undefined_symbol
)
833 (info
, h
->root
.root
.string
, input_bfd
,
834 input_section
, rel
->r_offset
, true)))
840 switch (ELF32_R_TYPE (rel
->r_info
))
844 bfd_vma reloc
= relocation
+ rel
->r_addend
;
847 x
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
850 x
|= (reloc
<< 8) & 0xffff0000;
851 bfd_put_32 (input_bfd
, x
, contents
+ rel
->r_offset
);
853 if (reloc
& ~0xffffff)
854 r
= bfd_reloc_overflow
;
860 case R_XSTORMY16_FPTR16
:
865 plt_offset
= &h
->plt
.offset
;
867 plt_offset
= elf_local_got_offsets (input_bfd
) + r_symndx
;
869 if (relocation
<= 0xffff)
871 /* If the symbol is in range for a 16-bit address, we should
872 have deallocated the plt entry in relax_section. */
873 BFD_ASSERT (*plt_offset
== (bfd_vma
) -1);
877 /* If the symbol is out of range for a 16-bit address,
878 we must have allocated a plt entry. */
879 BFD_ASSERT (*plt_offset
!= (bfd_vma
) -1);
881 /* If this is the first time we've processed this symbol,
882 fill in the plt entry with the correct symbol address. */
883 if ((*plt_offset
& 1) == 0)
887 x
= 0x00000200; /* jmpf */
888 x
|= relocation
& 0xff;
889 x
|= (relocation
<< 8) & 0xffff0000;
890 bfd_put_32 (input_bfd
, x
, splt
->contents
+ *plt_offset
);
894 relocation
= (splt
->output_section
->vma
895 + splt
->output_offset
896 + (*plt_offset
& -2));
898 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
899 contents
, rel
->r_offset
,
905 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
906 contents
, rel
->r_offset
,
907 relocation
, rel
->r_addend
);
911 if (r
!= bfd_reloc_ok
)
913 const char * msg
= (const char *) NULL
;
917 case bfd_reloc_overflow
:
918 r
= info
->callbacks
->reloc_overflow
919 (info
, name
, howto
->name
, (bfd_vma
) 0,
920 input_bfd
, input_section
, rel
->r_offset
);
923 case bfd_reloc_undefined
:
924 r
= info
->callbacks
->undefined_symbol
925 (info
, name
, input_bfd
, input_section
, rel
->r_offset
,
929 case bfd_reloc_outofrange
:
930 msg
= _("internal error: out of range error");
933 case bfd_reloc_notsupported
:
934 msg
= _("internal error: unsupported relocation error");
937 case bfd_reloc_dangerous
:
938 msg
= _("internal error: dangerous relocation");
942 msg
= _("internal error: unknown error");
947 r
= info
->callbacks
->warning
948 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
958 /* This must exist if dynobj is ever set. */
961 xstormy16_elf_finish_dynamic_sections (abfd
, info
)
962 bfd
*abfd ATTRIBUTE_UNUSED
;
963 struct bfd_link_info
*info
;
968 /* As an extra sanity check, verify that all plt entries have
971 if ((dynobj
= elf_hash_table (info
)->dynobj
) != NULL
972 && (splt
= bfd_get_section_by_name (dynobj
, ".plt")) != NULL
)
974 bfd_byte
*contents
= splt
->contents
;
975 unsigned int i
, size
= splt
->_raw_size
;
976 for (i
= 0; i
< size
; i
+= 4)
978 unsigned int x
= bfd_get_32 (dynobj
, contents
+ i
);
986 /* Return the section that should be marked against GC for a given
990 xstormy16_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
)
992 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
993 Elf_Internal_Rela
* rel
;
994 struct elf_link_hash_entry
* h
;
995 Elf_Internal_Sym
* sym
;
999 switch (ELF32_R_TYPE (rel
->r_info
))
1001 case R_XSTORMY16_GNU_VTINHERIT
:
1002 case R_XSTORMY16_GNU_VTENTRY
:
1006 switch (h
->root
.type
)
1008 case bfd_link_hash_defined
:
1009 case bfd_link_hash_defweak
:
1010 return h
->root
.u
.def
.section
;
1012 case bfd_link_hash_common
:
1013 return h
->root
.u
.c
.p
->section
;
1021 return bfd_section_from_elf_index (sec
->owner
, sym
->st_shndx
);
1026 /* Update the got entry reference counts for the section being removed. */
1029 xstormy16_elf_gc_sweep_hook (abfd
, info
, sec
, relocs
)
1030 bfd
* abfd ATTRIBUTE_UNUSED
;
1031 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
1032 asection
* sec ATTRIBUTE_UNUSED
;
1033 const Elf_Internal_Rela
* relocs ATTRIBUTE_UNUSED
;
1038 #define ELF_ARCH bfd_arch_xstormy16
1039 #define ELF_MACHINE_CODE EM_XSTORMY16
1040 #define ELF_MAXPAGESIZE 0x100
1042 #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1043 #define TARGET_LITTLE_NAME "elf32-xstormy16"
1045 #define elf_info_to_howto_rel NULL
1046 #define elf_info_to_howto xstormy16_info_to_howto_rela
1047 #define elf_backend_relocate_section xstormy16_elf_relocate_section
1048 #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1049 #define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
1050 #define elf_backend_check_relocs xstormy16_elf_check_relocs
1051 #define elf_backend_always_size_sections \
1052 xstormy16_elf_always_size_sections
1053 #define elf_backend_finish_dynamic_sections \
1054 xstormy16_elf_finish_dynamic_sections
1056 #define elf_backend_can_gc_sections 1
1057 #define elf_backend_rela_normal 1
1059 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1060 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1062 #include "elf32-target.h"