2002-12-23 Nathanael Nerode <neroden@gcc.gnu.org>
[deliverable/binutils-gdb.git] / bfd / elf32-xstormy16.c
CommitLineData
93fbbb04 1/* XSTORMY16-specific support for 32-bit ELF.
b34976b6 2 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
93fbbb04
GK
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "bfd.h"
21#include "sysdep.h"
22#include "libbfd.h"
23#include "elf-bfd.h"
24#include "elf/xstormy16.h"
1f7fd478 25#include "libiberty.h"
93fbbb04
GK
26
27/* Forward declarations. */
28static reloc_howto_type * xstormy16_reloc_type_lookup
29 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
cedb70c5 30static void xstormy16_info_to_howto_rela
947216bf 31 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
cedb70c5 32static bfd_reloc_status_type xstormy16_elf_24_reloc
93fbbb04
GK
33 PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol,
34 PTR data, asection *input_section, bfd *output_bfd,
35 char **error_message));
b34976b6 36static bfd_boolean xstormy16_elf_check_relocs
93fbbb04
GK
37 PARAMS ((bfd *, struct bfd_link_info *, asection *,
38 const Elf_Internal_Rela *));
b34976b6 39static bfd_boolean xstormy16_relax_plt_check
93fbbb04 40 PARAMS ((struct elf_link_hash_entry *, PTR));
b34976b6 41static bfd_boolean xstormy16_relax_plt_realloc
93fbbb04 42 PARAMS ((struct elf_link_hash_entry *, PTR));
b34976b6 43static bfd_boolean xstormy16_elf_relax_section
93fbbb04 44 PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
b34976b6
AM
45 bfd_boolean *again));
46static bfd_boolean xstormy16_elf_always_size_sections
93fbbb04 47 PARAMS ((bfd *, struct bfd_link_info *));
b34976b6 48static bfd_boolean xstormy16_elf_relocate_section
93fbbb04
GK
49 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
b34976b6 51static bfd_boolean xstormy16_elf_finish_dynamic_sections
93fbbb04 52 PARAMS((bfd *, struct bfd_link_info *));
b34976b6 53static bfd_boolean xstormy16_elf_gc_sweep_hook
93fbbb04
GK
54 PARAMS ((bfd *, struct bfd_link_info *, asection *,
55 const Elf_Internal_Rela *));
56static asection * xstormy16_elf_gc_mark_hook
1e2f5b6e 57 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
93fbbb04
GK
58 struct elf_link_hash_entry *, Elf_Internal_Sym *));
59
60static reloc_howto_type xstormy16_elf_howto_table [] =
61{
62 /* This reloc does nothing. */
63 HOWTO (R_XSTORMY16_NONE, /* type */
64 0, /* rightshift */
65 2, /* size (0 = byte, 1 = short, 2 = long) */
66 32, /* bitsize */
b34976b6 67 FALSE, /* pc_relative */
93fbbb04
GK
68 0, /* bitpos */
69 complain_overflow_bitfield, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_XSTORMY16_NONE", /* name */
b34976b6 72 FALSE, /* partial_inplace */
93fbbb04
GK
73 0, /* src_mask */
74 0, /* dst_mask */
b34976b6 75 FALSE), /* pcrel_offset */
93fbbb04
GK
76
77 /* A 32 bit absolute relocation. */
78 HOWTO (R_XSTORMY16_32, /* type */
79 0, /* rightshift */
80 2, /* size (0 = byte, 1 = short, 2 = long) */
81 32, /* bitsize */
b34976b6 82 FALSE, /* pc_relative */
93fbbb04
GK
83 0, /* bitpos */
84 complain_overflow_dont, /* complain_on_overflow */
85 bfd_elf_generic_reloc, /* special_function */
86 "R_XSTORMY16_32", /* name */
b34976b6 87 FALSE, /* partial_inplace */
93fbbb04
GK
88 0, /* src_mask */
89 0xffffffff, /* dst_mask */
b34976b6 90 FALSE), /* pcrel_offset */
cedb70c5 91
93fbbb04
GK
92 /* A 16 bit absolute relocation. */
93 HOWTO (R_XSTORMY16_16, /* type */
94 0, /* rightshift */
95 1, /* size (0 = byte, 1 = short, 2 = long) */
96 16, /* bitsize */
b34976b6 97 FALSE, /* pc_relative */
93fbbb04
GK
98 0, /* bitpos */
99 complain_overflow_bitfield, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_XSTORMY16_16", /* name */
b34976b6 102 FALSE, /* partial_inplace */
93fbbb04
GK
103 0, /* src_mask */
104 0xffffffff, /* dst_mask */
b34976b6 105 FALSE), /* pcrel_offset */
cedb70c5 106
93fbbb04
GK
107 /* An 8 bit absolute relocation. */
108 HOWTO (R_XSTORMY16_8, /* type */
109 0, /* rightshift */
110 0, /* size (0 = byte, 1 = short, 2 = long) */
111 8, /* bitsize */
b34976b6 112 FALSE, /* pc_relative */
93fbbb04
GK
113 0, /* bitpos */
114 complain_overflow_bitfield, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_XSTORMY16_8", /* name */
b34976b6 117 FALSE, /* partial_inplace */
93fbbb04
GK
118 0, /* src_mask */
119 0xffffffff, /* dst_mask */
b34976b6 120 FALSE), /* pcrel_offset */
cedb70c5 121
93fbbb04
GK
122 /* A 32 bit pc-relative relocation. */
123 HOWTO (R_XSTORMY16_PC32, /* type */
124 0, /* rightshift */
125 2, /* size (0 = byte, 1 = short, 2 = long) */
126 32, /* bitsize */
b34976b6 127 TRUE, /* pc_relative */
93fbbb04
GK
128 0, /* bitpos */
129 complain_overflow_dont, /* complain_on_overflow */
130 bfd_elf_generic_reloc, /* special_function */
131 "R_XSTORMY16_PC32", /* name */
b34976b6 132 FALSE, /* partial_inplace */
93fbbb04
GK
133 0, /* src_mask */
134 0xffffffff, /* dst_mask */
b34976b6 135 TRUE), /* pcrel_offset */
cedb70c5 136
93fbbb04
GK
137 /* A 16 bit pc-relative relocation. */
138 HOWTO (R_XSTORMY16_PC16, /* type */
139 0, /* rightshift */
140 1, /* size (0 = byte, 1 = short, 2 = long) */
141 16, /* bitsize */
b34976b6 142 TRUE, /* pc_relative */
93fbbb04
GK
143 0, /* bitpos */
144 complain_overflow_signed, /* complain_on_overflow */
145 bfd_elf_generic_reloc, /* special_function */
146 "R_XSTORMY16_PC16", /* name */
b34976b6 147 FALSE, /* partial_inplace */
93fbbb04
GK
148 0, /* src_mask */
149 0xffffffff, /* dst_mask */
b34976b6 150 TRUE), /* pcrel_offset */
cedb70c5 151
93fbbb04
GK
152 /* An 8 bit pc-relative relocation. */
153 HOWTO (R_XSTORMY16_PC8, /* type */
154 0, /* rightshift */
155 0, /* size (0 = byte, 1 = short, 2 = long) */
156 8, /* bitsize */
b34976b6 157 TRUE, /* pc_relative */
93fbbb04
GK
158 0, /* bitpos */
159 complain_overflow_signed, /* complain_on_overflow */
160 bfd_elf_generic_reloc, /* special_function */
161 "R_XSTORMY16_PC8", /* name */
b34976b6 162 FALSE, /* partial_inplace */
93fbbb04
GK
163 0, /* src_mask */
164 0xffffffff, /* dst_mask */
b34976b6 165 TRUE), /* pcrel_offset */
cedb70c5 166
93fbbb04
GK
167 /* A 12-bit pc-relative relocation suitable for the branch instructions. */
168 HOWTO (R_XSTORMY16_REL_12, /* type */
169 1, /* rightshift */
170 1, /* size (0 = byte, 1 = short, 2 = long) */
171 11, /* bitsize */
b34976b6 172 TRUE, /* pc_relative */
93fbbb04
GK
173 1, /* bitpos */
174 complain_overflow_signed, /* complain_on_overflow */
175 bfd_elf_generic_reloc, /* special_function */
176 "R_XSTORMY16_REL_12", /* name */
b34976b6 177 TRUE, /* partial_inplace */
93fbbb04
GK
178 0, /* src_mask */
179 0x0fff, /* dst_mask */
b34976b6 180 TRUE), /* pcrel_offset */
cedb70c5 181
93fbbb04
GK
182 /* A 24-bit absolute relocation suitable for the jump instructions. */
183 HOWTO (R_XSTORMY16_24, /* type */
184 0, /* rightshift */
185 2, /* size (0 = byte, 1 = short, 2 = long) */
186 24, /* bitsize */
b34976b6 187 FALSE, /* pc_relative */
93fbbb04
GK
188 0, /* bitpos */
189 complain_overflow_unsigned, /* complain_on_overflow */
190 xstormy16_elf_24_reloc, /* special_function */
191 "R_XSTORMY16_24", /* name */
b34976b6 192 TRUE, /* partial_inplace */
93fbbb04
GK
193 0, /* src_mask */
194 0xffff00ff, /* dst_mask */
b34976b6 195 TRUE), /* pcrel_offset */
cedb70c5 196
93fbbb04
GK
197 /* A 16 bit absolute relocation to a function pointer. */
198 HOWTO (R_XSTORMY16_FPTR16, /* type */
199 0, /* rightshift */
200 1, /* size (0 = byte, 1 = short, 2 = long) */
201 16, /* bitsize */
b34976b6 202 FALSE, /* pc_relative */
93fbbb04
GK
203 0, /* bitpos */
204 complain_overflow_bitfield, /* complain_on_overflow */
205 bfd_elf_generic_reloc, /* special_function */
206 "R_XSTORMY16_FPTR16", /* name */
b34976b6 207 FALSE, /* partial_inplace */
93fbbb04
GK
208 0, /* src_mask */
209 0xffffffff, /* dst_mask */
b34976b6 210 FALSE), /* pcrel_offset */
46f2b541
DD
211
212 /* Low order 16 bit value of a high memory address. */
213 HOWTO (R_XSTORMY16_LO16, /* type */
214 0, /* rightshift */
215 1, /* size (0 = byte, 1 = short, 2 = long) */
216 16, /* bitsize */
217 FALSE, /* pc_relative */
218 0, /* bitpos */
219 complain_overflow_dont, /* complain_on_overflow */
220 bfd_elf_generic_reloc, /* special_function */
221 "R_XSTORMY16_LO16", /* name */
222 FALSE, /* partial_inplace */
223 0, /* src_mask */
224 0xffff, /* dst_mask */
225 FALSE), /* pcrel_offset */
226
227 /* High order 16 bit value of a high memory address. */
228 HOWTO (R_XSTORMY16_HI16, /* type */
229 16, /* rightshift */
230 1, /* size (0 = byte, 1 = short, 2 = long) */
231 16, /* bitsize */
232 FALSE, /* pc_relative */
233 0, /* bitpos */
234 complain_overflow_dont, /* complain_on_overflow */
235 bfd_elf_generic_reloc, /* special_function */
236 "R_XSTORMY16_HI16", /* name */
237 FALSE, /* partial_inplace */
238 0, /* src_mask */
239 0xffff, /* dst_mask */
240 FALSE), /* pcrel_offset */
5fd63999
DD
241
242 /* A 12 bit absolute relocation. */
243 HOWTO (R_XSTORMY16_12, /* type */
244 0, /* rightshift */
245 1, /* size (0 = byte, 1 = short, 2 = long) */
246 12, /* bitsize */
247 FALSE, /* pc_relative */
248 0, /* bitpos */
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 */
93fbbb04 256};
cedb70c5 257
93fbbb04
GK
258static reloc_howto_type xstormy16_elf_howto_table2 [] =
259{
260 /* GNU extension to record C++ vtable hierarchy */
261 HOWTO (R_XSTORMY16_GNU_VTINHERIT, /* type */
262 0, /* rightshift */
263 2, /* size (0 = byte, 1 = short, 2 = long) */
264 0, /* bitsize */
b34976b6 265 FALSE, /* pc_relative */
93fbbb04
GK
266 0, /* bitpos */
267 complain_overflow_dont, /* complain_on_overflow */
268 NULL, /* special_function */
269 "R_XSTORMY16_GNU_VTINHERIT", /* name */
b34976b6 270 FALSE, /* partial_inplace */
93fbbb04
GK
271 0, /* src_mask */
272 0, /* dst_mask */
b34976b6 273 FALSE), /* pcrel_offset */
93fbbb04
GK
274
275 /* GNU extension to record C++ vtable member usage */
276 HOWTO (R_XSTORMY16_GNU_VTENTRY, /* type */
277 0, /* rightshift */
278 2, /* size (0 = byte, 1 = short, 2 = long) */
279 0, /* bitsize */
b34976b6 280 FALSE, /* pc_relative */
93fbbb04
GK
281 0, /* bitpos */
282 complain_overflow_dont, /* complain_on_overflow */
283 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
284 "R_XSTORMY16_GNU_VTENTRY", /* name */
b34976b6 285 FALSE, /* partial_inplace */
93fbbb04
GK
286 0, /* src_mask */
287 0, /* dst_mask */
b34976b6 288 FALSE), /* pcrel_offset */
cedb70c5 289
93fbbb04
GK
290};
291\f
292/* Map BFD reloc types to XSTORMY16 ELF reloc types. */
293
1f7fd478 294typedef struct xstormy16_reloc_map
93fbbb04 295{
1f7fd478
NC
296 bfd_reloc_code_real_type bfd_reloc_val;
297 unsigned int xstormy16_reloc_val;
298 reloc_howto_type * table;
299} reloc_map;
93fbbb04 300
1f7fd478 301static const reloc_map xstormy16_reloc_map [] =
93fbbb04 302{
1f7fd478
NC
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 },
46f2b541
DD
313 { BFD_RELOC_LO16, R_XSTORMY16_LO16, xstormy16_elf_howto_table },
314 { BFD_RELOC_HI16, R_XSTORMY16_HI16, xstormy16_elf_howto_table },
5fd63999 315 { BFD_RELOC_XSTORMY16_12, R_XSTORMY16_12, xstormy16_elf_howto_table },
1f7fd478
NC
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 },
93fbbb04
GK
318};
319
320static reloc_howto_type *
321xstormy16_reloc_type_lookup (abfd, code)
322 bfd * abfd ATTRIBUTE_UNUSED;
323 bfd_reloc_code_real_type code;
324{
325 unsigned int i;
326
1f7fd478
NC
327 for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
328 {
329 const reloc_map * entry;
330
331 entry = xstormy16_reloc_map + i;
332
333 if (entry->bfd_reloc_val == code)
334 return entry->table + (entry->xstormy16_reloc_val
335 - entry->table[0].type);
336 }
cedb70c5 337
93fbbb04
GK
338 return NULL;
339}
340
341/* Set the howto pointer for an XSTORMY16 ELF reloc. */
342
343static void
344xstormy16_info_to_howto_rela (abfd, cache_ptr, dst)
345 bfd * abfd ATTRIBUTE_UNUSED;
346 arelent * cache_ptr;
947216bf 347 Elf_Internal_Rela * dst;
93fbbb04
GK
348{
349 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
350
5fd63999 351 if (r_type <= (unsigned int) R_XSTORMY16_12)
93fbbb04
GK
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)
355 cache_ptr->howto
356 = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
357 else
358 abort ();
359}
360
361/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */
362
363static bfd_reloc_status_type
364xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section,
365 output_bfd, error_message)
366 bfd *abfd;
367 arelent *reloc_entry;
368 asymbol *symbol;
369 PTR data;
370 asection *input_section;
371 bfd *output_bfd;
372 char **error_message ATTRIBUTE_UNUSED;
373{
374 bfd_vma relocation, x;
375
376 if (output_bfd != NULL)
377 {
378 reloc_entry->address += input_section->output_offset;
379 return bfd_reloc_ok;
380 }
381
382 if (reloc_entry->address > input_section->_cooked_size)
383 return bfd_reloc_outofrange;
384
385 if (bfd_is_com_section (symbol->section))
386 relocation = 0;
387 else
388 relocation = symbol->value;
389
390 relocation += symbol->section->output_section->vma;
391 relocation += symbol->section->output_offset;
392 relocation += reloc_entry->addend;
393
394 x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
395 x &= 0x0000ff00;
396 x |= relocation & 0xff;
397 x |= (relocation << 8) & 0xffff0000;
398 bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
399
400 if (relocation & ~ (bfd_vma) 0xffffff)
401 return bfd_reloc_overflow;
402
403 return bfd_reloc_ok;
404}
405\f
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. */
411
b34976b6 412static bfd_boolean
93fbbb04
GK
413xstormy16_elf_check_relocs (abfd, info, sec, relocs)
414 bfd *abfd;
415 struct bfd_link_info *info;
416 asection *sec;
417 const Elf_Internal_Rela *relocs;
418{
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;
423 asection *splt;
424 bfd *dynobj;
425
426 if (info->relocateable)
b34976b6 427 return TRUE;
93fbbb04
GK
428
429 symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
430 sym_hashes = elf_sym_hashes (abfd);
431 local_plt_offsets = elf_local_got_offsets (abfd);
432 splt = NULL;
433 dynobj = elf_hash_table(info)->dynobj;
434
435 relend = relocs + sec->reloc_count;
436 for (rel = relocs; rel < relend; ++rel)
437 {
438 unsigned long r_symndx;
439 struct elf_link_hash_entry *h;
440 bfd_vma *offset;
441
442 r_symndx = ELF32_R_SYM (rel->r_info);
443 if (r_symndx < symtab_hdr->sh_info)
444 h = NULL;
445 else
446 {
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;
451 }
452
453 switch (ELF32_R_TYPE (rel->r_info))
454 {
455 /* This relocation describes a 16-bit pointer to a function.
456 We may need to allocate a thunk in low memory; reserve memory
457 for it now. */
458 case R_XSTORMY16_FPTR16:
459 if (rel->r_addend != 0)
460 {
461 (*info->callbacks->warning)
462 (info, _("non-zero addend in @fptr reloc"), 0,
463 abfd, 0, 0);
464 }
465
466 if (dynobj == NULL)
467 elf_hash_table (info)->dynobj = dynobj = abfd;
468 if (splt == NULL)
469 {
470 splt = bfd_get_section_by_name (dynobj, ".plt");
471 if (splt == NULL)
472 {
473 splt = bfd_make_section (dynobj, ".plt");
474 if (splt == NULL
475 || ! bfd_set_section_flags (dynobj, splt,
476 (SEC_ALLOC
477 | SEC_LOAD
478 | SEC_HAS_CONTENTS
479 | SEC_IN_MEMORY
480 | SEC_LINKER_CREATED
481 | SEC_READONLY
482 | SEC_CODE))
483 || ! bfd_set_section_alignment (dynobj, splt, 1))
b34976b6 484 return FALSE;
93fbbb04
GK
485 }
486 }
487
488 if (h != NULL)
489 offset = &h->plt.offset;
490 else
491 {
492 if (local_plt_offsets == NULL)
493 {
494 size_t size;
495 unsigned int i;
496
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)
b34976b6 500 return FALSE;
93fbbb04 501 elf_local_got_offsets (abfd) = local_plt_offsets;
cedb70c5 502
93fbbb04
GK
503 for (i = 0; i < symtab_hdr->sh_info; i++)
504 local_plt_offsets[i] = (bfd_vma) -1;
505 }
506 offset = &local_plt_offsets[r_symndx];
507 }
508
509 if (*offset == (bfd_vma) -1)
510 {
511 *offset = splt->_raw_size;
512 splt->_raw_size += 4;
513 }
514 break;
515
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_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
b34976b6 520 return FALSE;
93fbbb04 521 break;
cedb70c5 522
93fbbb04
GK
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_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
b34976b6 527 return FALSE;
93fbbb04
GK
528 break;
529 }
530 }
531
b34976b6 532 return TRUE;
93fbbb04
GK
533}
534
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. */
537
538struct relax_plt_data
539{
540 asection *splt;
b34976b6 541 bfd_boolean *again;
93fbbb04
GK
542};
543
b34976b6 544static bfd_boolean
93fbbb04
GK
545xstormy16_relax_plt_check (h, xdata)
546 struct elf_link_hash_entry *h;
547 PTR xdata;
548{
549 struct relax_plt_data *data = (struct relax_plt_data *) xdata;
550
e92d460e
AM
551 if (h->root.type == bfd_link_hash_warning)
552 h = (struct elf_link_hash_entry *) h->root.u.i.link;
553
93fbbb04
GK
554 if (h->plt.offset != (bfd_vma) -1)
555 {
556 bfd_vma address;
557
558 if (h->root.type == bfd_link_hash_undefined
559 || h->root.type == bfd_link_hash_undefweak)
560 address = 0;
561 else
562 address = (h->root.u.def.section->output_section->vma
563 + h->root.u.def.section->output_offset
564 + h->root.u.def.value);
565
566 if (address <= 0xffff)
567 {
568 h->plt.offset = -1;
569 data->splt->_cooked_size -= 4;
b34976b6 570 *data->again = TRUE;
93fbbb04
GK
571 }
572 }
573
b34976b6 574 return TRUE;
93fbbb04
GK
575}
576
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. */
579
b34976b6 580static bfd_boolean
93fbbb04
GK
581xstormy16_relax_plt_realloc (h, xdata)
582 struct elf_link_hash_entry *h;
583 PTR xdata;
584{
585 bfd_vma *entry = (bfd_vma *) xdata;
586
e92d460e
AM
587 if (h->root.type == bfd_link_hash_warning)
588 h = (struct elf_link_hash_entry *) h->root.u.i.link;
589
93fbbb04
GK
590 if (h->plt.offset != (bfd_vma) -1)
591 {
592 h->plt.offset = *entry;
593 *entry += 4;
594 }
595
b34976b6 596 return TRUE;
93fbbb04
GK
597}
598
b34976b6 599static bfd_boolean
93fbbb04
GK
600xstormy16_elf_relax_section (dynobj, splt, info, again)
601 bfd *dynobj;
602 asection *splt;
603 struct bfd_link_info *info;
b34976b6 604 bfd_boolean *again;
93fbbb04
GK
605{
606 struct relax_plt_data relax_plt_data;
607 bfd *ibfd;
608
609 /* Assume nothing changes. */
b34976b6 610 *again = FALSE;
93fbbb04
GK
611
612 if (info->relocateable)
b34976b6 613 return TRUE;
93fbbb04
GK
614
615 /* We only relax the .plt section at the moment. */
616 if (dynobj != elf_hash_table (info)->dynobj
617 || strcmp (splt->name, ".plt") != 0)
b34976b6 618 return TRUE;
93fbbb04
GK
619
620 /* Quick check for an empty plt. */
621 if (splt->_raw_size == 0)
b34976b6 622 return TRUE;
93fbbb04
GK
623
624 /* If this is the first time we have been called for this section,
625 initialize the cooked size. */
626 if (splt->_cooked_size == 0)
627 splt->_cooked_size = splt->_raw_size;
628
cedb70c5 629 /* Map across all global symbols; see which ones happen to
93fbbb04
GK
630 fall in the low 64k. */
631 relax_plt_data.splt = splt;
632 relax_plt_data.again = again;
633 elf_link_hash_traverse (elf_hash_table (info), xstormy16_relax_plt_check,
634 &relax_plt_data);
635
636 /* Likewise for local symbols, though that's somewhat less convenient
6cdc0ccc 637 as we have to walk the list of input bfds and swap in symbol data. */
93fbbb04
GK
638 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
639 {
640 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
641 Elf_Internal_Shdr *symtab_hdr;
6cdc0ccc 642 Elf_Internal_Sym *isymbuf = NULL;
93fbbb04
GK
643 unsigned int idx;
644
645 if (! local_plt_offsets)
646 continue;
647
648 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
6cdc0ccc 649 if (symtab_hdr->sh_info != 0)
93fbbb04 650 {
6cdc0ccc
AM
651 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
652 if (isymbuf == NULL)
653 isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
654 symtab_hdr->sh_info, 0,
655 NULL, NULL, NULL);
656 if (isymbuf == NULL)
b34976b6 657 return FALSE;
9ad5cbcf
AM
658 }
659
93fbbb04
GK
660 for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
661 {
6cdc0ccc 662 Elf_Internal_Sym *isym;
93fbbb04
GK
663 asection *tsec;
664 bfd_vma address;
665
666 if (local_plt_offsets[idx] == (bfd_vma) -1)
667 continue;
668
6cdc0ccc
AM
669 isym = &isymbuf[idx];
670 if (isym->st_shndx == SHN_UNDEF)
93fbbb04 671 continue;
6cdc0ccc 672 else if (isym->st_shndx == SHN_ABS)
93fbbb04 673 tsec = bfd_abs_section_ptr;
6cdc0ccc 674 else if (isym->st_shndx == SHN_COMMON)
9ad5cbcf 675 tsec = bfd_com_section_ptr;
93fbbb04 676 else
6cdc0ccc 677 tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
93fbbb04
GK
678
679 address = (tsec->output_section->vma
680 + tsec->output_offset
6cdc0ccc 681 + isym->st_value);
93fbbb04
GK
682 if (address <= 0xffff)
683 {
684 local_plt_offsets[idx] = -1;
685 splt->_cooked_size -= 4;
b34976b6 686 *again = TRUE;
93fbbb04
GK
687 }
688 }
689
6cdc0ccc
AM
690 if (isymbuf != NULL
691 && symtab_hdr->contents != (unsigned char *) isymbuf)
692 {
693 if (! info->keep_memory)
694 free (isymbuf);
695 else
696 {
697 /* Cache the symbols for elf_link_input_bfd. */
698 symtab_hdr->contents = (unsigned char *) isymbuf;
699 }
700 }
93fbbb04
GK
701 }
702
703 /* If we changed anything, walk the symbols again to reallocate
704 .plt entry addresses. */
705 if (*again && splt->_cooked_size > 0)
706 {
707 bfd_vma entry = 0;
708
709 elf_link_hash_traverse (elf_hash_table (info),
710 xstormy16_relax_plt_realloc, &entry);
711
712 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
713 {
714 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
715 unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
716 unsigned int idx;
717
718 if (! local_plt_offsets)
719 continue;
720
721 for (idx = 0; idx < nlocals; ++idx)
722 if (local_plt_offsets[idx] != (bfd_vma) -1)
723 {
724 local_plt_offsets[idx] = entry;
725 entry += 4;
726 }
727 }
728 }
729
730 splt->_raw_size = splt->_cooked_size;
b34976b6 731 return TRUE;
93fbbb04
GK
732}
733
b34976b6 734static bfd_boolean
93fbbb04
GK
735xstormy16_elf_always_size_sections (output_bfd, info)
736 bfd *output_bfd ATTRIBUTE_UNUSED;
737 struct bfd_link_info *info;
738{
739 bfd *dynobj;
740 asection *splt;
741
742 if (info->relocateable)
b34976b6 743 return TRUE;
93fbbb04
GK
744
745 dynobj = elf_hash_table (info)->dynobj;
746 if (dynobj == NULL)
b34976b6 747 return TRUE;
93fbbb04
GK
748
749 splt = bfd_get_section_by_name (dynobj, ".plt");
750 BFD_ASSERT (splt != NULL);
751
752 splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->_raw_size);
753 if (splt->contents == NULL)
b34976b6 754 return FALSE;
93fbbb04 755
b34976b6 756 return TRUE;
93fbbb04
GK
757}
758\f
759/* Relocate an XSTORMY16 ELF section.
93fbbb04
GK
760
761 The RELOCATE_SECTION function is called by the new ELF backend linker
762 to handle the relocations for a section.
763
764 The relocs are always passed as Rela structures; if the section
765 actually uses Rel structures, the r_addend field will always be
766 zero.
767
768 This function is responsible for adjusting the section contents as
769 necessary, and (if using Rela relocs and generating a relocateable
770 output file) adjusting the reloc addend as necessary.
771
772 This function does not have to worry about setting the reloc
773 address or the reloc symbol index.
774
775 LOCAL_SYMS is a pointer to the swapped in local symbols.
776
777 LOCAL_SECTIONS is an array giving the section in the input file
778 corresponding to the st_shndx field of each local symbol.
779
780 The global hash table entry for the global symbols can be found
781 via elf_sym_hashes (input_bfd).
782
783 When generating relocateable output, this function must handle
784 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
785 going to be the section symbol corresponding to the output
786 section, which means that the addend must be adjusted
787 accordingly. */
788
b34976b6 789static bfd_boolean
93fbbb04
GK
790xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
791 contents, relocs, local_syms, local_sections)
792 bfd * output_bfd ATTRIBUTE_UNUSED;
793 struct bfd_link_info * info;
794 bfd * input_bfd;
795 asection * input_section;
796 bfd_byte * contents;
797 Elf_Internal_Rela * relocs;
798 Elf_Internal_Sym * local_syms;
799 asection ** local_sections;
800{
801 Elf_Internal_Shdr * symtab_hdr;
802 struct elf_link_hash_entry ** sym_hashes;
803 Elf_Internal_Rela * rel;
804 Elf_Internal_Rela * relend;
805 bfd *dynobj;
806 asection *splt;
807
b491616a 808 if (info->relocateable)
b34976b6 809 return TRUE;
b491616a 810
93fbbb04
GK
811 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
812 sym_hashes = elf_sym_hashes (input_bfd);
813 relend = relocs + input_section->reloc_count;
814
815 dynobj = elf_hash_table (info)->dynobj;
816 splt = NULL;
817 if (dynobj != NULL)
818 splt = bfd_get_section_by_name (dynobj, ".plt");
819
820 for (rel = relocs; rel < relend; rel ++)
821 {
822 reloc_howto_type * howto;
823 unsigned long r_symndx;
824 Elf_Internal_Sym * sym;
825 asection * sec;
826 struct elf_link_hash_entry * h;
827 bfd_vma relocation;
828 bfd_reloc_status_type r;
829 const char * name = NULL;
830 int r_type;
cedb70c5 831
93fbbb04 832 r_type = ELF32_R_TYPE (rel->r_info);
cedb70c5 833
93fbbb04
GK
834 if ( r_type == R_XSTORMY16_GNU_VTINHERIT
835 || r_type == R_XSTORMY16_GNU_VTENTRY)
836 continue;
cedb70c5 837
93fbbb04 838 r_symndx = ELF32_R_SYM (rel->r_info);
93fbbb04
GK
839 howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
840 h = NULL;
841 sym = NULL;
842 sec = NULL;
cedb70c5 843
93fbbb04
GK
844 if (r_symndx < symtab_hdr->sh_info)
845 {
846 sym = local_syms + r_symndx;
847 sec = local_sections [r_symndx];
848 relocation = (sec->output_section->vma
849 + sec->output_offset
850 + sym->st_value);
cedb70c5 851
93fbbb04
GK
852 name = bfd_elf_string_from_elf_section
853 (input_bfd, symtab_hdr->sh_link, sym->st_name);
854 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
855 }
856 else
857 {
858 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
cedb70c5 859
93fbbb04
GK
860 while (h->root.type == bfd_link_hash_indirect
861 || h->root.type == bfd_link_hash_warning)
862 h = (struct elf_link_hash_entry *) h->root.u.i.link;
863
864 name = h->root.root.string;
cedb70c5 865
93fbbb04
GK
866 if (h->root.type == bfd_link_hash_defined
867 || h->root.type == bfd_link_hash_defweak)
868 {
869 sec = h->root.u.def.section;
870 relocation = (h->root.u.def.value
871 + sec->output_section->vma
872 + sec->output_offset);
873 }
874 else if (h->root.type == bfd_link_hash_undefweak)
875 {
876 relocation = 0;
877 }
878 else
879 {
880 if (! ((*info->callbacks->undefined_symbol)
881 (info, h->root.root.string, input_bfd,
b34976b6
AM
882 input_section, rel->r_offset, TRUE)))
883 return FALSE;
93fbbb04
GK
884 relocation = 0;
885 }
886 }
cedb70c5 887
93fbbb04
GK
888 switch (ELF32_R_TYPE (rel->r_info))
889 {
890 case R_XSTORMY16_24:
891 {
892 bfd_vma reloc = relocation + rel->r_addend;
893 unsigned int x;
cedb70c5 894
93fbbb04
GK
895 x = bfd_get_32 (input_bfd, contents + rel->r_offset);
896 x &= 0x0000ff00;
897 x |= reloc & 0xff;
898 x |= (reloc << 8) & 0xffff0000;
899 bfd_put_32 (input_bfd, x, contents + rel->r_offset);
900
901 if (reloc & ~0xffffff)
902 r = bfd_reloc_overflow;
903 else
904 r = bfd_reloc_ok;
905 break;
906 }
907
908 case R_XSTORMY16_FPTR16:
909 {
910 bfd_vma *plt_offset;
911
912 if (h != NULL)
913 plt_offset = &h->plt.offset;
914 else
915 plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
916
917 if (relocation <= 0xffff)
918 {
919 /* If the symbol is in range for a 16-bit address, we should
920 have deallocated the plt entry in relax_section. */
921 BFD_ASSERT (*plt_offset == (bfd_vma) -1);
922 }
923 else
924 {
925 /* If the symbol is out of range for a 16-bit address,
926 we must have allocated a plt entry. */
927 BFD_ASSERT (*plt_offset != (bfd_vma) -1);
928
929 /* If this is the first time we've processed this symbol,
930 fill in the plt entry with the correct symbol address. */
931 if ((*plt_offset & 1) == 0)
932 {
933 unsigned int x;
934
935 x = 0x00000200; /* jmpf */
936 x |= relocation & 0xff;
937 x |= (relocation << 8) & 0xffff0000;
938 bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
939 *plt_offset |= 1;
940 }
941
942 relocation = (splt->output_section->vma
943 + splt->output_offset
944 + (*plt_offset & -2));
945 }
946 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
947 contents, rel->r_offset,
948 relocation, 0);
949 break;
950 }
951
952 default:
953 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
954 contents, rel->r_offset,
955 relocation, rel->r_addend);
956 break;
957 }
958
959 if (r != bfd_reloc_ok)
960 {
961 const char * msg = (const char *) NULL;
962
963 switch (r)
964 {
965 case bfd_reloc_overflow:
966 r = info->callbacks->reloc_overflow
967 (info, name, howto->name, (bfd_vma) 0,
968 input_bfd, input_section, rel->r_offset);
969 break;
cedb70c5 970
93fbbb04
GK
971 case bfd_reloc_undefined:
972 r = info->callbacks->undefined_symbol
973 (info, name, input_bfd, input_section, rel->r_offset,
b34976b6 974 TRUE);
93fbbb04 975 break;
cedb70c5 976
93fbbb04
GK
977 case bfd_reloc_outofrange:
978 msg = _("internal error: out of range error");
979 break;
980
981 case bfd_reloc_notsupported:
982 msg = _("internal error: unsupported relocation error");
983 break;
984
985 case bfd_reloc_dangerous:
986 msg = _("internal error: dangerous relocation");
987 break;
988
989 default:
990 msg = _("internal error: unknown error");
991 break;
992 }
993
994 if (msg)
995 r = info->callbacks->warning
996 (info, msg, name, input_bfd, input_section, rel->r_offset);
997
998 if (! r)
b34976b6 999 return FALSE;
93fbbb04
GK
1000 }
1001 }
1002
b34976b6 1003 return TRUE;
93fbbb04
GK
1004}
1005
1006/* This must exist if dynobj is ever set. */
1007
b34976b6 1008static bfd_boolean
93fbbb04
GK
1009xstormy16_elf_finish_dynamic_sections (abfd, info)
1010 bfd *abfd ATTRIBUTE_UNUSED;
1011 struct bfd_link_info *info;
1012{
1013 bfd *dynobj;
1014 asection *splt;
1015
1016 /* As an extra sanity check, verify that all plt entries have
1017 been filled in. */
1018
1019 if ((dynobj = elf_hash_table (info)->dynobj) != NULL
1020 && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
1021 {
1022 bfd_byte *contents = splt->contents;
1023 unsigned int i, size = splt->_raw_size;
1024 for (i = 0; i < size; i += 4)
1025 {
1026 unsigned int x = bfd_get_32 (dynobj, contents + i);
1027 BFD_ASSERT (x != 0);
1028 }
1029 }
1030
b34976b6 1031 return TRUE;
93fbbb04
GK
1032}
1033\f
1034/* Return the section that should be marked against GC for a given
1035 relocation. */
1036
1037static asection *
1e2f5b6e
AM
1038xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
1039 asection * sec;
93fbbb04
GK
1040 struct bfd_link_info * info ATTRIBUTE_UNUSED;
1041 Elf_Internal_Rela * rel;
1042 struct elf_link_hash_entry * h;
1043 Elf_Internal_Sym * sym;
1044{
1045 if (h != NULL)
1046 {
1047 switch (ELF32_R_TYPE (rel->r_info))
1048 {
1049 case R_XSTORMY16_GNU_VTINHERIT:
1050 case R_XSTORMY16_GNU_VTENTRY:
1051 break;
1052
1053 default:
1054 switch (h->root.type)
1055 {
1056 case bfd_link_hash_defined:
1057 case bfd_link_hash_defweak:
1058 return h->root.u.def.section;
1059
1060 case bfd_link_hash_common:
1061 return h->root.u.c.p->section;
1062
1063 default:
1064 break;
1065 }
1066 }
1067 }
1068 else
1e2f5b6e 1069 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
93fbbb04
GK
1070
1071 return NULL;
1072}
1073
1074/* Update the got entry reference counts for the section being removed. */
1075
b34976b6 1076static bfd_boolean
93fbbb04
GK
1077xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs)
1078 bfd * abfd ATTRIBUTE_UNUSED;
1079 struct bfd_link_info * info ATTRIBUTE_UNUSED;
1080 asection * sec ATTRIBUTE_UNUSED;
1081 const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
1082{
b34976b6 1083 return TRUE;
93fbbb04
GK
1084}
1085\f
1086#define ELF_ARCH bfd_arch_xstormy16
1087#define ELF_MACHINE_CODE EM_XSTORMY16
1088#define ELF_MAXPAGESIZE 0x100
1089
1090#define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1091#define TARGET_LITTLE_NAME "elf32-xstormy16"
1092
1093#define elf_info_to_howto_rel NULL
1094#define elf_info_to_howto xstormy16_info_to_howto_rela
1095#define elf_backend_relocate_section xstormy16_elf_relocate_section
1096#define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1097#define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
1098#define elf_backend_check_relocs xstormy16_elf_check_relocs
1099#define elf_backend_always_size_sections \
1100 xstormy16_elf_always_size_sections
1101#define elf_backend_finish_dynamic_sections \
1102 xstormy16_elf_finish_dynamic_sections
1103
1104#define elf_backend_can_gc_sections 1
b491616a 1105#define elf_backend_rela_normal 1
93fbbb04
GK
1106
1107#define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1108#define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1109
1110#include "elf32-target.h"
This page took 0.145817 seconds and 4 git commands to generate.