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