1 /* XSTORMY16-specific support for 32-bit ELF.
2 Copyright 2000, 2001, 2002, 2003, 2004 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 0xffff, /* 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_unsigned
, /* complain_on_overflow */
115 bfd_elf_generic_reloc
, /* special_function */
116 "R_XSTORMY16_8", /* name */
117 FALSE
, /* partial_inplace */
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 FALSE
, /* partial_inplace */
179 0x0ffe, /* 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 */
242 /* A 12 bit absolute relocation. */
243 HOWTO (R_XSTORMY16_12
, /* type */
245 1, /* size (0 = byte, 1 = short, 2 = long) */
247 FALSE
, /* pc_relative */
249 complain_overflow_signed
, /* complain_on_overflow */
250 bfd_elf_generic_reloc
, /* special_function */
251 "R_XSTORMY16_12", /* name */
252 FALSE
, /* partial_inplace */
253 0x0000, /* src_mask */
254 0x0fff, /* dst_mask */
255 FALSE
), /* pcrel_offset */
258 static reloc_howto_type xstormy16_elf_howto_table2
[] =
260 /* GNU extension to record C++ vtable hierarchy */
261 HOWTO (R_XSTORMY16_GNU_VTINHERIT
, /* type */
263 2, /* size (0 = byte, 1 = short, 2 = long) */
265 FALSE
, /* pc_relative */
267 complain_overflow_dont
, /* complain_on_overflow */
268 NULL
, /* special_function */
269 "R_XSTORMY16_GNU_VTINHERIT", /* name */
270 FALSE
, /* partial_inplace */
273 FALSE
), /* pcrel_offset */
275 /* GNU extension to record C++ vtable member usage */
276 HOWTO (R_XSTORMY16_GNU_VTENTRY
, /* type */
278 2, /* size (0 = byte, 1 = short, 2 = long) */
280 FALSE
, /* pc_relative */
282 complain_overflow_dont
, /* complain_on_overflow */
283 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
284 "R_XSTORMY16_GNU_VTENTRY", /* name */
285 FALSE
, /* partial_inplace */
288 FALSE
), /* pcrel_offset */
292 /* Map BFD reloc types to XSTORMY16 ELF reloc types. */
294 typedef struct xstormy16_reloc_map
296 bfd_reloc_code_real_type bfd_reloc_val
;
297 unsigned int xstormy16_reloc_val
;
298 reloc_howto_type
* table
;
301 static const reloc_map xstormy16_reloc_map
[] =
303 { BFD_RELOC_NONE
, R_XSTORMY16_NONE
, xstormy16_elf_howto_table
},
304 { BFD_RELOC_32
, R_XSTORMY16_32
, xstormy16_elf_howto_table
},
305 { BFD_RELOC_16
, R_XSTORMY16_16
, xstormy16_elf_howto_table
},
306 { BFD_RELOC_8
, R_XSTORMY16_8
, xstormy16_elf_howto_table
},
307 { BFD_RELOC_32_PCREL
, R_XSTORMY16_PC32
, xstormy16_elf_howto_table
},
308 { BFD_RELOC_16_PCREL
, R_XSTORMY16_PC16
, xstormy16_elf_howto_table
},
309 { BFD_RELOC_8_PCREL
, R_XSTORMY16_PC8
, xstormy16_elf_howto_table
},
310 { BFD_RELOC_XSTORMY16_REL_12
, R_XSTORMY16_REL_12
, xstormy16_elf_howto_table
},
311 { BFD_RELOC_XSTORMY16_24
, R_XSTORMY16_24
, xstormy16_elf_howto_table
},
312 { BFD_RELOC_XSTORMY16_FPTR16
, R_XSTORMY16_FPTR16
, xstormy16_elf_howto_table
},
313 { BFD_RELOC_LO16
, R_XSTORMY16_LO16
, xstormy16_elf_howto_table
},
314 { BFD_RELOC_HI16
, R_XSTORMY16_HI16
, xstormy16_elf_howto_table
},
315 { BFD_RELOC_XSTORMY16_12
, R_XSTORMY16_12
, xstormy16_elf_howto_table
},
316 { BFD_RELOC_VTABLE_INHERIT
, R_XSTORMY16_GNU_VTINHERIT
, xstormy16_elf_howto_table2
},
317 { BFD_RELOC_VTABLE_ENTRY
, R_XSTORMY16_GNU_VTENTRY
, xstormy16_elf_howto_table2
},
320 static reloc_howto_type
*
321 xstormy16_reloc_type_lookup (abfd
, code
)
322 bfd
* abfd ATTRIBUTE_UNUSED
;
323 bfd_reloc_code_real_type code
;
327 for (i
= ARRAY_SIZE (xstormy16_reloc_map
); --i
;)
329 const reloc_map
* entry
;
331 entry
= xstormy16_reloc_map
+ i
;
333 if (entry
->bfd_reloc_val
== code
)
334 return entry
->table
+ (entry
->xstormy16_reloc_val
335 - entry
->table
[0].type
);
341 /* Set the howto pointer for an XSTORMY16 ELF reloc. */
344 xstormy16_info_to_howto_rela (abfd
, cache_ptr
, dst
)
345 bfd
* abfd ATTRIBUTE_UNUSED
;
347 Elf_Internal_Rela
* dst
;
349 unsigned int r_type
= ELF32_R_TYPE (dst
->r_info
);
351 if (r_type
<= (unsigned int) R_XSTORMY16_12
)
352 cache_ptr
->howto
= &xstormy16_elf_howto_table
[r_type
];
353 else if (r_type
- R_XSTORMY16_GNU_VTINHERIT
354 <= (unsigned int) R_XSTORMY16_GNU_VTENTRY
)
356 = &xstormy16_elf_howto_table2
[r_type
- R_XSTORMY16_GNU_VTINHERIT
];
361 /* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */
363 static bfd_reloc_status_type
364 xstormy16_elf_24_reloc (abfd
, reloc_entry
, symbol
, data
, input_section
,
365 output_bfd
, error_message
)
367 arelent
*reloc_entry
;
370 asection
*input_section
;
372 char **error_message ATTRIBUTE_UNUSED
;
374 bfd_vma relocation
, x
;
376 if (output_bfd
!= NULL
)
378 reloc_entry
->address
+= input_section
->output_offset
;
382 if (reloc_entry
->address
> bfd_get_section_limit (abfd
, input_section
))
383 return bfd_reloc_outofrange
;
385 if (bfd_is_com_section (symbol
->section
))
388 relocation
= symbol
->value
;
390 relocation
+= symbol
->section
->output_section
->vma
;
391 relocation
+= symbol
->section
->output_offset
;
392 relocation
+= reloc_entry
->addend
;
394 x
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ reloc_entry
->address
);
396 x
|= relocation
& 0xff;
397 x
|= (relocation
<< 8) & 0xffff0000;
398 bfd_put_32 (abfd
, x
, (bfd_byte
*) data
+ reloc_entry
->address
);
400 if (relocation
& ~ (bfd_vma
) 0xffffff)
401 return bfd_reloc_overflow
;
406 /* We support 16-bit pointers to code above 64k by generating a thunk
407 below 64k containing a JMPF instruction to the final address. We
408 cannot, unfortunately, minimize the number of thunks unless the
409 -relax switch is given, as otherwise we have no idea where the
410 sections will fall in the address space. */
413 xstormy16_elf_check_relocs (abfd
, info
, sec
, relocs
)
415 struct bfd_link_info
*info
;
417 const Elf_Internal_Rela
*relocs
;
419 const Elf_Internal_Rela
*rel
, *relend
;
420 struct elf_link_hash_entry
**sym_hashes
;
421 Elf_Internal_Shdr
*symtab_hdr
;
422 bfd_vma
*local_plt_offsets
;
426 if (info
->relocatable
)
429 symtab_hdr
= &elf_tdata(abfd
)->symtab_hdr
;
430 sym_hashes
= elf_sym_hashes (abfd
);
431 local_plt_offsets
= elf_local_got_offsets (abfd
);
433 dynobj
= elf_hash_table(info
)->dynobj
;
435 relend
= relocs
+ sec
->reloc_count
;
436 for (rel
= relocs
; rel
< relend
; ++rel
)
438 unsigned long r_symndx
;
439 struct elf_link_hash_entry
*h
;
442 r_symndx
= ELF32_R_SYM (rel
->r_info
);
443 if (r_symndx
< symtab_hdr
->sh_info
)
447 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
448 while (h
->root
.type
== bfd_link_hash_indirect
449 || h
->root
.type
== bfd_link_hash_warning
)
450 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
453 switch (ELF32_R_TYPE (rel
->r_info
))
455 /* This relocation describes a 16-bit pointer to a function.
456 We may need to allocate a thunk in low memory; reserve memory
458 case R_XSTORMY16_FPTR16
:
459 if (rel
->r_addend
!= 0)
461 (*info
->callbacks
->warning
)
462 (info
, _("non-zero addend in @fptr reloc"), 0,
467 elf_hash_table (info
)->dynobj
= dynobj
= abfd
;
470 splt
= bfd_get_section_by_name (dynobj
, ".plt");
473 splt
= bfd_make_section (dynobj
, ".plt");
475 || ! bfd_set_section_flags (dynobj
, splt
,
483 || ! bfd_set_section_alignment (dynobj
, splt
, 1))
489 offset
= &h
->plt
.offset
;
492 if (local_plt_offsets
== NULL
)
497 size
= symtab_hdr
->sh_info
* sizeof (bfd_vma
);
498 local_plt_offsets
= (bfd_vma
*) bfd_alloc (abfd
, size
);
499 if (local_plt_offsets
== NULL
)
501 elf_local_got_offsets (abfd
) = local_plt_offsets
;
503 for (i
= 0; i
< symtab_hdr
->sh_info
; i
++)
504 local_plt_offsets
[i
] = (bfd_vma
) -1;
506 offset
= &local_plt_offsets
[r_symndx
];
509 if (*offset
== (bfd_vma
) -1)
511 *offset
= splt
->size
;
516 /* This relocation describes the C++ object vtable hierarchy.
517 Reconstruct it for later use during GC. */
518 case R_XSTORMY16_GNU_VTINHERIT
:
519 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
523 /* This relocation describes which C++ vtable entries are actually
524 used. Record for later use during GC. */
525 case R_XSTORMY16_GNU_VTENTRY
:
526 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
535 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
536 is within the low 64k, remove any entry for it in the plt. */
538 struct relax_plt_data
545 xstormy16_relax_plt_check (h
, xdata
)
546 struct elf_link_hash_entry
*h
;
549 struct relax_plt_data
*data
= (struct relax_plt_data
*) xdata
;
551 if (h
->root
.type
== bfd_link_hash_warning
)
552 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
554 if (h
->plt
.offset
!= (bfd_vma
) -1)
558 if (h
->root
.type
== bfd_link_hash_undefined
559 || h
->root
.type
== bfd_link_hash_undefweak
)
562 address
= (h
->root
.u
.def
.section
->output_section
->vma
563 + h
->root
.u
.def
.section
->output_offset
564 + h
->root
.u
.def
.value
);
566 if (address
<= 0xffff)
569 data
->splt
->size
-= 4;
577 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
578 previously had a plt entry, give it a new entry offset. */
581 xstormy16_relax_plt_realloc (h
, xdata
)
582 struct elf_link_hash_entry
*h
;
585 bfd_vma
*entry
= (bfd_vma
*) xdata
;
587 if (h
->root
.type
== bfd_link_hash_warning
)
588 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
590 if (h
->plt
.offset
!= (bfd_vma
) -1)
592 h
->plt
.offset
= *entry
;
600 xstormy16_elf_relax_section (dynobj
, splt
, info
, again
)
603 struct bfd_link_info
*info
;
606 struct relax_plt_data relax_plt_data
;
609 /* Assume nothing changes. */
612 if (info
->relocatable
)
615 /* We only relax the .plt section at the moment. */
616 if (dynobj
!= elf_hash_table (info
)->dynobj
617 || strcmp (splt
->name
, ".plt") != 0)
620 /* Quick check for an empty plt. */
624 /* Map across all global symbols; see which ones happen to
625 fall in the low 64k. */
626 relax_plt_data
.splt
= splt
;
627 relax_plt_data
.again
= again
;
628 elf_link_hash_traverse (elf_hash_table (info
), xstormy16_relax_plt_check
,
631 /* Likewise for local symbols, though that's somewhat less convenient
632 as we have to walk the list of input bfds and swap in symbol data. */
633 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
635 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
636 Elf_Internal_Shdr
*symtab_hdr
;
637 Elf_Internal_Sym
*isymbuf
= NULL
;
640 if (! local_plt_offsets
)
643 symtab_hdr
= &elf_tdata (ibfd
)->symtab_hdr
;
644 if (symtab_hdr
->sh_info
!= 0)
646 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
648 isymbuf
= bfd_elf_get_elf_syms (ibfd
, symtab_hdr
,
649 symtab_hdr
->sh_info
, 0,
655 for (idx
= 0; idx
< symtab_hdr
->sh_info
; ++idx
)
657 Elf_Internal_Sym
*isym
;
661 if (local_plt_offsets
[idx
] == (bfd_vma
) -1)
664 isym
= &isymbuf
[idx
];
665 if (isym
->st_shndx
== SHN_UNDEF
)
667 else if (isym
->st_shndx
== SHN_ABS
)
668 tsec
= bfd_abs_section_ptr
;
669 else if (isym
->st_shndx
== SHN_COMMON
)
670 tsec
= bfd_com_section_ptr
;
672 tsec
= bfd_section_from_elf_index (ibfd
, isym
->st_shndx
);
674 address
= (tsec
->output_section
->vma
675 + tsec
->output_offset
677 if (address
<= 0xffff)
679 local_plt_offsets
[idx
] = -1;
686 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
688 if (! info
->keep_memory
)
692 /* Cache the symbols for elf_link_input_bfd. */
693 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
698 /* If we changed anything, walk the symbols again to reallocate
699 .plt entry addresses. */
700 if (*again
&& splt
->size
> 0)
704 elf_link_hash_traverse (elf_hash_table (info
),
705 xstormy16_relax_plt_realloc
, &entry
);
707 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
709 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
710 unsigned int nlocals
= elf_tdata (ibfd
)->symtab_hdr
.sh_info
;
713 if (! local_plt_offsets
)
716 for (idx
= 0; idx
< nlocals
; ++idx
)
717 if (local_plt_offsets
[idx
] != (bfd_vma
) -1)
719 local_plt_offsets
[idx
] = entry
;
729 xstormy16_elf_always_size_sections (output_bfd
, info
)
730 bfd
*output_bfd ATTRIBUTE_UNUSED
;
731 struct bfd_link_info
*info
;
736 if (info
->relocatable
)
739 dynobj
= elf_hash_table (info
)->dynobj
;
743 splt
= bfd_get_section_by_name (dynobj
, ".plt");
744 BFD_ASSERT (splt
!= NULL
);
746 splt
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, splt
->size
);
747 if (splt
->contents
== NULL
)
753 /* Relocate an XSTORMY16 ELF section.
755 The RELOCATE_SECTION function is called by the new ELF backend linker
756 to handle the relocations for a section.
758 The relocs are always passed as Rela structures; if the section
759 actually uses Rel structures, the r_addend field will always be
762 This function is responsible for adjusting the section contents as
763 necessary, and (if using Rela relocs and generating a relocatable
764 output file) adjusting the reloc addend as necessary.
766 This function does not have to worry about setting the reloc
767 address or the reloc symbol index.
769 LOCAL_SYMS is a pointer to the swapped in local symbols.
771 LOCAL_SECTIONS is an array giving the section in the input file
772 corresponding to the st_shndx field of each local symbol.
774 The global hash table entry for the global symbols can be found
775 via elf_sym_hashes (input_bfd).
777 When generating relocatable output, this function must handle
778 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
779 going to be the section symbol corresponding to the output
780 section, which means that the addend must be adjusted
784 xstormy16_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
785 contents
, relocs
, local_syms
, local_sections
)
786 bfd
* output_bfd ATTRIBUTE_UNUSED
;
787 struct bfd_link_info
* info
;
789 asection
* input_section
;
791 Elf_Internal_Rela
* relocs
;
792 Elf_Internal_Sym
* local_syms
;
793 asection
** local_sections
;
795 Elf_Internal_Shdr
* symtab_hdr
;
796 struct elf_link_hash_entry
** sym_hashes
;
797 Elf_Internal_Rela
* rel
;
798 Elf_Internal_Rela
* relend
;
802 if (info
->relocatable
)
805 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
806 sym_hashes
= elf_sym_hashes (input_bfd
);
807 relend
= relocs
+ input_section
->reloc_count
;
809 dynobj
= elf_hash_table (info
)->dynobj
;
812 splt
= bfd_get_section_by_name (dynobj
, ".plt");
814 for (rel
= relocs
; rel
< relend
; rel
++)
816 reloc_howto_type
* howto
;
817 unsigned long r_symndx
;
818 Elf_Internal_Sym
* sym
;
820 struct elf_link_hash_entry
* h
;
822 bfd_reloc_status_type r
;
823 const char * name
= NULL
;
826 r_type
= ELF32_R_TYPE (rel
->r_info
);
828 if ( r_type
== R_XSTORMY16_GNU_VTINHERIT
829 || r_type
== R_XSTORMY16_GNU_VTENTRY
)
832 r_symndx
= ELF32_R_SYM (rel
->r_info
);
833 howto
= xstormy16_elf_howto_table
+ ELF32_R_TYPE (rel
->r_info
);
838 if (r_symndx
< symtab_hdr
->sh_info
)
840 sym
= local_syms
+ r_symndx
;
841 sec
= local_sections
[r_symndx
];
842 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
844 name
= bfd_elf_string_from_elf_section
845 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
846 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
850 bfd_boolean unresolved_reloc
, warned
;
852 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
853 r_symndx
, symtab_hdr
, sym_hashes
,
855 unresolved_reloc
, warned
);
858 switch (ELF32_R_TYPE (rel
->r_info
))
862 bfd_vma reloc
= relocation
+ rel
->r_addend
;
865 x
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
868 x
|= (reloc
<< 8) & 0xffff0000;
869 bfd_put_32 (input_bfd
, x
, contents
+ rel
->r_offset
);
871 if (reloc
& ~0xffffff)
872 r
= bfd_reloc_overflow
;
878 case R_XSTORMY16_FPTR16
:
883 plt_offset
= &h
->plt
.offset
;
885 plt_offset
= elf_local_got_offsets (input_bfd
) + r_symndx
;
887 if (relocation
<= 0xffff)
889 /* If the symbol is in range for a 16-bit address, we should
890 have deallocated the plt entry in relax_section. */
891 BFD_ASSERT (*plt_offset
== (bfd_vma
) -1);
895 /* If the symbol is out of range for a 16-bit address,
896 we must have allocated a plt entry. */
897 BFD_ASSERT (*plt_offset
!= (bfd_vma
) -1);
899 /* If this is the first time we've processed this symbol,
900 fill in the plt entry with the correct symbol address. */
901 if ((*plt_offset
& 1) == 0)
905 x
= 0x00000200; /* jmpf */
906 x
|= relocation
& 0xff;
907 x
|= (relocation
<< 8) & 0xffff0000;
908 bfd_put_32 (input_bfd
, x
, splt
->contents
+ *plt_offset
);
912 relocation
= (splt
->output_section
->vma
913 + splt
->output_offset
914 + (*plt_offset
& -2));
916 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
917 contents
, rel
->r_offset
,
923 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
924 contents
, rel
->r_offset
,
925 relocation
, rel
->r_addend
);
929 if (r
!= bfd_reloc_ok
)
931 const char * msg
= (const char *) NULL
;
935 case bfd_reloc_overflow
:
936 r
= info
->callbacks
->reloc_overflow
937 (info
, name
, howto
->name
, (bfd_vma
) 0,
938 input_bfd
, input_section
, rel
->r_offset
);
941 case bfd_reloc_undefined
:
942 r
= info
->callbacks
->undefined_symbol
943 (info
, name
, input_bfd
, input_section
, rel
->r_offset
,
947 case bfd_reloc_outofrange
:
948 msg
= _("internal error: out of range error");
951 case bfd_reloc_notsupported
:
952 msg
= _("internal error: unsupported relocation error");
955 case bfd_reloc_dangerous
:
956 msg
= _("internal error: dangerous relocation");
960 msg
= _("internal error: unknown error");
965 r
= info
->callbacks
->warning
966 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
976 /* This must exist if dynobj is ever set. */
979 xstormy16_elf_finish_dynamic_sections (abfd
, info
)
980 bfd
*abfd ATTRIBUTE_UNUSED
;
981 struct bfd_link_info
*info
;
986 /* As an extra sanity check, verify that all plt entries have
989 if ((dynobj
= elf_hash_table (info
)->dynobj
) != NULL
990 && (splt
= bfd_get_section_by_name (dynobj
, ".plt")) != NULL
)
992 bfd_byte
*contents
= splt
->contents
;
993 unsigned int i
, size
= splt
->size
;
994 for (i
= 0; i
< size
; i
+= 4)
996 unsigned int x
= bfd_get_32 (dynobj
, contents
+ i
);
1004 /* Return the section that should be marked against GC for a given
1008 xstormy16_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
)
1010 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
1011 Elf_Internal_Rela
* rel
;
1012 struct elf_link_hash_entry
* h
;
1013 Elf_Internal_Sym
* sym
;
1017 switch (ELF32_R_TYPE (rel
->r_info
))
1019 case R_XSTORMY16_GNU_VTINHERIT
:
1020 case R_XSTORMY16_GNU_VTENTRY
:
1024 switch (h
->root
.type
)
1026 case bfd_link_hash_defined
:
1027 case bfd_link_hash_defweak
:
1028 return h
->root
.u
.def
.section
;
1030 case bfd_link_hash_common
:
1031 return h
->root
.u
.c
.p
->section
;
1039 return bfd_section_from_elf_index (sec
->owner
, sym
->st_shndx
);
1044 /* Update the got entry reference counts for the section being removed. */
1047 xstormy16_elf_gc_sweep_hook (abfd
, info
, sec
, relocs
)
1048 bfd
* abfd ATTRIBUTE_UNUSED
;
1049 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
1050 asection
* sec ATTRIBUTE_UNUSED
;
1051 const Elf_Internal_Rela
* relocs ATTRIBUTE_UNUSED
;
1056 #define ELF_ARCH bfd_arch_xstormy16
1057 #define ELF_MACHINE_CODE EM_XSTORMY16
1058 #define ELF_MAXPAGESIZE 0x100
1060 #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1061 #define TARGET_LITTLE_NAME "elf32-xstormy16"
1063 #define elf_info_to_howto_rel NULL
1064 #define elf_info_to_howto xstormy16_info_to_howto_rela
1065 #define elf_backend_relocate_section xstormy16_elf_relocate_section
1066 #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1067 #define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
1068 #define elf_backend_check_relocs xstormy16_elf_check_relocs
1069 #define elf_backend_always_size_sections \
1070 xstormy16_elf_always_size_sections
1071 #define elf_backend_finish_dynamic_sections \
1072 xstormy16_elf_finish_dynamic_sections
1074 #define elf_backend_can_gc_sections 1
1075 #define elf_backend_rela_normal 1
1077 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1078 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1080 #include "elf32-target.h"