elf32-visium.c revision 1.1.1.2
1/* Visium-specific support for 32-bit ELF. 2 3 Copyright (C) 2003-2015 Free Software Foundation, Inc. 4 5 This file is part of BFD, the Binary File Descriptor library. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, 20 Boston, MA 02110-1301, USA. */ 21 22#include "sysdep.h" 23#include "bfd.h" 24#include "sysdep.h" 25#include "libbfd.h" 26#include "elf-bfd.h" 27#include "elf/visium.h" 28 29static bfd_reloc_status_type visium_elf_howto_parity_reloc 30 (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **); 31 32static reloc_howto_type visium_elf_howto_table[] = { 33 /* This reloc does nothing. */ 34 HOWTO (R_VISIUM_NONE, /* type */ 35 0, /* rightshift */ 36 3, /* size (0 = byte, 1 = short, 2 = long) */ 37 0, /* bitsize */ 38 FALSE, /* pc_relative */ 39 0, /* bitpos */ 40 complain_overflow_dont, /* complain_on_overflow */ 41 bfd_elf_generic_reloc, /* special_function */ 42 "R_VISIUM_NONE", /* name */ 43 FALSE, /* partial_inplace */ 44 0, /* src_mask */ 45 0, /* dst_mask */ 46 FALSE), /* pcrel_offset */ 47 48 /* A 8 bit absolute relocation. */ 49 HOWTO (R_VISIUM_8, /* type */ 50 0, /* rightshift */ 51 0, /* size (0 = byte, 1 = short, 2 = long) */ 52 8, /* bitsize */ 53 FALSE, /* pc_relative */ 54 0, /* bitpos */ 55 complain_overflow_bitfield, /* complain_on_overflow */ 56 bfd_elf_generic_reloc, /* special_function */ 57 "R_VISIUM_8", /* name */ 58 FALSE, /* partial_inplace */ 59 0x00, /* src_mask */ 60 0xff, /* dst_mask */ 61 FALSE), /* pcrel_offset */ 62 63 /* A 16 bit absolute relocation. */ 64 HOWTO (R_VISIUM_16, /* type */ 65 0, /* rightshift */ 66 1, /* size (0 = byte, 1 = short, 2 = long) */ 67 16, /* bitsize */ 68 FALSE, /* pc_relative */ 69 0, /* bitpos */ 70 complain_overflow_bitfield, /* complain_on_overflow */ 71 bfd_elf_generic_reloc, /* special_function */ 72 "R_VISIUM_16", /* name */ 73 FALSE, /* partial_inplace */ 74 0x0000, /* src_mask */ 75 0xffff, /* dst_mask */ 76 FALSE), /* pcrel_offset */ 77 78 /* A 32 bit absolute relocation. */ 79 HOWTO (R_VISIUM_32, /* type */ 80 0, /* rightshift */ 81 2, /* size (0 = byte, 1 = short, 2 = long) */ 82 32, /* bitsize */ 83 FALSE, /* pc_relative */ 84 0, /* bitpos */ 85 complain_overflow_bitfield, /* complain_on_overflow */ 86 bfd_elf_generic_reloc, /* special_function */ 87 "R_VISIUM_32", /* name */ 88 FALSE, /* partial_inplace */ 89 0x00000000, /* src_mask */ 90 0xffffffff, /* dst_mask */ 91 FALSE), /* pcrel_offset */ 92 93 94 /* A 8 bit PC relative relocation. */ 95 HOWTO (R_VISIUM_8_PCREL, /* type */ 96 0, /* rightshift */ 97 0, /* size (0 = byte, 1 = short, 2 = long) */ 98 8, /* bitsize */ 99 TRUE, /* pc_relative */ 100 0, /* bitpos */ 101 complain_overflow_bitfield, /* complain_on_overflow */ 102 bfd_elf_generic_reloc, /* special_function */ 103 "R_VISIUM_8_PCREL", /* name */ 104 FALSE, /* partial_inplace */ 105 0x00, /* src_mask */ 106 0xff, /* dst_mask */ 107 TRUE), /* pcrel_offset */ 108 109 /* A 16 bit PC relative relocation. */ 110 HOWTO (R_VISIUM_16_PCREL, /* type */ 111 0, /* rightshift */ 112 1, /* size (0 = byte, 1 = short, 2 = long) */ 113 16, /* bitsize */ 114 TRUE, /* pc_relative */ 115 0, /* bitpos */ 116 complain_overflow_bitfield, /* complain_on_overflow */ 117 bfd_elf_generic_reloc, /* special_function */ 118 "R_VISIUM_16_PCREL", /* name */ 119 FALSE, /* partial inplace */ 120 0x0000, /* src_mask */ 121 0xffff, /* dst_mask */ 122 TRUE), /* pcrel_offset */ 123 124 /* A 32-bit PC relative relocation. */ 125 HOWTO (R_VISIUM_32_PCREL, /* type */ 126 0, /* rightshift */ 127 2, /* size (0 = byte, 1 = short, 2 = long) */ 128 32, /* bitsize */ 129 TRUE, /* pc_relative */ 130 0, /* bitpos */ 131 complain_overflow_bitfield, /* complain_on_overflow */ 132 bfd_elf_generic_reloc, /* special_function */ 133 "R_VISIUM_32_PCREL", /* name */ 134 FALSE, /* partial_inplace */ 135 0, /* src_mask */ 136 0xffffffff, /* dst_mask */ 137 TRUE), /* pcrel_offset */ 138 139 /* A 16-bit PC word relative offset, relative to start of instruction 140 and always in the second half of the instruction. */ 141 HOWTO (R_VISIUM_PC16, /* type */ 142 2, /* rightshift */ 143 2, /* size (0 = byte, 1 = short, 2 = long) */ 144 16, /* bitsize */ 145 TRUE, /* pc_relative */ 146 0, /* bitpos */ 147 complain_overflow_signed, /* complain_on_overflow */ 148 visium_elf_howto_parity_reloc, /* special_function */ 149 "R_VISIUM_PC16", /* name */ 150 FALSE, /* partial_inplace */ 151 0x00000000, /* src_mask */ 152 0x0000ffff, /* dst_mask */ 153 TRUE), /* pcrel_offset */ 154 155 /* The high 16 bits of symbol value. */ 156 HOWTO (R_VISIUM_HI16, /* type */ 157 16, /* rightshift */ 158 2, /* size (0 = byte, 1 = short, 2 = long) */ 159 16, /* bitsize */ 160 FALSE, /* pc_relative */ 161 0, /* bitpos */ 162 complain_overflow_dont, /* complain_on_overflow */ 163 visium_elf_howto_parity_reloc, /* special_function */ 164 "R_VISIUM_HI16", /* name */ 165 FALSE, /* partial_inplace */ 166 0x00000000, /* src_mask */ 167 0x0000ffff, /* dst_mask */ 168 FALSE), /* pcrel_offset */ 169 170 /* The low 16 bits of symbol value. */ 171 HOWTO (R_VISIUM_LO16, /* type */ 172 0, /* rightshift */ 173 2, /* size (0 = byte, 1 = short, 2 = long) */ 174 16, /* bitsize */ 175 FALSE, /* pc_relative */ 176 0, /* bitpos */ 177 complain_overflow_dont, /* complain_on_overflow */ 178 visium_elf_howto_parity_reloc, /* special_function */ 179 "R_VISIUM_LO16", /* name */ 180 FALSE, /* partial_inplace */ 181 0x00000000, /* src_mask */ 182 0x0000ffff, /* dst_mask */ 183 FALSE), /* pcrel_offset */ 184 185 /* A 16 bit immediate value. */ 186 HOWTO (R_VISIUM_IM16, /* type */ 187 0, /* rightshift */ 188 2, /* size (0 = byte, 1 = short, 2 = long) */ 189 16, /* bitsize */ 190 FALSE, /* pc_relative */ 191 0, /* bitpos */ 192 complain_overflow_unsigned, /* complain_on_overflow */ 193 visium_elf_howto_parity_reloc, /* special_function */ 194 "R_VISIUM_IM16", /* name */ 195 FALSE, /* partial_inplace */ 196 0x0000000, /* src_mask */ 197 0x000ffff, /* dst_mask */ 198 FALSE), /* pcrel_offset */ 199 200 /* The high 16 bits of symbol value, pc relative. */ 201 HOWTO (R_VISIUM_HI16_PCREL, /* type */ 202 16, /* rightshift */ 203 2, /* size (0 = byte, 1 = short, 2 = long) */ 204 16, /* bitsize */ 205 TRUE, /* pc_relative */ 206 0, /* bitpos */ 207 complain_overflow_dont, /* complain_on_overflow */ 208 visium_elf_howto_parity_reloc, /* special_function */ 209 "R_VISIUM_HI16_PCREL", /* name */ 210 FALSE, /* partial_inplace */ 211 0x00000000, /* src_mask */ 212 0x0000ffff, /* dst_mask */ 213 TRUE), /* pcrel_offset */ 214 215 /* The low 16 bits of symbol value, pc relative. */ 216 HOWTO (R_VISIUM_LO16_PCREL, /* type */ 217 0, /* rightshift */ 218 2, /* size (0 = byte, 1 = short, 2 = long) */ 219 16, /* bitsize */ 220 TRUE, /* pc_relative */ 221 0, /* bitpos */ 222 complain_overflow_dont, /* complain_on_overflow */ 223 visium_elf_howto_parity_reloc, /* special_function */ 224 "R_VISIUM_LO16_PCREL", /* name */ 225 FALSE, /* partial_inplace */ 226 0x00000000, /* src_mask */ 227 0x0000ffff, /* dst_mask */ 228 TRUE), /* pcrel_offset */ 229 230 /* A 16 bit immediate value, pc relative. */ 231 HOWTO (R_VISIUM_IM16_PCREL, /* type */ 232 0, /* rightshift */ 233 2, /* size (0 = byte, 1 = short, 2 = long) */ 234 16, /* bitsize */ 235 TRUE, /* pc_relative */ 236 0, /* bitpos */ 237 complain_overflow_unsigned, /* complain_on_overflow */ 238 visium_elf_howto_parity_reloc, /* special_function */ 239 "R_VISIUM_IM16_PCREL", /* name */ 240 FALSE, /* partial_inplace */ 241 0x0000000, /* src_mask */ 242 0x000ffff, /* dst_mask */ 243 TRUE), /* pcrel_offset */ 244 245}; 246 247/* GNU extension to record C++ vtable hierarchy. */ 248static reloc_howto_type visium_elf_vtinherit_howto = 249 HOWTO (R_VISIUM_GNU_VTINHERIT, /* type */ 250 0, /* rightshift */ 251 2, /* size (0 = byte, 1 = short, 2 = long) */ 252 0, /* bitsize */ 253 FALSE, /* pc_relative */ 254 0, /* bitpos */ 255 complain_overflow_dont, /* complain_on_overflow */ 256 NULL, /* special_function */ 257 "R_VISIUM_GNU_VTINHERIT", /* name */ 258 FALSE, /* partial_inplace */ 259 0, /* src_mask */ 260 0, /* dst_mask */ 261 FALSE); /* pcrel_offset */ 262 263/* GNU extension to record C++ vtable member usage. */ 264static reloc_howto_type visium_elf_vtentry_howto = 265 HOWTO (R_VISIUM_GNU_VTENTRY, /* type */ 266 0, /* rightshift */ 267 2, /* size (0 = byte, 1 = short, 2 = long) */ 268 0, /* bitsize */ 269 FALSE, /* pc_relative */ 270 0, /* bitpos */ 271 complain_overflow_dont, /* complain_on_overflow */ 272 NULL, /* special_function */ 273 "R_VISIUM_GNU_VTENTRY", /* name */ 274 FALSE, /* partial_inplace */ 275 0, /* src_mask */ 276 0, /* dst_mask */ 277 FALSE); /* pcrel_offset */ 278 279/* Map BFD reloc types to VISIUM ELF reloc types. */ 280struct visium_reloc_map 281{ 282 bfd_reloc_code_real_type bfd_reloc_val; 283 unsigned int visium_reloc_val; 284}; 285 286static const struct visium_reloc_map visium_reloc_map[] = { 287 {BFD_RELOC_NONE, R_VISIUM_NONE}, 288 {BFD_RELOC_8, R_VISIUM_8}, 289 {BFD_RELOC_16, R_VISIUM_16}, 290 {BFD_RELOC_32, R_VISIUM_32}, 291 {BFD_RELOC_8_PCREL, R_VISIUM_8_PCREL}, 292 {BFD_RELOC_16_PCREL, R_VISIUM_16_PCREL}, 293 {BFD_RELOC_32_PCREL, R_VISIUM_32_PCREL}, 294 {BFD_RELOC_VISIUM_REL16, R_VISIUM_PC16}, 295 {BFD_RELOC_VISIUM_HI16, R_VISIUM_HI16}, 296 {BFD_RELOC_VISIUM_LO16, R_VISIUM_LO16}, 297 {BFD_RELOC_VISIUM_IM16, R_VISIUM_IM16}, 298 {BFD_RELOC_VISIUM_HI16_PCREL, R_VISIUM_HI16_PCREL}, 299 {BFD_RELOC_VISIUM_LO16_PCREL, R_VISIUM_LO16_PCREL}, 300 {BFD_RELOC_VISIUM_IM16_PCREL, R_VISIUM_IM16_PCREL}, 301 {BFD_RELOC_VTABLE_INHERIT, R_VISIUM_GNU_VTINHERIT}, 302 {BFD_RELOC_VTABLE_ENTRY, R_VISIUM_GNU_VTENTRY}, 303}; 304 305/* Return the parity bit for INSN shifted to its final position. */ 306 307static bfd_vma 308visium_parity_bit (bfd_vma insn) 309{ 310 bfd_vma p = 0; 311 int i; 312 313 for (i = 0; i < 31; i++) 314 { 315 p ^= (insn & 1); 316 insn >>= 1; 317 } 318 319 return p << 31; 320} 321 322/* This "special function" will only be used when the input and 323 output files have different formats ie. when generating S-records 324 directly using "--oformat srec". Otherwise we use 325 _bfd_final_link_relocate which uses a howto structure, but does 326 not use the special_function field. 327 328 It sets instruction parity to even. This cannot be done by a howto. */ 329 330static bfd_reloc_status_type 331visium_elf_howto_parity_reloc (bfd * input_bfd, arelent *reloc_entry, 332 asymbol *symbol, PTR data, 333 asection *input_section, bfd *output_bfd, 334 char **error_message ATTRIBUTE_UNUSED) 335{ 336 bfd_reloc_status_type ret; 337 bfd_vma relocation; 338 bfd_byte *inplace_address; 339 bfd_vma insn; 340 const bfd_vma signmask = 0xffff8000; 341 342 /* This part is from bfd_elf_generic_reloc. 343 If we're relocating, and this an external symbol, we don't want 344 to change anything. */ 345 if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0) 346 { 347 reloc_entry->address += input_section->output_offset; 348 return bfd_reloc_ok; 349 } 350 351 /* Now do the reloc in the usual way. */ 352 353 /* Sanity check the address (offset in section). */ 354 if (reloc_entry->address > bfd_get_section_limit (input_bfd, input_section)) 355 return bfd_reloc_outofrange; 356 357 ret = bfd_reloc_ok; 358 if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL) 359 ret = bfd_reloc_undefined; 360 361 if (bfd_is_com_section (symbol->section) || output_bfd != (bfd *) NULL) 362 relocation = 0; 363 else 364 relocation = symbol->value; 365 366 /* Only do this for a final link. */ 367 if (output_bfd == (bfd *) NULL) 368 { 369 relocation += symbol->section->output_section->vma; 370 relocation += symbol->section->output_offset; 371 } 372 373 relocation += reloc_entry->addend; 374 inplace_address = (bfd_byte *) data + reloc_entry->address; 375 insn = bfd_get_32 (input_bfd, inplace_address); 376 377 if (reloc_entry->howto->pc_relative) 378 { 379 relocation -= input_section->output_section->vma 380 + input_section->output_offset; 381 relocation -= reloc_entry->address; 382 } 383 384 switch (reloc_entry->howto->type) 385 { 386 case R_VISIUM_PC16: 387 relocation >>= 2; 388 if (ret == bfd_reloc_ok && (relocation & signmask) != 0 389 && (relocation & signmask) != signmask) 390 ret = bfd_reloc_overflow; 391 relocation &= 0xffff; 392 break; 393 case R_VISIUM_HI16: 394 case R_VISIUM_HI16_PCREL: 395 relocation = (relocation >> 16) & 0xffff; 396 break; 397 case R_VISIUM_LO16: 398 case R_VISIUM_LO16_PCREL: 399 relocation &= 0xffff; 400 break; 401 case R_VISIUM_IM16: 402 case R_VISIUM_IM16_PCREL: 403 if (ret == bfd_reloc_ok && (relocation & 0xffff0000) != 0) 404 ret = bfd_reloc_overflow; 405 relocation &= 0xffff; 406 break; 407 } 408 insn = (insn & 0x7fff0000) | relocation; 409 insn |= visium_parity_bit (insn); 410 bfd_put_32 (input_bfd, insn, inplace_address); 411 412 if (output_bfd != (bfd *) NULL) 413 reloc_entry->address += input_section->output_offset; 414 415 return ret; 416} 417 418static reloc_howto_type * 419visium_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 420 bfd_reloc_code_real_type code) 421{ 422 /* Note that the visium_elf_howto_table is indexed by the R_ 423 constants. Thus, the order that the howto records appear in the 424 table *must* match the order of the relocation types defined in 425 include/elf/visium.h. */ 426 switch (code) 427 { 428 case BFD_RELOC_NONE: 429 return &visium_elf_howto_table[(int) R_VISIUM_NONE]; 430 case BFD_RELOC_8: 431 return &visium_elf_howto_table[(int) R_VISIUM_8]; 432 case BFD_RELOC_16: 433 return &visium_elf_howto_table[(int) R_VISIUM_16]; 434 case BFD_RELOC_32: 435 return &visium_elf_howto_table[(int) R_VISIUM_32]; 436 case BFD_RELOC_8_PCREL: 437 return &visium_elf_howto_table[(int) R_VISIUM_8_PCREL]; 438 case BFD_RELOC_16_PCREL: 439 return &visium_elf_howto_table[(int) R_VISIUM_16_PCREL]; 440 case BFD_RELOC_32_PCREL: 441 return &visium_elf_howto_table[(int) R_VISIUM_32_PCREL]; 442 case BFD_RELOC_VISIUM_REL16: 443 return &visium_elf_howto_table[(int) R_VISIUM_PC16]; 444 case BFD_RELOC_VISIUM_HI16: 445 return &visium_elf_howto_table[(int) R_VISIUM_HI16]; 446 case BFD_RELOC_VISIUM_LO16: 447 return &visium_elf_howto_table[(int) R_VISIUM_LO16]; 448 case BFD_RELOC_VISIUM_IM16: 449 return &visium_elf_howto_table[(int) R_VISIUM_IM16]; 450 case BFD_RELOC_VISIUM_HI16_PCREL: 451 return &visium_elf_howto_table[(int) R_VISIUM_HI16_PCREL]; 452 case BFD_RELOC_VISIUM_LO16_PCREL: 453 return &visium_elf_howto_table[(int) R_VISIUM_LO16_PCREL]; 454 case BFD_RELOC_VISIUM_IM16_PCREL: 455 return &visium_elf_howto_table[(int) R_VISIUM_IM16_PCREL]; 456 case BFD_RELOC_VTABLE_INHERIT: 457 return &visium_elf_vtinherit_howto; 458 case BFD_RELOC_VTABLE_ENTRY: 459 return &visium_elf_vtentry_howto; 460 default: 461 return NULL; 462 } 463} 464 465static reloc_howto_type * 466visium_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 467{ 468 unsigned int i; 469 470 for (i = 0; 471 i < (sizeof (visium_elf_howto_table) 472 / sizeof (visium_elf_howto_table[0])); i++) 473 if (visium_elf_howto_table[i].name != NULL 474 && strcasecmp (visium_elf_howto_table[i].name, r_name) == 0) 475 return &visium_elf_howto_table[i]; 476 477 if (strcasecmp (visium_elf_vtinherit_howto.name, r_name) == 0) 478 return &visium_elf_vtinherit_howto; 479 if (strcasecmp (visium_elf_vtentry_howto.name, r_name) == 0) 480 return &visium_elf_vtentry_howto; 481 482 return NULL; 483} 484 485/* Set the howto pointer for a VISIUM ELF reloc. */ 486 487static void 488visium_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, 489 Elf_Internal_Rela *dst) 490{ 491 unsigned int r_type = ELF32_R_TYPE (dst->r_info); 492 493 switch (r_type) 494 { 495 case R_VISIUM_GNU_VTINHERIT: 496 cache_ptr->howto = &visium_elf_vtinherit_howto; 497 break; 498 499 case R_VISIUM_GNU_VTENTRY: 500 cache_ptr->howto = &visium_elf_vtentry_howto; 501 break; 502 503 default: 504 if (r_type >= (unsigned int) R_VISIUM_max) 505 { 506 _bfd_error_handler (_("%B: invalid Visium reloc number: %d"), abfd, r_type); 507 r_type = 0; 508 } 509 cache_ptr->howto = &visium_elf_howto_table[r_type]; 510 break; 511 } 512} 513 514/* Look through the relocs for a section during the first phase. 515 Since we don't do .gots or .plts, we just need to consider the 516 virtual table relocs for gc. */ 517 518static bfd_boolean 519visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 520 asection *sec, const Elf_Internal_Rela *relocs) 521{ 522 Elf_Internal_Shdr *symtab_hdr; 523 struct elf_link_hash_entry **sym_hashes; 524 const Elf_Internal_Rela *rel; 525 const Elf_Internal_Rela *rel_end; 526 527 if (info->relocatable) 528 return TRUE; 529 530 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 531 sym_hashes = elf_sym_hashes (abfd); 532 533 rel_end = relocs + sec->reloc_count; 534 for (rel = relocs; rel < rel_end; rel++) 535 { 536 struct elf_link_hash_entry *h; 537 unsigned long r_symndx; 538 539 r_symndx = ELF32_R_SYM (rel->r_info); 540 if (r_symndx < symtab_hdr->sh_info) 541 h = NULL; 542 else 543 { 544 h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 545 while (h->root.type == bfd_link_hash_indirect 546 || h->root.type == bfd_link_hash_warning) 547 h = (struct elf_link_hash_entry *) h->root.u.i.link; 548 } 549 550 switch (ELF32_R_TYPE (rel->r_info)) 551 { 552 /* This relocation describes the C++ object vtable hierarchy. 553 Reconstruct it for later use during GC. */ 554 case R_VISIUM_GNU_VTINHERIT: 555 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 556 return FALSE; 557 break; 558 559 /* This relocation describes which C++ vtable entries are actually 560 used. Record for later use during GC. */ 561 case R_VISIUM_GNU_VTENTRY: 562 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 563 return FALSE; 564 break; 565 } 566 } 567 568 return TRUE; 569} 570 571/* Relocate a VISIUM ELF section. */ 572 573static bfd_boolean 574visium_elf_relocate_section (bfd *output_bfd, 575 struct bfd_link_info *info, bfd *input_bfd, 576 asection *input_section, bfd_byte *contents, 577 Elf_Internal_Rela *relocs, 578 Elf_Internal_Sym *local_syms, 579 asection **local_sections) 580{ 581 Elf_Internal_Shdr *symtab_hdr; 582 struct elf_link_hash_entry **sym_hashes; 583 Elf_Internal_Rela *rel; 584 Elf_Internal_Rela *relend; 585 586 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 587 sym_hashes = elf_sym_hashes (input_bfd); 588 relend = relocs + input_section->reloc_count; 589 590 for (rel = relocs; rel < relend; rel++) 591 { 592 reloc_howto_type *howto; 593 unsigned long r_symndx; 594 Elf_Internal_Sym *sym; 595 asection *sec; 596 struct elf_link_hash_entry *h; 597 bfd_vma relocation; 598 bfd_reloc_status_type r; 599 const char *name = NULL; 600 int r_type; 601 bfd_vma insn; 602 603 r_type = ELF32_R_TYPE (rel->r_info); 604 605 if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY) 606 continue; 607 608 r_symndx = ELF32_R_SYM (rel->r_info); 609 610 howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info); 611 h = NULL; 612 sym = NULL; 613 sec = NULL; 614 615 if (r_symndx < symtab_hdr->sh_info) 616 { 617 /* This is a local symbol. */ 618 sym = local_syms + r_symndx; 619 sec = local_sections[r_symndx]; 620 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 621 622 name = bfd_elf_string_from_elf_section 623 (input_bfd, symtab_hdr->sh_link, sym->st_name); 624 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; 625 } 626 else 627 { 628 bfd_boolean unresolved_reloc; 629 bfd_boolean warned, ignored; 630 631 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 632 r_symndx, symtab_hdr, sym_hashes, 633 h, sec, relocation, 634 unresolved_reloc, warned, ignored); 635 636 name = h->root.root.string; 637 } 638 639 if (sec != NULL && discarded_section (sec)) 640 { 641 /* For relocs against symbols from removed linkonce sections, 642 or sections discarded by a linker script, we just want the 643 section contents zeroed. Avoid any special processing. */ 644 _bfd_clear_contents (howto, input_bfd, input_section, 645 contents + rel->r_offset); 646 647 rel->r_info = 0; 648 rel->r_addend = 0; 649 continue; 650 } 651 652 if (info->relocatable) 653 continue; 654 655 switch (r_type) 656 { 657 case R_VISIUM_PC16: 658 case R_VISIUM_HI16: 659 case R_VISIUM_LO16: 660 case R_VISIUM_IM16: 661 case R_VISIUM_HI16_PCREL: 662 case R_VISIUM_LO16_PCREL: 663 case R_VISIUM_IM16_PCREL: 664 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 665 contents, rel->r_offset, 666 relocation, rel->r_addend); 667 668 /* For instruction relocations, the parity needs correcting. */ 669 if (r == bfd_reloc_ok) 670 { 671 insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 672 insn = (insn & 0x7fffffff) | visium_parity_bit (insn); 673 bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 674 } 675 break; 676 677 default: 678 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 679 contents, rel->r_offset, 680 relocation, rel->r_addend); 681 break; 682 } 683 684 if (r != bfd_reloc_ok) 685 { 686 const char *msg = (const char *) NULL; 687 688 switch (r) 689 { 690 case bfd_reloc_overflow: 691 r = info->callbacks->reloc_overflow 692 (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, 693 input_bfd, input_section, rel->r_offset); 694 break; 695 696 case bfd_reloc_undefined: 697 r = info->callbacks->undefined_symbol 698 (info, name, input_bfd, input_section, rel->r_offset, TRUE); 699 break; 700 701 case bfd_reloc_outofrange: 702 msg = _("internal error: out of range error"); 703 break; 704 705 case bfd_reloc_notsupported: 706 msg = _("internal error: unsupported relocation error"); 707 break; 708 709 case bfd_reloc_dangerous: 710 msg = _("internal error: dangerous relocation"); 711 break; 712 713 default: 714 msg = _("internal error: unknown error"); 715 break; 716 } 717 718 if (msg) 719 r = info->callbacks->warning 720 (info, msg, name, input_bfd, input_section, rel->r_offset); 721 722 if (!r) 723 return FALSE; 724 } 725 } 726 727 return TRUE; 728} 729 730/* This function is called during section gc to discover the section a 731 to which a particular relocation refers. Return the section that 732 should be marked against GC for a given relocation. */ 733 734static asection * 735visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, 736 Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, 737 Elf_Internal_Sym *sym) 738{ 739 if (h != NULL) 740 switch (ELF32_R_TYPE (rel->r_info)) 741 { 742 case R_VISIUM_GNU_VTINHERIT: 743 case R_VISIUM_GNU_VTENTRY: 744 return NULL; 745 } 746 747 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 748} 749 750static void 751visium_elf_post_process_headers (bfd *abfd, 752 struct bfd_link_info *info ATTRIBUTE_UNUSED) 753{ 754 Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); 755 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE; 756 i_ehdrp->e_ident[EI_ABIVERSION] = 1; 757} 758 759/* Function to set the ELF flag bits. */ 760 761static bfd_boolean 762visium_elf_set_private_flags (bfd *abfd, flagword flags) 763{ 764 elf_elfheader (abfd)->e_flags = flags; 765 elf_flags_init (abfd) = TRUE; 766 return TRUE; 767} 768 769/* Copy backend specific data from one object module to another. */ 770 771static bfd_boolean 772visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) 773{ 774 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 775 || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 776 return TRUE; 777 778 BFD_ASSERT (!elf_flags_init (obfd) 779 || elf_elfheader (obfd)->e_flags == 780 elf_elfheader (ibfd)->e_flags); 781 782 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; 783 elf_flags_init (obfd) = TRUE; 784 785 /* Copy object attributes. */ 786 _bfd_elf_copy_obj_attributes (ibfd, obfd); 787 788 return TRUE; 789} 790 791/* Merge backend specific data from an object 792 file to the output object file when linking. */ 793 794static bfd_boolean 795visium_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) 796{ 797 flagword old_flags; 798 flagword new_flags; 799 flagword mismatch; 800 const char *opt_arch = NULL; 801 const char *new_opt_with = NULL; 802 const char *old_opt_with = NULL; 803 const char *with = "with"; 804 const char *without = "without"; 805 const char *mcm = "mcm"; 806 const char *mcm24 = "mcm24"; 807 const char *gr6 = "gr6"; 808 809 new_flags = elf_elfheader (ibfd)->e_flags; 810 old_flags = elf_elfheader (obfd)->e_flags; 811 812 if (!elf_flags_init (obfd)) 813 { 814 /* First call, no flags set. */ 815 elf_flags_init (obfd) = TRUE; 816 elf_elfheader (obfd)->e_flags = new_flags; 817 } 818 else 819 { 820 mismatch = (new_flags ^ old_flags) 821 & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6); 822 if (mismatch & EF_VISIUM_ARCH_GR6) 823 { 824 opt_arch = gr6; 825 new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without; 826 old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without; 827 } 828 else if (mismatch & EF_VISIUM_ARCH_MCM) 829 { 830 opt_arch = mcm; 831 new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without; 832 old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without; 833 } 834 else if (mismatch & EF_VISIUM_ARCH_MCM24) 835 { 836 opt_arch = mcm24; 837 new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 838 old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 839 } 840 841 if (mismatch) 842 _bfd_error_handler 843 (_ 844 ("%s: compiled %s -mtune=%s and linked with modules" 845 " compiled %s -mtune=%s"), 846 bfd_get_filename (ibfd), new_opt_with, opt_arch, old_opt_with, 847 opt_arch); 848 } 849 850 return TRUE; 851} 852 853static bfd_boolean 854visium_elf_print_private_bfd_data (bfd *abfd, void *ptr) 855{ 856 FILE *file = (FILE *) ptr; 857 flagword flags; 858 859 BFD_ASSERT (abfd != NULL && ptr != NULL); 860 861 /* Print normal ELF private data. */ 862 _bfd_elf_print_private_bfd_data (abfd, ptr); 863 864 flags = elf_elfheader (abfd)->e_flags; 865 fprintf (file, _("private flags = 0x%lx:"), (long) flags); 866 867 if (flags & EF_VISIUM_ARCH_GR6) 868 fprintf (file, " -mtune=gr6"); 869 else if (flags & EF_VISIUM_ARCH_MCM) 870 fprintf (file, " -mtune=mcm"); 871 else if (flags & EF_VISIUM_ARCH_MCM24) 872 fprintf (file, " -mtune=mcm24"); 873 874 fputc ('\n', file); 875 return TRUE; 876} 877 878#define ELF_ARCH bfd_arch_visium 879#define ELF_MACHINE_CODE EM_VISIUM 880#define ELF_MAXPAGESIZE 1 881 882#define TARGET_BIG_SYM visium_elf32_vec 883#define TARGET_BIG_NAME "elf32-visium" 884 885#define elf_info_to_howto_rel NULL 886#define elf_info_to_howto visium_info_to_howto_rela 887#define elf_backend_relocate_section visium_elf_relocate_section 888#define elf_backend_gc_mark_hook visium_elf_gc_mark_hook 889#define elf_backend_check_relocs visium_elf_check_relocs 890#define elf_backend_rela_normal 1 891 892#define elf_backend_can_gc_sections 1 893 894#define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup 895#define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup 896 897#define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags 898#define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data 899#define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data 900#define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data 901#define elf_backend_post_process_headers visium_elf_post_process_headers 902 903#include "elf32-target.h" 904