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
;
377 if (output_bfd
!= NULL
)
379 reloc_entry
->address
+= input_section
->output_offset
;
383 sz
= input_section
->rawsize
? input_section
->rawsize
: input_section
->size
;
384 if (reloc_entry
->address
> sz
)
385 return bfd_reloc_outofrange
;
387 if (bfd_is_com_section (symbol
->section
))
390 relocation
= symbol
->value
;
392 relocation
+= symbol
->section
->output_section
->vma
;
393 relocation
+= symbol
->section
->output_offset
;
394 relocation
+= reloc_entry
->addend
;
396 x
= bfd_get_32 (abfd
, (bfd_byte
*) data
+ reloc_entry
->address
);
398 x
|= relocation
& 0xff;
399 x
|= (relocation
<< 8) & 0xffff0000;
400 bfd_put_32 (abfd
, x
, (bfd_byte
*) data
+ reloc_entry
->address
);
402 if (relocation
& ~ (bfd_vma
) 0xffffff)
403 return bfd_reloc_overflow
;
408 /* We support 16-bit pointers to code above 64k by generating a thunk
409 below 64k containing a JMPF instruction to the final address. We
410 cannot, unfortunately, minimize the number of thunks unless the
411 -relax switch is given, as otherwise we have no idea where the
412 sections will fall in the address space. */
415 xstormy16_elf_check_relocs (abfd
, info
, sec
, relocs
)
417 struct bfd_link_info
*info
;
419 const Elf_Internal_Rela
*relocs
;
421 const Elf_Internal_Rela
*rel
, *relend
;
422 struct elf_link_hash_entry
**sym_hashes
;
423 Elf_Internal_Shdr
*symtab_hdr
;
424 bfd_vma
*local_plt_offsets
;
428 if (info
->relocatable
)
431 symtab_hdr
= &elf_tdata(abfd
)->symtab_hdr
;
432 sym_hashes
= elf_sym_hashes (abfd
);
433 local_plt_offsets
= elf_local_got_offsets (abfd
);
435 dynobj
= elf_hash_table(info
)->dynobj
;
437 relend
= relocs
+ sec
->reloc_count
;
438 for (rel
= relocs
; rel
< relend
; ++rel
)
440 unsigned long r_symndx
;
441 struct elf_link_hash_entry
*h
;
444 r_symndx
= ELF32_R_SYM (rel
->r_info
);
445 if (r_symndx
< symtab_hdr
->sh_info
)
449 h
= sym_hashes
[r_symndx
- symtab_hdr
->sh_info
];
450 while (h
->root
.type
== bfd_link_hash_indirect
451 || h
->root
.type
== bfd_link_hash_warning
)
452 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
455 switch (ELF32_R_TYPE (rel
->r_info
))
457 /* This relocation describes a 16-bit pointer to a function.
458 We may need to allocate a thunk in low memory; reserve memory
460 case R_XSTORMY16_FPTR16
:
461 if (rel
->r_addend
!= 0)
463 (*info
->callbacks
->warning
)
464 (info
, _("non-zero addend in @fptr reloc"), 0,
469 elf_hash_table (info
)->dynobj
= dynobj
= abfd
;
472 splt
= bfd_get_section_by_name (dynobj
, ".plt");
475 splt
= bfd_make_section (dynobj
, ".plt");
477 || ! bfd_set_section_flags (dynobj
, splt
,
485 || ! bfd_set_section_alignment (dynobj
, splt
, 1))
491 offset
= &h
->plt
.offset
;
494 if (local_plt_offsets
== NULL
)
499 size
= symtab_hdr
->sh_info
* sizeof (bfd_vma
);
500 local_plt_offsets
= (bfd_vma
*) bfd_alloc (abfd
, size
);
501 if (local_plt_offsets
== NULL
)
503 elf_local_got_offsets (abfd
) = local_plt_offsets
;
505 for (i
= 0; i
< symtab_hdr
->sh_info
; i
++)
506 local_plt_offsets
[i
] = (bfd_vma
) -1;
508 offset
= &local_plt_offsets
[r_symndx
];
511 if (*offset
== (bfd_vma
) -1)
513 *offset
= splt
->size
;
518 /* This relocation describes the C++ object vtable hierarchy.
519 Reconstruct it for later use during GC. */
520 case R_XSTORMY16_GNU_VTINHERIT
:
521 if (!bfd_elf_gc_record_vtinherit (abfd
, sec
, h
, rel
->r_offset
))
525 /* This relocation describes which C++ vtable entries are actually
526 used. Record for later use during GC. */
527 case R_XSTORMY16_GNU_VTENTRY
:
528 if (!bfd_elf_gc_record_vtentry (abfd
, sec
, h
, rel
->r_addend
))
537 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
538 is within the low 64k, remove any entry for it in the plt. */
540 struct relax_plt_data
547 xstormy16_relax_plt_check (h
, xdata
)
548 struct elf_link_hash_entry
*h
;
551 struct relax_plt_data
*data
= (struct relax_plt_data
*) xdata
;
553 if (h
->root
.type
== bfd_link_hash_warning
)
554 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
556 if (h
->plt
.offset
!= (bfd_vma
) -1)
560 if (h
->root
.type
== bfd_link_hash_undefined
561 || h
->root
.type
== bfd_link_hash_undefweak
)
564 address
= (h
->root
.u
.def
.section
->output_section
->vma
565 + h
->root
.u
.def
.section
->output_offset
566 + h
->root
.u
.def
.value
);
568 if (address
<= 0xffff)
571 data
->splt
->size
-= 4;
579 /* A subroutine of xstormy16_elf_relax_section. If the global symbol H
580 previously had a plt entry, give it a new entry offset. */
583 xstormy16_relax_plt_realloc (h
, xdata
)
584 struct elf_link_hash_entry
*h
;
587 bfd_vma
*entry
= (bfd_vma
*) xdata
;
589 if (h
->root
.type
== bfd_link_hash_warning
)
590 h
= (struct elf_link_hash_entry
*) h
->root
.u
.i
.link
;
592 if (h
->plt
.offset
!= (bfd_vma
) -1)
594 h
->plt
.offset
= *entry
;
602 xstormy16_elf_relax_section (dynobj
, splt
, info
, again
)
605 struct bfd_link_info
*info
;
608 struct relax_plt_data relax_plt_data
;
611 /* Assume nothing changes. */
614 if (info
->relocatable
)
617 /* We only relax the .plt section at the moment. */
618 if (dynobj
!= elf_hash_table (info
)->dynobj
619 || strcmp (splt
->name
, ".plt") != 0)
622 /* Quick check for an empty plt. */
626 /* Map across all global symbols; see which ones happen to
627 fall in the low 64k. */
628 relax_plt_data
.splt
= splt
;
629 relax_plt_data
.again
= again
;
630 elf_link_hash_traverse (elf_hash_table (info
), xstormy16_relax_plt_check
,
633 /* Likewise for local symbols, though that's somewhat less convenient
634 as we have to walk the list of input bfds and swap in symbol data. */
635 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
637 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
638 Elf_Internal_Shdr
*symtab_hdr
;
639 Elf_Internal_Sym
*isymbuf
= NULL
;
642 if (! local_plt_offsets
)
645 symtab_hdr
= &elf_tdata (ibfd
)->symtab_hdr
;
646 if (symtab_hdr
->sh_info
!= 0)
648 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
650 isymbuf
= bfd_elf_get_elf_syms (ibfd
, symtab_hdr
,
651 symtab_hdr
->sh_info
, 0,
657 for (idx
= 0; idx
< symtab_hdr
->sh_info
; ++idx
)
659 Elf_Internal_Sym
*isym
;
663 if (local_plt_offsets
[idx
] == (bfd_vma
) -1)
666 isym
= &isymbuf
[idx
];
667 if (isym
->st_shndx
== SHN_UNDEF
)
669 else if (isym
->st_shndx
== SHN_ABS
)
670 tsec
= bfd_abs_section_ptr
;
671 else if (isym
->st_shndx
== SHN_COMMON
)
672 tsec
= bfd_com_section_ptr
;
674 tsec
= bfd_section_from_elf_index (ibfd
, isym
->st_shndx
);
676 address
= (tsec
->output_section
->vma
677 + tsec
->output_offset
679 if (address
<= 0xffff)
681 local_plt_offsets
[idx
] = -1;
688 && symtab_hdr
->contents
!= (unsigned char *) isymbuf
)
690 if (! info
->keep_memory
)
694 /* Cache the symbols for elf_link_input_bfd. */
695 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
700 /* If we changed anything, walk the symbols again to reallocate
701 .plt entry addresses. */
702 if (*again
&& splt
->size
> 0)
706 elf_link_hash_traverse (elf_hash_table (info
),
707 xstormy16_relax_plt_realloc
, &entry
);
709 for (ibfd
= info
->input_bfds
; ibfd
; ibfd
= ibfd
->link_next
)
711 bfd_vma
*local_plt_offsets
= elf_local_got_offsets (ibfd
);
712 unsigned int nlocals
= elf_tdata (ibfd
)->symtab_hdr
.sh_info
;
715 if (! local_plt_offsets
)
718 for (idx
= 0; idx
< nlocals
; ++idx
)
719 if (local_plt_offsets
[idx
] != (bfd_vma
) -1)
721 local_plt_offsets
[idx
] = entry
;
731 xstormy16_elf_always_size_sections (output_bfd
, info
)
732 bfd
*output_bfd ATTRIBUTE_UNUSED
;
733 struct bfd_link_info
*info
;
738 if (info
->relocatable
)
741 dynobj
= elf_hash_table (info
)->dynobj
;
745 splt
= bfd_get_section_by_name (dynobj
, ".plt");
746 BFD_ASSERT (splt
!= NULL
);
748 splt
->contents
= (bfd_byte
*) bfd_zalloc (dynobj
, splt
->size
);
749 if (splt
->contents
== NULL
)
755 /* Relocate an XSTORMY16 ELF section.
757 The RELOCATE_SECTION function is called by the new ELF backend linker
758 to handle the relocations for a section.
760 The relocs are always passed as Rela structures; if the section
761 actually uses Rel structures, the r_addend field will always be
764 This function is responsible for adjusting the section contents as
765 necessary, and (if using Rela relocs and generating a relocatable
766 output file) adjusting the reloc addend as necessary.
768 This function does not have to worry about setting the reloc
769 address or the reloc symbol index.
771 LOCAL_SYMS is a pointer to the swapped in local symbols.
773 LOCAL_SECTIONS is an array giving the section in the input file
774 corresponding to the st_shndx field of each local symbol.
776 The global hash table entry for the global symbols can be found
777 via elf_sym_hashes (input_bfd).
779 When generating relocatable output, this function must handle
780 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
781 going to be the section symbol corresponding to the output
782 section, which means that the addend must be adjusted
786 xstormy16_elf_relocate_section (output_bfd
, info
, input_bfd
, input_section
,
787 contents
, relocs
, local_syms
, local_sections
)
788 bfd
* output_bfd ATTRIBUTE_UNUSED
;
789 struct bfd_link_info
* info
;
791 asection
* input_section
;
793 Elf_Internal_Rela
* relocs
;
794 Elf_Internal_Sym
* local_syms
;
795 asection
** local_sections
;
797 Elf_Internal_Shdr
* symtab_hdr
;
798 struct elf_link_hash_entry
** sym_hashes
;
799 Elf_Internal_Rela
* rel
;
800 Elf_Internal_Rela
* relend
;
804 if (info
->relocatable
)
807 symtab_hdr
= & elf_tdata (input_bfd
)->symtab_hdr
;
808 sym_hashes
= elf_sym_hashes (input_bfd
);
809 relend
= relocs
+ input_section
->reloc_count
;
811 dynobj
= elf_hash_table (info
)->dynobj
;
814 splt
= bfd_get_section_by_name (dynobj
, ".plt");
816 for (rel
= relocs
; rel
< relend
; rel
++)
818 reloc_howto_type
* howto
;
819 unsigned long r_symndx
;
820 Elf_Internal_Sym
* sym
;
822 struct elf_link_hash_entry
* h
;
824 bfd_reloc_status_type r
;
825 const char * name
= NULL
;
828 r_type
= ELF32_R_TYPE (rel
->r_info
);
830 if ( r_type
== R_XSTORMY16_GNU_VTINHERIT
831 || r_type
== R_XSTORMY16_GNU_VTENTRY
)
834 r_symndx
= ELF32_R_SYM (rel
->r_info
);
835 howto
= xstormy16_elf_howto_table
+ ELF32_R_TYPE (rel
->r_info
);
840 if (r_symndx
< symtab_hdr
->sh_info
)
842 sym
= local_syms
+ r_symndx
;
843 sec
= local_sections
[r_symndx
];
844 relocation
= _bfd_elf_rela_local_sym (output_bfd
, sym
, &sec
, rel
);
846 name
= bfd_elf_string_from_elf_section
847 (input_bfd
, symtab_hdr
->sh_link
, sym
->st_name
);
848 name
= (name
== NULL
) ? bfd_section_name (input_bfd
, sec
) : name
;
852 bfd_boolean unresolved_reloc
, warned
;
854 RELOC_FOR_GLOBAL_SYMBOL (info
, input_bfd
, input_section
, rel
,
855 r_symndx
, symtab_hdr
, sym_hashes
,
857 unresolved_reloc
, warned
);
860 switch (ELF32_R_TYPE (rel
->r_info
))
864 bfd_vma reloc
= relocation
+ rel
->r_addend
;
867 x
= bfd_get_32 (input_bfd
, contents
+ rel
->r_offset
);
870 x
|= (reloc
<< 8) & 0xffff0000;
871 bfd_put_32 (input_bfd
, x
, contents
+ rel
->r_offset
);
873 if (reloc
& ~0xffffff)
874 r
= bfd_reloc_overflow
;
880 case R_XSTORMY16_FPTR16
:
885 plt_offset
= &h
->plt
.offset
;
887 plt_offset
= elf_local_got_offsets (input_bfd
) + r_symndx
;
889 if (relocation
<= 0xffff)
891 /* If the symbol is in range for a 16-bit address, we should
892 have deallocated the plt entry in relax_section. */
893 BFD_ASSERT (*plt_offset
== (bfd_vma
) -1);
897 /* If the symbol is out of range for a 16-bit address,
898 we must have allocated a plt entry. */
899 BFD_ASSERT (*plt_offset
!= (bfd_vma
) -1);
901 /* If this is the first time we've processed this symbol,
902 fill in the plt entry with the correct symbol address. */
903 if ((*plt_offset
& 1) == 0)
907 x
= 0x00000200; /* jmpf */
908 x
|= relocation
& 0xff;
909 x
|= (relocation
<< 8) & 0xffff0000;
910 bfd_put_32 (input_bfd
, x
, splt
->contents
+ *plt_offset
);
914 relocation
= (splt
->output_section
->vma
915 + splt
->output_offset
916 + (*plt_offset
& -2));
918 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
919 contents
, rel
->r_offset
,
925 r
= _bfd_final_link_relocate (howto
, input_bfd
, input_section
,
926 contents
, rel
->r_offset
,
927 relocation
, rel
->r_addend
);
931 if (r
!= bfd_reloc_ok
)
933 const char * msg
= (const char *) NULL
;
937 case bfd_reloc_overflow
:
938 r
= info
->callbacks
->reloc_overflow
939 (info
, name
, howto
->name
, (bfd_vma
) 0,
940 input_bfd
, input_section
, rel
->r_offset
);
943 case bfd_reloc_undefined
:
944 r
= info
->callbacks
->undefined_symbol
945 (info
, name
, input_bfd
, input_section
, rel
->r_offset
,
949 case bfd_reloc_outofrange
:
950 msg
= _("internal error: out of range error");
953 case bfd_reloc_notsupported
:
954 msg
= _("internal error: unsupported relocation error");
957 case bfd_reloc_dangerous
:
958 msg
= _("internal error: dangerous relocation");
962 msg
= _("internal error: unknown error");
967 r
= info
->callbacks
->warning
968 (info
, msg
, name
, input_bfd
, input_section
, rel
->r_offset
);
978 /* This must exist if dynobj is ever set. */
981 xstormy16_elf_finish_dynamic_sections (abfd
, info
)
982 bfd
*abfd ATTRIBUTE_UNUSED
;
983 struct bfd_link_info
*info
;
988 /* As an extra sanity check, verify that all plt entries have
991 if ((dynobj
= elf_hash_table (info
)->dynobj
) != NULL
992 && (splt
= bfd_get_section_by_name (dynobj
, ".plt")) != NULL
)
994 bfd_byte
*contents
= splt
->contents
;
995 unsigned int i
, size
= splt
->size
;
996 for (i
= 0; i
< size
; i
+= 4)
998 unsigned int x
= bfd_get_32 (dynobj
, contents
+ i
);
1006 /* Return the section that should be marked against GC for a given
1010 xstormy16_elf_gc_mark_hook (sec
, info
, rel
, h
, sym
)
1012 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
1013 Elf_Internal_Rela
* rel
;
1014 struct elf_link_hash_entry
* h
;
1015 Elf_Internal_Sym
* sym
;
1019 switch (ELF32_R_TYPE (rel
->r_info
))
1021 case R_XSTORMY16_GNU_VTINHERIT
:
1022 case R_XSTORMY16_GNU_VTENTRY
:
1026 switch (h
->root
.type
)
1028 case bfd_link_hash_defined
:
1029 case bfd_link_hash_defweak
:
1030 return h
->root
.u
.def
.section
;
1032 case bfd_link_hash_common
:
1033 return h
->root
.u
.c
.p
->section
;
1041 return bfd_section_from_elf_index (sec
->owner
, sym
->st_shndx
);
1046 /* Update the got entry reference counts for the section being removed. */
1049 xstormy16_elf_gc_sweep_hook (abfd
, info
, sec
, relocs
)
1050 bfd
* abfd ATTRIBUTE_UNUSED
;
1051 struct bfd_link_info
* info ATTRIBUTE_UNUSED
;
1052 asection
* sec ATTRIBUTE_UNUSED
;
1053 const Elf_Internal_Rela
* relocs ATTRIBUTE_UNUSED
;
1058 #define ELF_ARCH bfd_arch_xstormy16
1059 #define ELF_MACHINE_CODE EM_XSTORMY16
1060 #define ELF_MAXPAGESIZE 0x100
1062 #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1063 #define TARGET_LITTLE_NAME "elf32-xstormy16"
1065 #define elf_info_to_howto_rel NULL
1066 #define elf_info_to_howto xstormy16_info_to_howto_rela
1067 #define elf_backend_relocate_section xstormy16_elf_relocate_section
1068 #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1069 #define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
1070 #define elf_backend_check_relocs xstormy16_elf_check_relocs
1071 #define elf_backend_always_size_sections \
1072 xstormy16_elf_always_size_sections
1073 #define elf_backend_finish_dynamic_sections \
1074 xstormy16_elf_finish_dynamic_sections
1076 #define elf_backend_can_gc_sections 1
1077 #define elf_backend_rela_normal 1
1079 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1080 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1082 #include "elf32-target.h"