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