(linux_test_for_tracefork): Don't leave zombie
[deliverable/binutils-gdb.git] / bfd / elf32-d10v.c
CommitLineData
252b5132 1/* D10V-specific support for 32-bit ELF
47b0e7ad 2 Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
1049f94e 3 Free Software Foundation, Inc.
252b5132
RH
4 Contributed by Martin Hunt (hunt@cygnus.com).
5
47b0e7ad 6 This file is part of BFD, the Binary File Descriptor library.
252b5132 7
47b0e7ad
NC
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
252b5132 12
47b0e7ad
NC
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
252b5132 17
47b0e7ad
NC
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132
RH
22
23#include "bfd.h"
24#include "sysdep.h"
25#include "libbfd.h"
26#include "elf-bfd.h"
1b452ec6 27#include "elf/d10v.h"
252b5132 28
917583ad 29/* Use REL instead of RELA to save space. */
acf8aed4 30#define USE_REL 1
252b5132 31
252b5132 32static reloc_howto_type elf_d10v_howto_table[] =
47b0e7ad
NC
33{
34 /* This reloc does nothing. */
35 HOWTO (R_D10V_NONE, /* Type. */
36 0, /* Rightshift. */
37 2, /* Size (0 = byte, 1 = short, 2 = long). */
38 32, /* Bitsize. */
39 FALSE, /* PC_relative. */
40 0, /* Bitpos. */
41 complain_overflow_dont,/* Complain_on_overflow. */
42 bfd_elf_generic_reloc, /* Special_function. */
43 "R_D10V_NONE", /* Name. */
44 FALSE, /* Partial_inplace. */
45 0, /* Src_mask. */
46 0, /* Dst_mask. */
47 FALSE), /* PCrel_offset. */
48
49 /* An PC Relative 10-bit relocation, shifted by 2, right container. */
50 HOWTO (R_D10V_10_PCREL_R, /* Type. */
51 2, /* Rightshift. */
52 2, /* Size (0 = byte, 1 = short, 2 = long). */
a7985d73 53 8, /* Bitsize. */
47b0e7ad
NC
54 TRUE, /* PC_relative. */
55 0, /* Bitpos. */
a7985d73 56 complain_overflow_signed, /* Complain_on_overflow. */
47b0e7ad
NC
57 bfd_elf_generic_reloc, /* Special_function. */
58 "R_D10V_10_PCREL_R", /* Name. */
59 FALSE, /* Partial_inplace. */
60 0xff, /* Src_mask. */
61 0xff, /* Dst_mask. */
62 TRUE), /* PCrel_offset. */
63
64 /* An PC Relative 10-bit relocation, shifted by 2, left container. */
65 HOWTO (R_D10V_10_PCREL_L, /* Type. */
66 2, /* Rightshift. */
67 2, /* Size (0 = byte, 1 = short, 2 = long). */
a7985d73 68 8, /* Bitsize. */
47b0e7ad
NC
69 TRUE, /* PC_relative. */
70 15, /* Bitpos. */
a7985d73 71 complain_overflow_signed, /* Complain_on_overflow. */
47b0e7ad
NC
72 bfd_elf_generic_reloc, /* Special_function. */
73 "R_D10V_10_PCREL_L", /* Name. */
74 FALSE, /* Partial_inplace. */
75 0x07f8000, /* Src_mask. */
76 0x07f8000, /* Dst_mask. */
77 TRUE), /* PCrel_offset. */
78
79 /* A 16 bit absolute relocation. */
80 HOWTO (R_D10V_16, /* Type. */
81 0, /* Rightshift. */
82 1, /* Size (0 = byte, 1 = short, 2 = long). */
83 16, /* Bitsize. */
84 FALSE, /* PC_relative. */
85 0, /* Bitpos. */
86 complain_overflow_dont,/* Complain_on_overflow. */
87 bfd_elf_generic_reloc, /* Special_function. */
88 "R_D10V_16", /* Name. */
89 FALSE, /* Partial_inplace. */
90 0xffff, /* Src_mask. */
91 0xffff, /* Dst_mask. */
92 FALSE), /* PCrel_offset. */
93
94 /* An 18 bit absolute relocation, right shifted 2. */
95 HOWTO (R_D10V_18, /* Type. */
96 2, /* Rightshift. */
97 1, /* Size (0 = byte, 1 = short, 2 = long). */
98 16, /* Bitsize. */
99 FALSE, /* PC_relative. */
100 0, /* Bitpos. */
101 complain_overflow_dont, /* Complain_on_overflow. */
102 bfd_elf_generic_reloc, /* Special_function. */
103 "R_D10V_18", /* Name. */
104 FALSE, /* Partial_inplace. */
105 0xffff, /* Src_mask. */
106 0xffff, /* Dst_mask. */
107 FALSE), /* PCrel_offset. */
108
109 /* A relative 18 bit relocation, right shifted by 2. */
110 HOWTO (R_D10V_18_PCREL, /* Type. */
111 2, /* Rightshift. */
112 2, /* Size (0 = byte, 1 = short, 2 = long). */
a7985d73 113 16, /* Bitsize. */
47b0e7ad
NC
114 TRUE, /* PC_relative. */
115 0, /* Bitpos. */
a7985d73 116 complain_overflow_signed, /* Complain_on_overflow. */
47b0e7ad
NC
117 bfd_elf_generic_reloc, /* Special_function. */
118 "R_D10V_18_PCREL", /* Name. */
119 FALSE, /* Partial_inplace. */
120 0xffff, /* Src_mask. */
121 0xffff, /* Dst_mask. */
122 TRUE), /* PCrel_offset. */
123
124 /* A 32 bit absolute relocation. */
125 HOWTO (R_D10V_32, /* Type. */
126 0, /* Rightshift. */
127 2, /* Size (0 = byte, 1 = short, 2 = long). */
128 32, /* Bitsize. */
129 FALSE, /* PC_relative. */
130 0, /* Bitpos. */
131 complain_overflow_dont,/* Complain_on_overflow. */
132 bfd_elf_generic_reloc, /* Special_function. */
133 "R_D10V_32", /* Name. */
134 FALSE, /* Partial_inplace. */
135 0xffffffff, /* Src_mask. */
136 0xffffffff, /* Dst_mask. */
137 FALSE), /* PCrel_offset. */
138
139 /* GNU extension to record C++ vtable hierarchy. */
140 HOWTO (R_D10V_GNU_VTINHERIT, /* Type. */
141 0, /* Rightshift. */
142 2, /* Size (0 = byte, 1 = short, 2 = long). */
143 0, /* Bitsize. */
144 FALSE, /* PC_relative. */
145 0, /* Bitpos. */
146 complain_overflow_dont,/* Complain_on_overflow. */
147 NULL, /* Special_function. */
148 "R_D10V_GNU_VTINHERIT",/* Name. */
149 FALSE, /* Partial_inplace. */
150 0, /* Src_mask. */
151 0, /* Dst_mask. */
152 FALSE), /* PCrel_offset. */
153
154 /* GNU extension to record C++ vtable member usage. */
155 HOWTO (R_D10V_GNU_VTENTRY, /* Type. */
156 0, /* Rightshift. */
157 2, /* Size (0 = byte, 1 = short, 2 = long). */
158 0, /* Bitsize. */
159 FALSE, /* PC_relative. */
160 0, /* Bitpos. */
161 complain_overflow_dont,/* Complain_on_overflow. */
162 _bfd_elf_rel_vtable_reloc_fn, /* Special_function. */
163 "R_D10V_GNU_VTENTRY", /* Name. */
164 FALSE, /* Partial_inplace. */
165 0, /* Src_mask. */
166 0, /* Dst_mask. */
167 FALSE), /* PCrel_offset. */
168};
252b5132
RH
169
170/* Map BFD reloc types to D10V ELF reloc types. */
171
172struct d10v_reloc_map
47b0e7ad
NC
173{
174 bfd_reloc_code_real_type bfd_reloc_val;
175 unsigned char elf_reloc_val;
176};
917583ad
NC
177
178static const struct d10v_reloc_map d10v_reloc_map[] =
47b0e7ad
NC
179{
180 { BFD_RELOC_NONE, R_D10V_NONE, },
181 { BFD_RELOC_D10V_10_PCREL_R, R_D10V_10_PCREL_R },
182 { BFD_RELOC_D10V_10_PCREL_L, R_D10V_10_PCREL_L },
183 { BFD_RELOC_16, R_D10V_16 },
184 { BFD_RELOC_D10V_18, R_D10V_18 },
185 { BFD_RELOC_D10V_18_PCREL, R_D10V_18_PCREL },
186 { BFD_RELOC_32, R_D10V_32 },
187 { BFD_RELOC_VTABLE_INHERIT, R_D10V_GNU_VTINHERIT },
188 { BFD_RELOC_VTABLE_ENTRY, R_D10V_GNU_VTENTRY },
189};
252b5132
RH
190
191static reloc_howto_type *
47b0e7ad
NC
192bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
193 bfd_reloc_code_real_type code)
252b5132
RH
194{
195 unsigned int i;
196
197 for (i = 0;
198 i < sizeof (d10v_reloc_map) / sizeof (struct d10v_reloc_map);
199 i++)
47b0e7ad
NC
200 if (d10v_reloc_map[i].bfd_reloc_val == code)
201 return &elf_d10v_howto_table[d10v_reloc_map[i].elf_reloc_val];
252b5132
RH
202
203 return NULL;
204}
205
206/* Set the howto pointer for an D10V ELF reloc. */
207
208static void
47b0e7ad
NC
209d10v_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
210 arelent *cache_ptr,
211 Elf_Internal_Rela *dst)
252b5132
RH
212{
213 unsigned int r_type;
214
215 r_type = ELF32_R_TYPE (dst->r_info);
216 BFD_ASSERT (r_type < (unsigned int) R_D10V_max);
217 cache_ptr->howto = &elf_d10v_howto_table[r_type];
218}
219
220static asection *
47b0e7ad
NC
221elf32_d10v_gc_mark_hook (asection *sec,
222 struct bfd_link_info *info ATTRIBUTE_UNUSED,
223 Elf_Internal_Rela *rel,
224 struct elf_link_hash_entry *h,
225 Elf_Internal_Sym *sym)
252b5132
RH
226{
227 if (h != NULL)
228 {
229 switch (ELF32_R_TYPE (rel->r_info))
230 {
231 case R_D10V_GNU_VTINHERIT:
232 case R_D10V_GNU_VTENTRY:
233 break;
234
235 default:
236 switch (h->root.type)
237 {
238 case bfd_link_hash_defined:
239 case bfd_link_hash_defweak:
240 return h->root.u.def.section;
241
242 case bfd_link_hash_common:
243 return h->root.u.c.p->section;
e049a0de
ILT
244
245 default:
246 break;
252b5132
RH
247 }
248 }
249 }
250 else
1e2f5b6e
AM
251 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
252
252b5132
RH
253 return NULL;
254}
255
b34976b6 256static bfd_boolean
47b0e7ad
NC
257elf32_d10v_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
258 struct bfd_link_info *info ATTRIBUTE_UNUSED,
259 asection *sec ATTRIBUTE_UNUSED,
260 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
252b5132 261{
47b0e7ad 262 /* We don't use got and plt entries for d10v. */
b34976b6 263 return TRUE;
252b5132
RH
264}
265
266/* Look through the relocs for a section during the first phase.
267 Since we don't do .gots or .plts, we just need to consider the
268 virtual table relocs for gc. */
a7c10850 269
b34976b6 270static bfd_boolean
47b0e7ad
NC
271elf32_d10v_check_relocs (bfd *abfd,
272 struct bfd_link_info *info,
273 asection *sec,
274 const Elf_Internal_Rela *relocs)
252b5132
RH
275{
276 Elf_Internal_Shdr *symtab_hdr;
277 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
278 const Elf_Internal_Rela *rel;
279 const Elf_Internal_Rela *rel_end;
a7c10850 280
1049f94e 281 if (info->relocatable)
b34976b6 282 return TRUE;
a7c10850 283
252b5132
RH
284 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
285 sym_hashes = elf_sym_hashes (abfd);
a7c10850 286 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
252b5132
RH
287 if (!elf_bad_symtab (abfd))
288 sym_hashes_end -= symtab_hdr->sh_info;
a7c10850 289
252b5132
RH
290 rel_end = relocs + sec->reloc_count;
291 for (rel = relocs; rel < rel_end; rel++)
292 {
293 struct elf_link_hash_entry *h;
294 unsigned long r_symndx;
a7c10850 295
252b5132
RH
296 r_symndx = ELF32_R_SYM (rel->r_info);
297 if (r_symndx < symtab_hdr->sh_info)
298 h = NULL;
299 else
973a3492
L
300 {
301 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
302 while (h->root.type == bfd_link_hash_indirect
303 || h->root.type == bfd_link_hash_warning)
304 h = (struct elf_link_hash_entry *) h->root.u.i.link;
305 }
a7c10850 306
252b5132
RH
307 switch (ELF32_R_TYPE (rel->r_info))
308 {
309 /* This relocation describes the C++ object vtable hierarchy.
310 Reconstruct it for later use during GC. */
311 case R_D10V_GNU_VTINHERIT:
c152c796 312 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
b34976b6 313 return FALSE;
252b5132 314 break;
a7c10850 315
252b5132
RH
316 /* This relocation describes which C++ vtable entries are actually
317 used. Record for later use during GC. */
318 case R_D10V_GNU_VTENTRY:
c152c796 319 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
b34976b6 320 return FALSE;
252b5132
RH
321 break;
322 }
323 }
a7c10850 324
b34976b6 325 return TRUE;
252b5132
RH
326}
327
a2b0fe9d 328static bfd_vma
47b0e7ad
NC
329extract_rel_addend (bfd *abfd,
330 bfd_byte *where,
331 reloc_howto_type *howto)
a2b0fe9d
AM
332{
333 bfd_vma insn, val;
334
335 switch (howto->size)
336 {
337 case 0:
338 insn = bfd_get_8 (abfd, where);
339 break;
340 case 1:
341 insn = bfd_get_16 (abfd, where);
342 break;
343 case 2:
344 insn = bfd_get_32 (abfd, where);
345 break;
346 default:
347 abort ();
348 }
349
350 val = (insn & howto->dst_mask) >> howto->bitpos << howto->rightshift;
351 /* We should really be testing for signed addends here, but we don't
352 have that info directly in the howto. */
353 if (howto->pc_relative)
354 {
355 bfd_vma sign;
356 sign = howto->dst_mask & (~howto->dst_mask >> 1 | ~(-(bfd_vma) 1 >> 1));
357 sign = sign >> howto->bitpos << howto->rightshift;
358 val = (val ^ sign) - sign;
359 }
360 return val;
361}
362
363static void
47b0e7ad
NC
364insert_rel_addend (bfd *abfd,
365 bfd_byte *where,
366 reloc_howto_type *howto,
367 bfd_vma addend)
a2b0fe9d
AM
368{
369 bfd_vma insn;
370
371 addend = (addend >> howto->rightshift << howto->bitpos) & howto->dst_mask;
372 insn = ~howto->dst_mask;
373 switch (howto->size)
374 {
375 case 0:
376 insn &= bfd_get_8 (abfd, where);
377 insn |= addend;
378 bfd_put_8 (abfd, insn, where);
379 break;
380 case 1:
381 insn &= bfd_get_16 (abfd, where);
382 insn |= addend;
383 bfd_put_16 (abfd, insn, where);
384 break;
385 case 2:
386 insn &= bfd_get_32 (abfd, where);
387 insn |= addend;
388 bfd_put_32 (abfd, insn, where);
389 break;
390 default:
391 abort ();
392 }
393}
394
252b5132 395/* Relocate a D10V ELF section. */
47b0e7ad 396
b34976b6 397static bfd_boolean
47b0e7ad
NC
398elf32_d10v_relocate_section (bfd *output_bfd,
399 struct bfd_link_info *info,
400 bfd *input_bfd,
401 asection *input_section,
402 bfd_byte *contents,
403 Elf_Internal_Rela *relocs,
404 Elf_Internal_Sym *local_syms,
405 asection **local_sections)
252b5132
RH
406{
407 Elf_Internal_Shdr *symtab_hdr;
408 struct elf_link_hash_entry **sym_hashes;
409 Elf_Internal_Rela *rel, *relend;
410 const char *name;
411
412 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
413 sym_hashes = elf_sym_hashes (input_bfd);
414
415 rel = relocs;
416 relend = relocs + input_section->reloc_count;
417 for (; rel < relend; rel++)
418 {
419 int r_type;
420 reloc_howto_type *howto;
421 unsigned long r_symndx;
422 Elf_Internal_Sym *sym;
423 asection *sec;
424 struct elf_link_hash_entry *h;
425 bfd_vma relocation;
426 bfd_reloc_status_type r;
427
428 r_symndx = ELF32_R_SYM (rel->r_info);
429 r_type = ELF32_R_TYPE (rel->r_info);
430
431 if (r_type == R_D10V_GNU_VTENTRY
47b0e7ad 432 || r_type == R_D10V_GNU_VTINHERIT)
252b5132
RH
433 continue;
434
435 howto = elf_d10v_howto_table + r_type;
436
1049f94e 437 if (info->relocatable)
252b5132 438 {
a2b0fe9d
AM
439 bfd_vma val;
440 bfd_byte *where;
441
1049f94e 442 /* This is a relocatable link. We don't have to change
252b5132
RH
443 anything, unless the reloc is against a section symbol,
444 in which case we have to adjust according to where the
445 section symbol winds up in the output section. */
a2b0fe9d
AM
446 if (r_symndx >= symtab_hdr->sh_info)
447 continue;
252b5132 448
a2b0fe9d
AM
449 sym = local_syms + r_symndx;
450 if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
451 continue;
452
453 sec = local_sections[r_symndx];
454 val = sec->output_offset;
455 if (val == 0)
456 continue;
457
458 where = contents + rel->r_offset;
459 val += extract_rel_addend (input_bfd, where, howto);
460 insert_rel_addend (input_bfd, where, howto, val);
252b5132
RH
461 continue;
462 }
463
464 /* This is a final link. */
465 h = NULL;
466 sym = NULL;
467 sec = NULL;
468 if (r_symndx < symtab_hdr->sh_info)
469 {
470 sym = local_syms + r_symndx;
471 sec = local_sections[r_symndx];
a2b0fe9d
AM
472 relocation = (sec->output_section->vma
473 + sec->output_offset
474 + sym->st_value);
475 if ((sec->flags & SEC_MERGE)
476 && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
477 {
478 asection *msec;
479 bfd_vma addend;
480 bfd_byte *where = contents + rel->r_offset;
481
482 addend = extract_rel_addend (input_bfd, where, howto);
483 msec = sec;
484 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend);
485 addend -= relocation;
486 addend += msec->output_section->vma + msec->output_offset;
487 insert_rel_addend (input_bfd, where, howto, addend);
488 }
252b5132
RH
489 }
490 else
491 {
59c2e50f
L
492 bfd_boolean unresolved_reloc, warned;
493
b2a8e766
AM
494 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
495 r_symndx, symtab_hdr, sym_hashes,
496 h, sec, relocation,
497 unresolved_reloc, warned);
252b5132
RH
498 }
499
500 if (h != NULL)
501 name = h->root.root.string;
502 else
503 {
504 name = (bfd_elf_string_from_elf_section
505 (input_bfd, symtab_hdr->sh_link, sym->st_name));
506 if (name == NULL || *name == '\0')
507 name = bfd_section_name (input_bfd, sec);
508 }
a7c10850 509
252b5132
RH
510 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
511 contents, rel->r_offset,
a2b0fe9d 512 relocation, (bfd_vma) 0);
252b5132
RH
513
514 if (r != bfd_reloc_ok)
515 {
516 const char * msg = (const char *) 0;
517
518 switch (r)
519 {
520 case bfd_reloc_overflow:
521 if (!((*info->callbacks->reloc_overflow)
47b0e7ad 522 (info, (h ? &h->root : NULL), name, howto->name,
dfeffb9f
L
523 (bfd_vma) 0, input_bfd, input_section,
524 rel->r_offset)))
b34976b6 525 return FALSE;
252b5132
RH
526 break;
527
528 case bfd_reloc_undefined:
529 if (!((*info->callbacks->undefined_symbol)
530 (info, name, input_bfd, input_section,
b34976b6
AM
531 rel->r_offset, TRUE)))
532 return FALSE;
252b5132
RH
533 break;
534
535 case bfd_reloc_outofrange:
517662d4 536 msg = _("internal error: out of range error");
252b5132
RH
537 goto common_error;
538
539 case bfd_reloc_notsupported:
517662d4 540 msg = _("internal error: unsupported relocation error");
252b5132
RH
541 goto common_error;
542
543 case bfd_reloc_dangerous:
517662d4 544 msg = _("internal error: dangerous error");
252b5132
RH
545 goto common_error;
546
547 default:
517662d4 548 msg = _("internal error: unknown error");
252b5132
RH
549 /* fall through */
550
551 common_error:
552 if (!((*info->callbacks->warning)
553 (info, msg, name, input_bfd, input_section,
554 rel->r_offset)))
b34976b6 555 return FALSE;
252b5132
RH
556 break;
557 }
558 }
559 }
560
b34976b6 561 return TRUE;
252b5132
RH
562}
563#define ELF_ARCH bfd_arch_d10v
aa4f99bb
AO
564#define ELF_MACHINE_CODE EM_D10V
565#define ELF_MACHINE_ALT1 EM_CYGNUS_D10V
252b5132
RH
566#define ELF_MAXPAGESIZE 0x1000
567
568#define TARGET_BIG_SYM bfd_elf32_d10v_vec
569#define TARGET_BIG_NAME "elf32-d10v"
570
571#define elf_info_to_howto 0
572#define elf_info_to_howto_rel d10v_info_to_howto_rel
573#define elf_backend_object_p 0
574#define elf_backend_final_write_processing 0
575#define elf_backend_gc_mark_hook elf32_d10v_gc_mark_hook
576#define elf_backend_gc_sweep_hook elf32_d10v_gc_sweep_hook
577#define elf_backend_check_relocs elf32_d10v_check_relocs
578#define elf_backend_relocate_section elf32_d10v_relocate_section
579#define elf_backend_can_gc_sections 1
580
581#include "elf32-target.h"
This page took 0.366061 seconds and 4 git commands to generate.