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