* elf-bfd.h (struct elf_reloc_cookie): Remove locsym_shndx,
[deliverable/binutils-gdb.git] / bfd / elf32-xstormy16.c
1 /* XSTORMY16-specific support for 32-bit ELF.
2 Copyright (C) 2000, 2001, 2002 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 #include "libiberty.h"
26
27 /* Forward declarations. */
28 static reloc_howto_type * xstormy16_reloc_type_lookup
29 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
30 static void xstormy16_info_to_howto_rela
31 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
32 static bfd_reloc_status_type xstormy16_elf_24_reloc
33 PARAMS ((bfd *abfd, arelent *reloc_entry, asymbol *symbol,
34 PTR data, asection *input_section, bfd *output_bfd,
35 char **error_message));
36 static boolean xstormy16_elf_check_relocs
37 PARAMS ((bfd *, struct bfd_link_info *, asection *,
38 const Elf_Internal_Rela *));
39 static boolean xstormy16_relax_plt_check
40 PARAMS ((struct elf_link_hash_entry *, PTR));
41 static boolean xstormy16_relax_plt_realloc
42 PARAMS ((struct elf_link_hash_entry *, PTR));
43 static boolean xstormy16_elf_relax_section
44 PARAMS ((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
45 boolean *again));
46 static boolean xstormy16_elf_always_size_sections
47 PARAMS ((bfd *, struct bfd_link_info *));
48 static boolean xstormy16_elf_relocate_section
49 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
50 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
51 static boolean xstormy16_elf_finish_dynamic_sections
52 PARAMS((bfd *, struct bfd_link_info *));
53 static boolean xstormy16_elf_gc_sweep_hook
54 PARAMS ((bfd *, struct bfd_link_info *, asection *,
55 const Elf_Internal_Rela *));
56 static asection * xstormy16_elf_gc_mark_hook
57 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
58 struct elf_link_hash_entry *, Elf_Internal_Sym *));
59
60 static 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 */
67 false, /* pc_relative */
68 0, /* bitpos */
69 complain_overflow_bitfield, /* complain_on_overflow */
70 bfd_elf_generic_reloc, /* special_function */
71 "R_XSTORMY16_NONE", /* name */
72 false, /* partial_inplace */
73 0, /* src_mask */
74 0, /* dst_mask */
75 false), /* pcrel_offset */
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 */
82 false, /* pc_relative */
83 0, /* bitpos */
84 complain_overflow_dont, /* complain_on_overflow */
85 bfd_elf_generic_reloc, /* special_function */
86 "R_XSTORMY16_32", /* name */
87 false, /* partial_inplace */
88 0, /* src_mask */
89 0xffffffff, /* dst_mask */
90 false), /* pcrel_offset */
91
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 */
97 false, /* pc_relative */
98 0, /* bitpos */
99 complain_overflow_bitfield, /* complain_on_overflow */
100 bfd_elf_generic_reloc, /* special_function */
101 "R_XSTORMY16_16", /* name */
102 false, /* partial_inplace */
103 0, /* src_mask */
104 0xffffffff, /* dst_mask */
105 false), /* pcrel_offset */
106
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 */
112 false, /* pc_relative */
113 0, /* bitpos */
114 complain_overflow_bitfield, /* complain_on_overflow */
115 bfd_elf_generic_reloc, /* special_function */
116 "R_XSTORMY16_8", /* name */
117 false, /* partial_inplace */
118 0, /* src_mask */
119 0xffffffff, /* dst_mask */
120 false), /* pcrel_offset */
121
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 */
127 true, /* pc_relative */
128 0, /* bitpos */
129 complain_overflow_dont, /* complain_on_overflow */
130 bfd_elf_generic_reloc, /* special_function */
131 "R_XSTORMY16_PC32", /* name */
132 false, /* partial_inplace */
133 0, /* src_mask */
134 0xffffffff, /* dst_mask */
135 true), /* pcrel_offset */
136
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 */
142 true, /* pc_relative */
143 0, /* bitpos */
144 complain_overflow_signed, /* complain_on_overflow */
145 bfd_elf_generic_reloc, /* special_function */
146 "R_XSTORMY16_PC16", /* name */
147 false, /* partial_inplace */
148 0, /* src_mask */
149 0xffffffff, /* dst_mask */
150 true), /* pcrel_offset */
151
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 */
157 true, /* pc_relative */
158 0, /* bitpos */
159 complain_overflow_signed, /* complain_on_overflow */
160 bfd_elf_generic_reloc, /* special_function */
161 "R_XSTORMY16_PC8", /* name */
162 false, /* partial_inplace */
163 0, /* src_mask */
164 0xffffffff, /* dst_mask */
165 true), /* pcrel_offset */
166
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 */
172 true, /* pc_relative */
173 1, /* bitpos */
174 complain_overflow_signed, /* complain_on_overflow */
175 bfd_elf_generic_reloc, /* special_function */
176 "R_XSTORMY16_REL_12", /* name */
177 true, /* partial_inplace */
178 0, /* src_mask */
179 0x0fff, /* dst_mask */
180 true), /* pcrel_offset */
181
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 */
187 false, /* pc_relative */
188 0, /* bitpos */
189 complain_overflow_unsigned, /* complain_on_overflow */
190 xstormy16_elf_24_reloc, /* special_function */
191 "R_XSTORMY16_24", /* name */
192 true, /* partial_inplace */
193 0, /* src_mask */
194 0xffff00ff, /* dst_mask */
195 true), /* pcrel_offset */
196
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 */
202 false, /* pc_relative */
203 0, /* bitpos */
204 complain_overflow_bitfield, /* complain_on_overflow */
205 bfd_elf_generic_reloc, /* special_function */
206 "R_XSTORMY16_FPTR16", /* name */
207 false, /* partial_inplace */
208 0, /* src_mask */
209 0xffffffff, /* dst_mask */
210 false), /* pcrel_offset */
211 };
212
213 static 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 */
220 false, /* pc_relative */
221 0, /* bitpos */
222 complain_overflow_dont, /* complain_on_overflow */
223 NULL, /* special_function */
224 "R_XSTORMY16_GNU_VTINHERIT", /* name */
225 false, /* partial_inplace */
226 0, /* src_mask */
227 0, /* dst_mask */
228 false), /* pcrel_offset */
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 */
235 false, /* pc_relative */
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 */
240 false, /* partial_inplace */
241 0, /* src_mask */
242 0, /* dst_mask */
243 false), /* pcrel_offset */
244
245 };
246 \f
247 /* Map BFD reloc types to XSTORMY16 ELF reloc types. */
248
249 typedef struct xstormy16_reloc_map
250 {
251 bfd_reloc_code_real_type bfd_reloc_val;
252 unsigned int xstormy16_reloc_val;
253 reloc_howto_type * table;
254 } reloc_map;
255
256 static const reloc_map xstormy16_reloc_map [] =
257 {
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 },
270 };
271
272 static reloc_howto_type *
273 xstormy16_reloc_type_lookup (abfd, code)
274 bfd * abfd ATTRIBUTE_UNUSED;
275 bfd_reloc_code_real_type code;
276 {
277 unsigned int i;
278
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 }
289
290 return NULL;
291 }
292
293 /* Set the howto pointer for an XSTORMY16 ELF reloc. */
294
295 static void
296 xstormy16_info_to_howto_rela (abfd, cache_ptr, dst)
297 bfd * abfd ATTRIBUTE_UNUSED;
298 arelent * cache_ptr;
299 Elf32_Internal_Rela * dst;
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
315 static bfd_reloc_status_type
316 xstormy16_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
364 static boolean
365 xstormy16_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)
379 return true;
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))
436 return false;
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)
452 return false;
453 elf_local_got_offsets (abfd) = local_plt_offsets;
454
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))
472 return false;
473 break;
474
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))
479 return false;
480 break;
481 }
482 }
483
484 return true;
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
490 struct relax_plt_data
491 {
492 asection *splt;
493 boolean *again;
494 };
495
496 static boolean
497 xstormy16_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
503 if (h->root.type == bfd_link_hash_warning)
504 h = (struct elf_link_hash_entry *) h->root.u.i.link;
505
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;
522 *data->again = true;
523 }
524 }
525
526 return true;
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
532 static boolean
533 xstormy16_relax_plt_realloc (h, xdata)
534 struct elf_link_hash_entry *h;
535 PTR xdata;
536 {
537 bfd_vma *entry = (bfd_vma *) xdata;
538
539 if (h->root.type == bfd_link_hash_warning)
540 h = (struct elf_link_hash_entry *) h->root.u.i.link;
541
542 if (h->plt.offset != (bfd_vma) -1)
543 {
544 h->plt.offset = *entry;
545 *entry += 4;
546 }
547
548 return true;
549 }
550
551 static boolean
552 xstormy16_elf_relax_section (dynobj, splt, info, again)
553 bfd *dynobj;
554 asection *splt;
555 struct bfd_link_info *info;
556 boolean *again;
557 {
558 struct relax_plt_data relax_plt_data;
559 bfd *ibfd;
560
561 /* Assume nothing changes. */
562 *again = false;
563
564 if (info->relocateable)
565 return true;
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)
570 return true;
571
572 /* Quick check for an empty plt. */
573 if (splt->_raw_size == 0)
574 return true;
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
581 /* Map across all global symbols; see which ones happen to
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
589 as we have to walk the list of input bfds and swap in symbol data. */
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;
594 Elf_Internal_Sym *isymbuf = NULL;
595 unsigned int idx;
596
597 if (! local_plt_offsets)
598 continue;
599
600 symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
601 if (symtab_hdr->sh_info != 0)
602 {
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)
609 return false;
610 }
611
612 for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
613 {
614 Elf_Internal_Sym *isym;
615 asection *tsec;
616 bfd_vma address;
617
618 if (local_plt_offsets[idx] == (bfd_vma) -1)
619 continue;
620
621 isym = &isymbuf[idx];
622 if (isym->st_shndx == SHN_UNDEF)
623 continue;
624 else if (isym->st_shndx == SHN_ABS)
625 tsec = bfd_abs_section_ptr;
626 else if (isym->st_shndx == SHN_COMMON)
627 tsec = bfd_com_section_ptr;
628 else
629 tsec = bfd_section_from_elf_index (ibfd, isym->st_shndx);
630
631 address = (tsec->output_section->vma
632 + tsec->output_offset
633 + isym->st_value);
634 if (address <= 0xffff)
635 {
636 local_plt_offsets[idx] = -1;
637 splt->_cooked_size -= 4;
638 *again = true;
639 }
640 }
641
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 }
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;
683 return true;
684 }
685
686 static boolean
687 xstormy16_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)
695 return true;
696
697 dynobj = elf_hash_table (info)->dynobj;
698 if (dynobj == NULL)
699 return true;
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)
706 return false;
707
708 return true;
709 }
710 \f
711 /* Relocate an XSTORMY16 ELF section.
712 There is some attempt to make this function usable for many architectures,
713 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
714 if only to serve as a learning tool.
715
716 The RELOCATE_SECTION function is called by the new ELF backend linker
717 to handle the relocations for a section.
718
719 The relocs are always passed as Rela structures; if the section
720 actually uses Rel structures, the r_addend field will always be
721 zero.
722
723 This function is responsible for adjusting the section contents as
724 necessary, and (if using Rela relocs and generating a relocateable
725 output file) adjusting the reloc addend as necessary.
726
727 This function does not have to worry about setting the reloc
728 address or the reloc symbol index.
729
730 LOCAL_SYMS is a pointer to the swapped in local symbols.
731
732 LOCAL_SECTIONS is an array giving the section in the input file
733 corresponding to the st_shndx field of each local symbol.
734
735 The global hash table entry for the global symbols can be found
736 via elf_sym_hashes (input_bfd).
737
738 When generating relocateable output, this function must handle
739 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
740 going to be the section symbol corresponding to the output
741 section, which means that the addend must be adjusted
742 accordingly. */
743
744 static boolean
745 xstormy16_elf_relocate_section (output_bfd, info, input_bfd, input_section,
746 contents, relocs, local_syms, local_sections)
747 bfd * output_bfd ATTRIBUTE_UNUSED;
748 struct bfd_link_info * info;
749 bfd * input_bfd;
750 asection * input_section;
751 bfd_byte * contents;
752 Elf_Internal_Rela * relocs;
753 Elf_Internal_Sym * local_syms;
754 asection ** local_sections;
755 {
756 Elf_Internal_Shdr * symtab_hdr;
757 struct elf_link_hash_entry ** sym_hashes;
758 Elf_Internal_Rela * rel;
759 Elf_Internal_Rela * relend;
760 bfd *dynobj;
761 asection *splt;
762
763 if (info->relocateable)
764 return true;
765
766 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
767 sym_hashes = elf_sym_hashes (input_bfd);
768 relend = relocs + input_section->reloc_count;
769
770 dynobj = elf_hash_table (info)->dynobj;
771 splt = NULL;
772 if (dynobj != NULL)
773 splt = bfd_get_section_by_name (dynobj, ".plt");
774
775 for (rel = relocs; rel < relend; rel ++)
776 {
777 reloc_howto_type * howto;
778 unsigned long r_symndx;
779 Elf_Internal_Sym * sym;
780 asection * sec;
781 struct elf_link_hash_entry * h;
782 bfd_vma relocation;
783 bfd_reloc_status_type r;
784 const char * name = NULL;
785 int r_type;
786
787 r_type = ELF32_R_TYPE (rel->r_info);
788
789 if ( r_type == R_XSTORMY16_GNU_VTINHERIT
790 || r_type == R_XSTORMY16_GNU_VTENTRY)
791 continue;
792
793 r_symndx = ELF32_R_SYM (rel->r_info);
794 howto = xstormy16_elf_howto_table + ELF32_R_TYPE (rel->r_info);
795 h = NULL;
796 sym = NULL;
797 sec = NULL;
798
799 if (r_symndx < symtab_hdr->sh_info)
800 {
801 sym = local_syms + r_symndx;
802 sec = local_sections [r_symndx];
803 relocation = (sec->output_section->vma
804 + sec->output_offset
805 + sym->st_value);
806
807 name = bfd_elf_string_from_elf_section
808 (input_bfd, symtab_hdr->sh_link, sym->st_name);
809 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
810 }
811 else
812 {
813 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
814
815 while (h->root.type == bfd_link_hash_indirect
816 || h->root.type == bfd_link_hash_warning)
817 h = (struct elf_link_hash_entry *) h->root.u.i.link;
818
819 name = h->root.root.string;
820
821 if (h->root.type == bfd_link_hash_defined
822 || h->root.type == bfd_link_hash_defweak)
823 {
824 sec = h->root.u.def.section;
825 relocation = (h->root.u.def.value
826 + sec->output_section->vma
827 + sec->output_offset);
828 }
829 else if (h->root.type == bfd_link_hash_undefweak)
830 {
831 relocation = 0;
832 }
833 else
834 {
835 if (! ((*info->callbacks->undefined_symbol)
836 (info, h->root.root.string, input_bfd,
837 input_section, rel->r_offset, true)))
838 return false;
839 relocation = 0;
840 }
841 }
842
843 switch (ELF32_R_TYPE (rel->r_info))
844 {
845 case R_XSTORMY16_24:
846 {
847 bfd_vma reloc = relocation + rel->r_addend;
848 unsigned int x;
849
850 x = bfd_get_32 (input_bfd, contents + rel->r_offset);
851 x &= 0x0000ff00;
852 x |= reloc & 0xff;
853 x |= (reloc << 8) & 0xffff0000;
854 bfd_put_32 (input_bfd, x, contents + rel->r_offset);
855
856 if (reloc & ~0xffffff)
857 r = bfd_reloc_overflow;
858 else
859 r = bfd_reloc_ok;
860 break;
861 }
862
863 case R_XSTORMY16_FPTR16:
864 {
865 bfd_vma *plt_offset;
866
867 if (h != NULL)
868 plt_offset = &h->plt.offset;
869 else
870 plt_offset = elf_local_got_offsets (input_bfd) + r_symndx;
871
872 if (relocation <= 0xffff)
873 {
874 /* If the symbol is in range for a 16-bit address, we should
875 have deallocated the plt entry in relax_section. */
876 BFD_ASSERT (*plt_offset == (bfd_vma) -1);
877 }
878 else
879 {
880 /* If the symbol is out of range for a 16-bit address,
881 we must have allocated a plt entry. */
882 BFD_ASSERT (*plt_offset != (bfd_vma) -1);
883
884 /* If this is the first time we've processed this symbol,
885 fill in the plt entry with the correct symbol address. */
886 if ((*plt_offset & 1) == 0)
887 {
888 unsigned int x;
889
890 x = 0x00000200; /* jmpf */
891 x |= relocation & 0xff;
892 x |= (relocation << 8) & 0xffff0000;
893 bfd_put_32 (input_bfd, x, splt->contents + *plt_offset);
894 *plt_offset |= 1;
895 }
896
897 relocation = (splt->output_section->vma
898 + splt->output_offset
899 + (*plt_offset & -2));
900 }
901 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
902 contents, rel->r_offset,
903 relocation, 0);
904 break;
905 }
906
907 default:
908 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
909 contents, rel->r_offset,
910 relocation, rel->r_addend);
911 break;
912 }
913
914 if (r != bfd_reloc_ok)
915 {
916 const char * msg = (const char *) NULL;
917
918 switch (r)
919 {
920 case bfd_reloc_overflow:
921 r = info->callbacks->reloc_overflow
922 (info, name, howto->name, (bfd_vma) 0,
923 input_bfd, input_section, rel->r_offset);
924 break;
925
926 case bfd_reloc_undefined:
927 r = info->callbacks->undefined_symbol
928 (info, name, input_bfd, input_section, rel->r_offset,
929 true);
930 break;
931
932 case bfd_reloc_outofrange:
933 msg = _("internal error: out of range error");
934 break;
935
936 case bfd_reloc_notsupported:
937 msg = _("internal error: unsupported relocation error");
938 break;
939
940 case bfd_reloc_dangerous:
941 msg = _("internal error: dangerous relocation");
942 break;
943
944 default:
945 msg = _("internal error: unknown error");
946 break;
947 }
948
949 if (msg)
950 r = info->callbacks->warning
951 (info, msg, name, input_bfd, input_section, rel->r_offset);
952
953 if (! r)
954 return false;
955 }
956 }
957
958 return true;
959 }
960
961 /* This must exist if dynobj is ever set. */
962
963 static boolean
964 xstormy16_elf_finish_dynamic_sections (abfd, info)
965 bfd *abfd ATTRIBUTE_UNUSED;
966 struct bfd_link_info *info;
967 {
968 bfd *dynobj;
969 asection *splt;
970
971 /* As an extra sanity check, verify that all plt entries have
972 been filled in. */
973
974 if ((dynobj = elf_hash_table (info)->dynobj) != NULL
975 && (splt = bfd_get_section_by_name (dynobj, ".plt")) != NULL)
976 {
977 bfd_byte *contents = splt->contents;
978 unsigned int i, size = splt->_raw_size;
979 for (i = 0; i < size; i += 4)
980 {
981 unsigned int x = bfd_get_32 (dynobj, contents + i);
982 BFD_ASSERT (x != 0);
983 }
984 }
985
986 return true;
987 }
988 \f
989 /* Return the section that should be marked against GC for a given
990 relocation. */
991
992 static asection *
993 xstormy16_elf_gc_mark_hook (sec, info, rel, h, sym)
994 asection * sec;
995 struct bfd_link_info * info ATTRIBUTE_UNUSED;
996 Elf_Internal_Rela * rel;
997 struct elf_link_hash_entry * h;
998 Elf_Internal_Sym * sym;
999 {
1000 if (h != NULL)
1001 {
1002 switch (ELF32_R_TYPE (rel->r_info))
1003 {
1004 case R_XSTORMY16_GNU_VTINHERIT:
1005 case R_XSTORMY16_GNU_VTENTRY:
1006 break;
1007
1008 default:
1009 switch (h->root.type)
1010 {
1011 case bfd_link_hash_defined:
1012 case bfd_link_hash_defweak:
1013 return h->root.u.def.section;
1014
1015 case bfd_link_hash_common:
1016 return h->root.u.c.p->section;
1017
1018 default:
1019 break;
1020 }
1021 }
1022 }
1023 else
1024 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
1025
1026 return NULL;
1027 }
1028
1029 /* Update the got entry reference counts for the section being removed. */
1030
1031 static boolean
1032 xstormy16_elf_gc_sweep_hook (abfd, info, sec, relocs)
1033 bfd * abfd ATTRIBUTE_UNUSED;
1034 struct bfd_link_info * info ATTRIBUTE_UNUSED;
1035 asection * sec ATTRIBUTE_UNUSED;
1036 const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED;
1037 {
1038 return true;
1039 }
1040 \f
1041 #define ELF_ARCH bfd_arch_xstormy16
1042 #define ELF_MACHINE_CODE EM_XSTORMY16
1043 #define ELF_MAXPAGESIZE 0x100
1044
1045 #define TARGET_LITTLE_SYM bfd_elf32_xstormy16_vec
1046 #define TARGET_LITTLE_NAME "elf32-xstormy16"
1047
1048 #define elf_info_to_howto_rel NULL
1049 #define elf_info_to_howto xstormy16_info_to_howto_rela
1050 #define elf_backend_relocate_section xstormy16_elf_relocate_section
1051 #define elf_backend_gc_mark_hook xstormy16_elf_gc_mark_hook
1052 #define elf_backend_gc_sweep_hook xstormy16_elf_gc_sweep_hook
1053 #define elf_backend_check_relocs xstormy16_elf_check_relocs
1054 #define elf_backend_always_size_sections \
1055 xstormy16_elf_always_size_sections
1056 #define elf_backend_finish_dynamic_sections \
1057 xstormy16_elf_finish_dynamic_sections
1058
1059 #define elf_backend_can_gc_sections 1
1060 #define elf_backend_rela_normal 1
1061
1062 #define bfd_elf32_bfd_reloc_type_lookup xstormy16_reloc_type_lookup
1063 #define bfd_elf32_bfd_relax_section xstormy16_elf_relax_section
1064
1065 #include "elf32-target.h"
This page took 0.050716 seconds and 5 git commands to generate.