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