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