1/* Visium-specific support for 32-bit ELF. 2 3 Copyright (C) 2003-2017 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 /* xgettext:c-format */ 481 _bfd_error_handler (_("%B: invalid Visium reloc number: %d"), abfd, r_type); 482 r_type = 0; 483 } 484 cache_ptr->howto = &visium_elf_howto_table[r_type]; 485 break; 486 } 487} 488 489/* Look through the relocs for a section during the first phase. 490 Since we don't do .gots or .plts, we just need to consider the 491 virtual table relocs for gc. */ 492 493static bfd_boolean 494visium_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, 495 asection *sec, const Elf_Internal_Rela *relocs) 496{ 497 Elf_Internal_Shdr *symtab_hdr; 498 struct elf_link_hash_entry **sym_hashes; 499 const Elf_Internal_Rela *rel; 500 const Elf_Internal_Rela *rel_end; 501 502 if (bfd_link_relocatable (info)) 503 return TRUE; 504 505 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 506 sym_hashes = elf_sym_hashes (abfd); 507 508 rel_end = relocs + sec->reloc_count; 509 for (rel = relocs; rel < rel_end; rel++) 510 { 511 struct elf_link_hash_entry *h; 512 unsigned long r_symndx; 513 514 r_symndx = ELF32_R_SYM (rel->r_info); 515 if (r_symndx < symtab_hdr->sh_info) 516 h = NULL; 517 else 518 { 519 h = sym_hashes[r_symndx - symtab_hdr->sh_info]; 520 while (h->root.type == bfd_link_hash_indirect 521 || h->root.type == bfd_link_hash_warning) 522 h = (struct elf_link_hash_entry *) h->root.u.i.link; 523 } 524 525 switch (ELF32_R_TYPE (rel->r_info)) 526 { 527 /* This relocation describes the C++ object vtable hierarchy. 528 Reconstruct it for later use during GC. */ 529 case R_VISIUM_GNU_VTINHERIT: 530 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) 531 return FALSE; 532 break; 533 534 /* This relocation describes which C++ vtable entries are actually 535 used. Record for later use during GC. */ 536 case R_VISIUM_GNU_VTENTRY: 537 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) 538 return FALSE; 539 break; 540 } 541 } 542 543 return TRUE; 544} 545 546/* Relocate a VISIUM ELF section. */ 547 548static bfd_boolean 549visium_elf_relocate_section (bfd *output_bfd, 550 struct bfd_link_info *info, bfd *input_bfd, 551 asection *input_section, bfd_byte *contents, 552 Elf_Internal_Rela *relocs, 553 Elf_Internal_Sym *local_syms, 554 asection **local_sections) 555{ 556 Elf_Internal_Shdr *symtab_hdr; 557 struct elf_link_hash_entry **sym_hashes; 558 Elf_Internal_Rela *rel; 559 Elf_Internal_Rela *relend; 560 561 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; 562 sym_hashes = elf_sym_hashes (input_bfd); 563 relend = relocs + input_section->reloc_count; 564 565 for (rel = relocs; rel < relend; rel++) 566 { 567 reloc_howto_type *howto; 568 unsigned long r_symndx; 569 Elf_Internal_Sym *sym; 570 asection *sec; 571 struct elf_link_hash_entry *h; 572 bfd_vma relocation; 573 bfd_reloc_status_type r; 574 const char *name = NULL; 575 int r_type; 576 bfd_vma insn; 577 578 r_type = ELF32_R_TYPE (rel->r_info); 579 580 if (r_type == R_VISIUM_GNU_VTINHERIT || r_type == R_VISIUM_GNU_VTENTRY) 581 continue; 582 583 r_symndx = ELF32_R_SYM (rel->r_info); 584 585 howto = visium_elf_howto_table + ELF32_R_TYPE (rel->r_info); 586 h = NULL; 587 sym = NULL; 588 sec = NULL; 589 590 if (r_symndx < symtab_hdr->sh_info) 591 { 592 /* This is a local symbol. */ 593 sym = local_syms + r_symndx; 594 sec = local_sections[r_symndx]; 595 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); 596 597 name = bfd_elf_string_from_elf_section 598 (input_bfd, symtab_hdr->sh_link, sym->st_name); 599 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; 600 } 601 else 602 { 603 bfd_boolean unresolved_reloc; 604 bfd_boolean warned, ignored; 605 606 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, 607 r_symndx, symtab_hdr, sym_hashes, 608 h, sec, relocation, 609 unresolved_reloc, warned, ignored); 610 611 name = h->root.root.string; 612 } 613 614 if (sec != NULL && discarded_section (sec)) 615 { 616 /* For relocs against symbols from removed linkonce sections, 617 or sections discarded by a linker script, we just want the 618 section contents zeroed. Avoid any special processing. */ 619 _bfd_clear_contents (howto, input_bfd, input_section, 620 contents + rel->r_offset); 621 622 rel->r_info = 0; 623 rel->r_addend = 0; 624 continue; 625 } 626 627 if (bfd_link_relocatable (info)) 628 continue; 629 630 switch (r_type) 631 { 632 case R_VISIUM_PC16: 633 case R_VISIUM_HI16: 634 case R_VISIUM_LO16: 635 case R_VISIUM_IM16: 636 case R_VISIUM_HI16_PCREL: 637 case R_VISIUM_LO16_PCREL: 638 case R_VISIUM_IM16_PCREL: 639 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 640 contents, rel->r_offset, 641 relocation, rel->r_addend); 642 643 /* For instruction relocations, the parity needs correcting. */ 644 if (r == bfd_reloc_ok) 645 { 646 insn = bfd_get_32 (input_bfd, contents + rel->r_offset); 647 insn = (insn & 0x7fffffff) | visium_parity_bit (insn); 648 bfd_put_32 (input_bfd, insn, contents + rel->r_offset); 649 } 650 break; 651 652 default: 653 r = _bfd_final_link_relocate (howto, input_bfd, input_section, 654 contents, rel->r_offset, 655 relocation, rel->r_addend); 656 break; 657 } 658 659 if (r != bfd_reloc_ok) 660 { 661 const char *msg = (const char *) NULL; 662 663 switch (r) 664 { 665 case bfd_reloc_overflow: 666 (*info->callbacks->reloc_overflow) 667 (info, (h ? &h->root : NULL), name, howto->name, (bfd_vma) 0, 668 input_bfd, input_section, rel->r_offset); 669 break; 670 671 case bfd_reloc_undefined: 672 (*info->callbacks->undefined_symbol) 673 (info, name, input_bfd, input_section, rel->r_offset, TRUE); 674 break; 675 676 case bfd_reloc_outofrange: 677 msg = _("internal error: out of range error"); 678 break; 679 680 case bfd_reloc_notsupported: 681 msg = _("internal error: unsupported relocation error"); 682 break; 683 684 case bfd_reloc_dangerous: 685 msg = _("internal error: dangerous relocation"); 686 break; 687 688 default: 689 msg = _("internal error: unknown error"); 690 break; 691 } 692 693 if (msg) 694 (*info->callbacks->warning) (info, msg, name, input_bfd, 695 input_section, rel->r_offset); 696 } 697 } 698 699 return TRUE; 700} 701 702/* This function is called during section gc to discover the section a 703 to which a particular relocation refers. Return the section that 704 should be marked against GC for a given relocation. */ 705 706static asection * 707visium_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info, 708 Elf_Internal_Rela *rel, struct elf_link_hash_entry *h, 709 Elf_Internal_Sym *sym) 710{ 711 if (h != NULL) 712 switch (ELF32_R_TYPE (rel->r_info)) 713 { 714 case R_VISIUM_GNU_VTINHERIT: 715 case R_VISIUM_GNU_VTENTRY: 716 return NULL; 717 } 718 719 return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); 720} 721 722static void 723visium_elf_post_process_headers (bfd *abfd, 724 struct bfd_link_info *info ATTRIBUTE_UNUSED) 725{ 726 Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd); 727 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE; 728 i_ehdrp->e_ident[EI_ABIVERSION] = 1; 729} 730 731/* Function to set the ELF flag bits. */ 732 733static bfd_boolean 734visium_elf_set_private_flags (bfd *abfd, flagword flags) 735{ 736 elf_elfheader (abfd)->e_flags = flags; 737 elf_flags_init (abfd) = TRUE; 738 return TRUE; 739} 740 741/* Copy backend specific data from one object module to another. */ 742 743static bfd_boolean 744visium_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) 745{ 746 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour 747 || bfd_get_flavour (obfd) != bfd_target_elf_flavour) 748 return TRUE; 749 750 BFD_ASSERT (!elf_flags_init (obfd) 751 || elf_elfheader (obfd)->e_flags == 752 elf_elfheader (ibfd)->e_flags); 753 754 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; 755 elf_flags_init (obfd) = TRUE; 756 757 /* Copy object attributes. */ 758 _bfd_elf_copy_obj_attributes (ibfd, obfd); 759 760 return TRUE; 761} 762 763/* Merge backend specific data from an object 764 file to the output object file when linking. */ 765 766static bfd_boolean 767visium_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) 768{ 769 bfd *obfd = info->output_bfd; 770 flagword old_flags; 771 flagword new_flags; 772 flagword mismatch; 773 const char *opt_arch = NULL; 774 const char *new_opt_with = NULL; 775 const char *old_opt_with = NULL; 776 const char *with = "with"; 777 const char *without = "without"; 778 const char *mcm = "mcm"; 779 const char *mcm24 = "mcm24"; 780 const char *gr6 = "gr6"; 781 782 new_flags = elf_elfheader (ibfd)->e_flags; 783 old_flags = elf_elfheader (obfd)->e_flags; 784 785 if (!elf_flags_init (obfd)) 786 { 787 /* First call, no flags set. */ 788 elf_flags_init (obfd) = TRUE; 789 elf_elfheader (obfd)->e_flags = new_flags; 790 } 791 else 792 { 793 mismatch = (new_flags ^ old_flags) 794 & (EF_VISIUM_ARCH_MCM | EF_VISIUM_ARCH_MCM24 | EF_VISIUM_ARCH_GR6); 795 if (mismatch & EF_VISIUM_ARCH_GR6) 796 { 797 opt_arch = gr6; 798 new_opt_with = new_flags & EF_VISIUM_ARCH_GR6 ? with : without; 799 old_opt_with = old_flags & EF_VISIUM_ARCH_GR6 ? with : without; 800 } 801 else if (mismatch & EF_VISIUM_ARCH_MCM) 802 { 803 opt_arch = mcm; 804 new_opt_with = new_flags & EF_VISIUM_ARCH_MCM ? with : without; 805 old_opt_with = old_flags & EF_VISIUM_ARCH_MCM ? with : without; 806 } 807 else if (mismatch & EF_VISIUM_ARCH_MCM24) 808 { 809 opt_arch = mcm24; 810 new_opt_with = new_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 811 old_opt_with = old_flags & EF_VISIUM_ARCH_MCM24 ? with : without; 812 } 813 814 if (mismatch) 815 _bfd_error_handler 816 /* xgettext:c-format */ 817 (_("%s: compiled %s -mtune=%s and linked with modules" 818 " compiled %s -mtune=%s"), 819 bfd_get_filename (ibfd), new_opt_with, opt_arch, old_opt_with, 820 opt_arch); 821 } 822 823 return TRUE; 824} 825 826static bfd_boolean 827visium_elf_print_private_bfd_data (bfd *abfd, void *ptr) 828{ 829 FILE *file = (FILE *) ptr; 830 flagword flags; 831 832 BFD_ASSERT (abfd != NULL && ptr != NULL); 833 834 /* Print normal ELF private data. */ 835 _bfd_elf_print_private_bfd_data (abfd, ptr); 836 837 flags = elf_elfheader (abfd)->e_flags; 838 fprintf (file, _("private flags = 0x%lx:"), (long) flags); 839 840 if (flags & EF_VISIUM_ARCH_GR6) 841 fprintf (file, " -mtune=gr6"); 842 else if (flags & EF_VISIUM_ARCH_MCM) 843 fprintf (file, " -mtune=mcm"); 844 else if (flags & EF_VISIUM_ARCH_MCM24) 845 fprintf (file, " -mtune=mcm24"); 846 847 fputc ('\n', file); 848 return TRUE; 849} 850 851#define ELF_ARCH bfd_arch_visium 852#define ELF_MACHINE_CODE EM_VISIUM 853#define ELF_MAXPAGESIZE 1 854 855#define TARGET_BIG_SYM visium_elf32_vec 856#define TARGET_BIG_NAME "elf32-visium" 857 858#define elf_info_to_howto_rel NULL 859#define elf_info_to_howto visium_info_to_howto_rela 860#define elf_backend_relocate_section visium_elf_relocate_section 861#define elf_backend_gc_mark_hook visium_elf_gc_mark_hook 862#define elf_backend_check_relocs visium_elf_check_relocs 863#define elf_backend_rela_normal 1 864 865#define elf_backend_can_gc_sections 1 866 867#define bfd_elf32_bfd_reloc_type_lookup visium_reloc_type_lookup 868#define bfd_elf32_bfd_reloc_name_lookup visium_reloc_name_lookup 869 870#define bfd_elf32_bfd_set_private_flags visium_elf_set_private_flags 871#define bfd_elf32_bfd_copy_private_bfd_data visium_elf_copy_private_bfd_data 872#define bfd_elf32_bfd_merge_private_bfd_data visium_elf_merge_private_bfd_data 873#define bfd_elf32_bfd_print_private_bfd_data visium_elf_print_private_bfd_data 874#define elf_backend_post_process_headers visium_elf_post_process_headers 875 876#include "elf32-target.h" 877