Back to index

cell-binutils  2.17cvs20070401
coff-x86_64.c
Go to the documentation of this file.
00001 /* BFD back-end for AMD 64 COFF files.
00002    Copyright 2006, 2007 Free Software Foundation, Inc.
00003 
00004    This file is part of BFD, the Binary File Descriptor library.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
00019    
00020    Written by Kai Tietz, OneVision Software GmbH&CoKg.  */
00021 
00022 #ifndef COFF_WITH_pex64
00023 #define COFF_WITH_pex64
00024 #endif
00025 
00026 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "libbfd.h"
00029 #include "coff/x86_64.h"
00030 #include "coff/internal.h"
00031 #include "coff/pe.h"
00032 #include "libcoff.h"
00033 #include "libiberty.h"
00034 
00035 #define BADMAG(x) AMD64BADMAG(x)
00036 
00037 #ifdef COFF_WITH_pex64
00038 # undef  AOUTSZ
00039 # define AOUTSZ             PEPAOUTSZ
00040 # define PEAOUTHDR   PEPAOUTHDR
00041 #endif
00042 
00043 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00044 
00045 /* The page size is a guess based on ELF.  */
00046 
00047 #define COFF_PAGE_SIZE 0x1000
00048 
00049 /* For some reason when using AMD COFF the value stored in the .text
00050    section for a reference to a common symbol is the value itself plus
00051    any desired offset.  Ian Taylor, Cygnus Support.  */
00052 
00053 /* If we are producing relocatable output, we need to do some
00054    adjustments to the object file that are not done by the
00055    bfd_perform_relocation function.  This function is called by every
00056    reloc type to make any required adjustments.  */
00057 
00058 static bfd_reloc_status_type
00059 coff_amd64_reloc (bfd *abfd,
00060                 arelent *reloc_entry,
00061                 asymbol *symbol,
00062                 void * data,
00063                 asection *input_section ATTRIBUTE_UNUSED,
00064                 bfd *output_bfd,
00065                 char **error_message ATTRIBUTE_UNUSED)
00066 {
00067   symvalue diff;
00068 
00069 #if !defined(COFF_WITH_PE)
00070   if (output_bfd == NULL)
00071     return bfd_reloc_continue;
00072 #endif
00073 
00074   if (bfd_is_com_section (symbol->section))
00075     {
00076 #if !defined(COFF_WITH_PE)
00077       /* We are relocating a common symbol.  The current value in the
00078         object file is ORIG + OFFSET, where ORIG is the value of the
00079         common symbol as seen by the object file when it was compiled
00080         (this may be zero if the symbol was undefined) and OFFSET is
00081         the offset into the common symbol (normally zero, but may be
00082         non-zero when referring to a field in a common structure).
00083         ORIG is the negative of reloc_entry->addend, which is set by
00084         the CALC_ADDEND macro below.  We want to replace the value in
00085         the object file with NEW + OFFSET, where NEW is the value of
00086         the common symbol which we are going to put in the final
00087         object file.  NEW is symbol->value.  */
00088       diff = symbol->value + reloc_entry->addend;
00089 #else
00090       /* In PE mode, we do not offset the common symbol.  */
00091       diff = reloc_entry->addend;
00092 #endif
00093     }
00094   else
00095     {
00096       /* For some reason bfd_perform_relocation always effectively
00097         ignores the addend for a COFF target when producing
00098         relocatable output.  This seems to be always wrong for 386
00099         COFF, so we handle the addend here instead.  */
00100 #if defined(COFF_WITH_PE)
00101       if (output_bfd == NULL)
00102        {
00103          reloc_howto_type *howto = reloc_entry->howto;
00104 
00105          /* Although PC relative relocations are very similar between
00106             PE and non-PE formats, but they are off by 1 << howto->size
00107             bytes. For the external relocation, PE is very different
00108             from others. See md_apply_fix3 () in gas/config/tc-amd64.c.
00109             When we link PE and non-PE object files together to
00110             generate a non-PE executable, we have to compensate it
00111             here.  */
00112          if(howto->pc_relative && howto->pcrel_offset)
00113            diff = -(1 << howto->size);
00114          else if(symbol->flags & BSF_WEAK)
00115            diff = reloc_entry->addend - symbol->value;
00116          else
00117            diff = -reloc_entry->addend;
00118        }
00119       else
00120 #endif
00121        diff = reloc_entry->addend;
00122     }
00123 
00124 #if defined(COFF_WITH_PE)
00125   /* FIXME: How should this case be handled?  */
00126   if (reloc_entry->howto->type == R_AMD64_IMAGEBASE
00127       && output_bfd != NULL
00128       && bfd_get_flavour (output_bfd) == bfd_target_coff_flavour)
00129     diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
00130 #endif
00131 
00132 #define DOIT(x) \
00133   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
00134 
00135     if (diff != 0)
00136       {
00137        reloc_howto_type *howto = reloc_entry->howto;
00138        unsigned char *addr = (unsigned char *) data + reloc_entry->address;
00139 
00140        switch (howto->size)
00141          {
00142          case 0:
00143            {
00144              char x = bfd_get_8 (abfd, addr);
00145              DOIT (x);
00146              bfd_put_8 (abfd, x, addr);
00147            }
00148            break;
00149 
00150          case 1:
00151            {
00152              short x = bfd_get_16 (abfd, addr);
00153              DOIT (x);
00154              bfd_put_16 (abfd, (bfd_vma) x, addr);
00155            }
00156            break;
00157 
00158          case 2:
00159            {
00160              long x = bfd_get_32 (abfd, addr);
00161              DOIT (x);
00162              bfd_put_32 (abfd, (bfd_vma) x, addr);
00163            }
00164            break;
00165          case 4:
00166            {
00167              long long x = bfd_get_64 (abfd, addr);
00168              DOIT (x);
00169              bfd_put_64 (abfd, (bfd_vma) x, addr);
00170            }
00171            break;
00172 
00173          default:
00174            abort ();
00175          }
00176       }
00177 
00178   /* Now let bfd_perform_relocation finish everything up.  */
00179   return bfd_reloc_continue;
00180 }
00181 
00182 #if defined(COFF_WITH_PE)
00183 /* Return TRUE if this relocation should appear in the output .reloc
00184    section.  */
00185 
00186 static bfd_boolean
00187 in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
00188 {
00189   return ! howto->pc_relative && howto->type != R_AMD64_IMAGEBASE;
00190 }
00191 #endif /* COFF_WITH_PE */
00192 
00193 #ifndef PCRELOFFSET
00194 #define PCRELOFFSET TRUE
00195 #endif
00196 
00197 static reloc_howto_type howto_table[] =
00198 {
00199   EMPTY_HOWTO (0),
00200   HOWTO (R_AMD64_DIR64,            /* type  1*/
00201         0,                  /* rightshift */
00202         4,                  /* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
00203         64,                 /* bitsize */
00204         FALSE,                     /* pc_relative */
00205         0,                  /* bitpos */
00206         complain_overflow_bitfield, /* complain_on_overflow */
00207         coff_amd64_reloc,   /* special_function */
00208         "R_X86_64_64",             /* name */
00209         TRUE,               /* partial_inplace */
00210         0xffffffffffffffffll,      /* src_mask */
00211         0xffffffffffffffffll,      /* dst_mask */
00212         TRUE),                     /* pcrel_offset */
00213   HOWTO (R_AMD64_DIR32,            /* type 2 */
00214         0,                  /* rightshift */
00215         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00216         32,                 /* bitsize */
00217         FALSE,                     /* pc_relative */
00218         0,                  /* bitpos */
00219         complain_overflow_bitfield, /* complain_on_overflow */
00220         coff_amd64_reloc,   /* special_function */
00221         "R_X86_64_32",             /* name */
00222         TRUE,               /* partial_inplace */
00223         0xffffffff,         /* src_mask */
00224         0xffffffff,         /* dst_mask */
00225         TRUE),                     /* pcrel_offset */
00226   /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3). */
00227   HOWTO (R_AMD64_IMAGEBASE, /* type */
00228         0,                  /* rightshift */
00229         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00230         32,                 /* bitsize */
00231         FALSE,                     /* pc_relative */
00232         0,                  /* bitpos */
00233         complain_overflow_bitfield, /* complain_on_overflow */
00234         coff_amd64_reloc,   /* special_function */
00235         "rva32",            /* name */
00236         TRUE,               /* partial_inplace */
00237         0xffffffff,         /* src_mask */
00238         0xffffffff,         /* dst_mask */
00239         FALSE),             /* pcrel_offset */
00240   /* 32-bit longword PC relative relocation (4).  */
00241   HOWTO (R_AMD64_PCRLONG,   /* type 4 */
00242         0,                  /* rightshift */
00243         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00244         32,                 /* bitsize */
00245         TRUE,               /* pc_relative */
00246         0,                  /* bitpos */
00247         complain_overflow_signed, /* complain_on_overflow */
00248         coff_amd64_reloc,   /* special_function */
00249         "R_X86_64_PC32",    /* name */
00250         TRUE,               /* partial_inplace */
00251         0xffffffff,         /* src_mask */
00252         0xffffffff,         /* dst_mask */
00253         PCRELOFFSET),              /* pcrel_offset */
00254 
00255  HOWTO (R_AMD64_PCRLONG_1,  /* type 5 */
00256         0,                  /* rightshift */
00257         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00258         32,                 /* bitsize */
00259         TRUE,               /* pc_relative */
00260         0,                  /* bitpos */
00261         complain_overflow_signed, /* complain_on_overflow */
00262         coff_amd64_reloc,   /* special_function */
00263         "DISP32+1",         /* name */
00264         TRUE,               /* partial_inplace */
00265         0xffffffff,         /* src_mask */
00266         0xffffffff,         /* dst_mask */
00267         PCRELOFFSET),              /* pcrel_offset */
00268  HOWTO (R_AMD64_PCRLONG_2,  /* type 6 */
00269         0,                  /* rightshift */
00270         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00271         32,                 /* bitsize */
00272         TRUE,               /* pc_relative */
00273         0,                  /* bitpos */
00274         complain_overflow_signed, /* complain_on_overflow */
00275         coff_amd64_reloc,   /* special_function */
00276         "DISP32+2",         /* name */
00277         TRUE,               /* partial_inplace */
00278         0xffffffff,         /* src_mask */
00279         0xffffffff,         /* dst_mask */
00280         PCRELOFFSET),              /* pcrel_offset */
00281  HOWTO (R_AMD64_PCRLONG_3,  /* type 7 */
00282         0,                  /* rightshift */
00283         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00284         32,                 /* bitsize */
00285         TRUE,               /* pc_relative */
00286         0,                  /* bitpos */
00287         complain_overflow_signed, /* complain_on_overflow */
00288         coff_amd64_reloc,   /* special_function */
00289         "DISP32+3",         /* name */
00290         TRUE,               /* partial_inplace */
00291         0xffffffff,         /* src_mask */
00292         0xffffffff,         /* dst_mask */
00293         PCRELOFFSET),              /* pcrel_offset */
00294  HOWTO (R_AMD64_PCRLONG_4,  /* type 8 */
00295         0,                  /* rightshift */
00296         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00297         32,                 /* bitsize */
00298         TRUE,               /* pc_relative */
00299         0,                  /* bitpos */
00300         complain_overflow_signed, /* complain_on_overflow */
00301         coff_amd64_reloc,   /* special_function */
00302         "DISP32+4",         /* name */
00303         TRUE,               /* partial_inplace */
00304         0xffffffff,         /* src_mask */
00305         0xffffffff,         /* dst_mask */
00306         PCRELOFFSET),              /* pcrel_offset */
00307  HOWTO (R_AMD64_PCRLONG_5,  /* type 9 */
00308         0,                  /* rightshift */
00309         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00310         32,                 /* bitsize */
00311         TRUE,               /* pc_relative */
00312         0,                  /* bitpos */
00313         complain_overflow_signed, /* complain_on_overflow */
00314         coff_amd64_reloc,   /* special_function */
00315         "DISP32+5",         /* name */
00316         TRUE,               /* partial_inplace */
00317         0xffffffff,         /* src_mask */
00318         0xffffffff,         /* dst_mask */
00319         PCRELOFFSET),              /* pcrel_offset */
00320   EMPTY_HOWTO (10), /* R_AMD64_SECTION 10  */
00321 #if defined(COFF_WITH_PE)
00322   /* 32-bit longword section relative relocation (11).  */
00323   HOWTO (R_AMD64_SECREL,    /* type */
00324         0,                  /* rightshift */
00325         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00326         32,                 /* bitsize */
00327         FALSE,                     /* pc_relative */
00328         0,                  /* bitpos */
00329         complain_overflow_bitfield, /* complain_on_overflow */
00330         coff_amd64_reloc,   /* special_function */
00331         "secrel32",         /* name */
00332         TRUE,               /* partial_inplace */
00333         0xffffffff,         /* src_mask */
00334         0xffffffff,         /* dst_mask */
00335         TRUE),                     /* pcrel_offset */
00336 #else
00337   EMPTY_HOWTO (11),
00338 #endif
00339   EMPTY_HOWTO (12),
00340   EMPTY_HOWTO (13),
00341 #ifndef DONT_EXTEND_AMD64
00342   HOWTO (R_AMD64_PCRQUAD,
00343          0,                     /* rightshift */
00344          4,                     /* size (0 = byte, 1 = short, 2 = long) */
00345          64,                    /* bitsize */
00346          TRUE,                  /* pc_relative */
00347          0,                     /* bitpos */
00348          complain_overflow_signed, /* complain_on_overflow */
00349          coff_amd64_reloc,      /* special_function */
00350          "R_X86_64_PC64",       /* name */
00351          TRUE,                  /* partial_inplace */
00352          0xffffffffffffffffll,  /* src_mask */
00353          0xffffffffffffffffll,  /* dst_mask */
00354          PCRELOFFSET),           /* pcrel_offset */
00355 #else
00356   EMPTY_HOWTO (14),
00357 #endif
00358   /* Byte relocation (15).  */
00359   HOWTO (R_RELBYTE,         /* type */
00360         0,                  /* rightshift */
00361         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00362         8,                  /* bitsize */
00363         FALSE,                     /* pc_relative */
00364         0,                  /* bitpos */
00365         complain_overflow_bitfield, /* complain_on_overflow */
00366         coff_amd64_reloc,   /* special_function */
00367         "R_X86_64_8",              /* name */
00368         TRUE,               /* partial_inplace */
00369         0x000000ff,         /* src_mask */
00370         0x000000ff,         /* dst_mask */
00371         PCRELOFFSET),              /* pcrel_offset */
00372   /* 16-bit word relocation (16).  */
00373   HOWTO (R_RELWORD,         /* type */
00374         0,                  /* rightshift */
00375         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00376         16,                 /* bitsize */
00377         FALSE,                     /* pc_relative */
00378         0,                  /* bitpos */
00379         complain_overflow_bitfield, /* complain_on_overflow */
00380         coff_amd64_reloc,   /* special_function */
00381         "R_X86_64_16",             /* name */
00382         TRUE,               /* partial_inplace */
00383         0x0000ffff,         /* src_mask */
00384         0x0000ffff,         /* dst_mask */
00385         PCRELOFFSET),              /* pcrel_offset */
00386   /* 32-bit longword relocation (17).     */
00387   HOWTO (R_RELLONG,         /* type */
00388         0,                  /* rightshift */
00389         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00390         32,                 /* bitsize */
00391         FALSE,                     /* pc_relative */
00392         0,                  /* bitpos */
00393         complain_overflow_bitfield, /* complain_on_overflow */
00394         coff_amd64_reloc,   /* special_function */
00395         "R_X86_64_32S",     /* name */
00396         TRUE,               /* partial_inplace */
00397         0xffffffff,         /* src_mask */
00398         0xffffffff,         /* dst_mask */
00399         PCRELOFFSET),              /* pcrel_offset */
00400   /* Byte PC relative relocation (18).     */
00401   HOWTO (R_PCRBYTE,         /* type */
00402         0,                  /* rightshift */
00403         0,                  /* size (0 = byte, 1 = short, 2 = long) */
00404         8,                  /* bitsize */
00405         TRUE,               /* pc_relative */
00406         0,                  /* bitpos */
00407         complain_overflow_signed, /* complain_on_overflow */
00408         coff_amd64_reloc,   /* special_function */
00409         "R_X86_64_PC8",     /* name */
00410         TRUE,               /* partial_inplace */
00411         0x000000ff,         /* src_mask */
00412         0x000000ff,         /* dst_mask */
00413         PCRELOFFSET),              /* pcrel_offset */
00414   /* 16-bit word PC relative relocation (19).    */
00415   HOWTO (R_PCRWORD,         /* type */
00416         0,                  /* rightshift */
00417         1,                  /* size (0 = byte, 1 = short, 2 = long) */
00418         16,                 /* bitsize */
00419         TRUE,               /* pc_relative */
00420         0,                  /* bitpos */
00421         complain_overflow_signed, /* complain_on_overflow */
00422         coff_amd64_reloc,   /* special_function */
00423         "R_X86_64_PC16",    /* name */
00424         TRUE,               /* partial_inplace */
00425         0x0000ffff,         /* src_mask */
00426         0x0000ffff,         /* dst_mask */
00427         PCRELOFFSET),              /* pcrel_offset */
00428   /* 32-bit longword PC relative relocation (20).  */
00429   HOWTO (R_PCRLONG,         /* type */
00430         0,                  /* rightshift */
00431         2,                  /* size (0 = byte, 1 = short, 2 = long) */
00432         32,                 /* bitsize */
00433         TRUE,               /* pc_relative */
00434         0,                  /* bitpos */
00435         complain_overflow_signed, /* complain_on_overflow */
00436         coff_amd64_reloc,   /* special_function */
00437         "R_X86_64_PC32",    /* name */
00438         TRUE,               /* partial_inplace */
00439         0xffffffff,         /* src_mask */
00440         0xffffffff,         /* dst_mask */
00441         PCRELOFFSET)        /* pcrel_offset */
00442 };
00443 
00444 /* Turn a howto into a reloc  nunmber */
00445 
00446 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
00447 #define I386  1                    /* Customize coffcode.h */
00448 #define AMD64 1
00449 
00450 #define RTYPE2HOWTO(cache_ptr, dst)              \
00451   ((cache_ptr)->howto =                          \
00452    ((dst)->r_type < ARRAY_SIZE (howto_table))    \
00453     ? howto_table + (dst)->r_type         \
00454     : NULL)
00455 
00456 /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
00457    library.  On some other COFF targets STYP_BSS is normally
00458    STYP_NOLOAD.  */
00459 #define BSS_NOLOAD_IS_SHARED_LIBRARY
00460 
00461 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
00462    the object file contains the value of the common symbol.  By the
00463    time this is called, the linker may be using a different symbol
00464    from a different object file with a different value.  Therefore, we
00465    hack wildly to locate the original symbol from this file so that we
00466    can make the correct adjustment.  This macro sets coffsym to the
00467    symbol from the original file, and uses it to set the addend value
00468    correctly.  If this is not a common symbol, the usual addend
00469    calculation is done, except that an additional tweak is needed for
00470    PC relative relocs.
00471    FIXME: This macro refers to symbols and asect; these are from the
00472    calling function, not the macro arguments.  */
00473 
00474 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)        \
00475   {                                                     \
00476     coff_symbol_type *coffsym = NULL;                          \
00477                                                         \
00478     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                  \
00479       coffsym = (obj_symbols (abfd)                            \
00480                 + (cache_ptr->sym_ptr_ptr - symbols));         \
00481     else if (ptr)                                       \
00482       coffsym = coff_symbol_from (abfd, ptr);                  \
00483                                                         \
00484     if (coffsym != NULL                                        \
00485        && coffsym->native->u.syment.n_scnum == 0)              \
00486       cache_ptr->addend = - coffsym->native->u.syment.n_value; \
00487     else if (ptr && bfd_asymbol_bfd (ptr) == abfd              \
00488             && ptr->section != NULL)                           \
00489       cache_ptr->addend = - (ptr->section->vma + ptr->value);  \
00490     else                                                \
00491       cache_ptr->addend = 0;                                   \
00492     if (ptr && howto_table[reloc.r_type].pc_relative)          \
00493       cache_ptr->addend += asect->vma;                         \
00494   }
00495 
00496 /* We use the special COFF backend linker.  For normal AMD64 COFF, we
00497    can use the generic relocate_section routine.  For PE, we need our
00498    own routine.  */
00499 
00500 #if !defined(COFF_WITH_PE)
00501 
00502 #define coff_relocate_section _bfd_coff_generic_relocate_section
00503 
00504 #else /* COFF_WITH_PE */
00505 
00506 /* The PE relocate section routine.  The only difference between this
00507    and the regular routine is that we don't want to do anything for a
00508    relocatable link.  */
00509 
00510 static bfd_boolean
00511 coff_pe_amd64_relocate_section (bfd *output_bfd,
00512                             struct bfd_link_info *info,
00513                             bfd *input_bfd,
00514                             asection *input_section,
00515                             bfd_byte *contents,
00516                             struct internal_reloc *relocs,
00517                             struct internal_syment *syms,
00518                             asection **sections)
00519 {
00520   if (info->relocatable)
00521     return TRUE;
00522 
00523   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
00524 }
00525 
00526 #define coff_relocate_section coff_pe_amd64_relocate_section
00527 
00528 #endif /* COFF_WITH_PE */
00529 
00530 /* Convert an rtype to howto for the COFF backend linker.  */
00531 
00532 static reloc_howto_type *
00533 coff_amd64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
00534                         asection *sec,
00535                         struct internal_reloc *rel,
00536                         struct coff_link_hash_entry *h,
00537                         struct internal_syment *sym,
00538                         bfd_vma *addendp)
00539 {
00540   reloc_howto_type *howto;
00541 
00542   if (rel->r_type > ARRAY_SIZE (howto_table))
00543     {
00544       bfd_set_error (bfd_error_bad_value);
00545       return NULL;
00546     }
00547   if (rel->r_type >= R_AMD64_PCRLONG_1 && rel->r_type <= R_AMD64_PCRLONG_5)
00548     {
00549       rel->r_vaddr += (bfd_vma)(rel->r_type-R_AMD64_PCRLONG);
00550       rel->r_type = R_AMD64_PCRLONG;
00551     }
00552   howto = howto_table + rel->r_type;
00553 
00554 #if defined(COFF_WITH_PE)
00555   /* Cancel out code in _bfd_coff_generic_relocate_section.  */
00556   *addendp = 0;
00557 #endif
00558 
00559   if (howto->pc_relative)
00560     *addendp += sec->vma;
00561 
00562   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
00563     {
00564       /* This is a common symbol.  The section contents include the
00565         size (sym->n_value) as an addend.  The relocate_section
00566         function will be adding in the final value of the symbol.  We
00567         need to subtract out the current size in order to get the
00568         correct result.  */
00569       BFD_ASSERT (h != NULL);
00570 
00571 #if !defined(COFF_WITH_PE)
00572       /* I think we *do* want to bypass this.  If we don't, I have
00573         seen some data parameters get the wrong relocation address.
00574         If I link two versions with and without this section bypassed
00575         and then do a binary comparison, the addresses which are
00576         different can be looked up in the map.  The case in which
00577         this section has been bypassed has addresses which correspond
00578         to values I can find in the map.  */
00579       *addendp -= sym->n_value;
00580 #endif
00581     }
00582 
00583 #if !defined(COFF_WITH_PE)
00584   /* If the output symbol is common (in which case this must be a
00585      relocatable link), we need to add in the final size of the
00586      common symbol.  */
00587   if (h != NULL && h->root.type == bfd_link_hash_common)
00588     *addendp += h->root.u.c.size;
00589 #endif
00590 
00591 #if defined(COFF_WITH_PE)
00592   if (howto->pc_relative)
00593     {
00594       *addendp -= 4;
00595 
00596       /* If the symbol is defined, then the generic code is going to
00597          add back the symbol value in order to cancel out an
00598          adjustment it made to the addend.  However, we set the addend
00599          to 0 at the start of this function.  We need to adjust here,
00600          to avoid the adjustment the generic code will make.  FIXME:
00601          This is getting a bit hackish.  */
00602       if (sym != NULL && sym->n_scnum != 0)
00603        *addendp -= sym->n_value;
00604     }
00605 
00606   if (rel->r_type == R_AMD64_IMAGEBASE
00607       && (bfd_get_flavour (sec->output_section->owner) == bfd_target_coff_flavour))
00608     *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
00609 
00610   if (rel->r_type == R_AMD64_SECREL)
00611     {
00612       bfd_vma osect_vma;
00613 
00614       if (h && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak))
00615        osect_vma = h->root.u.def.section->output_section->vma;
00616       else
00617        {
00618          asection *sec;
00619          int i;
00620 
00621          /* Sigh, the only way to get the section to offset against
00622             is to find it the hard way.  */
00623          for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
00624            sec = sec->next;
00625 
00626          osect_vma = sec->output_section->vma;
00627        }
00628 
00629       *addendp -= osect_vma;
00630     }
00631 #endif
00632 
00633   return howto;
00634 }
00635 
00636 #define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
00637 #define coff_bfd_reloc_name_lookup coff_amd64_reloc_name_lookup
00638 
00639 static reloc_howto_type *
00640 coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
00641 {
00642   switch (code)
00643     {
00644     case BFD_RELOC_RVA:
00645       return howto_table + R_AMD64_IMAGEBASE;
00646     case BFD_RELOC_32:
00647       return howto_table + R_AMD64_DIR32;
00648     case BFD_RELOC_64:
00649       return howto_table + R_AMD64_DIR64;
00650     case BFD_RELOC_64_PCREL:
00651 #ifndef DONT_EXTEND_AMD64
00652       return howto_table + R_AMD64_PCRQUAD;
00653 #else
00654       /* Fall through.  */
00655 #endif
00656     case BFD_RELOC_32_PCREL:
00657       return howto_table + R_AMD64_PCRLONG;
00658     case BFD_RELOC_X86_64_32S:
00659       return howto_table + R_RELLONG;
00660     case BFD_RELOC_16:
00661       return howto_table + R_RELWORD;
00662     case BFD_RELOC_16_PCREL:
00663       return howto_table + R_PCRWORD;
00664     case BFD_RELOC_8:
00665       return howto_table + R_RELBYTE;
00666     case BFD_RELOC_8_PCREL:
00667       return howto_table + R_PCRBYTE;
00668 #if defined(COFF_WITH_PE)
00669     case BFD_RELOC_32_SECREL:
00670       return howto_table + R_AMD64_SECREL;
00671 #endif
00672     default:
00673       BFD_FAIL ();
00674       return 0;
00675     }
00676 }
00677 
00678 static reloc_howto_type *
00679 coff_amd64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00680                            const char *r_name)
00681 {
00682   unsigned int i;
00683 
00684   for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
00685     if (howto_table[i].name != NULL
00686        && strcasecmp (howto_table[i].name, r_name) == 0)
00687       return &howto_table[i];
00688 
00689   return NULL;
00690 }
00691 
00692 #define coff_rtype_to_howto coff_amd64_rtype_to_howto
00693 
00694 #ifdef TARGET_UNDERSCORE
00695 
00696 /* If amd64 gcc uses underscores for symbol names, then it does not use
00697    a leading dot for local labels, so if TARGET_UNDERSCORE is defined
00698    we treat all symbols starting with L as local.  */
00699 
00700 static bfd_boolean
00701 coff_amd64_is_local_label_name (bfd *abfd, const char *name)
00702 {
00703   if (name[0] == 'L')
00704     return TRUE;
00705 
00706   return _bfd_coff_is_local_label_name (abfd, name);
00707 }
00708 
00709 #define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
00710 
00711 #endif /* TARGET_UNDERSCORE */
00712 
00713 #include "coffcode.h"
00714 
00715 #ifdef PE
00716 #define amd64coff_object_p pe_bfd_object_p
00717 #else
00718 #define amd64coff_object_p coff_object_p
00719 #endif
00720 
00721 const bfd_target
00722 #ifdef TARGET_SYM
00723   TARGET_SYM =
00724 #else
00725   x86_64coff_vec =
00726 #endif
00727 {
00728 #ifdef TARGET_NAME
00729   TARGET_NAME,
00730 #else
00731  "coff-x86-64",                    /* Name.  */
00732 #endif
00733   bfd_target_coff_flavour,
00734   BFD_ENDIAN_LITTLE,        /* Data byte order is little.  */
00735   BFD_ENDIAN_LITTLE,        /* Header byte order is little.  */
00736 
00737   (HAS_RELOC | EXEC_P |            /* Object flags.  */
00738    HAS_LINENO | HAS_DEBUG |
00739    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00740 
00741   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
00742 #if defined(COFF_WITH_PE)
00743    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
00744 #endif
00745    | SEC_CODE | SEC_DATA),
00746 
00747 #ifdef TARGET_UNDERSCORE
00748   TARGET_UNDERSCORE,        /* Leading underscore.  */
00749 #else
00750   0,                        /* Leading underscore.  */
00751 #endif
00752   '/',                      /* Ar_pad_char.  */
00753   15,                       /* Ar_max_namelen.  */
00754 
00755   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00756      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00757      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
00758   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00759      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00760      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
00761 
00762   /* Note that we allow an object file to be treated as a core file as well.  */
00763   { _bfd_dummy_target, amd64coff_object_p, /* BFD_check_format.  */
00764     bfd_generic_archive_p, amd64coff_object_p },
00765   { bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format.  */
00766     bfd_false },
00767   { bfd_false, coff_write_object_contents, /* bfd_write_contents.  */
00768    _bfd_write_archive_contents, bfd_false },
00769 
00770   BFD_JUMP_TABLE_GENERIC (coff),
00771   BFD_JUMP_TABLE_COPY (coff),
00772   BFD_JUMP_TABLE_CORE (_bfd_nocore),
00773   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
00774   BFD_JUMP_TABLE_SYMBOLS (coff),
00775   BFD_JUMP_TABLE_RELOCS (coff),
00776   BFD_JUMP_TABLE_WRITE (coff),
00777   BFD_JUMP_TABLE_LINK (coff),
00778   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00779 
00780   NULL,
00781 
00782   COFF_SWAP_TABLE
00783 };