Revert debugging change
[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 */
93fbbb04 211};
cedb70c5 212
93fbbb04
GK
213static reloc_howto_type xstormy16_elf_howto_table2 [] =
214{
215 /* GNU extension to record C++ vtable hierarchy */
216 HOWTO (R_XSTORMY16_GNU_VTINHERIT, /* type */
217 0, /* rightshift */
218 2, /* size (0 = byte, 1 = short, 2 = long) */
219 0, /* bitsize */
b34976b6 220 FALSE, /* pc_relative */
93fbbb04
GK
221 0, /* bitpos */
222 complain_overflow_dont, /* complain_on_overflow */
223 NULL, /* special_function */
224 "R_XSTORMY16_GNU_VTINHERIT", /* name */
b34976b6 225 FALSE, /* partial_inplace */
93fbbb04
GK
226 0, /* src_mask */
227 0, /* dst_mask */
b34976b6 228 FALSE), /* pcrel_offset */
93fbbb04
GK
229
230 /* GNU extension to record C++ vtable member usage */
231 HOWTO (R_XSTORMY16_GNU_VTENTRY, /* type */
232 0, /* rightshift */
233 2, /* size (0 = byte, 1 = short, 2 = long) */
234 0, /* bitsize */
b34976b6 235 FALSE, /* pc_relative */
93fbbb04
GK
236 0, /* bitpos */
237 complain_overflow_dont, /* complain_on_overflow */
238 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
239 "R_XSTORMY16_GNU_VTENTRY", /* name */
b34976b6 240 FALSE, /* partial_inplace */
93fbbb04
GK
241 0, /* src_mask */
242 0, /* dst_mask */
b34976b6 243 FALSE), /* pcrel_offset */
cedb70c5 244
93fbbb04
GK
245};
246\f
247/* Map BFD reloc types to XSTORMY16 ELF reloc types. */
248
1f7fd478 249typedef struct xstormy16_reloc_map
93fbbb04 250{
1f7fd478
NC
251 bfd_reloc_code_real_type bfd_reloc_val;
252 unsigned int xstormy16_reloc_val;
253 reloc_howto_type * table;
254} reloc_map;
93fbbb04 255
1f7fd478 256static const reloc_map xstormy16_reloc_map [] =
93fbbb04 257{
1f7fd478
NC
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 },
93fbbb04
GK
270};
271
272static reloc_howto_type *
273xstormy16_reloc_type_lookup (abfd, code)
274 bfd * abfd ATTRIBUTE_UNUSED;
275 bfd_reloc_code_real_type code;
276{
277 unsigned int i;
278
1f7fd478
NC
279 for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
280 {
281 const reloc_map * entry;
282
283 entry = xstormy16_reloc_map + i;
284
285 if (entry->bfd_reloc_val == code)
286 return entry->table + (entry->xstormy16_reloc_val
287 - entry->table[0].type);
288 }
cedb70c5 289
93fbbb04
GK
290 return NULL;
291}
292
293/* Set the howto pointer for an XSTORMY16 ELF reloc. */
294
295static void
296xstormy16_info_to_howto_rela (abfd, cache_ptr, dst)
297 bfd * abfd ATTRIBUTE_UNUSED;
298 arelent * cache_ptr;
947216bf 299 Elf_Internal_Rela * dst;
93fbbb04
GK
300{
301 unsigned int r_type = ELF32_R_TYPE (dst->r_info);
302
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)
307 cache_ptr->howto
308 = &xstormy16_elf_howto_table2 [r_type - R_XSTORMY16_GNU_VTINHERIT];
309 else
310 abort ();
311}
312
313/* Handle the R_XSTORMY16_24 reloc, which has an odd bit arrangement. */
314
315static bfd_reloc_status_type
316xstormy16_elf_24_reloc (abfd, reloc_entry, symbol, data, input_section,
317 output_bfd, error_message)
318 bfd *abfd;
319 arelent *reloc_entry;
320 asymbol *symbol;
321 PTR data;
322 asection *input_section;
323 bfd *output_bfd;
324 char **error_message ATTRIBUTE_UNUSED;
325{
326 bfd_vma relocation, x;
327
328 if (output_bfd != NULL)
329 {
330 reloc_entry->address += input_section->output_offset;
331 return bfd_reloc_ok;
332 }
333
334 if (reloc_entry->address > input_section->_cooked_size)
335 return bfd_reloc_outofrange;
336
337 if (bfd_is_com_section (symbol->section))
338 relocation = 0;
339 else
340 relocation = symbol->value;
341
342 relocation += symbol->section->output_section->vma;
343 relocation += symbol->section->output_offset;
344 relocation += reloc_entry->addend;
345
346 x = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
347 x &= 0x0000ff00;
348 x |= relocation & 0xff;
349 x |= (relocation << 8) & 0xffff0000;
350 bfd_put_32 (abfd, x, (bfd_byte *) data + reloc_entry->address);
351
352 if (relocation & ~ (bfd_vma) 0xffffff)
353 return bfd_reloc_overflow;
354
355 return bfd_reloc_ok;
356}
357\f
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. */
363
b34976b6 364static bfd_boolean
93fbbb04
GK
365xstormy16_elf_check_relocs (abfd, info, sec, relocs)
366 bfd *abfd;
367 struct bfd_link_info *info;
368 asection *sec;
369 const Elf_Internal_Rela *relocs;
370{
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;
375 asection *splt;
376 bfd *dynobj;
377
378 if (info->relocateable)
b34976b6 379 return TRUE;
93fbbb04
GK
380
381 symtab_hdr = &elf_tdata(abfd)->symtab_hdr;
382 sym_hashes = elf_sym_hashes (abfd);
383 local_plt_offsets = elf_local_got_offsets (abfd);
384 splt = NULL;
385 dynobj = elf_hash_table(info)->dynobj;
386
387 relend = relocs + sec->reloc_count;
388 for (rel = relocs; rel < relend; ++rel)
389 {
390 unsigned long r_symndx;
391 struct elf_link_hash_entry *h;
392 bfd_vma *offset;
393
394 r_symndx = ELF32_R_SYM (rel->r_info);
395 if (r_symndx < symtab_hdr->sh_info)
396 h = NULL;
397 else
398 {
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;
403 }
404
405 switch (ELF32_R_TYPE (rel->r_info))
406 {
407 /* This relocation describes a 16-bit pointer to a function.
408 We may need to allocate a thunk in low memory; reserve memory
409 for it now. */
410 case R_XSTORMY16_FPTR16:
411 if (rel->r_addend != 0)
412 {
413 (*info->callbacks->warning)
414 (info, _("non-zero addend in @fptr reloc"), 0,
415 abfd, 0, 0);
416 }
417
418 if (dynobj == NULL)
419 elf_hash_table (info)->dynobj = dynobj = abfd;
420 if (splt == NULL)
421 {
422 splt = bfd_get_section_by_name (dynobj, ".plt");
423 if (splt == NULL)
424 {
425 splt = bfd_make_section (dynobj, ".plt");
426 if (splt == NULL
427 || ! bfd_set_section_flags (dynobj, splt,
428 (SEC_ALLOC
429 | SEC_LOAD
430 | SEC_HAS_CONTENTS
431 | SEC_IN_MEMORY
432 | SEC_LINKER_CREATED
433 | SEC_READONLY
434 | SEC_CODE))
435 || ! bfd_set_section_alignment (dynobj, splt, 1))
b34976b6 436 return FALSE;
93fbbb04
GK
437 }
438 }
439
440 if (h != NULL)
441 offset = &h->plt.offset;
442 else
443 {
444 if (local_plt_offsets == NULL)
445 {
446 size_t size;
447 unsigned int i;
448
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)
b34976b6 452 return FALSE;
93fbbb04 453 elf_local_got_offsets (abfd) = local_plt_offsets;
cedb70c5 454
93fbbb04
GK
455 for (i = 0; i < symtab_hdr->sh_info; i++)
456 local_plt_offsets[i] = (bfd_vma) -1;
457 }
458 offset = &local_plt_offsets[r_symndx];
459 }
460
461 if (*offset == (bfd_vma) -1)
462 {
463 *offset = splt->_raw_size;
464 splt->_raw_size += 4;
465 }
466 break;
467
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))
b34976b6 472 return FALSE;
93fbbb04 473 break;
cedb70c5 474
93fbbb04
GK
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))
b34976b6 479 return FALSE;
93fbbb04
GK
480 break;
481 }
482 }
483
b34976b6 484 return TRUE;
93fbbb04
GK
485}
486
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. */
489
490struct relax_plt_data
491{
492 asection *splt;
b34976b6 493 bfd_boolean *again;
93fbbb04
GK
494};
495
b34976b6 496static bfd_boolean
93fbbb04
GK
497xstormy16_relax_plt_check (h, xdata)
498 struct elf_link_hash_entry *h;
499 PTR xdata;
500{
501 struct relax_plt_data *data = (struct relax_plt_data *) xdata;
502
e92d460e
AM
503 if (h->root.type == bfd_link_hash_warning)
504 h = (struct elf_link_hash_entry *) h->root.u.i.link;
505
93fbbb04
GK
506 if (h->plt.offset != (bfd_vma) -1)
507 {
508 bfd_vma address;
509
510 if (h->root.type == bfd_link_hash_undefined
511 || h->root.type == bfd_link_hash_undefweak)
512 address = 0;
513 else
514 address = (h->root.u.def.section->output_section->vma
515 + h->root.u.def.section->output_offset
516 + h->root.u.def.value);
517
518 if (address <= 0xffff)
519 {
520 h->plt.offset = -1;
521 data->splt->_cooked_size -= 4;
b34976b6 522 *data->again = TRUE;
93fbbb04
GK
523 }
524 }
525
b34976b6 526 return TRUE;
93fbbb04
GK
527}
528
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. */
531
b34976b6 532static bfd_boolean
93fbbb04
GK
533xstormy16_relax_plt_realloc (h, xdata)
534 struct elf_link_hash_entry *h;
535 PTR xdata;
536{
537 bfd_vma *entry = (bfd_vma *) xdata;
538
e92d460e
AM
539 if (h->root.type == bfd_link_hash_warning)
540 h = (struct elf_link_hash_entry *) h->root.u.i.link;
541
93fbbb04
GK
542 if (h->plt.offset != (bfd_vma) -1)
543 {
544 h->plt.offset = *entry;
545 *entry += 4;
546 }
547
b34976b6 548 return TRUE;
93fbbb04
GK
549}
550
b34976b6 551static bfd_boolean
93fbbb04
GK
552xstormy16_elf_relax_section (dynobj, splt, info, again)
553 bfd *dynobj;
554 asection *splt;
555 struct bfd_link_info *info;
b34976b6 556 bfd_boolean *again;
93fbbb04
GK
557{
558 struct relax_plt_data relax_plt_data;
559 bfd *ibfd;
560
561 /* Assume nothing changes. */
b34976b6 562 *again = FALSE;
93fbbb04
GK
563
564 if (info->relocateable)
b34976b6 565 return TRUE;
93fbbb04
GK
566
567 /* We only relax the .plt section at the moment. */
568 if (dynobj != elf_hash_table (info)->dynobj
569 || strcmp (splt->name, ".plt") != 0)
b34976b6 570 return TRUE;
93fbbb04
GK
571
572 /* Quick check for an empty plt. */
573 if (splt->_raw_size == 0)
b34976b6 574 return TRUE;
93fbbb04
GK
575
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;
580
cedb70c5 581 /* Map across all global symbols; see which ones happen to
93fbbb04
GK
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,
586 &relax_plt_data);
587
588 /* Likewise for local symbols, though that's somewhat less convenient
6cdc0ccc 589 as we have to walk the list of input bfds and swap in symbol data. */
93fbbb04
GK
590 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
591 {
592 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
593 Elf_Internal_Shdr *symtab_hdr;
6cdc0ccc 594 Elf_Internal_Sym *isymbuf = NULL;
93fbbb04
GK
595 unsigned int idx;
596
597 if (! local_plt_offsets)
598 continue;
599
600 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
6cdc0ccc 601 if (symtab_hdr->sh_info != 0)
93fbbb04 602 {
6cdc0ccc
AM
603 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
604 if (isymbuf == NULL)
605 isymbuf = bfd_elf_get_elf_syms (ibfd, symtab_hdr,
606 symtab_hdr->sh_info, 0,
607 NULL, NULL, NULL);
608 if (isymbuf == NULL)
b34976b6 609 return FALSE;
9ad5cbcf
AM
610 }
611
93fbbb04
GK
612 for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
613 {
6cdc0ccc 614 Elf_Internal_Sym *isym;
93fbbb04
GK
615 asection *tsec;
616 bfd_vma address;
617
618 if (local_plt_offsets[idx] == (bfd_vma) -1)
619 continue;
620
6cdc0ccc
AM
621 isym = &isymbuf[idx];
622 if (isym->st_shndx == SHN_UNDEF)
93fbbb04 623 continue;
6cdc0ccc 624 else if (isym->st_shndx == SHN_ABS)
93fbbb04 625 tsec = bfd_abs_section_ptr;
6cdc0ccc 626 else if (isym->st_shndx == SHN_COMMON)
9ad5cbcf 627 tsec = bfd_com_section_ptr;
93fbbb04 628 else
6cdc0ccc 629 tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
93fbbb04
GK
630
631 address = (tsec->output_section->vma
632 + tsec->output_offset
6cdc0ccc 633 + isym->st_value);
93fbbb04
GK
634 if (address <= 0xffff)
635 {
636 local_plt_offsets[idx] = -1;
637 splt->_cooked_size -= 4;
b34976b6 638 *again = TRUE;
93fbbb04
GK
639 }
640 }
641
6cdc0ccc
AM
642 if (isymbuf != NULL
643 && symtab_hdr->contents != (unsigned char *) isymbuf)
644 {
645 if (! info->keep_memory)
646 free (isymbuf);
647 else
648 {
649 /* Cache the symbols for elf_link_input_bfd. */
650 symtab_hdr->contents = (unsigned char *) isymbuf;
651 }
652 }
93fbbb04
GK
653 }
654
655 /* If we changed anything, walk the symbols again to reallocate
656 .plt entry addresses. */
657 if (*again && splt->_cooked_size > 0)
658 {
659 bfd_vma entry = 0;
660
661 elf_link_hash_traverse (elf_hash_table (info),
662 xstormy16_relax_plt_realloc, &entry);
663
664 for (ibfd = info->input_bfds; ibfd ; ibfd = ibfd->link_next)
665 {
666 bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
667 unsigned int nlocals = elf_tdata (ibfd)->symtab_hdr.sh_info;
668 unsigned int idx;
669
670 if (! local_plt_offsets)
671 continue;
672
673 for (idx = 0; idx < nlocals; ++idx)
674 if (local_plt_offsets[idx] != (bfd_vma) -1)
675 {
676 local_plt_offsets[idx] = entry;
677 entry += 4;
678 }
679 }
680 }
681
682 splt->_raw_size = splt->_cooked_size;
b34976b6 683 return TRUE;
93fbbb04
GK
684}
685
b34976b6 686static bfd_boolean
93fbbb04
GK
687xstormy16_elf_always_size_sections (output_bfd, info)
688 bfd *output_bfd ATTRIBUTE_UNUSED;
689 struct bfd_link_info *info;
690{
691 bfd *dynobj;
692 asection *splt;
693
694 if (info->relocateable)
b34976b6 695 return TRUE;
93fbbb04
GK
696
697 dynobj = elf_hash_table (info)->dynobj;
698 if (dynobj == NULL)
b34976b6 699 return TRUE;
93fbbb04
GK
700
701 splt = bfd_get_section_by_name (dynobj, ".plt");
702 BFD_ASSERT (splt != NULL);
703
704 splt->contents = (bfd_byte *) bfd_zalloc (dynobj, splt->_raw_size);
705 if (splt->contents == NULL)
b34976b6 706 return FALSE;
93fbbb04 707
b34976b6 708 return TRUE;
93fbbb04
GK
709}
710\f
711/* Relocate an XSTORMY16 ELF section.
93fbbb04
GK
712
713 The RELOCATE_SECTION function is called by the new ELF backend linker
714 to handle the relocations for a section.
715
716 The relocs are always passed as Rela structures; if the section
717 actually uses Rel structures, the r_addend field will always be
718 zero.
719
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.
723
724 This function does not have to worry about setting the reloc
725 address or the reloc symbol index.
726
727 LOCAL_SYMS is a pointer to the swapped in local symbols.
728
729 LOCAL_SECTIONS is an array giving the section in the input file
730 corresponding to the st_shndx field of each local symbol.
731
732 The global hash table entry for the global symbols can be found
733 via elf_sym_hashes (input_bfd).
734
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
739 accordingly. */
740
b34976b6 741static bfd_boolean
93fbbb04
GK
742xstormy16_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;
746 bfd * input_bfd;
747 asection * input_section;
748 bfd_byte * contents;
749 Elf_Internal_Rela * relocs;
750 Elf_Internal_Sym * local_syms;
751 asection ** local_sections;
752{
753 Elf_Internal_Shdr * symtab_hdr;
754 struct elf_link_hash_entry ** sym_hashes;
755 Elf_Internal_Rela * rel;
756 Elf_Internal_Rela * relend;
757 bfd *dynobj;
758 asection *splt;
759
b491616a 760 if (info->relocateable)
b34976b6 761 return TRUE;
b491616a 762
93fbbb04
GK
763 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
764 sym_hashes = elf_sym_hashes (input_bfd);
765 relend = relocs + input_section->reloc_count;
766
767 dynobj = elf_hash_table (info)->dynobj;
768 splt = NULL;
769 if (dynobj != NULL)
770 splt = bfd_get_section_by_name (dynobj, ".plt");
771
772 for (rel = relocs; rel < relend; rel ++)
773 {
774 reloc_howto_type * howto;
775 unsigned long r_symndx;
776 Elf_Internal_Sym * sym;
777 asection * sec;
778 struct elf_link_hash_entry * h;
779 bfd_vma relocation;
780 bfd_reloc_status_type r;
781 const char * name = NULL;
782 int r_type;
cedb70c5 783
93fbbb04 784 r_type = ELF32_R_TYPE (rel->r_info);
cedb70c5 785
93fbbb04
GK
786 if ( r_type == R_XSTORMY16_GNU_VTINHERIT
787 || r_type == R_XSTORMY16_GNU_VTENTRY)
788 continue;
cedb70c5 789
93fbbb04 790 r_symndx = ELF32_R_SYM (rel->r_info);
93fbbb04
GK
791 howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
792 h = NULL;
793 sym = NULL;
794 sec = NULL;
cedb70c5 795
93fbbb04
GK
796 if (r_symndx < symtab_hdr->sh_info)
797 {
798 sym = local_syms + r_symndx;
799 sec = local_sections [r_symndx];
800 relocation = (sec->output_section->vma
801 + sec->output_offset
802 + sym->st_value);
cedb70c5 803
93fbbb04
GK
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;
807 }
808 else
809 {
810 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
cedb70c5 811
93fbbb04
GK
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;
815
816 name = h->root.root.string;
cedb70c5 817
93fbbb04
GK
818 if (h->root.type == bfd_link_hash_defined
819 || h->root.type == bfd_link_hash_defweak)
820 {
821 sec = h->root.u.def.section;
822 relocation = (h->root.u.def.value
823 + sec->output_section->vma
824 + sec->output_offset);
825 }
826 else if (h->root.type == bfd_link_hash_undefweak)
827 {
828 relocation = 0;
829 }
830 else
831 {
832 if (! ((*info->callbacks->undefined_symbol)
833 (info, h->root.root.string, input_bfd,
b34976b6
AM
834 input_section, rel->r_offset, TRUE)))
835 return FALSE;
93fbbb04
GK
836 relocation = 0;
837 }
838 }
cedb70c5 839
93fbbb04
GK
840 switch (ELF32_R_TYPE (rel->r_info))
841 {
842 case R_XSTORMY16_24:
843 {
844 bfd_vma reloc = relocation + rel->r_addend;
845 unsigned int x;
cedb70c5 846
93fbbb04
GK
847 x = bfd_get_32 (input_bfd, contents + rel->r_offset);
848 x &= 0x0000ff00;
849 x |= reloc & 0xff;
850 x |= (reloc << 8) & 0xffff0000;
851 bfd_put_32 (input_bfd, x, contents + rel->r_offset);
852
853 if (reloc & ~0xffffff)
854 r = bfd_reloc_overflow;
855 else
856 r = bfd_reloc_ok;
857 break;
858 }
859
860 case R_XSTORMY16_FPTR16:
861 {
862 bfd_vma *plt_offset;
863
864 if (h != NULL)
865 plt_offset = &h->plt.offset;
866 else
867 plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
868
869 if (relocation <= 0xffff)
870 {
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);
874 }
875 else
876 {
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);
880
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)
884 {
885 unsigned int x;
886
887 x = 0x00000200; /* jmpf */
888 x |= relocation & 0xff;
889 x |= (relocation << 8) & 0xffff0000;
890 bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
891 *plt_offset |= 1;
892 }
893
894 relocation = (splt->output_section->vma
895 + splt->output_offset
896 + (*plt_offset & -2));
897 }
898 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
899 contents, rel->r_offset,
900 relocation, 0);
901 break;
902 }
903
904 default:
905 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
906 contents, rel->r_offset,
907 relocation, rel->r_addend);
908 break;
909 }
910
911 if (r != bfd_reloc_ok)
912 {
913 const char * msg = (const char *) NULL;
914
915 switch (r)
916 {
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);
921 break;
cedb70c5 922
93fbbb04
GK
923 case bfd_reloc_undefined:
924 r = info->callbacks->undefined_symbol
925 (info, name, input_bfd, input_section, rel->r_offset,
b34976b6 926 TRUE);
93fbbb04 927 break;
cedb70c5 928
93fbbb04
GK
929 case bfd_reloc_outofrange:
930 msg = _("internal error: out of range error");
931 break;
932
933 case bfd_reloc_notsupported:
934 msg = _("internal error: unsupported relocation error");
935 break;
936
937 case bfd_reloc_dangerous:
938 msg = _("internal error: dangerous relocation");
939 break;
940
941 default:
942 msg = _("internal error: unknown error");
943 break;
944 }
945
946 if (msg)
947 r = info->callbacks->warning
948 (info, msg, name, input_bfd, input_section, rel->r_offset);
949
950 if (! r)
b34976b6 951 return FALSE;
93fbbb04
GK
952 }
953 }
954
b34976b6 955 return TRUE;
93fbbb04
GK
956}
957
958/* This must exist if dynobj is ever set. */
959
b34976b6 960static bfd_boolean
93fbbb04
GK
961xstormy16_elf_finish_dynamic_sections (abfd, info)
962 bfd *abfd ATTRIBUTE_UNUSED;
963 struct bfd_link_info *info;
964{
965 bfd *dynobj;
966 asection *splt;
967
968 /* As an extra sanity check, verify that all plt entries have
969 been filled in. */
970
971 if ((dynobj = elf_hash_table (info)->dynobj) != NULL
972 && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
973 {
974 bfd_byte *contents = splt->contents;
975 unsigned int i, size = splt->_raw_size;
976 for (i = 0; i < size; i += 4)
977 {
978 unsigned int x = bfd_get_32 (dynobj, contents + i);
979 BFD_ASSERT (x != 0);
980 }
981 }
982
b34976b6 983 return TRUE;
93fbbb04
GK
984}
985\f
986/* Return the section that should be marked against GC for a given
987 relocation. */
988
989static asection *
1e2f5b6e
AM
990xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
991 asection * sec;
93fbbb04
GK
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;
996{
997 if (h != NULL)
998 {
999 switch (ELF32_R_TYPE (rel->r_info))
1000 {
1001 case R_XSTORMY16_GNU_VTINHERIT:
1002 case R_XSTORMY16_GNU_VTENTRY:
1003 break;
1004
1005 default:
1006 switch (h->root.type)
1007 {
1008 case bfd_link_hash_defined:
1009 case bfd_link_hash_defweak:
1010 return h->root.u.def.section;
1011
1012 case bfd_link_hash_common:
1013 return h->root.u.c.p->section;
1014
1015 default:
1016 break;
1017 }
1018 }
1019 }
1020 else
1e2f5b6e 1021 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
93fbbb04
GK
1022
1023 return NULL;
1024}
1025
1026/* Update the got entry reference counts for the section being removed. */
1027
b34976b6 1028static bfd_boolean
93fbbb04
GK
1029xstormy16_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;
1034{
b34976b6 1035 return TRUE;
93fbbb04
GK
1036}
1037\f
1038#define ELF_ARCH bfd_arch_xstormy16
1039#define ELF_MACHINE_CODE EM_XSTORMY16
1040#define ELF_MAXPAGESIZE 0x100
1041
1042#define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1043#define TARGET_LITTLE_NAME "elf32-xstormy16"
1044
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
1055
1056#define elf_backend_can_gc_sections 1
b491616a 1057#define elf_backend_rela_normal 1
93fbbb04
GK
1058
1059#define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1060#define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1061
1062#include "elf32-target.h"
This page took 0.131007 seconds and 4 git commands to generate.