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