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