elf32-visium.c revision 1.1.1.2
1/* Visium-specific support for 32-bit ELF. 2 3 Copyright (C) 2003-2016 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/* Return the parity bit for INSN shifted to its final position. */ 280 281static bfd_vma 282visium_parity_bit (bfd_vma insn) 283{ 284 bfd_vma p = 0; 285 int i; 286 287 for (i = 0; i < 31; i++) 288 { 289 p ^= (insn & 1); 290 insn >>= 1; 291 } 292 293 return p << 31; 294} 295 296/* This "special function" will only be used when the input and 297 output files have different formats ie. when generating S-records 298 directly using "--oformat srec". Otherwise we use 299 _bfd_final_link_relocate which uses a howto structure, but does 300 not use the special_function field. 301 302 It sets instruction parity to even. This cannot be done by a howto. */ 303 304static bfd_reloc_status_type 305visium_elf_howto_parity_reloc (bfd * input_bfd, arelent *reloc_entry, 306 asymbol *symbol, PTR data, 307 asection *input_section, bfd *output_bfd, 308 char **error_message ATTRIBUTE_UNUSED) 309{ 310 bfd_reloc_status_type ret; 311 bfd_vma relocation; 312 bfd_byte *inplace_address; 313 bfd_vma insn; 314 const bfd_vma signmask = 0xffff8000; 315 316 /* This part is from bfd_elf_generic_reloc. 317 If we're relocating, and this an external symbol, we don't want 318 to change anything. */ 319 if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0) 320 { 321 reloc_entry->address += input_section->output_offset; 322 return bfd_reloc_ok; 323 } 324 325 /* Now do the reloc in the usual way. */ 326 327 /* Sanity check the address (offset in section). */ 328 if (reloc_entry->address > bfd_get_section_limit (input_bfd, input_section)) 329 return bfd_reloc_outofrange; 330 331 ret = bfd_reloc_ok; 332 if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL) 333 ret = bfd_reloc_undefined; 334 335 if (bfd_is_com_section (symbol->section) || output_bfd != (bfd *) NULL) 336 relocation = 0; 337 else 338 relocation = symbol->value; 339 340 /* Only do this for a final link. */ 341 if (output_bfd == (bfd *) NULL) 342 { 343 relocation += symbol->section->output_section->vma; 344 relocation += symbol->section->output_offset; 345 } 346 347 relocation += reloc_entry->addend; 348 inplace_address = (bfd_byte *) data + reloc_entry->address; 349 insn = bfd_get_32 (input_bfd, inplace_address); 350 351 if (reloc_entry->howto->pc_relative) 352 { 353 relocation -= input_section->output_section->vma 354 + input_section->output_offset; 355 relocation -= reloc_entry->address; 356 } 357 358 switch (reloc_entry->howto->type) 359 { 360 case R_VISIUM_PC16: 361 relocation >>= 2; 362 if (ret == bfd_reloc_ok && (relocation & signmask) != 0 363 && (relocation & signmask) != signmask) 364 ret = bfd_reloc_overflow; 365 relocation &= 0xffff; 366 break; 367 case R_VISIUM_HI16: 368 case R_VISIUM_HI16_PCREL: 369 relocation = (relocation >> 16) & 0xffff; 370 break; 371 case R_VISIUM_LO16: 372 case R_VISIUM_LO16_PCREL: 373 relocation &= 0xffff; 374 break; 375 case R_VISIUM_IM16: 376 case R_VISIUM_IM16_PCREL: 377 if (ret == bfd_reloc_ok && (relocation & 0xffff0000) != 0) 378 ret = bfd_reloc_overflow; 379 relocation &= 0xffff; 380 break; 381 } 382 insn = (insn & 0x7fff0000) | relocation; 383 insn |= visium_parity_bit (insn); 384 bfd_put_32 (input_bfd, insn, inplace_address); 385 386 if (output_bfd != (bfd *) NULL) 387 reloc_entry->address += input_section->output_offset; 388 389 return ret; 390} 391 392static reloc_howto_type * 393visium_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 394 bfd_reloc_code_real_type code) 395{ 396 /* Note that the visium_elf_howto_table is indexed by the R_ 397 constants. Thus, the order that the howto records appear in the 398 table *must* match the order of the relocation types defined in 399 include/elf/visium.h. */ 400 switch (code) 401 { 402 case BFD_RELOC_NONE: 403 return &visium_elf_howto_table[(int) R_VISIUM_NONE]; 404 case BFD_RELOC_8: 405 return &visium_elf_howto_table[(int) R_VISIUM_8]; 406 case BFD_RELOC_16: 407 return &visium_elf_howto_table[(int) R_VISIUM_16]; 408 case BFD_RELOC_32: 409 return &visium_elf_howto_table[(int) R_VISIUM_32]; 410 case BFD_RELOC_8_PCREL: 411 return &visium_elf_howto_table[(int) R_VISIUM_8_PCREL]; 412 case BFD_RELOC_16_PCREL: 413 return &visium_elf_howto_table[(int) R_VISIUM_16_PCREL]; 414 case BFD_RELOC_32_PCREL: 415 return &visium_elf_howto_table[(int) R_VISIUM_32_PCREL]; 416 case BFD_RELOC_VISIUM_REL16: 417 return &visium_elf_howto_table[(int) R_VISIUM_PC16]; 418 case BFD_RELOC_VISIUM_HI16: 419 return &visium_elf_howto_table[(int) R_VISIUM_HI16]; 420 case BFD_RELOC_VISIUM_LO16: 421 return &visium_elf_howto_table[(int) R_VISIUM_LO16]; 422 case BFD_RELOC_VISIUM_IM16: 423 return &visium_elf_howto_table[(int) R_VISIUM_IM16]; 424 case BFD_RELOC_VISIUM_HI16_PCREL: 425 return &visium_elf_howto_table[(int) R_VISIUM_HI16_PCREL]; 426 case BFD_RELOC_VISIUM_LO16_PCREL: 427 return &visium_elf_howto_table[(int) R_VISIUM_LO16_PCREL]; 428 case BFD_RELOC_VISIUM_IM16_PCREL: 429 return &visium_elf_howto_table[(int) R_VISIUM_IM16_PCREL]; 430 case BFD_RELOC_VTABLE_INHERIT: 431 return &visium_elf_vtinherit_howto; 432 case BFD_RELOC_VTABLE_ENTRY: 433 return &visium_elf_vtentry_howto; 434 default: 435 return NULL; 436 } 437} 438 439static reloc_howto_type * 440visium_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 441{ 442 unsigned int i; 443 444 for (i = 0; 445 i < (sizeof (visium_elf_howto_table) 446 / sizeof (visium_elf_howto_table[0])); i++) 447 if (visium_elf_howto_table[i].name != NULL 448 && strcasecmp (visium_elf_howto_table[i].name, r_name) == 0) 449 return &visium_elf_howto_table[i]; 450 451 if (strcasecmp (visium_elf_vtinherit_howto.name, r_name) == 0) 452 return &visium_elf_vtinherit_howto; 453 if (strcasecmp (visium_elf_vtentry_howto.name, r_name) == 0) 454 return &visium_elf_vtentry_howto; 455 456 return NULL; 457} 458 459/* Set the howto pointer for a VISIUM ELF reloc. */ 460 461static void 462visium_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr, 463 Elf_Internal_Rela *dst) 464{ 465 unsigned int r_type = ELF32_R_TYPE (dst->r_info); 466 467 switch (r_type) 468 { 469 case R_VISIUM_GNU_VTINHERIT: 470 cache_ptr->howto = &visium_elf_vtinherit_howto; 471 break; 472 473 case R_VISIUM_GNU_VTENTRY: 474 cache_ptr->howto = &visium_elf_vtentry_howto; 475 break; 476 477 default: 478 if (r_type >= (unsigned int) R_VISIUM_max) 479 { 480 _bfd_error_handler (_("%B: invalid Visium reloc number: %d"), abfd, r_type); 481 r_type = 0; 482 } 483 cache_ptr->howto = &visium_elf_howto_table[r_type]; 484 break; 485 } 486} 487 488/* Look through the relocs for a section during the first phase. 489 Since we don't do .gots or .plts, we just need to consider the 490 virtual table relocs for gc. */ 491 492static bfd_boolean 493visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 494 asection *sec, const Elf_Internal_Rela *relocs) 495{ 496 Elf_Internal_Shdr *symtab_hdr; 497 struct elf_link_hash_entry **sym_hashes; 498 const Elf_Internal_Rela *rel; 499 const Elf_Internal_Rela *rel_end; 500 501 if (bfd_link_relocatable (info)) 502 return TRUE; 503 504 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 505 sym_hashes = elf_sym_hashes (abfd); 506 507 rel_end = relocs + sec->reloc_count; 508 for (rel = relocs; rel < rel_end; rel++) 509 { 510 struct elf_link_hash_entry *h; 511 unsigned long r_symndx; 512 513 r_symndx = ELF32_R_SYM (rel->r_info); 514 if (r_symndx < symtab_hdr->sh_info) 515 h = NULL; 516 else 517 { 518 h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 519 while (h->root.type == bfd_link_hash_indirect 520 || h->root.type == bfd_link_hash_warning) 521 h = (struct elf_link_hash_entry *) h->root.u.i.link; 522 } 523 524 switch (ELF32_R_TYPE (rel->r_info)) 525 { 526 /* This relocation describes the C++ object vtable hierarchy. 527 Reconstruct it for later use during GC. */ 528 case R_VISIUM_GNU_VTINHERIT: 529 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 530 return FALSE; 531 break; 532 533 /* This relocation describes which C++ vtable entries are actually 534 used. Record for later use during GC. */ 535 case R_VISIUM_GNU_VTENTRY: 536 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 537 return FALSE; 538 break; 539 } 540 } 541 542 return TRUE; 543} 544 545/* Relocate a VISIUM ELF section. */ 546 547static bfd_boolean 548visium_elf_relocate_section (bfd *output_bfd, 549 struct bfd_link_info *info, bfd *input_bfd, 550 asection *input_section, bfd_byte *contents, 551 Elf_Internal_Rela *relocs, 552 Elf_Internal_Sym *local_syms, 553 asection **local_sections) 554{ 555 Elf_Internal_Shdr *symtab_hdr; 556 struct elf_link_hash_entry **sym_hashes; 557 Elf_Internal_Rela *rel; 558 Elf_Internal_Rela *relend; 559 560 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 561 sym_hashes = elf_sym_hashes (input_bfd); 562 relend = relocs + input_section->reloc_count; 563 564 for (rel = relocs; rel < relend; rel++) 565 { 566 reloc_howto_type *howto; 567 unsigned long r_symndx; 568 Elf_Internal_Sym *sym; 569 asection *sec; 570 struct elf_link_hash_entry *h; 571 bfd_vma relocation; 572 bfd_reloc_status_type r; 573 const char *name = NULL; 574 int r_type; 575 bfd_vma insn; 576 577 r_type = ELF32_R_TYPE (rel->r_info); 578 579 if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY) 580 continue; 581 582 r_symndx = ELF32_R_SYM (rel->r_info); 583 584 howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info); 585 h = NULL; 586 sym = NULL; 587 sec = NULL; 588 589 if (r_symndx < symtab_hdr->sh_info) 590 { 591 /* This is a local symbol. */ 592 sym = local_syms + r_symndx; 593 sec = local_sections[r_symndx]; 594 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 595 596 name = bfd_elf_string_from_elf_section 597 (input_bfd, symtab_hdr->sh_link, sym->st_name); 598 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; 599 } 600 else 601 { 602 bfd_boolean unresolved_reloc; 603 bfd_boolean warned, ignored; 604 605 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 606 r_symndx, symtab_hdr, sym_hashes, 607 h, sec, relocation, 608 unresolved_reloc, warned, ignored); 609 610 name = h->root.root.string; 611 } 612 613 if (sec != NULL && discarded_section (sec)) 614 { 615 /* For relocs against symbols from removed linkonce sections, 616 or sections discarded by a linker script, we just want the 617 section contents zeroed. Avoid any special processing. */ 618 _bfd_clear_contents (howto, input_bfd, input_section, 619 contents + rel->r_offset); 620 621 rel->r_info = 0; 622 rel->r_addend = 0; 623 continue; 624 } 625 626 if (bfd_link_relocatable (info)) 627 continue; 628 629 switch (r_type) 630 { 631 case R_VISIUM_PC16: 632 case R_VISIUM_HI16: 633 case R_VISIUM_LO16: 634 case R_VISIUM_IM16: 635 case R_VISIUM_HI16_PCREL: 636 case R_VISIUM_LO16_PCREL: 637 case R_VISIUM_IM16_PCREL: 638 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 639 contents, rel->r_offset, 640 relocation, rel->r_addend); 641 642 /* For instruction relocations, the parity needs correcting. */ 643 if (r == bfd_reloc_ok) 644 { 645 insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 646 insn = (insn & 0x7fffffff) | visium_parity_bit (insn); 647 bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 648 } 649 break; 650 651 default: 652 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 653 contents, rel->r_offset, 654 relocation, rel->r_addend); 655 break; 656 } 657 658 if (r != bfd_reloc_ok) 659 { 660 const char *msg = (const char *) NULL; 661 662 switch (r) 663 { 664 case bfd_reloc_overflow: 665 (*info->callbacks->reloc_overflow) 666 (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, 667 input_bfd, input_section, rel->r_offset); 668 break; 669 670 case bfd_reloc_undefined: 671 (*info->callbacks->undefined_symbol) 672 (info, name, input_bfd, input_section, rel->r_offset, TRUE); 673 break; 674 675 case bfd_reloc_outofrange: 676 msg = _("internal error: out of range error"); 677 break; 678 679 case bfd_reloc_notsupported: 680 msg = _("internal error: unsupported relocation error"); 681 break; 682 683 case bfd_reloc_dangerous: 684 msg = _("internal error: dangerous relocation"); 685 break; 686 687 default: 688 msg = _("internal error: unknown error"); 689 break; 690 } 691 692 if (msg) 693 (*info->callbacks->warning) (info, msg, name, input_bfd, 694 input_section, rel->r_offset); 695 } 696 } 697 698 return TRUE; 699} 700 701/* This function is called during section gc to discover the section a 702 to which a particular relocation refers. Return the section that 703 should be marked against GC for a given relocation. */ 704 705static asection * 706visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, 707 Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, 708 Elf_Internal_Sym *sym) 709{ 710 if (h != NULL) 711 switch (ELF32_R_TYPE (rel->r_info)) 712 { 713 case R_VISIUM_GNU_VTINHERIT: 714 case R_VISIUM_GNU_VTENTRY: 715 return NULL; 716 } 717 718 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 719} 720 721static void 722visium_elf_post_process_headers (bfd *abfd, 723 struct bfd_link_info *info ATTRIBUTE_UNUSED) 724{ 725 Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); 726 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE; 727 i_ehdrp->e_ident[EI_ABIVERSION] = 1; 728} 729 730/* Function to set the ELF flag bits. */ 731 732static bfd_boolean 733visium_elf_set_private_flags (bfd *abfd, flagword flags) 734{ 735 elf_elfheader (abfd)->e_flags = flags; 736 elf_flags_init (abfd) = TRUE; 737 return TRUE; 738} 739 740/* Copy backend specific data from one object module to another. */ 741 742static bfd_boolean 743visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) 744{ 745 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 746 || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 747 return TRUE; 748 749 BFD_ASSERT (!elf_flags_init (obfd) 750 || elf_elfheader (obfd)->e_flags == 751 elf_elfheader (ibfd)->e_flags); 752 753 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; 754 elf_flags_init (obfd) = TRUE; 755 756 /* Copy object attributes. */ 757 _bfd_elf_copy_obj_attributes (ibfd, obfd); 758 759 return TRUE; 760} 761 762/* Merge backend specific data from an object 763 file to the output object file when linking. */ 764 765static bfd_boolean 766visium_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) 767{ 768 flagword old_flags; 769 flagword new_flags; 770 flagword mismatch; 771 const char *opt_arch = NULL; 772 const char *new_opt_with = NULL; 773 const char *old_opt_with = NULL; 774 const char *with = "with"; 775 const char *without = "without"; 776 const char *mcm = "mcm"; 777 const char *mcm24 = "mcm24"; 778 const char *gr6 = "gr6"; 779 780 new_flags = elf_elfheader (ibfd)->e_flags; 781 old_flags = elf_elfheader (obfd)->e_flags; 782 783 if (!elf_flags_init (obfd)) 784 { 785 /* First call, no flags set. */ 786 elf_flags_init (obfd) = TRUE; 787 elf_elfheader (obfd)->e_flags = new_flags; 788 } 789 else 790 { 791 mismatch = (new_flags ^ old_flags) 792 & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6); 793 if (mismatch & EF_VISIUM_ARCH_GR6) 794 { 795 opt_arch = gr6; 796 new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without; 797 old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without; 798 } 799 else if (mismatch & EF_VISIUM_ARCH_MCM) 800 { 801 opt_arch = mcm; 802 new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without; 803 old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without; 804 } 805 else if (mismatch & EF_VISIUM_ARCH_MCM24) 806 { 807 opt_arch = mcm24; 808 new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 809 old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 810 } 811 812 if (mismatch) 813 _bfd_error_handler 814 (_ 815 ("%s: compiled %s -mtune=%s and linked with modules" 816 " compiled %s -mtune=%s"), 817 bfd_get_filename (ibfd), new_opt_with, opt_arch, old_opt_with, 818 opt_arch); 819 } 820 821 return TRUE; 822} 823 824static bfd_boolean 825visium_elf_print_private_bfd_data (bfd *abfd, void *ptr) 826{ 827 FILE *file = (FILE *) ptr; 828 flagword flags; 829 830 BFD_ASSERT (abfd != NULL && ptr != NULL); 831 832 /* Print normal ELF private data. */ 833 _bfd_elf_print_private_bfd_data (abfd, ptr); 834 835 flags = elf_elfheader (abfd)->e_flags; 836 fprintf (file, _("private flags = 0x%lx:"), (long) flags); 837 838 if (flags & EF_VISIUM_ARCH_GR6) 839 fprintf (file, " -mtune=gr6"); 840 else if (flags & EF_VISIUM_ARCH_MCM) 841 fprintf (file, " -mtune=mcm"); 842 else if (flags & EF_VISIUM_ARCH_MCM24) 843 fprintf (file, " -mtune=mcm24"); 844 845 fputc ('\n', file); 846 return TRUE; 847} 848 849#define ELF_ARCH bfd_arch_visium 850#define ELF_MACHINE_CODE EM_VISIUM 851#define ELF_MAXPAGESIZE 1 852 853#define TARGET_BIG_SYM visium_elf32_vec 854#define TARGET_BIG_NAME "elf32-visium" 855 856#define elf_info_to_howto_rel NULL 857#define elf_info_to_howto visium_info_to_howto_rela 858#define elf_backend_relocate_section visium_elf_relocate_section 859#define elf_backend_gc_mark_hook visium_elf_gc_mark_hook 860#define elf_backend_check_relocs visium_elf_check_relocs 861#define elf_backend_rela_normal 1 862 863#define elf_backend_can_gc_sections 1 864 865#define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup 866#define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup 867 868#define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags 869#define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data 870#define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data 871#define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data 872#define elf_backend_post_process_headers visium_elf_post_process_headers 873 874#include "elf32-target.h" 875