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