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