Revert the value change of DT_ENCODING from 2003-01-17. Luckily (and
[deliverable/binutils-gdb.git] / bfd / elf32-d10v.c
CommitLineData
252b5132 1/* D10V-specific support for 32-bit ELF
ab96bf03
AM
2 Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3 2007 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
157090f7
AM
206static reloc_howto_type *
207bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
208 const char *r_name)
209{
210 unsigned int i;
211
212 for (i = 0;
213 i < sizeof (elf_d10v_howto_table) / sizeof (elf_d10v_howto_table[0]);
214 i++)
215 if (elf_d10v_howto_table[i].name != NULL
216 && strcasecmp (elf_d10v_howto_table[i].name, r_name) == 0)
217 return &elf_d10v_howto_table[i];
218
219 return NULL;
220}
221
252b5132
RH
222/* Set the howto pointer for an D10V ELF reloc. */
223
224static void
47b0e7ad
NC
225d10v_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
226 arelent *cache_ptr,
227 Elf_Internal_Rela *dst)
252b5132
RH
228{
229 unsigned int r_type;
230
231 r_type = ELF32_R_TYPE (dst->r_info);
232 BFD_ASSERT (r_type < (unsigned int) R_D10V_max);
233 cache_ptr->howto = &elf_d10v_howto_table[r_type];
234}
235
236static asection *
47b0e7ad 237elf32_d10v_gc_mark_hook (asection *sec,
07adf181 238 struct bfd_link_info *info,
47b0e7ad
NC
239 Elf_Internal_Rela *rel,
240 struct elf_link_hash_entry *h,
241 Elf_Internal_Sym *sym)
252b5132
RH
242{
243 if (h != NULL)
07adf181 244 switch (ELF32_R_TYPE (rel->r_info))
252b5132
RH
245 {
246 case R_D10V_GNU_VTINHERIT:
247 case R_D10V_GNU_VTENTRY:
07adf181
AM
248 return NULL;
249 }
1e2f5b6e 250
07adf181 251 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
252b5132
RH
252}
253
254/* Look through the relocs for a section during the first phase.
255 Since we don't do .gots or .plts, we just need to consider the
256 virtual table relocs for gc. */
a7c10850 257
b34976b6 258static bfd_boolean
47b0e7ad
NC
259elf32_d10v_check_relocs (bfd *abfd,
260 struct bfd_link_info *info,
261 asection *sec,
262 const Elf_Internal_Rela *relocs)
252b5132
RH
263{
264 Elf_Internal_Shdr *symtab_hdr;
265 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
266 const Elf_Internal_Rela *rel;
267 const Elf_Internal_Rela *rel_end;
a7c10850 268
1049f94e 269 if (info->relocatable)
b34976b6 270 return TRUE;
a7c10850 271
252b5132
RH
272 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
273 sym_hashes = elf_sym_hashes (abfd);
a7c10850 274 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym);
252b5132
RH
275 if (!elf_bad_symtab (abfd))
276 sym_hashes_end -= symtab_hdr->sh_info;
a7c10850 277
252b5132
RH
278 rel_end = relocs + sec->reloc_count;
279 for (rel = relocs; rel < rel_end; rel++)
280 {
281 struct elf_link_hash_entry *h;
282 unsigned long r_symndx;
a7c10850 283
252b5132
RH
284 r_symndx = ELF32_R_SYM (rel->r_info);
285 if (r_symndx < symtab_hdr->sh_info)
286 h = NULL;
287 else
973a3492
L
288 {
289 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
290 while (h->root.type == bfd_link_hash_indirect
291 || h->root.type == bfd_link_hash_warning)
292 h = (struct elf_link_hash_entry *) h->root.u.i.link;
293 }
a7c10850 294
252b5132
RH
295 switch (ELF32_R_TYPE (rel->r_info))
296 {
297 /* This relocation describes the C++ object vtable hierarchy.
298 Reconstruct it for later use during GC. */
299 case R_D10V_GNU_VTINHERIT:
c152c796 300 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
b34976b6 301 return FALSE;
252b5132 302 break;
a7c10850 303
252b5132
RH
304 /* This relocation describes which C++ vtable entries are actually
305 used. Record for later use during GC. */
306 case R_D10V_GNU_VTENTRY:
c152c796 307 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset))
b34976b6 308 return FALSE;
252b5132
RH
309 break;
310 }
311 }
a7c10850 312
b34976b6 313 return TRUE;
252b5132
RH
314}
315
a2b0fe9d 316static bfd_vma
47b0e7ad
NC
317extract_rel_addend (bfd *abfd,
318 bfd_byte *where,
319 reloc_howto_type *howto)
a2b0fe9d
AM
320{
321 bfd_vma insn, val;
322
323 switch (howto->size)
324 {
325 case 0:
326 insn = bfd_get_8 (abfd, where);
327 break;
328 case 1:
329 insn = bfd_get_16 (abfd, where);
330 break;
331 case 2:
332 insn = bfd_get_32 (abfd, where);
333 break;
334 default:
335 abort ();
336 }
337
338 val = (insn & howto->dst_mask) >> howto->bitpos << howto->rightshift;
339 /* We should really be testing for signed addends here, but we don't
340 have that info directly in the howto. */
341 if (howto->pc_relative)
342 {
343 bfd_vma sign;
344 sign = howto->dst_mask & (~howto->dst_mask >> 1 | ~(-(bfd_vma) 1 >> 1));
345 sign = sign >> howto->bitpos << howto->rightshift;
346 val = (val ^ sign) - sign;
347 }
348 return val;
349}
350
351static void
47b0e7ad
NC
352insert_rel_addend (bfd *abfd,
353 bfd_byte *where,
354 reloc_howto_type *howto,
355 bfd_vma addend)
a2b0fe9d
AM
356{
357 bfd_vma insn;
358
359 addend = (addend >> howto->rightshift << howto->bitpos) & howto->dst_mask;
360 insn = ~howto->dst_mask;
361 switch (howto->size)
362 {
363 case 0:
364 insn &= bfd_get_8 (abfd, where);
365 insn |= addend;
366 bfd_put_8 (abfd, insn, where);
367 break;
368 case 1:
369 insn &= bfd_get_16 (abfd, where);
370 insn |= addend;
371 bfd_put_16 (abfd, insn, where);
372 break;
373 case 2:
374 insn &= bfd_get_32 (abfd, where);
375 insn |= addend;
376 bfd_put_32 (abfd, insn, where);
377 break;
378 default:
379 abort ();
380 }
381}
382
252b5132 383/* Relocate a D10V ELF section. */
47b0e7ad 384
b34976b6 385static bfd_boolean
47b0e7ad
NC
386elf32_d10v_relocate_section (bfd *output_bfd,
387 struct bfd_link_info *info,
388 bfd *input_bfd,
389 asection *input_section,
390 bfd_byte *contents,
391 Elf_Internal_Rela *relocs,
392 Elf_Internal_Sym *local_syms,
393 asection **local_sections)
252b5132
RH
394{
395 Elf_Internal_Shdr *symtab_hdr;
396 struct elf_link_hash_entry **sym_hashes;
397 Elf_Internal_Rela *rel, *relend;
398 const char *name;
399
400 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
401 sym_hashes = elf_sym_hashes (input_bfd);
402
403 rel = relocs;
404 relend = relocs + input_section->reloc_count;
405 for (; rel < relend; rel++)
406 {
407 int r_type;
408 reloc_howto_type *howto;
409 unsigned long r_symndx;
410 Elf_Internal_Sym *sym;
411 asection *sec;
412 struct elf_link_hash_entry *h;
413 bfd_vma relocation;
414 bfd_reloc_status_type r;
415
416 r_symndx = ELF32_R_SYM (rel->r_info);
417 r_type = ELF32_R_TYPE (rel->r_info);
418
419 if (r_type == R_D10V_GNU_VTENTRY
47b0e7ad 420 || r_type == R_D10V_GNU_VTINHERIT)
252b5132
RH
421 continue;
422
423 howto = elf_d10v_howto_table + r_type;
252b5132
RH
424 h = NULL;
425 sym = NULL;
426 sec = NULL;
427 if (r_symndx < symtab_hdr->sh_info)
428 {
429 sym = local_syms + r_symndx;
430 sec = local_sections[r_symndx];
a2b0fe9d
AM
431 relocation = (sec->output_section->vma
432 + sec->output_offset
433 + sym->st_value);
ab96bf03
AM
434 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION
435 && ((sec->flags & SEC_MERGE) != 0
436 || (info->relocatable
437 && sec->output_offset != 0)))
a2b0fe9d 438 {
a2b0fe9d
AM
439 bfd_vma addend;
440 bfd_byte *where = contents + rel->r_offset;
441
442 addend = extract_rel_addend (input_bfd, where, howto);
ab96bf03
AM
443
444 if (info->relocatable)
445 addend += sec->output_offset;
446 else
447 {
448 asection *msec = sec;
449 addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec,
450 addend);
451 addend -= relocation;
452 addend += msec->output_section->vma + msec->output_offset;
453 }
a2b0fe9d
AM
454 insert_rel_addend (input_bfd, where, howto, addend);
455 }
252b5132
RH
456 }
457 else
458 {
59c2e50f
L
459 bfd_boolean unresolved_reloc, warned;
460
b2a8e766
AM
461 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
462 r_symndx, symtab_hdr, sym_hashes,
463 h, sec, relocation,
464 unresolved_reloc, warned);
252b5132
RH
465 }
466
ab96bf03 467 if (sec != NULL && elf_discarded_section (sec))
b1e24c02 468 {
ab96bf03
AM
469 /* For relocs against symbols from removed linkonce sections,
470 or sections discarded by a linker script, we just want the
471 section contents zeroed. Avoid any special processing. */
b1e24c02 472 _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
ab96bf03
AM
473 rel->r_info = 0;
474 rel->r_addend = 0;
b1e24c02
DJ
475 continue;
476 }
477
ab96bf03
AM
478 if (info->relocatable)
479 continue;
480
252b5132
RH
481 if (h != NULL)
482 name = h->root.root.string;
483 else
484 {
485 name = (bfd_elf_string_from_elf_section
486 (input_bfd, symtab_hdr->sh_link, sym->st_name));
487 if (name == NULL || *name == '\0')
488 name = bfd_section_name (input_bfd, sec);
489 }
a7c10850 490
252b5132
RH
491 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
492 contents, rel->r_offset,
a2b0fe9d 493 relocation, (bfd_vma) 0);
252b5132
RH
494
495 if (r != bfd_reloc_ok)
496 {
497 const char * msg = (const char *) 0;
498
499 switch (r)
500 {
501 case bfd_reloc_overflow:
502 if (!((*info->callbacks->reloc_overflow)
47b0e7ad 503 (info, (h ? &h->root : NULL), name, howto->name,
dfeffb9f
L
504 (bfd_vma) 0, input_bfd, input_section,
505 rel->r_offset)))
b34976b6 506 return FALSE;
252b5132
RH
507 break;
508
509 case bfd_reloc_undefined:
510 if (!((*info->callbacks->undefined_symbol)
511 (info, name, input_bfd, input_section,
b34976b6
AM
512 rel->r_offset, TRUE)))
513 return FALSE;
252b5132
RH
514 break;
515
516 case bfd_reloc_outofrange:
517662d4 517 msg = _("internal error: out of range error");
252b5132
RH
518 goto common_error;
519
520 case bfd_reloc_notsupported:
517662d4 521 msg = _("internal error: unsupported relocation error");
252b5132
RH
522 goto common_error;
523
524 case bfd_reloc_dangerous:
517662d4 525 msg = _("internal error: dangerous error");
252b5132
RH
526 goto common_error;
527
528 default:
517662d4 529 msg = _("internal error: unknown error");
252b5132
RH
530 /* fall through */
531
532 common_error:
533 if (!((*info->callbacks->warning)
534 (info, msg, name, input_bfd, input_section,
535 rel->r_offset)))
b34976b6 536 return FALSE;
252b5132
RH
537 break;
538 }
539 }
540 }
541
b34976b6 542 return TRUE;
252b5132
RH
543}
544#define ELF_ARCH bfd_arch_d10v
aa4f99bb
AO
545#define ELF_MACHINE_CODE EM_D10V
546#define ELF_MACHINE_ALT1 EM_CYGNUS_D10V
252b5132
RH
547#define ELF_MAXPAGESIZE 0x1000
548
549#define TARGET_BIG_SYM bfd_elf32_d10v_vec
550#define TARGET_BIG_NAME "elf32-d10v"
551
552#define elf_info_to_howto 0
553#define elf_info_to_howto_rel d10v_info_to_howto_rel
554#define elf_backend_object_p 0
555#define elf_backend_final_write_processing 0
556#define elf_backend_gc_mark_hook elf32_d10v_gc_mark_hook
252b5132
RH
557#define elf_backend_check_relocs elf32_d10v_check_relocs
558#define elf_backend_relocate_section elf32_d10v_relocate_section
559#define elf_backend_can_gc_sections 1
560
561#include "elf32-target.h"
This page took 0.445846 seconds and 4 git commands to generate.