1/* BFD back-end for AMD 64 COFF files.
2   Copyright 2006, 2007 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
59static bfd_reloc_status_type
60coff_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
187static bfd_boolean
188in_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
198static 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
511static bfd_boolean
512coff_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
533static reloc_howto_type *
534coff_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
640static reloc_howto_type *
641coff_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
679static reloc_howto_type *
680coff_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
701static bfd_boolean
702coff_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#include "coffcode.h"
715
716#ifdef PE
717#define amd64coff_object_p pe_bfd_object_p
718#else
719#define amd64coff_object_p coff_object_p
720#endif
721
722const bfd_target
723#ifdef TARGET_SYM
724  TARGET_SYM =
725#else
726  x86_64coff_vec =
727#endif
728{
729#ifdef TARGET_NAME
730  TARGET_NAME,
731#else
732 "coff-x86-64",			/* Name.  */
733#endif
734  bfd_target_coff_flavour,
735  BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
736  BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
737
738  (HAS_RELOC | EXEC_P |		/* Object flags.  */
739   HAS_LINENO | HAS_DEBUG |
740   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
741
742  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
743#if defined(COFF_WITH_PE)
744   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
745#endif
746   | SEC_CODE | SEC_DATA),
747
748#ifdef TARGET_UNDERSCORE
749  TARGET_UNDERSCORE,		/* Leading underscore.  */
750#else
751  0,				/* Leading underscore.  */
752#endif
753  '/',				/* Ar_pad_char.  */
754  15,				/* Ar_max_namelen.  */
755
756  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
757     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
758     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
759  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
760     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
761     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
762
763  /* Note that we allow an object file to be treated as a core file as well.  */
764  { _bfd_dummy_target, amd64coff_object_p, /* BFD_check_format.  */
765    bfd_generic_archive_p, amd64coff_object_p },
766  { bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format.  */
767    bfd_false },
768  { bfd_false, coff_write_object_contents, /* bfd_write_contents.  */
769   _bfd_write_archive_contents, bfd_false },
770
771  BFD_JUMP_TABLE_GENERIC (coff),
772  BFD_JUMP_TABLE_COPY (coff),
773  BFD_JUMP_TABLE_CORE (_bfd_nocore),
774  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
775  BFD_JUMP_TABLE_SYMBOLS (coff),
776  BFD_JUMP_TABLE_RELOCS (coff),
777  BFD_JUMP_TABLE_WRITE (coff),
778  BFD_JUMP_TABLE_LINK (coff),
779  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
780
781  NULL,
782
783  COFF_SWAP_TABLE
784};
785