coff-x86_64.c revision 1.1.1.11
1/* BFD back-end for AMD 64 COFF files. 2 Copyright (C) 2006-2024 Free Software Foundation, Inc. 3 4 This file is part of BFD, the Binary File Descriptor library. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. 20 21 Written by Kai Tietz, OneVision Software GmbH&CoKg. */ 22 23#include "sysdep.h" 24#include "bfd.h" 25#include "libbfd.h" 26#include "coff/x86_64.h" 27#include "coff/internal.h" 28#include "libcoff.h" 29#include "libiberty.h" 30 31#define BADMAG(x) AMD64BADMAG(x) 32 33#ifdef COFF_WITH_pex64 34# undef AOUTSZ 35# define AOUTSZ PEPAOUTSZ 36# define PEAOUTHDR PEPAOUTHDR 37#endif 38 39#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2) 40 41/* The page size is a guess based on ELF. */ 42 43#define COFF_PAGE_SIZE 0x1000 44 45/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */ 46#define OCTETS_PER_BYTE(ABFD, SEC) 1 47 48/* For some reason when using AMD COFF the value stored in the .text 49 section for a reference to a common symbol is the value itself plus 50 any desired offset. Ian Taylor, Cygnus Support. */ 51 52/* If we are producing relocatable output, we need to do some 53 adjustments to the object file that are not done by the 54 bfd_perform_relocation function. This function is called by every 55 reloc type to make any required adjustments. */ 56 57static bfd_reloc_status_type 58coff_amd64_reloc (bfd *abfd, 59 arelent *reloc_entry, 60 asymbol *symbol, 61 void * data, 62 asection *input_section ATTRIBUTE_UNUSED, 63 bfd *output_bfd, 64 char **error_message ATTRIBUTE_UNUSED) 65{ 66 symvalue diff; 67 68#if !defined (COFF_WITH_PE) 69 if (output_bfd == NULL) 70 return bfd_reloc_continue; 71#endif 72 73 if (bfd_is_com_section (symbol->section)) 74 { 75#if !defined (COFF_WITH_PE) 76 /* We are relocating a common symbol. The current value in the 77 object file is ORIG + OFFSET, where ORIG is the value of the 78 common symbol as seen by the object file when it was compiled 79 (this may be zero if the symbol was undefined) and OFFSET is 80 the offset into the common symbol (normally zero, but may be 81 non-zero when referring to a field in a common structure). 82 ORIG is the negative of reloc_entry->addend, which is set by 83 the CALC_ADDEND macro below. We want to replace the value in 84 the object file with NEW + OFFSET, where NEW is the value of 85 the common symbol which we are going to put in the final 86 object file. NEW is symbol->value. */ 87 diff = symbol->value + reloc_entry->addend; 88#else 89 /* In PE mode, we do not offset the common symbol. */ 90 diff = reloc_entry->addend; 91#endif 92 } 93 else 94 { 95 /* For some reason bfd_perform_relocation always effectively 96 ignores the addend for a COFF target when producing 97 relocatable output. This seems to be always wrong for 386 98 COFF, so we handle the addend here instead. */ 99#if defined (COFF_WITH_PE) 100 if (output_bfd == NULL) 101 { 102 if (symbol->flags & BSF_WEAK) 103 diff = reloc_entry->addend - symbol->value; 104 else 105 diff = -reloc_entry->addend; 106 } 107 else 108#endif 109 diff = reloc_entry->addend; 110 } 111 112#if defined (COFF_WITH_PE) 113 if (output_bfd == NULL) 114 { 115 /* PC relative relocations are off by their size. */ 116 if (reloc_entry->howto->pc_relative) 117 diff -= bfd_get_reloc_size (reloc_entry->howto); 118 119 if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1 120 && reloc_entry->howto->type <= R_AMD64_PCRLONG_5) 121 diff -= reloc_entry->howto->type - R_AMD64_PCRLONG; 122 } 123 124 if (reloc_entry->howto->type == R_AMD64_IMAGEBASE 125 && output_bfd == NULL) 126 { 127 bfd *obfd = input_section->output_section->owner; 128 struct bfd_link_info *link_info; 129 struct bfd_link_hash_entry *h; 130 switch (bfd_get_flavour (obfd)) 131 { 132 case bfd_target_coff_flavour: 133 diff -= pe_data (obfd)->pe_opthdr.ImageBase; 134 break; 135 case bfd_target_elf_flavour: 136 /* Subtract __ImageBase. */ 137 h = NULL; 138 link_info = _bfd_get_link_info (obfd); 139 if (link_info != NULL) 140 h = bfd_link_hash_lookup (link_info->hash, "__ImageBase", 141 false, false, true); 142 if (h == NULL 143 || (h->type != bfd_link_hash_defined 144 && h->type != bfd_link_hash_defweak)) 145 { 146 *error_message 147 = (char *) _("R_AMD64_IMAGEBASE with __ImageBase undefined"); 148 return bfd_reloc_dangerous; 149 } 150 /* ELF symbols in relocatable files are section relative, 151 but in nonrelocatable files they are virtual addresses. */ 152 diff -= (h->u.def.value 153 + h->u.def.section->output_offset 154 + h->u.def.section->output_section->vma); 155 break; 156 default: 157 break; 158 } 159 } 160#endif 161 162#define DOIT(x) \ 163 x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask)) 164 165 if (diff != 0) 166 { 167 reloc_howto_type *howto = reloc_entry->howto; 168 bfd_size_type octets = (reloc_entry->address 169 * OCTETS_PER_BYTE (abfd, input_section)); 170 unsigned char *addr = (unsigned char *) data + octets; 171 172 if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets)) 173 return bfd_reloc_outofrange; 174 175 switch (bfd_get_reloc_size (howto)) 176 { 177 case 1: 178 { 179 char x = bfd_get_8 (abfd, addr); 180 DOIT (x); 181 bfd_put_8 (abfd, x, addr); 182 } 183 break; 184 185 case 2: 186 { 187 short x = bfd_get_16 (abfd, addr); 188 DOIT (x); 189 bfd_put_16 (abfd, (bfd_vma) x, addr); 190 } 191 break; 192 193 case 4: 194 { 195 long x = bfd_get_32 (abfd, addr); 196 DOIT (x); 197 bfd_put_32 (abfd, (bfd_vma) x, addr); 198 } 199 break; 200 201 case 8: 202 { 203 uint64_t x = bfd_get_64 (abfd, addr); 204 DOIT (x); 205 bfd_put_64 (abfd, x, addr); 206 } 207 break; 208 209 default: 210 bfd_set_error (bfd_error_bad_value); 211 return bfd_reloc_notsupported; 212 } 213 } 214 215 /* Now let bfd_perform_relocation finish everything up. */ 216 return bfd_reloc_continue; 217} 218 219#if defined(COFF_WITH_PE) 220/* Return TRUE if this relocation should appear in the output .reloc 221 section. */ 222 223static bool 224in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto) 225{ 226 return ! howto->pc_relative 227 && howto->type != R_AMD64_IMAGEBASE 228 && howto->type != R_AMD64_SECREL 229 && howto->type != R_AMD64_SECTION; 230} 231#endif /* COFF_WITH_PE */ 232 233#ifndef PCRELOFFSET 234#define PCRELOFFSET true 235#endif 236 237static reloc_howto_type howto_table[] = 238{ 239 EMPTY_HOWTO (0), 240 HOWTO (R_AMD64_DIR64, /* type 1*/ 241 0, /* rightshift */ 242 8, /* size */ 243 64, /* bitsize */ 244 false, /* pc_relative */ 245 0, /* bitpos */ 246 complain_overflow_bitfield, /* complain_on_overflow */ 247 coff_amd64_reloc, /* special_function */ 248 "IMAGE_REL_AMD64_ADDR64", /* name */ 249 true, /* partial_inplace */ 250 0xffffffffffffffffll, /* src_mask */ 251 0xffffffffffffffffll, /* dst_mask */ 252 true), /* pcrel_offset */ 253 HOWTO (R_AMD64_DIR32, /* type 2 */ 254 0, /* rightshift */ 255 4, /* size */ 256 32, /* bitsize */ 257 false, /* pc_relative */ 258 0, /* bitpos */ 259 complain_overflow_bitfield, /* complain_on_overflow */ 260 coff_amd64_reloc, /* special_function */ 261 "IMAGE_REL_AMD64_ADDR32", /* name */ 262 true, /* partial_inplace */ 263 0xffffffff, /* src_mask */ 264 0xffffffff, /* dst_mask */ 265 true), /* pcrel_offset */ 266 /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3). */ 267 HOWTO (R_AMD64_IMAGEBASE, /* type */ 268 0, /* rightshift */ 269 4, /* size */ 270 32, /* bitsize */ 271 false, /* pc_relative */ 272 0, /* bitpos */ 273 complain_overflow_bitfield, /* complain_on_overflow */ 274 coff_amd64_reloc, /* special_function */ 275 "IMAGE_REL_AMD64_ADDR32NB", /* name */ 276 true, /* partial_inplace */ 277 0xffffffff, /* src_mask */ 278 0xffffffff, /* dst_mask */ 279 false), /* pcrel_offset */ 280 /* 32-bit longword PC relative relocation (4). */ 281 HOWTO (R_AMD64_PCRLONG, /* type 4 */ 282 0, /* rightshift */ 283 4, /* size */ 284 32, /* bitsize */ 285 true, /* pc_relative */ 286 0, /* bitpos */ 287 complain_overflow_signed, /* complain_on_overflow */ 288 coff_amd64_reloc, /* special_function */ 289 "IMAGE_REL_AMD64_REL32", /* name */ 290 true, /* partial_inplace */ 291 0xffffffff, /* src_mask */ 292 0xffffffff, /* dst_mask */ 293 PCRELOFFSET), /* pcrel_offset */ 294 295 HOWTO (R_AMD64_PCRLONG_1, /* type 5 */ 296 0, /* rightshift */ 297 4, /* size */ 298 32, /* bitsize */ 299 true, /* pc_relative */ 300 0, /* bitpos */ 301 complain_overflow_signed, /* complain_on_overflow */ 302 coff_amd64_reloc, /* special_function */ 303 "IMAGE_REL_AMD64_REL32_1", /* name */ 304 true, /* partial_inplace */ 305 0xffffffff, /* src_mask */ 306 0xffffffff, /* dst_mask */ 307 PCRELOFFSET), /* pcrel_offset */ 308 HOWTO (R_AMD64_PCRLONG_2, /* type 6 */ 309 0, /* rightshift */ 310 4, /* size */ 311 32, /* bitsize */ 312 true, /* pc_relative */ 313 0, /* bitpos */ 314 complain_overflow_signed, /* complain_on_overflow */ 315 coff_amd64_reloc, /* special_function */ 316 "IMAGE_REL_AMD64_REL32_2", /* name */ 317 true, /* partial_inplace */ 318 0xffffffff, /* src_mask */ 319 0xffffffff, /* dst_mask */ 320 PCRELOFFSET), /* pcrel_offset */ 321 HOWTO (R_AMD64_PCRLONG_3, /* type 7 */ 322 0, /* rightshift */ 323 4, /* size */ 324 32, /* bitsize */ 325 true, /* pc_relative */ 326 0, /* bitpos */ 327 complain_overflow_signed, /* complain_on_overflow */ 328 coff_amd64_reloc, /* special_function */ 329 "IMAGE_REL_AMD64_REL32_3", /* name */ 330 true, /* partial_inplace */ 331 0xffffffff, /* src_mask */ 332 0xffffffff, /* dst_mask */ 333 PCRELOFFSET), /* pcrel_offset */ 334 HOWTO (R_AMD64_PCRLONG_4, /* type 8 */ 335 0, /* rightshift */ 336 4, /* size */ 337 32, /* bitsize */ 338 true, /* pc_relative */ 339 0, /* bitpos */ 340 complain_overflow_signed, /* complain_on_overflow */ 341 coff_amd64_reloc, /* special_function */ 342 "IMAGE_REL_AMD64_REL32_4", /* name */ 343 true, /* partial_inplace */ 344 0xffffffff, /* src_mask */ 345 0xffffffff, /* dst_mask */ 346 PCRELOFFSET), /* pcrel_offset */ 347 HOWTO (R_AMD64_PCRLONG_5, /* type 9 */ 348 0, /* rightshift */ 349 4, /* size */ 350 32, /* bitsize */ 351 true, /* pc_relative */ 352 0, /* bitpos */ 353 complain_overflow_signed, /* complain_on_overflow */ 354 coff_amd64_reloc, /* special_function */ 355 "IMAGE_REL_AMD64_REL32_5", /* name */ 356 true, /* partial_inplace */ 357 0xffffffff, /* src_mask */ 358 0xffffffff, /* dst_mask */ 359 PCRELOFFSET), /* pcrel_offset */ 360#if defined(COFF_WITH_PE) 361 /* 16-bit word section relocation (10). */ 362 HOWTO (R_AMD64_SECTION, /* type */ 363 0, /* rightshift */ 364 2, /* size */ 365 16, /* bitsize */ 366 false, /* pc_relative */ 367 0, /* bitpos */ 368 complain_overflow_bitfield, /* complain_on_overflow */ 369 coff_amd64_reloc, /* special_function */ 370 "IMAGE_REL_AMD64_SECTION", /* name */ 371 true, /* partial_inplace */ 372 0x0000ffff, /* src_mask */ 373 0x0000ffff, /* dst_mask */ 374 true), 375 /* 32-bit longword section relative relocation (11). */ 376 HOWTO (R_AMD64_SECREL, /* type */ 377 0, /* rightshift */ 378 4, /* size */ 379 32, /* bitsize */ 380 false, /* pc_relative */ 381 0, /* bitpos */ 382 complain_overflow_bitfield, /* complain_on_overflow */ 383 coff_amd64_reloc, /* special_function */ 384 "IMAGE_REL_AMD64_SECREL", /* name */ 385 true, /* partial_inplace */ 386 0xffffffff, /* src_mask */ 387 0xffffffff, /* dst_mask */ 388 true), /* pcrel_offset */ 389#else 390 EMPTY_HOWTO (10), 391 EMPTY_HOWTO (11), 392#endif 393 EMPTY_HOWTO (12), 394 EMPTY_HOWTO (13), 395#ifndef DONT_EXTEND_AMD64 396 HOWTO (R_AMD64_PCRQUAD, 397 0, /* rightshift */ 398 8, /* size */ 399 64, /* bitsize */ 400 true, /* pc_relative */ 401 0, /* bitpos */ 402 complain_overflow_signed, /* complain_on_overflow */ 403 coff_amd64_reloc, /* special_function */ 404 "R_X86_64_PC64", /* name */ 405 true, /* partial_inplace */ 406 0xffffffffffffffffll, /* src_mask */ 407 0xffffffffffffffffll, /* dst_mask */ 408 PCRELOFFSET), /* pcrel_offset */ 409#else 410 EMPTY_HOWTO (14), 411#endif 412 /* Byte relocation (15). */ 413 HOWTO (R_RELBYTE, /* type */ 414 0, /* rightshift */ 415 1, /* size */ 416 8, /* bitsize */ 417 false, /* pc_relative */ 418 0, /* bitpos */ 419 complain_overflow_bitfield, /* complain_on_overflow */ 420 coff_amd64_reloc, /* special_function */ 421 "R_X86_64_8", /* name */ 422 true, /* partial_inplace */ 423 0x000000ff, /* src_mask */ 424 0x000000ff, /* dst_mask */ 425 PCRELOFFSET), /* pcrel_offset */ 426 /* 16-bit word relocation (16). */ 427 HOWTO (R_RELWORD, /* type */ 428 0, /* rightshift */ 429 2, /* size */ 430 16, /* bitsize */ 431 false, /* pc_relative */ 432 0, /* bitpos */ 433 complain_overflow_bitfield, /* complain_on_overflow */ 434 coff_amd64_reloc, /* special_function */ 435 "R_X86_64_16", /* name */ 436 true, /* partial_inplace */ 437 0x0000ffff, /* src_mask */ 438 0x0000ffff, /* dst_mask */ 439 PCRELOFFSET), /* pcrel_offset */ 440 /* 32-bit longword relocation (17). */ 441 HOWTO (R_RELLONG, /* type */ 442 0, /* rightshift */ 443 4, /* size */ 444 32, /* bitsize */ 445 false, /* pc_relative */ 446 0, /* bitpos */ 447 complain_overflow_bitfield, /* complain_on_overflow */ 448 coff_amd64_reloc, /* special_function */ 449 "R_X86_64_32S", /* name */ 450 true, /* partial_inplace */ 451 0xffffffff, /* src_mask */ 452 0xffffffff, /* dst_mask */ 453 PCRELOFFSET), /* pcrel_offset */ 454 /* Byte PC relative relocation (18). */ 455 HOWTO (R_PCRBYTE, /* type */ 456 0, /* rightshift */ 457 1, /* size */ 458 8, /* bitsize */ 459 true, /* pc_relative */ 460 0, /* bitpos */ 461 complain_overflow_signed, /* complain_on_overflow */ 462 coff_amd64_reloc, /* special_function */ 463 "R_X86_64_PC8", /* name */ 464 true, /* partial_inplace */ 465 0x000000ff, /* src_mask */ 466 0x000000ff, /* dst_mask */ 467 PCRELOFFSET), /* pcrel_offset */ 468 /* 16-bit word PC relative relocation (19). */ 469 HOWTO (R_PCRWORD, /* type */ 470 0, /* rightshift */ 471 2, /* size */ 472 16, /* bitsize */ 473 true, /* pc_relative */ 474 0, /* bitpos */ 475 complain_overflow_signed, /* complain_on_overflow */ 476 coff_amd64_reloc, /* special_function */ 477 "R_X86_64_PC16", /* name */ 478 true, /* partial_inplace */ 479 0x0000ffff, /* src_mask */ 480 0x0000ffff, /* dst_mask */ 481 PCRELOFFSET), /* pcrel_offset */ 482 /* 32-bit longword PC relative relocation (20). */ 483 HOWTO (R_PCRLONG, /* type */ 484 0, /* rightshift */ 485 4, /* size */ 486 32, /* bitsize */ 487 true, /* pc_relative */ 488 0, /* bitpos */ 489 complain_overflow_signed, /* complain_on_overflow */ 490 coff_amd64_reloc, /* special_function */ 491 "R_X86_64_PC32", /* name */ 492 true, /* partial_inplace */ 493 0xffffffff, /* src_mask */ 494 0xffffffff, /* dst_mask */ 495 PCRELOFFSET) /* pcrel_offset */ 496}; 497 498#define NUM_HOWTOS ARRAY_SIZE (howto_table) 499 500/* Turn a howto into a reloc nunmber */ 501 502#define SELECT_RELOC(x,howto) { x.r_type = howto->type; } 503#define I386 1 /* Customize coffcode.h */ 504#define AMD64 1 505 506#define RTYPE2HOWTO(cache_ptr, dst) \ 507 ((cache_ptr)->howto = \ 508 ((dst)->r_type < NUM_HOWTOS) \ 509 ? howto_table + (dst)->r_type \ 510 : NULL) 511 512/* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared 513 library. On some other COFF targets STYP_BSS is normally 514 STYP_NOLOAD. */ 515#define BSS_NOLOAD_IS_SHARED_LIBRARY 516 517/* Compute the addend of a reloc. If the reloc is to a common symbol, 518 the object file contains the value of the common symbol. By the 519 time this is called, the linker may be using a different symbol 520 from a different object file with a different value. Therefore, we 521 hack wildly to locate the original symbol from this file so that we 522 can make the correct adjustment. This macro sets coffsym to the 523 symbol from the original file, and uses it to set the addend value 524 correctly. If this is not a common symbol, the usual addend 525 calculation is done, except that an additional tweak is needed for 526 PC relative relocs. 527 FIXME: This macro refers to symbols and asect; these are from the 528 calling function, not the macro arguments. */ 529 530#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \ 531 { \ 532 coff_symbol_type *coffsym = NULL; \ 533 \ 534 if (ptr && bfd_asymbol_bfd (ptr) != abfd) \ 535 coffsym = (obj_symbols (abfd) \ 536 + (cache_ptr->sym_ptr_ptr - symbols)); \ 537 else if (ptr) \ 538 coffsym = coff_symbol_from (ptr); \ 539 \ 540 if (coffsym != NULL \ 541 && coffsym->native->u.syment.n_scnum == 0) \ 542 cache_ptr->addend = - coffsym->native->u.syment.n_value; \ 543 else if (ptr && bfd_asymbol_bfd (ptr) == abfd \ 544 && ptr->section != NULL) \ 545 cache_ptr->addend = - (ptr->section->vma \ 546 + COFF_PE_ADDEND_BIAS (ptr)); \ 547 else \ 548 cache_ptr->addend = 0; \ 549 if (ptr && reloc.r_type < NUM_HOWTOS \ 550 && howto_table[reloc.r_type].pc_relative) \ 551 cache_ptr->addend += asect->vma; \ 552 } 553 554/* We use the special COFF backend linker. For normal AMD64 COFF, we 555 can use the generic relocate_section routine. For PE, we need our 556 own routine. */ 557 558#if !defined(COFF_WITH_PE) 559 560#define coff_relocate_section _bfd_coff_generic_relocate_section 561 562#else /* COFF_WITH_PE */ 563 564/* The PE relocate section routine. We handle secidx relocations here, 565 as well as making sure that we don't do anything for a relocatable 566 link. */ 567 568static bool 569coff_pe_amd64_relocate_section (bfd *output_bfd, 570 struct bfd_link_info *info, 571 bfd *input_bfd, 572 asection *input_section, 573 bfd_byte *contents, 574 struct internal_reloc *relocs, 575 struct internal_syment *syms, 576 asection **sections) 577{ 578 struct internal_reloc *rel; 579 struct internal_reloc *relend; 580 581 if (bfd_link_relocatable (info)) 582 return true; 583 584 rel = relocs; 585 relend = rel + input_section->reloc_count; 586 587 for (; rel < relend; rel++) 588 { 589 long symndx; 590 struct coff_link_hash_entry *h; 591 asection *sec, *s; 592 uint16_t idx = 0, i = 1; 593 594 if (rel->r_type != R_SECTION) 595 continue; 596 597 /* Make sure that _bfd_coff_generic_relocate_section won't parse 598 this reloc after us. */ 599 rel->r_type = 0; 600 601 symndx = rel->r_symndx; 602 603 if (symndx < 0 604 || (unsigned long) symndx >= obj_raw_syment_count (input_bfd)) 605 continue; 606 607 h = obj_coff_sym_hashes (input_bfd)[symndx]; 608 609 if (h == NULL) 610 sec = sections[symndx]; 611 else 612 { 613 if (h->root.type == bfd_link_hash_defined 614 || h->root.type == bfd_link_hash_defweak) 615 { 616 /* Defined weak symbols are a GNU extension. */ 617 sec = h->root.u.def.section; 618 } 619 else 620 { 621 sec = NULL; 622 } 623 } 624 625 if (!sec) 626 continue; 627 628 if (bfd_is_abs_section (sec)) 629 continue; 630 631 if (discarded_section (sec)) 632 continue; 633 634 s = output_bfd->sections; 635 while (s) 636 { 637 if (s == sec->output_section) 638 { 639 idx = i; 640 break; 641 } 642 643 i++; 644 s = s->next; 645 } 646 647 bfd_putl16 (idx, contents + rel->r_vaddr - input_section->vma); 648 } 649 650 return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections); 651} 652 653#define coff_relocate_section coff_pe_amd64_relocate_section 654 655static hashval_t 656htab_hash_section_index (const void * entry) 657{ 658 const struct bfd_section * sec = entry; 659 return sec->index; 660} 661 662static int 663htab_eq_section_index (const void * e1, const void * e2) 664{ 665 const struct bfd_section * sec1 = e1; 666 const struct bfd_section * sec2 = e2; 667 return sec1->index == sec2->index; 668} 669#endif /* COFF_WITH_PE */ 670 671/* Convert an rtype to howto for the COFF backend linker. */ 672 673static reloc_howto_type * 674coff_amd64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED, 675 asection *sec, 676 struct internal_reloc *rel, 677 struct coff_link_hash_entry *h, 678 struct internal_syment *sym, 679 bfd_vma *addendp) 680{ 681 reloc_howto_type *howto; 682 683 if (rel->r_type >= NUM_HOWTOS) 684 { 685 bfd_set_error (bfd_error_bad_value); 686 return NULL; 687 } 688 howto = howto_table + rel->r_type; 689 690#if defined(COFF_WITH_PE) 691 /* Cancel out code in _bfd_coff_generic_relocate_section. */ 692 *addendp = 0; 693 if (rel->r_type >= R_AMD64_PCRLONG_1 && rel->r_type <= R_AMD64_PCRLONG_5) 694 { 695 *addendp -= (bfd_vma)(rel->r_type - R_AMD64_PCRLONG); 696 rel->r_type = R_AMD64_PCRLONG; 697 } 698#endif 699 700 if (howto->pc_relative) 701 *addendp += sec->vma; 702 703 if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0) 704 { 705 /* This is a common symbol. The section contents include the 706 size (sym->n_value) as an addend. The relocate_section 707 function will be adding in the final value of the symbol. We 708 need to subtract out the current size in order to get the 709 correct result. */ 710 BFD_ASSERT (h != NULL); 711 712#if !defined(COFF_WITH_PE) 713 /* I think we *do* want to bypass this. If we don't, I have 714 seen some data parameters get the wrong relocation address. 715 If I link two versions with and without this section bypassed 716 and then do a binary comparison, the addresses which are 717 different can be looked up in the map. The case in which 718 this section has been bypassed has addresses which correspond 719 to values I can find in the map. */ 720 *addendp -= sym->n_value; 721#endif 722 } 723 724#if !defined(COFF_WITH_PE) 725 /* If the output symbol is common (in which case this must be a 726 relocatable link), we need to add in the final size of the 727 common symbol. */ 728 if (h != NULL && h->root.type == bfd_link_hash_common) 729 *addendp += h->root.u.c.size; 730#endif 731 732#if defined(COFF_WITH_PE) 733 if (howto->pc_relative) 734 { 735#ifndef DONT_EXTEND_AMD64 736 if (rel->r_type == R_AMD64_PCRQUAD) 737 *addendp -= 8; 738 else 739#endif 740 *addendp -= 4; 741 742 /* If the symbol is defined, then the generic code is going to 743 add back the symbol value in order to cancel out an 744 adjustment it made to the addend. However, we set the addend 745 to 0 at the start of this function. We need to adjust here, 746 to avoid the adjustment the generic code will make. FIXME: 747 This is getting a bit hackish. */ 748 if (sym != NULL && sym->n_scnum != 0) 749 *addendp -= sym->n_value; 750 } 751 752 if (rel->r_type == R_AMD64_IMAGEBASE 753 && (bfd_get_flavour (sec->output_section->owner) == bfd_target_coff_flavour)) 754 *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase; 755 756 if (rel->r_type == R_AMD64_SECREL) 757 { 758 bfd_vma osect_vma = 0; 759 760 if (h != NULL 761 && (h->root.type == bfd_link_hash_defined 762 || h->root.type == bfd_link_hash_defweak)) 763 osect_vma = h->root.u.def.section->output_section->vma; 764 else 765 { 766 htab_t table = coff_data (abfd)->section_by_index; 767 asection *s; 768 769 if (!table) 770 { 771 table = htab_create (10, htab_hash_section_index, 772 htab_eq_section_index, NULL); 773 if (table == NULL) 774 return NULL; 775 coff_data (abfd)->section_by_index = table; 776 } 777 778 if (htab_elements (table) == 0) 779 { 780 for (s = abfd->sections; s != NULL; s = s->next) 781 { 782 void ** slot = htab_find_slot (table, s, INSERT); 783 784 if (slot != NULL) 785 *slot = s; 786 } 787 } 788 789 struct bfd_section needle; 790 791 needle.index = sym->n_scnum - 1; 792 s = htab_find (table, &needle); 793 if (s != NULL) 794 osect_vma = s->output_section->vma; 795 } 796 797 *addendp -= osect_vma; 798 } 799#endif 800 801 return howto; 802} 803 804#define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup 805#define coff_bfd_reloc_name_lookup coff_amd64_reloc_name_lookup 806 807static reloc_howto_type * 808coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) 809{ 810 switch (code) 811 { 812 case BFD_RELOC_RVA: 813 return howto_table + R_AMD64_IMAGEBASE; 814 case BFD_RELOC_32: 815 return howto_table + R_AMD64_DIR32; 816 case BFD_RELOC_64: 817 return howto_table + R_AMD64_DIR64; 818 case BFD_RELOC_64_PCREL: 819#ifndef DONT_EXTEND_AMD64 820 return howto_table + R_AMD64_PCRQUAD; 821#else 822 /* Fall through. */ 823#endif 824 case BFD_RELOC_32_PCREL: 825 return howto_table + R_AMD64_PCRLONG; 826 case BFD_RELOC_X86_64_32S: 827 return howto_table + R_RELLONG; 828 case BFD_RELOC_16: 829 return howto_table + R_RELWORD; 830 case BFD_RELOC_16_PCREL: 831 return howto_table + R_PCRWORD; 832 case BFD_RELOC_8: 833 return howto_table + R_RELBYTE; 834 case BFD_RELOC_8_PCREL: 835 return howto_table + R_PCRBYTE; 836#if defined(COFF_WITH_PE) 837 case BFD_RELOC_32_SECREL: 838 return howto_table + R_AMD64_SECREL; 839 case BFD_RELOC_16_SECIDX: 840 return howto_table + R_AMD64_SECTION; 841#endif 842 default: 843 BFD_FAIL (); 844 return 0; 845 } 846} 847 848static reloc_howto_type * 849coff_amd64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 850 const char *r_name) 851{ 852 unsigned int i; 853 854 for (i = 0; i < NUM_HOWTOS; i++) 855 if (howto_table[i].name != NULL 856 && strcasecmp (howto_table[i].name, r_name) == 0) 857 return &howto_table[i]; 858 859 return NULL; 860} 861 862#define coff_rtype_to_howto coff_amd64_rtype_to_howto 863 864#ifdef TARGET_UNDERSCORE 865 866/* If amd64 gcc uses underscores for symbol names, then it does not use 867 a leading dot for local labels, so if TARGET_UNDERSCORE is defined 868 we treat all symbols starting with L as local. */ 869 870static bool 871coff_amd64_is_local_label_name (bfd *abfd, const char *name) 872{ 873 if (name[0] == 'L') 874 return true; 875 876 return _bfd_coff_is_local_label_name (abfd, name); 877} 878 879#define coff_bfd_is_local_label_name coff_amd64_is_local_label_name 880 881#endif /* TARGET_UNDERSCORE */ 882 883#ifndef bfd_pe_print_pdata 884#define bfd_pe_print_pdata NULL 885#endif 886 887#include "coffcode.h" 888 889#ifdef PE 890#define amd64coff_object_p pe_bfd_object_p 891#else 892#define amd64coff_object_p coff_object_p 893#endif 894 895const bfd_target 896#ifdef TARGET_SYM 897 TARGET_SYM = 898#else 899 x86_64_coff_vec = 900#endif 901{ 902#ifdef TARGET_NAME 903 TARGET_NAME, 904#else 905 "coff-x86-64", /* Name. */ 906#endif 907 bfd_target_coff_flavour, 908 BFD_ENDIAN_LITTLE, /* Data byte order is little. */ 909 BFD_ENDIAN_LITTLE, /* Header byte order is little. */ 910 911 (HAS_RELOC | EXEC_P /* Object flags. */ 912 | HAS_LINENO | HAS_DEBUG 913 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS), 914 915 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags. */ 916#if defined(COFF_WITH_PE) 917 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING 918#endif 919 | SEC_CODE | SEC_DATA | SEC_EXCLUDE ), 920 921#ifdef TARGET_UNDERSCORE 922 TARGET_UNDERSCORE, /* Leading underscore. */ 923#else 924 0, /* Leading underscore. */ 925#endif 926 '/', /* Ar_pad_char. */ 927 15, /* Ar_max_namelen. */ 928 0, /* match priority. */ 929 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 930 931 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 932 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 933 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ 934 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 935 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 936 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ 937 938 /* Note that we allow an object file to be treated as a core file as well. */ 939 { /* bfd_check_format. */ 940 _bfd_dummy_target, 941 amd64coff_object_p, 942 bfd_generic_archive_p, 943 amd64coff_object_p 944 }, 945 { /* bfd_set_format. */ 946 _bfd_bool_bfd_false_error, 947 coff_mkobject, 948 _bfd_generic_mkarchive, 949 _bfd_bool_bfd_false_error 950 }, 951 { /* bfd_write_contents. */ 952 _bfd_bool_bfd_false_error, 953 coff_write_object_contents, 954 _bfd_write_archive_contents, 955 _bfd_bool_bfd_false_error 956 }, 957 958 BFD_JUMP_TABLE_GENERIC (coff), 959 BFD_JUMP_TABLE_COPY (coff), 960 BFD_JUMP_TABLE_CORE (_bfd_nocore), 961 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), 962 BFD_JUMP_TABLE_SYMBOLS (coff), 963 BFD_JUMP_TABLE_RELOCS (coff), 964 BFD_JUMP_TABLE_WRITE (coff), 965 BFD_JUMP_TABLE_LINK (coff), 966 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 967 968 NULL, 969 970 COFF_SWAP_TABLE 971}; 972 973/* Entry for big object files. */ 974 975#ifdef COFF_WITH_PE_BIGOBJ 976const bfd_target 977 TARGET_SYM_BIG = 978{ 979 TARGET_NAME_BIG, 980 bfd_target_coff_flavour, 981 BFD_ENDIAN_LITTLE, /* Data byte order is little. */ 982 BFD_ENDIAN_LITTLE, /* Header byte order is little. */ 983 984 (HAS_RELOC | EXEC_P /* Object flags. */ 985 | HAS_LINENO | HAS_DEBUG 986 | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS), 987 988 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags. */ 989#if defined(COFF_WITH_PE) 990 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING 991#endif 992 | SEC_CODE | SEC_DATA | SEC_EXCLUDE ), 993 994#ifdef TARGET_UNDERSCORE 995 TARGET_UNDERSCORE, /* Leading underscore. */ 996#else 997 0, /* Leading underscore. */ 998#endif 999 '/', /* Ar_pad_char. */ 1000 15, /* Ar_max_namelen. */ 1001 0, /* match priority. */ 1002 TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */ 1003 1004 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1005 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1006 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data. */ 1007 bfd_getl64, bfd_getl_signed_64, bfd_putl64, 1008 bfd_getl32, bfd_getl_signed_32, bfd_putl32, 1009 bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs. */ 1010 1011 /* Note that we allow an object file to be treated as a core file as well. */ 1012 { /* bfd_check_format. */ 1013 _bfd_dummy_target, 1014 amd64coff_object_p, 1015 bfd_generic_archive_p, 1016 amd64coff_object_p 1017 }, 1018 { /* bfd_set_format. */ 1019 _bfd_bool_bfd_false_error, 1020 coff_mkobject, 1021 _bfd_generic_mkarchive, 1022 _bfd_bool_bfd_false_error 1023 }, 1024 { /* bfd_write_contents. */ 1025 _bfd_bool_bfd_false_error, 1026 coff_write_object_contents, 1027 _bfd_write_archive_contents, 1028 _bfd_bool_bfd_false_error 1029 }, 1030 1031 BFD_JUMP_TABLE_GENERIC (coff), 1032 BFD_JUMP_TABLE_COPY (coff), 1033 BFD_JUMP_TABLE_CORE (_bfd_nocore), 1034 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), 1035 BFD_JUMP_TABLE_SYMBOLS (coff), 1036 BFD_JUMP_TABLE_RELOCS (coff), 1037 BFD_JUMP_TABLE_WRITE (coff), 1038 BFD_JUMP_TABLE_LINK (coff), 1039 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 1040 1041 NULL, 1042 1043 &bigobj_swap_table 1044}; 1045#endif 1046