coff-x86_64.c revision 1.1.1.4
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
64static bfd_reloc_status_type
65coff_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
203static bfd_boolean
204in_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
215static 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
531static bfd_boolean
532coff_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 (bfd_link_relocatable (info))
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
553static reloc_howto_type *
554coff_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
661static reloc_howto_type *
662coff_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
700static reloc_howto_type *
701coff_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
722static bfd_boolean
723coff_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
747const 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