Home | History | Annotate | Download | only in bfd
      1 /* BFD back-end for AMD 64 COFF files.
      2    Copyright (C) 2006-2014 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 #ifndef COFF_WITH_pex64
     24 #define COFF_WITH_pex64
     25 #endif
     26 
     27 /* Note we have to make sure not to include headers twice.
     28    Not all headers are wrapped in #ifdef guards, so we define
     29    PEI_HEADERS to prevent double including here.  */
     30 #ifndef PEI_HEADERS
     31 #include "sysdep.h"
     32 #include "bfd.h"
     33 #include "libbfd.h"
     34 #include "coff/x86_64.h"
     35 #include "coff/internal.h"
     36 #include "coff/pe.h"
     37 #include "libcoff.h"
     38 #include "libiberty.h"
     39 #endif
     40 
     41 #define BADMAG(x) AMD64BADMAG(x)
     42 
     43 #ifdef COFF_WITH_pex64
     44 # undef  AOUTSZ
     45 # define AOUTSZ		PEPAOUTSZ
     46 # define PEAOUTHDR	PEPAOUTHDR
     47 #endif
     48 
     49 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
     50 
     51 /* The page size is a guess based on ELF.  */
     52 
     53 #define COFF_PAGE_SIZE 0x1000
     54 
     55 /* For some reason when using AMD COFF the value stored in the .text
     56    section for a reference to a common symbol is the value itself plus
     57    any desired offset.  Ian Taylor, Cygnus Support.  */
     58 
     59 /* If we are producing relocatable output, we need to do some
     60    adjustments to the object file that are not done by the
     61    bfd_perform_relocation function.  This function is called by every
     62    reloc type to make any required adjustments.  */
     63 
     64 static bfd_reloc_status_type
     65 coff_amd64_reloc (bfd *abfd,
     66 		  arelent *reloc_entry,
     67 		  asymbol *symbol,
     68 		  void * data,
     69 		  asection *input_section ATTRIBUTE_UNUSED,
     70 		  bfd *output_bfd,
     71 		  char **error_message ATTRIBUTE_UNUSED)
     72 {
     73   symvalue diff;
     74 
     75 #if !defined(COFF_WITH_PE)
     76   if (output_bfd == NULL)
     77     return bfd_reloc_continue;
     78 #endif
     79 
     80   if (bfd_is_com_section (symbol->section))
     81     {
     82 #if !defined(COFF_WITH_PE)
     83       /* We are relocating a common symbol.  The current value in the
     84 	 object file is ORIG + OFFSET, where ORIG is the value of the
     85 	 common symbol as seen by the object file when it was compiled
     86 	 (this may be zero if the symbol was undefined) and OFFSET is
     87 	 the offset into the common symbol (normally zero, but may be
     88 	 non-zero when referring to a field in a common structure).
     89 	 ORIG is the negative of reloc_entry->addend, which is set by
     90 	 the CALC_ADDEND macro below.  We want to replace the value in
     91 	 the object file with NEW + OFFSET, where NEW is the value of
     92 	 the common symbol which we are going to put in the final
     93 	 object file.  NEW is symbol->value.  */
     94       diff = symbol->value + reloc_entry->addend;
     95 #else
     96       /* In PE mode, we do not offset the common symbol.  */
     97       diff = reloc_entry->addend;
     98 #endif
     99     }
    100   else
    101     {
    102       /* For some reason bfd_perform_relocation always effectively
    103 	 ignores the addend for a COFF target when producing
    104 	 relocatable output.  This seems to be always wrong for 386
    105 	 COFF, so we handle the addend here instead.  */
    106 #if defined(COFF_WITH_PE)
    107       if (output_bfd == NULL)
    108 	{
    109 	  reloc_howto_type *howto = reloc_entry->howto;
    110 
    111 	  /* Although PC relative relocations are very similar between
    112 	     PE and non-PE formats, but they are off by 1 << howto->size
    113 	     bytes. For the external relocation, PE is very different
    114 	     from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
    115 	     When we link PE and non-PE object files together to
    116 	     generate a non-PE executable, we have to compensate it
    117 	     here.  */
    118 	  if(howto->pc_relative && howto->pcrel_offset)
    119 	    diff = -(1 << howto->size);
    120 	  else if(symbol->flags & BSF_WEAK)
    121 	    diff = reloc_entry->addend - symbol->value;
    122 	  else
    123 	    diff = -reloc_entry->addend;
    124 	}
    125       else
    126 #endif
    127 	diff = reloc_entry->addend;
    128     }
    129 
    130 #if defined(COFF_WITH_PE)
    131   /* FIXME: How should this case be handled?  */
    132   if (reloc_entry->howto->type == R_AMD64_IMAGEBASE
    133       && output_bfd != NULL
    134       && bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
    135     diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
    136 #endif
    137 
    138 #define DOIT(x) \
    139   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
    140 
    141     if (diff != 0)
    142       {
    143 	reloc_howto_type *howto = reloc_entry->howto;
    144 	unsigned char *addr = (unsigned char *) data + reloc_entry->address;
    145 
    146 	switch (howto->size)
    147 	  {
    148 	  case 0:
    149 	    {
    150 	      char x = bfd_get_8 (abfd, addr);
    151 	      DOIT (x);
    152 	      bfd_put_8 (abfd, x, addr);
    153 	    }
    154 	    break;
    155 
    156 	  case 1:
    157 	    {
    158 	      short x = bfd_get_16 (abfd, addr);
    159 	      DOIT (x);
    160 	      bfd_put_16 (abfd, (bfd_vma) x, addr);
    161 	    }
    162 	    break;
    163 
    164 	  case 2:
    165 	    {
    166 	      long x = bfd_get_32 (abfd, addr);
    167 	      DOIT (x);
    168 	      bfd_put_32 (abfd, (bfd_vma) x, addr);
    169 	    }
    170 	    break;
    171 	  case 4:
    172 	    {
    173 	      long long x = bfd_get_64 (abfd, addr);
    174 	      DOIT (x);
    175 	      bfd_put_64 (abfd, (bfd_vma) x, addr);
    176 	    }
    177 	    break;
    178 
    179 	  default:
    180 	    abort ();
    181 	  }
    182       }
    183 
    184   /* Now let bfd_perform_relocation finish everything up.  */
    185   return bfd_reloc_continue;
    186 }
    187 
    188 #if defined(COFF_WITH_PE)
    189 /* Return TRUE if this relocation should appear in the output .reloc
    190    section.  */
    191 
    192 static bfd_boolean
    193 in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
    194 {
    195   return ! howto->pc_relative && howto->type != R_AMD64_IMAGEBASE
    196 	 && howto->type != R_AMD64_SECREL;
    197 }
    198 #endif /* COFF_WITH_PE */
    199 
    200 #ifndef PCRELOFFSET
    201 #define PCRELOFFSET TRUE
    202 #endif
    203 
    204 static reloc_howto_type howto_table[] =
    205 {
    206   EMPTY_HOWTO (0),
    207   HOWTO (R_AMD64_DIR64,		/* type  1*/
    208 	 0,			/* rightshift */
    209 	 4,			/* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
    210 	 64,			/* bitsize */
    211 	 FALSE,			/* pc_relative */
    212 	 0,			/* bitpos */
    213 	 complain_overflow_bitfield, /* complain_on_overflow */
    214 	 coff_amd64_reloc,	/* special_function */
    215 	 "R_X86_64_64",		/* name */
    216 	 TRUE,			/* partial_inplace */
    217 	 0xffffffffffffffffll,	/* src_mask */
    218 	 0xffffffffffffffffll,	/* dst_mask */
    219 	 TRUE),			/* pcrel_offset */
    220   HOWTO (R_AMD64_DIR32,		/* type 2 */
    221 	 0,			/* rightshift */
    222 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    223 	 32,			/* bitsize */
    224 	 FALSE,			/* pc_relative */
    225 	 0,			/* bitpos */
    226 	 complain_overflow_bitfield, /* complain_on_overflow */
    227 	 coff_amd64_reloc,	/* special_function */
    228 	 "R_X86_64_32",		/* name */
    229 	 TRUE,			/* partial_inplace */
    230 	 0xffffffff,		/* src_mask */
    231 	 0xffffffff,		/* dst_mask */
    232 	 TRUE),			/* pcrel_offset */
    233   /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).	*/
    234   HOWTO (R_AMD64_IMAGEBASE,	/* type */
    235 	 0,			/* rightshift */
    236 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    237 	 32,			/* bitsize */
    238 	 FALSE,			/* pc_relative */
    239 	 0,			/* bitpos */
    240 	 complain_overflow_bitfield, /* complain_on_overflow */
    241 	 coff_amd64_reloc,	/* special_function */
    242 	 "rva32",		/* name */
    243 	 TRUE,			/* partial_inplace */
    244 	 0xffffffff,		/* src_mask */
    245 	 0xffffffff,		/* dst_mask */
    246 	 FALSE),		/* pcrel_offset */
    247   /* 32-bit longword PC relative relocation (4).  */
    248   HOWTO (R_AMD64_PCRLONG,	/* type 4 */
    249 	 0,			/* rightshift */
    250 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    251 	 32,			/* bitsize */
    252 	 TRUE,			/* pc_relative */
    253 	 0,			/* bitpos */
    254 	 complain_overflow_signed, /* complain_on_overflow */
    255 	 coff_amd64_reloc,	/* special_function */
    256 	 "R_X86_64_PC32",	/* name */
    257 	 TRUE,			/* partial_inplace */
    258 	 0xffffffff,		/* src_mask */
    259 	 0xffffffff,		/* dst_mask */
    260 	 PCRELOFFSET),		/* pcrel_offset */
    261 
    262  HOWTO (R_AMD64_PCRLONG_1,	/* type 5 */
    263 	 0,			/* rightshift */
    264 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    265 	 32,			/* bitsize */
    266 	 TRUE,			/* pc_relative */
    267 	 0,			/* bitpos */
    268 	 complain_overflow_signed, /* complain_on_overflow */
    269 	 coff_amd64_reloc,	/* special_function */
    270 	 "DISP32+1",		/* name */
    271 	 TRUE,			/* partial_inplace */
    272 	 0xffffffff,		/* src_mask */
    273 	 0xffffffff,		/* dst_mask */
    274 	 PCRELOFFSET),		/* pcrel_offset */
    275  HOWTO (R_AMD64_PCRLONG_2,	/* type 6 */
    276 	 0,			/* rightshift */
    277 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    278 	 32,			/* bitsize */
    279 	 TRUE,			/* pc_relative */
    280 	 0,			/* bitpos */
    281 	 complain_overflow_signed, /* complain_on_overflow */
    282 	 coff_amd64_reloc,	/* special_function */
    283 	 "DISP32+2",		/* name */
    284 	 TRUE,			/* partial_inplace */
    285 	 0xffffffff,		/* src_mask */
    286 	 0xffffffff,		/* dst_mask */
    287 	 PCRELOFFSET),		/* pcrel_offset */
    288  HOWTO (R_AMD64_PCRLONG_3,	/* type 7 */
    289 	 0,			/* rightshift */
    290 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    291 	 32,			/* bitsize */
    292 	 TRUE,			/* pc_relative */
    293 	 0,			/* bitpos */
    294 	 complain_overflow_signed, /* complain_on_overflow */
    295 	 coff_amd64_reloc,	/* special_function */
    296 	 "DISP32+3",		/* name */
    297 	 TRUE,			/* partial_inplace */
    298 	 0xffffffff,		/* src_mask */
    299 	 0xffffffff,		/* dst_mask */
    300 	 PCRELOFFSET),		/* pcrel_offset */
    301  HOWTO (R_AMD64_PCRLONG_4,	/* type 8 */
    302 	 0,			/* rightshift */
    303 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    304 	 32,			/* bitsize */
    305 	 TRUE,			/* pc_relative */
    306 	 0,			/* bitpos */
    307 	 complain_overflow_signed, /* complain_on_overflow */
    308 	 coff_amd64_reloc,	/* special_function */
    309 	 "DISP32+4",		/* name */
    310 	 TRUE,			/* partial_inplace */
    311 	 0xffffffff,		/* src_mask */
    312 	 0xffffffff,		/* dst_mask */
    313 	 PCRELOFFSET),		/* pcrel_offset */
    314  HOWTO (R_AMD64_PCRLONG_5,	/* type 9 */
    315 	 0,			/* rightshift */
    316 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    317 	 32,			/* bitsize */
    318 	 TRUE,			/* pc_relative */
    319 	 0,			/* bitpos */
    320 	 complain_overflow_signed, /* complain_on_overflow */
    321 	 coff_amd64_reloc,	/* special_function */
    322 	 "DISP32+5",		/* name */
    323 	 TRUE,			/* partial_inplace */
    324 	 0xffffffff,		/* src_mask */
    325 	 0xffffffff,		/* dst_mask */
    326 	 PCRELOFFSET),		/* pcrel_offset */
    327   EMPTY_HOWTO (10), /* R_AMD64_SECTION 10  */
    328 #if defined(COFF_WITH_PE)
    329   /* 32-bit longword section relative relocation (11).  */
    330   HOWTO (R_AMD64_SECREL,	/* type */
    331 	 0,			/* rightshift */
    332 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    333 	 32,			/* bitsize */
    334 	 FALSE,			/* pc_relative */
    335 	 0,			/* bitpos */
    336 	 complain_overflow_bitfield, /* complain_on_overflow */
    337 	 coff_amd64_reloc,	/* special_function */
    338 	 "secrel32",		/* name */
    339 	 TRUE,			/* partial_inplace */
    340 	 0xffffffff,		/* src_mask */
    341 	 0xffffffff,		/* dst_mask */
    342 	 TRUE),			/* pcrel_offset */
    343 #else
    344   EMPTY_HOWTO (11),
    345 #endif
    346   EMPTY_HOWTO (12),
    347   EMPTY_HOWTO (13),
    348 #ifndef DONT_EXTEND_AMD64
    349   HOWTO (R_AMD64_PCRQUAD,
    350          0,                     /* rightshift */
    351          4,                     /* size (0 = byte, 1 = short, 2 = long) */
    352          64,                    /* bitsize */
    353          TRUE,                  /* pc_relative */
    354          0,                     /* bitpos */
    355          complain_overflow_signed, /* complain_on_overflow */
    356          coff_amd64_reloc,      /* special_function */
    357          "R_X86_64_PC64",       /* name */
    358          TRUE,                  /* partial_inplace */
    359          0xffffffffffffffffll,  /* src_mask */
    360          0xffffffffffffffffll,  /* dst_mask */
    361          PCRELOFFSET),           /* pcrel_offset */
    362 #else
    363   EMPTY_HOWTO (14),
    364 #endif
    365   /* Byte relocation (15).  */
    366   HOWTO (R_RELBYTE,		/* type */
    367 	 0,			/* rightshift */
    368 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    369 	 8,			/* bitsize */
    370 	 FALSE,			/* pc_relative */
    371 	 0,			/* bitpos */
    372 	 complain_overflow_bitfield, /* complain_on_overflow */
    373 	 coff_amd64_reloc,	/* special_function */
    374 	 "R_X86_64_8",		/* name */
    375 	 TRUE,			/* partial_inplace */
    376 	 0x000000ff,		/* src_mask */
    377 	 0x000000ff,		/* dst_mask */
    378 	 PCRELOFFSET),		/* pcrel_offset */
    379   /* 16-bit word relocation (16).  */
    380   HOWTO (R_RELWORD,		/* type */
    381 	 0,			/* rightshift */
    382 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    383 	 16,			/* bitsize */
    384 	 FALSE,			/* pc_relative */
    385 	 0,			/* bitpos */
    386 	 complain_overflow_bitfield, /* complain_on_overflow */
    387 	 coff_amd64_reloc,	/* special_function */
    388 	 "R_X86_64_16",		/* name */
    389 	 TRUE,			/* partial_inplace */
    390 	 0x0000ffff,		/* src_mask */
    391 	 0x0000ffff,		/* dst_mask */
    392 	 PCRELOFFSET),		/* pcrel_offset */
    393   /* 32-bit longword relocation (17).	*/
    394   HOWTO (R_RELLONG,		/* type */
    395 	 0,			/* rightshift */
    396 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    397 	 32,			/* bitsize */
    398 	 FALSE,			/* pc_relative */
    399 	 0,			/* bitpos */
    400 	 complain_overflow_bitfield, /* complain_on_overflow */
    401 	 coff_amd64_reloc,	/* special_function */
    402 	 "R_X86_64_32S",	/* name */
    403 	 TRUE,			/* partial_inplace */
    404 	 0xffffffff,		/* src_mask */
    405 	 0xffffffff,		/* dst_mask */
    406 	 PCRELOFFSET),		/* pcrel_offset */
    407   /* Byte PC relative relocation (18).	 */
    408   HOWTO (R_PCRBYTE,		/* type */
    409 	 0,			/* rightshift */
    410 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
    411 	 8,			/* bitsize */
    412 	 TRUE,			/* pc_relative */
    413 	 0,			/* bitpos */
    414 	 complain_overflow_signed, /* complain_on_overflow */
    415 	 coff_amd64_reloc,	/* special_function */
    416 	 "R_X86_64_PC8",	/* name */
    417 	 TRUE,			/* partial_inplace */
    418 	 0x000000ff,		/* src_mask */
    419 	 0x000000ff,		/* dst_mask */
    420 	 PCRELOFFSET),		/* pcrel_offset */
    421   /* 16-bit word PC relative relocation (19).	*/
    422   HOWTO (R_PCRWORD,		/* type */
    423 	 0,			/* rightshift */
    424 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
    425 	 16,			/* bitsize */
    426 	 TRUE,			/* pc_relative */
    427 	 0,			/* bitpos */
    428 	 complain_overflow_signed, /* complain_on_overflow */
    429 	 coff_amd64_reloc,	/* special_function */
    430 	 "R_X86_64_PC16",	/* name */
    431 	 TRUE,			/* partial_inplace */
    432 	 0x0000ffff,		/* src_mask */
    433 	 0x0000ffff,		/* dst_mask */
    434 	 PCRELOFFSET),		/* pcrel_offset */
    435   /* 32-bit longword PC relative relocation (20).  */
    436   HOWTO (R_PCRLONG,		/* type */
    437 	 0,			/* rightshift */
    438 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
    439 	 32,			/* bitsize */
    440 	 TRUE,			/* pc_relative */
    441 	 0,			/* bitpos */
    442 	 complain_overflow_signed, /* complain_on_overflow */
    443 	 coff_amd64_reloc,	/* special_function */
    444 	 "R_X86_64_PC32",	/* name */
    445 	 TRUE,			/* partial_inplace */
    446 	 0xffffffff,		/* src_mask */
    447 	 0xffffffff,		/* dst_mask */
    448 	 PCRELOFFSET)		/* pcrel_offset */
    449 };
    450 
    451 #define NUM_HOWTOS ARRAY_SIZE (howto_table)
    452 
    453 /* Turn a howto into a reloc  nunmber */
    454 
    455 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
    456 #define I386  1			/* Customize coffcode.h */
    457 #define AMD64 1
    458 
    459 #define RTYPE2HOWTO(cache_ptr, dst)		\
    460   ((cache_ptr)->howto =				\
    461    ((dst)->r_type < NUM_HOWTOS)			\
    462     ? howto_table + (dst)->r_type		\
    463     : NULL)
    464 
    465 /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
    466    library.  On some other COFF targets STYP_BSS is normally
    467    STYP_NOLOAD.  */
    468 #define BSS_NOLOAD_IS_SHARED_LIBRARY
    469 
    470 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
    471    the object file contains the value of the common symbol.  By the
    472    time this is called, the linker may be using a different symbol
    473    from a different object file with a different value.  Therefore, we
    474    hack wildly to locate the original symbol from this file so that we
    475    can make the correct adjustment.  This macro sets coffsym to the
    476    symbol from the original file, and uses it to set the addend value
    477    correctly.  If this is not a common symbol, the usual addend
    478    calculation is done, except that an additional tweak is needed for
    479    PC relative relocs.
    480    FIXME: This macro refers to symbols and asect; these are from the
    481    calling function, not the macro arguments.  */
    482 
    483 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)		\
    484   {								\
    485     coff_symbol_type *coffsym = NULL;				\
    486     								\
    487     if (ptr && bfd_asymbol_bfd (ptr) != abfd)			\
    488       coffsym = (obj_symbols (abfd)				\
    489 	         + (cache_ptr->sym_ptr_ptr - symbols));		\
    490     else if (ptr)						\
    491       coffsym = coff_symbol_from (abfd, ptr);			\
    492     								\
    493     if (coffsym != NULL						\
    494 	&& coffsym->native->u.syment.n_scnum == 0)		\
    495       cache_ptr->addend = - coffsym->native->u.syment.n_value;	\
    496     else if (ptr && bfd_asymbol_bfd (ptr) == abfd		\
    497 	     && ptr->section != NULL)				\
    498       cache_ptr->addend = - (ptr->section->vma + ptr->value);	\
    499     else							\
    500       cache_ptr->addend = 0;					\
    501     if (ptr && reloc.r_type < NUM_HOWTOS			\
    502 	&& howto_table[reloc.r_type].pc_relative)		\
    503       cache_ptr->addend += asect->vma;				\
    504   }
    505 
    506 /* We use the special COFF backend linker.  For normal AMD64 COFF, we
    507    can use the generic relocate_section routine.  For PE, we need our
    508    own routine.  */
    509 
    510 #if !defined(COFF_WITH_PE)
    511 
    512 #define coff_relocate_section _bfd_coff_generic_relocate_section
    513 
    514 #else /* COFF_WITH_PE */
    515 
    516 /* The PE relocate section routine.  The only difference between this
    517    and the regular routine is that we don't want to do anything for a
    518    relocatable link.  */
    519 
    520 static bfd_boolean
    521 coff_pe_amd64_relocate_section (bfd *output_bfd,
    522 				struct bfd_link_info *info,
    523 				bfd *input_bfd,
    524 				asection *input_section,
    525 				bfd_byte *contents,
    526 				struct internal_reloc *relocs,
    527 				struct internal_syment *syms,
    528 				asection **sections)
    529 {
    530   if (info->relocatable)
    531     return TRUE;
    532 
    533   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
    534 }
    535 
    536 #define coff_relocate_section coff_pe_amd64_relocate_section
    537 
    538 #endif /* COFF_WITH_PE */
    539 
    540 /* Convert an rtype to howto for the COFF backend linker.  */
    541 
    542 static reloc_howto_type *
    543 coff_amd64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
    544 			   asection *sec,
    545 			   struct internal_reloc *rel,
    546 			   struct coff_link_hash_entry *h,
    547 			   struct internal_syment *sym,
    548 			   bfd_vma *addendp)
    549 {
    550   reloc_howto_type *howto;
    551 
    552   if (rel->r_type >= NUM_HOWTOS)
    553     {
    554       bfd_set_error (bfd_error_bad_value);
    555       return NULL;
    556     }
    557   howto = howto_table + rel->r_type;
    558 
    559 #if defined(COFF_WITH_PE)
    560   /* Cancel out code in _bfd_coff_generic_relocate_section.  */
    561   *addendp = 0;
    562   if (rel->r_type >= R_AMD64_PCRLONG_1 && rel->r_type <= R_AMD64_PCRLONG_5)
    563     {
    564       *addendp -= (bfd_vma)(rel->r_type - R_AMD64_PCRLONG);
    565       rel->r_type = R_AMD64_PCRLONG;
    566     }
    567 #endif
    568 
    569   if (howto->pc_relative)
    570     *addendp += sec->vma;
    571 
    572   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
    573     {
    574       /* This is a common symbol.  The section contents include the
    575 	 size (sym->n_value) as an addend.  The relocate_section
    576 	 function will be adding in the final value of the symbol.  We
    577 	 need to subtract out the current size in order to get the
    578 	 correct result.  */
    579       BFD_ASSERT (h != NULL);
    580 
    581 #if !defined(COFF_WITH_PE)
    582       /* I think we *do* want to bypass this.  If we don't, I have
    583 	 seen some data parameters get the wrong relocation address.
    584 	 If I link two versions with and without this section bypassed
    585 	 and then do a binary comparison, the addresses which are
    586 	 different can be looked up in the map.  The case in which
    587 	 this section has been bypassed has addresses which correspond
    588 	 to values I can find in the map.  */
    589       *addendp -= sym->n_value;
    590 #endif
    591     }
    592 
    593 #if !defined(COFF_WITH_PE)
    594   /* If the output symbol is common (in which case this must be a
    595      relocatable link), we need to add in the final size of the
    596      common symbol.  */
    597   if (h != NULL && h->root.type == bfd_link_hash_common)
    598     *addendp += h->root.u.c.size;
    599 #endif
    600 
    601 #if defined(COFF_WITH_PE)
    602   if (howto->pc_relative)
    603     {
    604       *addendp -= 4;
    605 
    606       /* If the symbol is defined, then the generic code is going to
    607          add back the symbol value in order to cancel out an
    608          adjustment it made to the addend.  However, we set the addend
    609          to 0 at the start of this function.  We need to adjust here,
    610          to avoid the adjustment the generic code will make.  FIXME:
    611          This is getting a bit hackish.  */
    612       if (sym != NULL && sym->n_scnum != 0)
    613 	*addendp -= sym->n_value;
    614     }
    615 
    616   if (rel->r_type == R_AMD64_IMAGEBASE
    617       && (bfd_get_flavour (sec->output_section->owner) == bfd_target_coff_flavour))
    618     *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
    619 
    620   if (rel->r_type == R_AMD64_SECREL)
    621     {
    622       bfd_vma osect_vma;
    623 
    624       if (h && (h->root.type == bfd_link_hash_defined
    625 		|| h->root.type == bfd_link_hash_defweak))
    626 	osect_vma = h->root.u.def.section->output_section->vma;
    627       else
    628 	{
    629 	  asection *s;
    630 	  int i;
    631 
    632 	  /* Sigh, the only way to get the section to offset against
    633 	     is to find it the hard way.  */
    634 	  for (s = abfd->sections, i = 1; i < sym->n_scnum; i++)
    635 	    s = s->next;
    636 
    637 	  osect_vma = s->output_section->vma;
    638 	}
    639 
    640       *addendp -= osect_vma;
    641     }
    642 #endif
    643 
    644   return howto;
    645 }
    646 
    647 #define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
    648 #define coff_bfd_reloc_name_lookup coff_amd64_reloc_name_lookup
    649 
    650 static reloc_howto_type *
    651 coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
    652 {
    653   switch (code)
    654     {
    655     case BFD_RELOC_RVA:
    656       return howto_table + R_AMD64_IMAGEBASE;
    657     case BFD_RELOC_32:
    658       return howto_table + R_AMD64_DIR32;
    659     case BFD_RELOC_64:
    660       return howto_table + R_AMD64_DIR64;
    661     case BFD_RELOC_64_PCREL:
    662 #ifndef DONT_EXTEND_AMD64
    663       return howto_table + R_AMD64_PCRQUAD;
    664 #else
    665       /* Fall through.  */
    666 #endif
    667     case BFD_RELOC_32_PCREL:
    668       return howto_table + R_AMD64_PCRLONG;
    669     case BFD_RELOC_X86_64_32S:
    670       return howto_table + R_RELLONG;
    671     case BFD_RELOC_16:
    672       return howto_table + R_RELWORD;
    673     case BFD_RELOC_16_PCREL:
    674       return howto_table + R_PCRWORD;
    675     case BFD_RELOC_8:
    676       return howto_table + R_RELBYTE;
    677     case BFD_RELOC_8_PCREL:
    678       return howto_table + R_PCRBYTE;
    679 #if defined(COFF_WITH_PE)
    680     case BFD_RELOC_32_SECREL:
    681       return howto_table + R_AMD64_SECREL;
    682 #endif
    683     default:
    684       BFD_FAIL ();
    685       return 0;
    686     }
    687 }
    688 
    689 static reloc_howto_type *
    690 coff_amd64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    691 			      const char *r_name)
    692 {
    693   unsigned int i;
    694 
    695   for (i = 0; i < NUM_HOWTOS; i++)
    696     if (howto_table[i].name != NULL
    697 	&& strcasecmp (howto_table[i].name, r_name) == 0)
    698       return &howto_table[i];
    699 
    700   return NULL;
    701 }
    702 
    703 #define coff_rtype_to_howto coff_amd64_rtype_to_howto
    704 
    705 #ifdef TARGET_UNDERSCORE
    706 
    707 /* If amd64 gcc uses underscores for symbol names, then it does not use
    708    a leading dot for local labels, so if TARGET_UNDERSCORE is defined
    709    we treat all symbols starting with L as local.  */
    710 
    711 static bfd_boolean
    712 coff_amd64_is_local_label_name (bfd *abfd, const char *name)
    713 {
    714   if (name[0] == 'L')
    715     return TRUE;
    716 
    717   return _bfd_coff_is_local_label_name (abfd, name);
    718 }
    719 
    720 #define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
    721 
    722 #endif /* TARGET_UNDERSCORE */
    723 
    724 #ifndef bfd_pe_print_pdata
    725 #define bfd_pe_print_pdata   NULL
    726 #endif
    727 
    728 #include "coffcode.h"
    729 
    730 #ifdef PE
    731 #define amd64coff_object_p pe_bfd_object_p
    732 #else
    733 #define amd64coff_object_p coff_object_p
    734 #endif
    735 
    736 const bfd_target
    737 #ifdef TARGET_SYM
    738   TARGET_SYM =
    739 #else
    740   x86_64_coff_vec =
    741 #endif
    742 {
    743 #ifdef TARGET_NAME
    744   TARGET_NAME,
    745 #else
    746  "coff-x86-64",			/* Name.  */
    747 #endif
    748   bfd_target_coff_flavour,
    749   BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
    750   BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
    751 
    752   (HAS_RELOC | EXEC_P |		/* Object flags.  */
    753    HAS_LINENO | HAS_DEBUG |
    754    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
    755 
    756   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
    757 #if defined(COFF_WITH_PE)
    758    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
    759 #endif
    760    | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
    761 
    762 #ifdef TARGET_UNDERSCORE
    763   TARGET_UNDERSCORE,		/* Leading underscore.  */
    764 #else
    765   0,				/* Leading underscore.  */
    766 #endif
    767   '/',				/* Ar_pad_char.  */
    768   15,				/* Ar_max_namelen.  */
    769   0,				/* match priority.  */
    770 
    771   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    772      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    773      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
    774   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
    775      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
    776      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
    777 
    778   /* Note that we allow an object file to be treated as a core file as well.  */
    779   { _bfd_dummy_target, amd64coff_object_p, /* BFD_check_format.  */
    780     bfd_generic_archive_p, amd64coff_object_p },
    781   { bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format.  */
    782     bfd_false },
    783   { bfd_false, coff_write_object_contents, /* bfd_write_contents.  */
    784    _bfd_write_archive_contents, bfd_false },
    785 
    786   BFD_JUMP_TABLE_GENERIC (coff),
    787   BFD_JUMP_TABLE_COPY (coff),
    788   BFD_JUMP_TABLE_CORE (_bfd_nocore),
    789   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
    790   BFD_JUMP_TABLE_SYMBOLS (coff),
    791   BFD_JUMP_TABLE_RELOCS (coff),
    792   BFD_JUMP_TABLE_WRITE (coff),
    793   BFD_JUMP_TABLE_LINK (coff),
    794   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
    795 
    796   NULL,
    797 
    798   COFF_SWAP_TABLE
    799 };
    800