Add -Wshadow to the gcc command line options used when compiling the binutils.
[external/binutils.git] / bfd / coff-x86_64.c
1 /* BFD back-end for AMD 64 COFF files.
2    Copyright 2006, 2007, 2008, 2009  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 }
197 #endif /* COFF_WITH_PE */
198
199 #ifndef PCRELOFFSET
200 #define PCRELOFFSET TRUE
201 #endif
202
203 static reloc_howto_type howto_table[] =
204 {
205   EMPTY_HOWTO (0),
206   HOWTO (R_AMD64_DIR64,         /* type  1*/
207          0,                     /* rightshift */
208          4,                     /* size (0 = byte, 1 = short, 2 = long, 4 = long long) */
209          64,                    /* bitsize */
210          FALSE,                 /* pc_relative */
211          0,                     /* bitpos */
212          complain_overflow_bitfield, /* complain_on_overflow */
213          coff_amd64_reloc,      /* special_function */
214          "R_X86_64_64",         /* name */
215          TRUE,                  /* partial_inplace */
216          0xffffffffffffffffll,  /* src_mask */
217          0xffffffffffffffffll,  /* dst_mask */
218          TRUE),                 /* pcrel_offset */
219   HOWTO (R_AMD64_DIR32,         /* type 2 */
220          0,                     /* rightshift */
221          2,                     /* size (0 = byte, 1 = short, 2 = long) */
222          32,                    /* bitsize */
223          FALSE,                 /* pc_relative */
224          0,                     /* bitpos */
225          complain_overflow_bitfield, /* complain_on_overflow */
226          coff_amd64_reloc,      /* special_function */
227          "R_X86_64_32",         /* name */
228          TRUE,                  /* partial_inplace */
229          0xffffffff,            /* src_mask */
230          0xffffffff,            /* dst_mask */
231          TRUE),                 /* pcrel_offset */
232   /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).        */
233   HOWTO (R_AMD64_IMAGEBASE,     /* type */
234          0,                     /* rightshift */
235          2,                     /* size (0 = byte, 1 = short, 2 = long) */
236          32,                    /* bitsize */
237          FALSE,                 /* pc_relative */
238          0,                     /* bitpos */
239          complain_overflow_bitfield, /* complain_on_overflow */
240          coff_amd64_reloc,      /* special_function */
241          "rva32",               /* name */
242          TRUE,                  /* partial_inplace */
243          0xffffffff,            /* src_mask */
244          0xffffffff,            /* dst_mask */
245          FALSE),                /* pcrel_offset */
246   /* 32-bit longword PC relative relocation (4).  */
247   HOWTO (R_AMD64_PCRLONG,       /* type 4 */
248          0,                     /* rightshift */
249          2,                     /* size (0 = byte, 1 = short, 2 = long) */
250          32,                    /* bitsize */
251          TRUE,                  /* pc_relative */
252          0,                     /* bitpos */
253          complain_overflow_signed, /* complain_on_overflow */
254          coff_amd64_reloc,      /* special_function */
255          "R_X86_64_PC32",       /* name */
256          TRUE,                  /* partial_inplace */
257          0xffffffff,            /* src_mask */
258          0xffffffff,            /* dst_mask */
259          PCRELOFFSET),          /* pcrel_offset */
260
261  HOWTO (R_AMD64_PCRLONG_1,      /* type 5 */
262          0,                     /* rightshift */
263          2,                     /* size (0 = byte, 1 = short, 2 = long) */
264          32,                    /* bitsize */
265          TRUE,                  /* pc_relative */
266          0,                     /* bitpos */
267          complain_overflow_signed, /* complain_on_overflow */
268          coff_amd64_reloc,      /* special_function */
269          "DISP32+1",            /* name */
270          TRUE,                  /* partial_inplace */
271          0xffffffff,            /* src_mask */
272          0xffffffff,            /* dst_mask */
273          PCRELOFFSET),          /* pcrel_offset */
274  HOWTO (R_AMD64_PCRLONG_2,      /* type 6 */
275          0,                     /* rightshift */
276          2,                     /* size (0 = byte, 1 = short, 2 = long) */
277          32,                    /* bitsize */
278          TRUE,                  /* pc_relative */
279          0,                     /* bitpos */
280          complain_overflow_signed, /* complain_on_overflow */
281          coff_amd64_reloc,      /* special_function */
282          "DISP32+2",            /* name */
283          TRUE,                  /* partial_inplace */
284          0xffffffff,            /* src_mask */
285          0xffffffff,            /* dst_mask */
286          PCRELOFFSET),          /* pcrel_offset */
287  HOWTO (R_AMD64_PCRLONG_3,      /* type 7 */
288          0,                     /* rightshift */
289          2,                     /* size (0 = byte, 1 = short, 2 = long) */
290          32,                    /* bitsize */
291          TRUE,                  /* pc_relative */
292          0,                     /* bitpos */
293          complain_overflow_signed, /* complain_on_overflow */
294          coff_amd64_reloc,      /* special_function */
295          "DISP32+3",            /* name */
296          TRUE,                  /* partial_inplace */
297          0xffffffff,            /* src_mask */
298          0xffffffff,            /* dst_mask */
299          PCRELOFFSET),          /* pcrel_offset */
300  HOWTO (R_AMD64_PCRLONG_4,      /* type 8 */
301          0,                     /* rightshift */
302          2,                     /* size (0 = byte, 1 = short, 2 = long) */
303          32,                    /* bitsize */
304          TRUE,                  /* pc_relative */
305          0,                     /* bitpos */
306          complain_overflow_signed, /* complain_on_overflow */
307          coff_amd64_reloc,      /* special_function */
308          "DISP32+4",            /* name */
309          TRUE,                  /* partial_inplace */
310          0xffffffff,            /* src_mask */
311          0xffffffff,            /* dst_mask */
312          PCRELOFFSET),          /* pcrel_offset */
313  HOWTO (R_AMD64_PCRLONG_5,      /* type 9 */
314          0,                     /* rightshift */
315          2,                     /* size (0 = byte, 1 = short, 2 = long) */
316          32,                    /* bitsize */
317          TRUE,                  /* pc_relative */
318          0,                     /* bitpos */
319          complain_overflow_signed, /* complain_on_overflow */
320          coff_amd64_reloc,      /* special_function */
321          "DISP32+5",            /* name */
322          TRUE,                  /* partial_inplace */
323          0xffffffff,            /* src_mask */
324          0xffffffff,            /* dst_mask */
325          PCRELOFFSET),          /* pcrel_offset */
326   EMPTY_HOWTO (10), /* R_AMD64_SECTION 10  */
327 #if defined(COFF_WITH_PE)
328   /* 32-bit longword section relative relocation (11).  */
329   HOWTO (R_AMD64_SECREL,        /* type */
330          0,                     /* rightshift */
331          2,                     /* size (0 = byte, 1 = short, 2 = long) */
332          32,                    /* bitsize */
333          FALSE,                 /* pc_relative */
334          0,                     /* bitpos */
335          complain_overflow_bitfield, /* complain_on_overflow */
336          coff_amd64_reloc,      /* special_function */
337          "secrel32",            /* name */
338          TRUE,                  /* partial_inplace */
339          0xffffffff,            /* src_mask */
340          0xffffffff,            /* dst_mask */
341          TRUE),                 /* pcrel_offset */
342 #else
343   EMPTY_HOWTO (11),
344 #endif
345   EMPTY_HOWTO (12),
346   EMPTY_HOWTO (13),
347 #ifndef DONT_EXTEND_AMD64
348   HOWTO (R_AMD64_PCRQUAD,
349          0,                     /* rightshift */
350          4,                     /* size (0 = byte, 1 = short, 2 = long) */
351          64,                    /* bitsize */
352          TRUE,                  /* pc_relative */
353          0,                     /* bitpos */
354          complain_overflow_signed, /* complain_on_overflow */
355          coff_amd64_reloc,      /* special_function */
356          "R_X86_64_PC64",       /* name */
357          TRUE,                  /* partial_inplace */
358          0xffffffffffffffffll,  /* src_mask */
359          0xffffffffffffffffll,  /* dst_mask */
360          PCRELOFFSET),           /* pcrel_offset */
361 #else
362   EMPTY_HOWTO (14),
363 #endif
364   /* Byte relocation (15).  */
365   HOWTO (R_RELBYTE,             /* type */
366          0,                     /* rightshift */
367          0,                     /* size (0 = byte, 1 = short, 2 = long) */
368          8,                     /* bitsize */
369          FALSE,                 /* pc_relative */
370          0,                     /* bitpos */
371          complain_overflow_bitfield, /* complain_on_overflow */
372          coff_amd64_reloc,      /* special_function */
373          "R_X86_64_8",          /* name */
374          TRUE,                  /* partial_inplace */
375          0x000000ff,            /* src_mask */
376          0x000000ff,            /* dst_mask */
377          PCRELOFFSET),          /* pcrel_offset */
378   /* 16-bit word relocation (16).  */
379   HOWTO (R_RELWORD,             /* type */
380          0,                     /* rightshift */
381          1,                     /* size (0 = byte, 1 = short, 2 = long) */
382          16,                    /* bitsize */
383          FALSE,                 /* pc_relative */
384          0,                     /* bitpos */
385          complain_overflow_bitfield, /* complain_on_overflow */
386          coff_amd64_reloc,      /* special_function */
387          "R_X86_64_16",         /* name */
388          TRUE,                  /* partial_inplace */
389          0x0000ffff,            /* src_mask */
390          0x0000ffff,            /* dst_mask */
391          PCRELOFFSET),          /* pcrel_offset */
392   /* 32-bit longword relocation (17).   */
393   HOWTO (R_RELLONG,             /* type */
394          0,                     /* rightshift */
395          2,                     /* size (0 = byte, 1 = short, 2 = long) */
396          32,                    /* bitsize */
397          FALSE,                 /* pc_relative */
398          0,                     /* bitpos */
399          complain_overflow_bitfield, /* complain_on_overflow */
400          coff_amd64_reloc,      /* special_function */
401          "R_X86_64_32S",        /* name */
402          TRUE,                  /* partial_inplace */
403          0xffffffff,            /* src_mask */
404          0xffffffff,            /* dst_mask */
405          PCRELOFFSET),          /* pcrel_offset */
406   /* Byte PC relative relocation (18).   */
407   HOWTO (R_PCRBYTE,             /* type */
408          0,                     /* rightshift */
409          0,                     /* size (0 = byte, 1 = short, 2 = long) */
410          8,                     /* bitsize */
411          TRUE,                  /* pc_relative */
412          0,                     /* bitpos */
413          complain_overflow_signed, /* complain_on_overflow */
414          coff_amd64_reloc,      /* special_function */
415          "R_X86_64_PC8",        /* name */
416          TRUE,                  /* partial_inplace */
417          0x000000ff,            /* src_mask */
418          0x000000ff,            /* dst_mask */
419          PCRELOFFSET),          /* pcrel_offset */
420   /* 16-bit word PC relative relocation (19).   */
421   HOWTO (R_PCRWORD,             /* type */
422          0,                     /* rightshift */
423          1,                     /* size (0 = byte, 1 = short, 2 = long) */
424          16,                    /* bitsize */
425          TRUE,                  /* pc_relative */
426          0,                     /* bitpos */
427          complain_overflow_signed, /* complain_on_overflow */
428          coff_amd64_reloc,      /* special_function */
429          "R_X86_64_PC16",       /* name */
430          TRUE,                  /* partial_inplace */
431          0x0000ffff,            /* src_mask */
432          0x0000ffff,            /* dst_mask */
433          PCRELOFFSET),          /* pcrel_offset */
434   /* 32-bit longword PC relative relocation (20).  */
435   HOWTO (R_PCRLONG,             /* type */
436          0,                     /* rightshift */
437          2,                     /* size (0 = byte, 1 = short, 2 = long) */
438          32,                    /* bitsize */
439          TRUE,                  /* pc_relative */
440          0,                     /* bitpos */
441          complain_overflow_signed, /* complain_on_overflow */
442          coff_amd64_reloc,      /* special_function */
443          "R_X86_64_PC32",       /* name */
444          TRUE,                  /* partial_inplace */
445          0xffffffff,            /* src_mask */
446          0xffffffff,            /* dst_mask */
447          PCRELOFFSET)           /* pcrel_offset */
448 };
449
450 /* Turn a howto into a reloc  nunmber */
451
452 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
453 #define I386  1                 /* Customize coffcode.h */
454 #define AMD64 1
455
456 #define RTYPE2HOWTO(cache_ptr, dst)             \
457   ((cache_ptr)->howto =                         \
458    ((dst)->r_type < ARRAY_SIZE (howto_table))   \
459     ? howto_table + (dst)->r_type               \
460     : NULL)
461
462 /* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
463    library.  On some other COFF targets STYP_BSS is normally
464    STYP_NOLOAD.  */
465 #define BSS_NOLOAD_IS_SHARED_LIBRARY
466
467 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
468    the object file contains the value of the common symbol.  By the
469    time this is called, the linker may be using a different symbol
470    from a different object file with a different value.  Therefore, we
471    hack wildly to locate the original symbol from this file so that we
472    can make the correct adjustment.  This macro sets coffsym to the
473    symbol from the original file, and uses it to set the addend value
474    correctly.  If this is not a common symbol, the usual addend
475    calculation is done, except that an additional tweak is needed for
476    PC relative relocs.
477    FIXME: This macro refers to symbols and asect; these are from the
478    calling function, not the macro arguments.  */
479
480 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)                \
481   {                                                             \
482     coff_symbol_type *coffsym = NULL;                           \
483                                                                 \
484     if (ptr && bfd_asymbol_bfd (ptr) != abfd)                   \
485       coffsym = (obj_symbols (abfd)                             \
486                  + (cache_ptr->sym_ptr_ptr - symbols));         \
487     else if (ptr)                                               \
488       coffsym = coff_symbol_from (abfd, ptr);                   \
489                                                                 \
490     if (coffsym != NULL                                         \
491         && coffsym->native->u.syment.n_scnum == 0)              \
492       cache_ptr->addend = - coffsym->native->u.syment.n_value;  \
493     else if (ptr && bfd_asymbol_bfd (ptr) == abfd               \
494              && ptr->section != NULL)                           \
495       cache_ptr->addend = - (ptr->section->vma + ptr->value);   \
496     else                                                        \
497       cache_ptr->addend = 0;                                    \
498     if (ptr && howto_table[reloc.r_type].pc_relative)           \
499       cache_ptr->addend += asect->vma;                          \
500   }
501
502 /* We use the special COFF backend linker.  For normal AMD64 COFF, we
503    can use the generic relocate_section routine.  For PE, we need our
504    own routine.  */
505
506 #if !defined(COFF_WITH_PE)
507
508 #define coff_relocate_section _bfd_coff_generic_relocate_section
509
510 #else /* COFF_WITH_PE */
511
512 /* The PE relocate section routine.  The only difference between this
513    and the regular routine is that we don't want to do anything for a
514    relocatable link.  */
515
516 static bfd_boolean
517 coff_pe_amd64_relocate_section (bfd *output_bfd,
518                                 struct bfd_link_info *info,
519                                 bfd *input_bfd,
520                                 asection *input_section,
521                                 bfd_byte *contents,
522                                 struct internal_reloc *relocs,
523                                 struct internal_syment *syms,
524                                 asection **sections)
525 {
526   if (info->relocatable)
527     return TRUE;
528
529   return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
530 }
531
532 #define coff_relocate_section coff_pe_amd64_relocate_section
533
534 #endif /* COFF_WITH_PE */
535
536 /* Convert an rtype to howto for the COFF backend linker.  */
537
538 static reloc_howto_type *
539 coff_amd64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
540                            asection *sec,
541                            struct internal_reloc *rel,
542                            struct coff_link_hash_entry *h,
543                            struct internal_syment *sym,
544                            bfd_vma *addendp)
545 {
546   reloc_howto_type *howto;
547
548   if (rel->r_type > ARRAY_SIZE (howto_table))
549     {
550       bfd_set_error (bfd_error_bad_value);
551       return NULL;
552     }
553   howto = howto_table + rel->r_type;
554
555 #if defined(COFF_WITH_PE)
556   /* Cancel out code in _bfd_coff_generic_relocate_section.  */
557   *addendp = 0;
558   if (rel->r_type >= R_AMD64_PCRLONG_1 && rel->r_type <= R_AMD64_PCRLONG_5)\r
559     {\r
560       *addendp -= (bfd_vma)(rel->r_type - R_AMD64_PCRLONG);\r
561       rel->r_type = R_AMD64_PCRLONG;\r
562     }
563 #endif
564
565   if (howto->pc_relative)
566     *addendp += sec->vma;
567
568   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
569     {
570       /* This is a common symbol.  The section contents include the
571          size (sym->n_value) as an addend.  The relocate_section
572          function will be adding in the final value of the symbol.  We
573          need to subtract out the current size in order to get the
574          correct result.  */
575       BFD_ASSERT (h != NULL);
576
577 #if !defined(COFF_WITH_PE)
578       /* I think we *do* want to bypass this.  If we don't, I have
579          seen some data parameters get the wrong relocation address.
580          If I link two versions with and without this section bypassed
581          and then do a binary comparison, the addresses which are
582          different can be looked up in the map.  The case in which
583          this section has been bypassed has addresses which correspond
584          to values I can find in the map.  */
585       *addendp -= sym->n_value;
586 #endif
587     }
588
589 #if !defined(COFF_WITH_PE)
590   /* If the output symbol is common (in which case this must be a
591      relocatable link), we need to add in the final size of the
592      common symbol.  */
593   if (h != NULL && h->root.type == bfd_link_hash_common)
594     *addendp += h->root.u.c.size;
595 #endif
596
597 #if defined(COFF_WITH_PE)
598   if (howto->pc_relative)
599     {
600       *addendp -= 4;
601
602       /* If the symbol is defined, then the generic code is going to
603          add back the symbol value in order to cancel out an
604          adjustment it made to the addend.  However, we set the addend
605          to 0 at the start of this function.  We need to adjust here,
606          to avoid the adjustment the generic code will make.  FIXME:
607          This is getting a bit hackish.  */
608       if (sym != NULL && sym->n_scnum != 0)
609         *addendp -= sym->n_value;
610     }
611
612   if (rel->r_type == R_AMD64_IMAGEBASE
613       && (bfd_get_flavour (sec->output_section->owner) == bfd_target_coff_flavour))
614     *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
615
616   if (rel->r_type == R_AMD64_SECREL)
617     {
618       bfd_vma osect_vma;
619
620       if (h && (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak))
621         osect_vma = h->root.u.def.section->output_section->vma;
622       else
623         {
624           asection *s;
625           int i;
626
627           /* Sigh, the only way to get the section to offset against
628              is to find it the hard way.  */
629           for (s = abfd->sections, i = 1; i < sym->n_scnum; i++)
630             s = s->next;
631
632           osect_vma = s->output_section->vma;
633         }
634
635       *addendp -= osect_vma;
636     }
637 #endif
638
639   return howto;
640 }
641
642 #define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
643 #define coff_bfd_reloc_name_lookup coff_amd64_reloc_name_lookup
644
645 static reloc_howto_type *
646 coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
647 {
648   switch (code)
649     {
650     case BFD_RELOC_RVA:
651       return howto_table + R_AMD64_IMAGEBASE;
652     case BFD_RELOC_32:
653       return howto_table + R_AMD64_DIR32;
654     case BFD_RELOC_64:
655       return howto_table + R_AMD64_DIR64;
656     case BFD_RELOC_64_PCREL:
657 #ifndef DONT_EXTEND_AMD64
658       return howto_table + R_AMD64_PCRQUAD;
659 #else
660       /* Fall through.  */
661 #endif
662     case BFD_RELOC_32_PCREL:
663       return howto_table + R_AMD64_PCRLONG;
664     case BFD_RELOC_X86_64_32S:
665       return howto_table + R_RELLONG;
666     case BFD_RELOC_16:
667       return howto_table + R_RELWORD;
668     case BFD_RELOC_16_PCREL:
669       return howto_table + R_PCRWORD;
670     case BFD_RELOC_8:
671       return howto_table + R_RELBYTE;
672     case BFD_RELOC_8_PCREL:
673       return howto_table + R_PCRBYTE;
674 #if defined(COFF_WITH_PE)
675     case BFD_RELOC_32_SECREL:
676       return howto_table + R_AMD64_SECREL;
677 #endif
678     default:
679       BFD_FAIL ();
680       return 0;
681     }
682 }
683
684 static reloc_howto_type *
685 coff_amd64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
686                               const char *r_name)
687 {
688   unsigned int i;
689
690   for (i = 0; i < sizeof (howto_table) / sizeof (howto_table[0]); i++)
691     if (howto_table[i].name != NULL
692         && strcasecmp (howto_table[i].name, r_name) == 0)
693       return &howto_table[i];
694
695   return NULL;
696 }
697
698 #define coff_rtype_to_howto coff_amd64_rtype_to_howto
699
700 #ifdef TARGET_UNDERSCORE
701
702 /* If amd64 gcc uses underscores for symbol names, then it does not use
703    a leading dot for local labels, so if TARGET_UNDERSCORE is defined
704    we treat all symbols starting with L as local.  */
705
706 static bfd_boolean
707 coff_amd64_is_local_label_name (bfd *abfd, const char *name)
708 {
709   if (name[0] == 'L')
710     return TRUE;
711
712   return _bfd_coff_is_local_label_name (abfd, name);
713 }
714
715 #define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
716
717 #endif /* TARGET_UNDERSCORE */
718
719 #ifndef bfd_pe_print_pdata
720 #define bfd_pe_print_pdata   NULL
721 #endif
722
723 #include "coffcode.h"
724
725 #ifdef PE
726 #define amd64coff_object_p pe_bfd_object_p
727 #else
728 #define amd64coff_object_p coff_object_p
729 #endif
730
731 const bfd_target
732 #ifdef TARGET_SYM
733   TARGET_SYM =
734 #else
735   x86_64coff_vec =
736 #endif
737 {
738 #ifdef TARGET_NAME
739   TARGET_NAME,
740 #else
741  "coff-x86-64",                 /* Name.  */
742 #endif
743   bfd_target_coff_flavour,
744   BFD_ENDIAN_LITTLE,            /* Data byte order is little.  */
745   BFD_ENDIAN_LITTLE,            /* Header byte order is little.  */
746
747   (HAS_RELOC | EXEC_P |         /* Object flags.  */
748    HAS_LINENO | HAS_DEBUG |
749    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
750
751   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
752 #if defined(COFF_WITH_PE)
753    | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
754 #endif
755    | SEC_CODE | SEC_DATA),
756
757 #ifdef TARGET_UNDERSCORE
758   TARGET_UNDERSCORE,            /* Leading underscore.  */
759 #else
760   0,                            /* Leading underscore.  */
761 #endif
762   '/',                          /* Ar_pad_char.  */
763   15,                           /* Ar_max_namelen.  */
764
765   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
766      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
767      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
768   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
769      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
770      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
771
772   /* Note that we allow an object file to be treated as a core file as well.  */
773   { _bfd_dummy_target, amd64coff_object_p, /* BFD_check_format.  */
774     bfd_generic_archive_p, amd64coff_object_p },
775   { bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format.  */
776     bfd_false },
777   { bfd_false, coff_write_object_contents, /* bfd_write_contents.  */
778    _bfd_write_archive_contents, bfd_false },
779
780   BFD_JUMP_TABLE_GENERIC (coff),
781   BFD_JUMP_TABLE_COPY (coff),
782   BFD_JUMP_TABLE_CORE (_bfd_nocore),
783   BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
784   BFD_JUMP_TABLE_SYMBOLS (coff),
785   BFD_JUMP_TABLE_RELOCS (coff),
786   BFD_JUMP_TABLE_WRITE (coff),
787   BFD_JUMP_TABLE_LINK (coff),
788   BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
789
790   NULL,
791
792   COFF_SWAP_TABLE
793 };