1/* BFD back-end for AMD 64 COFF files.
2   Copyright (C) 2006-2024 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#include "sysdep.h"
24#include "bfd.h"
25#include "libbfd.h"
26#include "coff/x86_64.h"
27#include "coff/internal.h"
28#include "libcoff.h"
29#include "libiberty.h"
30
31#define BADMAG(x) AMD64BADMAG(x)
32
33#ifdef COFF_WITH_pex64
34# undef  AOUTSZ
35# define AOUTSZ		PEPAOUTSZ
36# define PEAOUTHDR	PEPAOUTHDR
37#endif
38
39#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
40
41/* The page size is a guess based on ELF.  */
42
43#define COFF_PAGE_SIZE 0x1000
44
45/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
46#define OCTETS_PER_BYTE(ABFD, SEC) 1
47
48/* For some reason when using AMD COFF the value stored in the .text
49   section for a reference to a common symbol is the value itself plus
50   any desired offset.  Ian Taylor, Cygnus Support.  */
51
52/* If we are producing relocatable output, we need to do some
53   adjustments to the object file that are not done by the
54   bfd_perform_relocation function.  This function is called by every
55   reloc type to make any required adjustments.  */
56
57static bfd_reloc_status_type
58coff_amd64_reloc (bfd *abfd,
59		  arelent *reloc_entry,
60		  asymbol *symbol,
61		  void * data,
62		  asection *input_section ATTRIBUTE_UNUSED,
63		  bfd *output_bfd,
64		  char **error_message ATTRIBUTE_UNUSED)
65{
66  symvalue diff;
67
68#if !defined (COFF_WITH_PE)
69  if (output_bfd == NULL)
70    return bfd_reloc_continue;
71#endif
72
73  if (bfd_is_com_section (symbol->section))
74    {
75#if !defined (COFF_WITH_PE)
76      /* We are relocating a common symbol.  The current value in the
77	 object file is ORIG + OFFSET, where ORIG is the value of the
78	 common symbol as seen by the object file when it was compiled
79	 (this may be zero if the symbol was undefined) and OFFSET is
80	 the offset into the common symbol (normally zero, but may be
81	 non-zero when referring to a field in a common structure).
82	 ORIG is the negative of reloc_entry->addend, which is set by
83	 the CALC_ADDEND macro below.  We want to replace the value in
84	 the object file with NEW + OFFSET, where NEW is the value of
85	 the common symbol which we are going to put in the final
86	 object file.  NEW is symbol->value.  */
87      diff = symbol->value + reloc_entry->addend;
88#else
89      /* In PE mode, we do not offset the common symbol.  */
90      diff = reloc_entry->addend;
91#endif
92    }
93  else
94    {
95      /* For some reason bfd_perform_relocation always effectively
96	 ignores the addend for a COFF target when producing
97	 relocatable output.  This seems to be always wrong for 386
98	 COFF, so we handle the addend here instead.  */
99#if defined (COFF_WITH_PE)
100      if (output_bfd == NULL)
101	{
102	  if (symbol->flags & BSF_WEAK)
103	    diff = reloc_entry->addend - symbol->value;
104	  else
105	    diff = -reloc_entry->addend;
106	}
107      else
108#endif
109	diff = reloc_entry->addend;
110    }
111
112#if defined (COFF_WITH_PE)
113  if (output_bfd == NULL)
114    {
115      /* PC relative relocations are off by their size.  */
116      if (reloc_entry->howto->pc_relative)
117	diff -= bfd_get_reloc_size (reloc_entry->howto);
118
119      if (reloc_entry->howto->type >= R_AMD64_PCRLONG_1
120	  && reloc_entry->howto->type <= R_AMD64_PCRLONG_5)
121	diff -= reloc_entry->howto->type - R_AMD64_PCRLONG;
122    }
123
124  if (reloc_entry->howto->type == R_AMD64_IMAGEBASE
125      && output_bfd == NULL)
126    {
127      bfd *obfd = input_section->output_section->owner;
128      struct bfd_link_info *link_info;
129      struct bfd_link_hash_entry *h;
130      switch (bfd_get_flavour (obfd))
131	{
132	case bfd_target_coff_flavour:
133	  diff -= pe_data (obfd)->pe_opthdr.ImageBase;
134	  break;
135	case bfd_target_elf_flavour:
136	  /* Subtract __ImageBase.  */
137	  h = NULL;
138	  link_info = _bfd_get_link_info (obfd);
139	  if (link_info != NULL)
140	    h = bfd_link_hash_lookup (link_info->hash, "__ImageBase",
141				      false, false, true);
142	  if (h == NULL
143	      || (h->type != bfd_link_hash_defined
144		  && h->type != bfd_link_hash_defweak))
145	    {
146	      *error_message
147		= (char *) _("R_AMD64_IMAGEBASE with __ImageBase undefined");
148	      return bfd_reloc_dangerous;
149	    }
150	  /* ELF symbols in relocatable files are section relative,
151	     but in nonrelocatable files they are virtual addresses.  */
152	  diff -= (h->u.def.value
153		   + h->u.def.section->output_offset
154		   + h->u.def.section->output_section->vma);
155	  break;
156	default:
157	  break;
158	}
159    }
160#endif
161
162#define DOIT(x) \
163  x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
164
165  if (diff != 0)
166    {
167      reloc_howto_type *howto = reloc_entry->howto;
168      bfd_size_type octets = (reloc_entry->address
169			      * OCTETS_PER_BYTE (abfd, input_section));
170      unsigned char *addr = (unsigned char *) data + octets;
171
172      if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets))
173	return bfd_reloc_outofrange;
174
175      switch (bfd_get_reloc_size (howto))
176	{
177	case 1:
178	  {
179	    char x = bfd_get_8 (abfd, addr);
180	    DOIT (x);
181	    bfd_put_8 (abfd, x, addr);
182	  }
183	  break;
184
185	case 2:
186	  {
187	    short x = bfd_get_16 (abfd, addr);
188	    DOIT (x);
189	    bfd_put_16 (abfd, (bfd_vma) x, addr);
190	  }
191	  break;
192
193	case 4:
194	  {
195	    long x = bfd_get_32 (abfd, addr);
196	    DOIT (x);
197	    bfd_put_32 (abfd, (bfd_vma) x, addr);
198	  }
199	  break;
200
201	case 8:
202	  {
203	    uint64_t x = bfd_get_64 (abfd, addr);
204	    DOIT (x);
205	    bfd_put_64 (abfd, x, addr);
206	  }
207	  break;
208
209	default:
210	  bfd_set_error (bfd_error_bad_value);
211	  return bfd_reloc_notsupported;
212	}
213    }
214
215  /* Now let bfd_perform_relocation finish everything up.  */
216  return bfd_reloc_continue;
217}
218
219#if defined(COFF_WITH_PE)
220/* Return TRUE if this relocation should appear in the output .reloc
221   section.  */
222
223static bool
224in_reloc_p (bfd *abfd ATTRIBUTE_UNUSED, reloc_howto_type *howto)
225{
226  return ! howto->pc_relative
227    && howto->type != R_AMD64_IMAGEBASE
228    && howto->type != R_AMD64_SECREL
229    && howto->type != R_AMD64_SECTION;
230}
231#endif /* COFF_WITH_PE */
232
233#ifndef PCRELOFFSET
234#define PCRELOFFSET true
235#endif
236
237static reloc_howto_type howto_table[] =
238{
239  EMPTY_HOWTO (0),
240  HOWTO (R_AMD64_DIR64,		/* type  1*/
241	 0,			/* rightshift */
242	 8,			/* size */
243	 64,			/* bitsize */
244	 false,			/* pc_relative */
245	 0,			/* bitpos */
246	 complain_overflow_bitfield, /* complain_on_overflow */
247	 coff_amd64_reloc,	/* special_function */
248	 "IMAGE_REL_AMD64_ADDR64", /* name */
249	 true,			/* partial_inplace */
250	 0xffffffffffffffffll,	/* src_mask */
251	 0xffffffffffffffffll,	/* dst_mask */
252	 true),			/* pcrel_offset */
253  HOWTO (R_AMD64_DIR32,		/* type 2 */
254	 0,			/* rightshift */
255	 4,			/* size */
256	 32,			/* bitsize */
257	 false,			/* pc_relative */
258	 0,			/* bitpos */
259	 complain_overflow_bitfield, /* complain_on_overflow */
260	 coff_amd64_reloc,	/* special_function */
261	 "IMAGE_REL_AMD64_ADDR32", /* name */
262	 true,			/* partial_inplace */
263	 0xffffffff,		/* src_mask */
264	 0xffffffff,		/* dst_mask */
265	 true),			/* pcrel_offset */
266  /* PE IMAGE_REL_AMD64_ADDR32NB relocation (3).	*/
267  HOWTO (R_AMD64_IMAGEBASE,	/* type */
268	 0,			/* rightshift */
269	 4,			/* size */
270	 32,			/* bitsize */
271	 false,			/* pc_relative */
272	 0,			/* bitpos */
273	 complain_overflow_bitfield, /* complain_on_overflow */
274	 coff_amd64_reloc,	/* special_function */
275	 "IMAGE_REL_AMD64_ADDR32NB", /* name */
276	 true,			/* partial_inplace */
277	 0xffffffff,		/* src_mask */
278	 0xffffffff,		/* dst_mask */
279	 false),		/* pcrel_offset */
280  /* 32-bit longword PC relative relocation (4).  */
281  HOWTO (R_AMD64_PCRLONG,	/* type 4 */
282	 0,			/* rightshift */
283	 4,			/* size */
284	 32,			/* bitsize */
285	 true,			/* pc_relative */
286	 0,			/* bitpos */
287	 complain_overflow_signed, /* complain_on_overflow */
288	 coff_amd64_reloc,	/* special_function */
289	 "IMAGE_REL_AMD64_REL32", /* name */
290	 true,			/* partial_inplace */
291	 0xffffffff,		/* src_mask */
292	 0xffffffff,		/* dst_mask */
293	 PCRELOFFSET),		/* pcrel_offset */
294
295 HOWTO (R_AMD64_PCRLONG_1,	/* type 5 */
296	 0,			/* rightshift */
297	 4,			/* size */
298	 32,			/* bitsize */
299	 true,			/* pc_relative */
300	 0,			/* bitpos */
301	 complain_overflow_signed, /* complain_on_overflow */
302	 coff_amd64_reloc,	/* special_function */
303	 "IMAGE_REL_AMD64_REL32_1", /* name */
304	 true,			/* partial_inplace */
305	 0xffffffff,		/* src_mask */
306	 0xffffffff,		/* dst_mask */
307	 PCRELOFFSET),		/* pcrel_offset */
308 HOWTO (R_AMD64_PCRLONG_2,	/* type 6 */
309	 0,			/* rightshift */
310	 4,			/* size */
311	 32,			/* bitsize */
312	 true,			/* pc_relative */
313	 0,			/* bitpos */
314	 complain_overflow_signed, /* complain_on_overflow */
315	 coff_amd64_reloc,	/* special_function */
316	 "IMAGE_REL_AMD64_REL32_2", /* name */
317	 true,			/* partial_inplace */
318	 0xffffffff,		/* src_mask */
319	 0xffffffff,		/* dst_mask */
320	 PCRELOFFSET),		/* pcrel_offset */
321 HOWTO (R_AMD64_PCRLONG_3,	/* type 7 */
322	 0,			/* rightshift */
323	 4,			/* size */
324	 32,			/* bitsize */
325	 true,			/* pc_relative */
326	 0,			/* bitpos */
327	 complain_overflow_signed, /* complain_on_overflow */
328	 coff_amd64_reloc,	/* special_function */
329	 "IMAGE_REL_AMD64_REL32_3", /* name */
330	 true,			/* partial_inplace */
331	 0xffffffff,		/* src_mask */
332	 0xffffffff,		/* dst_mask */
333	 PCRELOFFSET),		/* pcrel_offset */
334 HOWTO (R_AMD64_PCRLONG_4,	/* type 8 */
335	 0,			/* rightshift */
336	 4,			/* size */
337	 32,			/* bitsize */
338	 true,			/* pc_relative */
339	 0,			/* bitpos */
340	 complain_overflow_signed, /* complain_on_overflow */
341	 coff_amd64_reloc,	/* special_function */
342	 "IMAGE_REL_AMD64_REL32_4", /* name */
343	 true,			/* partial_inplace */
344	 0xffffffff,		/* src_mask */
345	 0xffffffff,		/* dst_mask */
346	 PCRELOFFSET),		/* pcrel_offset */
347 HOWTO (R_AMD64_PCRLONG_5,	/* type 9 */
348	 0,			/* rightshift */
349	 4,			/* size */
350	 32,			/* bitsize */
351	 true,			/* pc_relative */
352	 0,			/* bitpos */
353	 complain_overflow_signed, /* complain_on_overflow */
354	 coff_amd64_reloc,	/* special_function */
355	 "IMAGE_REL_AMD64_REL32_5", /* name */
356	 true,			/* partial_inplace */
357	 0xffffffff,		/* src_mask */
358	 0xffffffff,		/* dst_mask */
359	 PCRELOFFSET),		/* pcrel_offset */
360#if defined(COFF_WITH_PE)
361  /* 16-bit word section relocation (10).  */
362  HOWTO (R_AMD64_SECTION,	/* type */
363	 0,			/* rightshift */
364	 2,			/* size */
365	 16,			/* bitsize */
366	 false,			/* pc_relative */
367	 0,			/* bitpos */
368	 complain_overflow_bitfield, /* complain_on_overflow */
369	 coff_amd64_reloc,	/* special_function */
370	 "IMAGE_REL_AMD64_SECTION", /* name */
371	 true,			/* partial_inplace */
372	 0x0000ffff,		/* src_mask */
373	 0x0000ffff,		/* dst_mask */
374	 true),
375  /* 32-bit longword section relative relocation (11).  */
376  HOWTO (R_AMD64_SECREL,	/* type */
377	 0,			/* rightshift */
378	 4,			/* size */
379	 32,			/* bitsize */
380	 false,			/* pc_relative */
381	 0,			/* bitpos */
382	 complain_overflow_bitfield, /* complain_on_overflow */
383	 coff_amd64_reloc,	/* special_function */
384	 "IMAGE_REL_AMD64_SECREL", /* name */
385	 true,			/* partial_inplace */
386	 0xffffffff,		/* src_mask */
387	 0xffffffff,		/* dst_mask */
388	 true),			/* pcrel_offset */
389#else
390  EMPTY_HOWTO (10),
391  EMPTY_HOWTO (11),
392#endif
393  EMPTY_HOWTO (12),
394  EMPTY_HOWTO (13),
395#ifndef DONT_EXTEND_AMD64
396  HOWTO (R_AMD64_PCRQUAD,
397	 0,			/* rightshift */
398	 8,			/* size */
399	 64,			/* bitsize */
400	 true,			/* pc_relative */
401	 0,			/* bitpos */
402	 complain_overflow_signed, /* complain_on_overflow */
403	 coff_amd64_reloc,	/* special_function */
404	 "R_X86_64_PC64",	/* name */
405	 true,			/* partial_inplace */
406	 0xffffffffffffffffll,	/* src_mask */
407	 0xffffffffffffffffll,	/* dst_mask */
408	 PCRELOFFSET),		 /* pcrel_offset */
409#else
410  EMPTY_HOWTO (14),
411#endif
412  /* Byte relocation (15).  */
413  HOWTO (R_RELBYTE,		/* type */
414	 0,			/* rightshift */
415	 1,			/* size */
416	 8,			/* bitsize */
417	 false,			/* pc_relative */
418	 0,			/* bitpos */
419	 complain_overflow_bitfield, /* complain_on_overflow */
420	 coff_amd64_reloc,	/* special_function */
421	 "R_X86_64_8",		/* name */
422	 true,			/* partial_inplace */
423	 0x000000ff,		/* src_mask */
424	 0x000000ff,		/* dst_mask */
425	 PCRELOFFSET),		/* pcrel_offset */
426  /* 16-bit word relocation (16).  */
427  HOWTO (R_RELWORD,		/* type */
428	 0,			/* rightshift */
429	 2,			/* size */
430	 16,			/* bitsize */
431	 false,			/* pc_relative */
432	 0,			/* bitpos */
433	 complain_overflow_bitfield, /* complain_on_overflow */
434	 coff_amd64_reloc,	/* special_function */
435	 "R_X86_64_16",		/* name */
436	 true,			/* partial_inplace */
437	 0x0000ffff,		/* src_mask */
438	 0x0000ffff,		/* dst_mask */
439	 PCRELOFFSET),		/* pcrel_offset */
440  /* 32-bit longword relocation (17).	*/
441  HOWTO (R_RELLONG,		/* type */
442	 0,			/* rightshift */
443	 4,			/* size */
444	 32,			/* bitsize */
445	 false,			/* pc_relative */
446	 0,			/* bitpos */
447	 complain_overflow_bitfield, /* complain_on_overflow */
448	 coff_amd64_reloc,	/* special_function */
449	 "R_X86_64_32S",	/* name */
450	 true,			/* partial_inplace */
451	 0xffffffff,		/* src_mask */
452	 0xffffffff,		/* dst_mask */
453	 PCRELOFFSET),		/* pcrel_offset */
454  /* Byte PC relative relocation (18).	 */
455  HOWTO (R_PCRBYTE,		/* type */
456	 0,			/* rightshift */
457	 1,			/* size */
458	 8,			/* bitsize */
459	 true,			/* pc_relative */
460	 0,			/* bitpos */
461	 complain_overflow_signed, /* complain_on_overflow */
462	 coff_amd64_reloc,	/* special_function */
463	 "R_X86_64_PC8",	/* name */
464	 true,			/* partial_inplace */
465	 0x000000ff,		/* src_mask */
466	 0x000000ff,		/* dst_mask */
467	 PCRELOFFSET),		/* pcrel_offset */
468  /* 16-bit word PC relative relocation (19).	*/
469  HOWTO (R_PCRWORD,		/* type */
470	 0,			/* rightshift */
471	 2,			/* size */
472	 16,			/* bitsize */
473	 true,			/* pc_relative */
474	 0,			/* bitpos */
475	 complain_overflow_signed, /* complain_on_overflow */
476	 coff_amd64_reloc,	/* special_function */
477	 "R_X86_64_PC16",	/* name */
478	 true,			/* partial_inplace */
479	 0x0000ffff,		/* src_mask */
480	 0x0000ffff,		/* dst_mask */
481	 PCRELOFFSET),		/* pcrel_offset */
482  /* 32-bit longword PC relative relocation (20).  */
483  HOWTO (R_PCRLONG,		/* type */
484	 0,			/* rightshift */
485	 4,			/* size */
486	 32,			/* bitsize */
487	 true,			/* pc_relative */
488	 0,			/* bitpos */
489	 complain_overflow_signed, /* complain_on_overflow */
490	 coff_amd64_reloc,	/* special_function */
491	 "R_X86_64_PC32",	/* name */
492	 true,			/* partial_inplace */
493	 0xffffffff,		/* src_mask */
494	 0xffffffff,		/* dst_mask */
495	 PCRELOFFSET)		/* pcrel_offset */
496};
497
498#define NUM_HOWTOS ARRAY_SIZE (howto_table)
499
500/* Turn a howto into a reloc  nunmber */
501
502#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
503#define I386  1			/* Customize coffcode.h */
504#define AMD64 1
505
506#define RTYPE2HOWTO(cache_ptr, dst)		\
507  ((cache_ptr)->howto =				\
508   ((dst)->r_type < NUM_HOWTOS)			\
509    ? howto_table + (dst)->r_type		\
510    : NULL)
511
512/* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
513   library.  On some other COFF targets STYP_BSS is normally
514   STYP_NOLOAD.  */
515#define BSS_NOLOAD_IS_SHARED_LIBRARY
516
517/* Compute the addend of a reloc.  If the reloc is to a common symbol,
518   the object file contains the value of the common symbol.  By the
519   time this is called, the linker may be using a different symbol
520   from a different object file with a different value.  Therefore, we
521   hack wildly to locate the original symbol from this file so that we
522   can make the correct adjustment.  This macro sets coffsym to the
523   symbol from the original file, and uses it to set the addend value
524   correctly.  If this is not a common symbol, the usual addend
525   calculation is done, except that an additional tweak is needed for
526   PC relative relocs.
527   FIXME: This macro refers to symbols and asect; these are from the
528   calling function, not the macro arguments.  */
529
530#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)		\
531  {								\
532    coff_symbol_type *coffsym = NULL;				\
533								\
534    if (ptr && bfd_asymbol_bfd (ptr) != abfd)			\
535      coffsym = (obj_symbols (abfd)				\
536		 + (cache_ptr->sym_ptr_ptr - symbols));		\
537    else if (ptr)						\
538      coffsym = coff_symbol_from (ptr);				\
539								\
540    if (coffsym != NULL						\
541	&& coffsym->native->u.syment.n_scnum == 0)		\
542      cache_ptr->addend = - coffsym->native->u.syment.n_value;	\
543    else if (ptr && bfd_asymbol_bfd (ptr) == abfd		\
544	     && ptr->section != NULL)				\
545      cache_ptr->addend = - (ptr->section->vma			\
546			     + COFF_PE_ADDEND_BIAS (ptr));	\
547    else							\
548      cache_ptr->addend = 0;					\
549    if (ptr && reloc.r_type < NUM_HOWTOS			\
550	&& howto_table[reloc.r_type].pc_relative)		\
551      cache_ptr->addend += asect->vma;				\
552  }
553
554/* We use the special COFF backend linker.  For normal AMD64 COFF, we
555   can use the generic relocate_section routine.  For PE, we need our
556   own routine.  */
557
558#if !defined(COFF_WITH_PE)
559
560#define coff_relocate_section _bfd_coff_generic_relocate_section
561
562#else /* COFF_WITH_PE */
563
564/* The PE relocate section routine.  We handle secidx relocations here,
565   as well as making sure that we don't do anything for a relocatable
566   link.  */
567
568static bool
569coff_pe_amd64_relocate_section (bfd *output_bfd,
570				struct bfd_link_info *info,
571				bfd *input_bfd,
572				asection *input_section,
573				bfd_byte *contents,
574				struct internal_reloc *relocs,
575				struct internal_syment *syms,
576				asection **sections)
577{
578  struct internal_reloc *rel;
579  struct internal_reloc *relend;
580
581  if (bfd_link_relocatable (info))
582    return true;
583
584  rel = relocs;
585  relend = rel + input_section->reloc_count;
586
587  for (; rel < relend; rel++)
588    {
589      long symndx;
590      struct coff_link_hash_entry *h;
591      asection *sec, *s;
592      uint16_t idx = 0, i = 1;
593
594      if (rel->r_type != R_SECTION)
595	continue;
596
597      /* Make sure that _bfd_coff_generic_relocate_section won't parse
598         this reloc after us.  */
599      rel->r_type = 0;
600
601      symndx = rel->r_symndx;
602
603      if (symndx < 0
604	  || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
605	continue;
606
607      h = obj_coff_sym_hashes (input_bfd)[symndx];
608
609      if (h == NULL)
610	sec = sections[symndx];
611      else
612	{
613	  if (h->root.type == bfd_link_hash_defined
614	      || h->root.type == bfd_link_hash_defweak)
615	    {
616	      /* Defined weak symbols are a GNU extension.  */
617	      sec = h->root.u.def.section;
618	    }
619	  else
620	    {
621	      sec = NULL;
622	    }
623	}
624
625      if (!sec)
626	continue;
627
628      if (bfd_is_abs_section (sec))
629	continue;
630
631      if (discarded_section (sec))
632	continue;
633
634      s = output_bfd->sections;
635      while (s)
636	{
637	  if (s == sec->output_section)
638	    {
639	      idx = i;
640	      break;
641	    }
642
643	  i++;
644	  s = s->next;
645	}
646
647      bfd_putl16 (idx, contents + rel->r_vaddr - input_section->vma);
648    }
649
650  return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,input_section, contents,relocs, syms, sections);
651}
652
653#define coff_relocate_section coff_pe_amd64_relocate_section
654
655static hashval_t
656htab_hash_section_index (const void * entry)
657{
658  const struct bfd_section * sec = entry;
659  return sec->index;
660}
661
662static int
663htab_eq_section_index (const void * e1, const void * e2)
664{
665  const struct bfd_section * sec1 = e1;
666  const struct bfd_section * sec2 = e2;
667  return sec1->index == sec2->index;
668}
669#endif /* COFF_WITH_PE */
670
671/* Convert an rtype to howto for the COFF backend linker.  */
672
673static reloc_howto_type *
674coff_amd64_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
675			   asection *sec,
676			   struct internal_reloc *rel,
677			   struct coff_link_hash_entry *h,
678			   struct internal_syment *sym,
679			   bfd_vma *addendp)
680{
681  reloc_howto_type *howto;
682
683  if (rel->r_type >= NUM_HOWTOS)
684    {
685      bfd_set_error (bfd_error_bad_value);
686      return NULL;
687    }
688  howto = howto_table + rel->r_type;
689
690#if defined(COFF_WITH_PE)
691  /* Cancel out code in _bfd_coff_generic_relocate_section.  */
692  *addendp = 0;
693  if (rel->r_type >= R_AMD64_PCRLONG_1 && rel->r_type <= R_AMD64_PCRLONG_5)
694    {
695      *addendp -= (bfd_vma)(rel->r_type - R_AMD64_PCRLONG);
696      rel->r_type = R_AMD64_PCRLONG;
697    }
698#endif
699
700  if (howto->pc_relative)
701    *addendp += sec->vma;
702
703  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
704    {
705      /* This is a common symbol.  The section contents include the
706	 size (sym->n_value) as an addend.  The relocate_section
707	 function will be adding in the final value of the symbol.  We
708	 need to subtract out the current size in order to get the
709	 correct result.  */
710      BFD_ASSERT (h != NULL);
711
712#if !defined(COFF_WITH_PE)
713      /* I think we *do* want to bypass this.  If we don't, I have
714	 seen some data parameters get the wrong relocation address.
715	 If I link two versions with and without this section bypassed
716	 and then do a binary comparison, the addresses which are
717	 different can be looked up in the map.  The case in which
718	 this section has been bypassed has addresses which correspond
719	 to values I can find in the map.  */
720      *addendp -= sym->n_value;
721#endif
722    }
723
724#if !defined(COFF_WITH_PE)
725  /* If the output symbol is common (in which case this must be a
726     relocatable link), we need to add in the final size of the
727     common symbol.  */
728  if (h != NULL && h->root.type == bfd_link_hash_common)
729    *addendp += h->root.u.c.size;
730#endif
731
732#if defined(COFF_WITH_PE)
733  if (howto->pc_relative)
734    {
735#ifndef DONT_EXTEND_AMD64
736      if (rel->r_type == R_AMD64_PCRQUAD)
737	*addendp -= 8;
738      else
739#endif
740	*addendp -= 4;
741
742      /* If the symbol is defined, then the generic code is going to
743	 add back the symbol value in order to cancel out an
744	 adjustment it made to the addend.  However, we set the addend
745	 to 0 at the start of this function.  We need to adjust here,
746	 to avoid the adjustment the generic code will make.  FIXME:
747	 This is getting a bit hackish.  */
748      if (sym != NULL && sym->n_scnum != 0)
749	*addendp -= sym->n_value;
750    }
751
752  if (rel->r_type == R_AMD64_IMAGEBASE
753      && (bfd_get_flavour (sec->output_section->owner) == bfd_target_coff_flavour))
754    *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
755
756  if (rel->r_type == R_AMD64_SECREL)
757    {
758      bfd_vma osect_vma = 0;
759
760      if (h != NULL
761	  && (h->root.type == bfd_link_hash_defined
762	      || h->root.type == bfd_link_hash_defweak))
763	osect_vma = h->root.u.def.section->output_section->vma;
764      else
765	{
766	  htab_t table = coff_data (abfd)->section_by_index;
767	  asection *s;
768
769	  if (!table)
770	    {
771	      table = htab_create (10, htab_hash_section_index,
772				   htab_eq_section_index, NULL);
773	      if (table == NULL)
774		return NULL;
775	      coff_data (abfd)->section_by_index = table;
776	    }
777
778	  if (htab_elements (table) == 0)
779	    {
780	      for (s = abfd->sections; s != NULL; s = s->next)
781		{
782		  void ** slot = htab_find_slot (table, s, INSERT);
783
784		  if (slot != NULL)
785		    *slot = s;
786		}
787	    }
788
789	  struct bfd_section needle;
790
791	  needle.index = sym->n_scnum - 1;
792	  s = htab_find (table, &needle);
793	  if (s != NULL)
794	    osect_vma = s->output_section->vma;
795	}
796
797      *addendp -= osect_vma;
798    }
799#endif
800
801  return howto;
802}
803
804#define coff_bfd_reloc_type_lookup coff_amd64_reloc_type_lookup
805#define coff_bfd_reloc_name_lookup coff_amd64_reloc_name_lookup
806
807static reloc_howto_type *
808coff_amd64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code)
809{
810  switch (code)
811    {
812    case BFD_RELOC_RVA:
813      return howto_table + R_AMD64_IMAGEBASE;
814    case BFD_RELOC_32:
815      return howto_table + R_AMD64_DIR32;
816    case BFD_RELOC_64:
817      return howto_table + R_AMD64_DIR64;
818    case BFD_RELOC_64_PCREL:
819#ifndef DONT_EXTEND_AMD64
820      return howto_table + R_AMD64_PCRQUAD;
821#else
822      /* Fall through.  */
823#endif
824    case BFD_RELOC_32_PCREL:
825      return howto_table + R_AMD64_PCRLONG;
826    case BFD_RELOC_X86_64_32S:
827      return howto_table + R_RELLONG;
828    case BFD_RELOC_16:
829      return howto_table + R_RELWORD;
830    case BFD_RELOC_16_PCREL:
831      return howto_table + R_PCRWORD;
832    case BFD_RELOC_8:
833      return howto_table + R_RELBYTE;
834    case BFD_RELOC_8_PCREL:
835      return howto_table + R_PCRBYTE;
836#if defined(COFF_WITH_PE)
837    case BFD_RELOC_32_SECREL:
838      return howto_table + R_AMD64_SECREL;
839    case BFD_RELOC_16_SECIDX:
840      return howto_table + R_AMD64_SECTION;
841#endif
842    default:
843      BFD_FAIL ();
844      return 0;
845    }
846}
847
848static reloc_howto_type *
849coff_amd64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
850			      const char *r_name)
851{
852  unsigned int i;
853
854  for (i = 0; i < NUM_HOWTOS; i++)
855    if (howto_table[i].name != NULL
856	&& strcasecmp (howto_table[i].name, r_name) == 0)
857      return &howto_table[i];
858
859  return NULL;
860}
861
862#define coff_rtype_to_howto coff_amd64_rtype_to_howto
863
864#ifdef TARGET_UNDERSCORE
865
866/* If amd64 gcc uses underscores for symbol names, then it does not use
867   a leading dot for local labels, so if TARGET_UNDERSCORE is defined
868   we treat all symbols starting with L as local.  */
869
870static bool
871coff_amd64_is_local_label_name (bfd *abfd, const char *name)
872{
873  if (name[0] == 'L')
874    return true;
875
876  return _bfd_coff_is_local_label_name (abfd, name);
877}
878
879#define coff_bfd_is_local_label_name coff_amd64_is_local_label_name
880
881#endif /* TARGET_UNDERSCORE */
882
883#ifndef bfd_pe_print_pdata
884#define bfd_pe_print_pdata   NULL
885#endif
886
887#include "coffcode.h"
888
889#ifdef PE
890#define amd64coff_object_p pe_bfd_object_p
891#else
892#define amd64coff_object_p coff_object_p
893#endif
894
895const bfd_target
896#ifdef TARGET_SYM
897  TARGET_SYM =
898#else
899  x86_64_coff_vec =
900#endif
901{
902#ifdef TARGET_NAME
903  TARGET_NAME,
904#else
905 "coff-x86-64",			/* Name.  */
906#endif
907  bfd_target_coff_flavour,
908  BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
909  BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
910
911  (HAS_RELOC | EXEC_P		/* Object flags.  */
912   | HAS_LINENO | HAS_DEBUG
913   | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
914
915  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
916#if defined(COFF_WITH_PE)
917   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
918#endif
919   | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
920
921#ifdef TARGET_UNDERSCORE
922  TARGET_UNDERSCORE,		/* Leading underscore.  */
923#else
924  0,				/* Leading underscore.  */
925#endif
926  '/',				/* Ar_pad_char.  */
927  15,				/* Ar_max_namelen.  */
928  0,				/* match priority.  */
929  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
930
931  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
932     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
933     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
934  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
935     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
936     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
937
938  /* Note that we allow an object file to be treated as a core file as well.  */
939  {				/* bfd_check_format.  */
940    _bfd_dummy_target,
941    amd64coff_object_p,
942    bfd_generic_archive_p,
943    amd64coff_object_p
944  },
945  {				/* bfd_set_format.  */
946    _bfd_bool_bfd_false_error,
947    coff_mkobject,
948    _bfd_generic_mkarchive,
949    _bfd_bool_bfd_false_error
950  },
951  {				/* bfd_write_contents.  */
952    _bfd_bool_bfd_false_error,
953    coff_write_object_contents,
954    _bfd_write_archive_contents,
955    _bfd_bool_bfd_false_error
956  },
957
958  BFD_JUMP_TABLE_GENERIC (coff),
959  BFD_JUMP_TABLE_COPY (coff),
960  BFD_JUMP_TABLE_CORE (_bfd_nocore),
961  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
962  BFD_JUMP_TABLE_SYMBOLS (coff),
963  BFD_JUMP_TABLE_RELOCS (coff),
964  BFD_JUMP_TABLE_WRITE (coff),
965  BFD_JUMP_TABLE_LINK (coff),
966  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
967
968  NULL,
969
970  COFF_SWAP_TABLE
971};
972
973/* Entry for big object files.  */
974
975#ifdef COFF_WITH_PE_BIGOBJ
976const bfd_target
977  TARGET_SYM_BIG =
978{
979  TARGET_NAME_BIG,
980  bfd_target_coff_flavour,
981  BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
982  BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
983
984  (HAS_RELOC | EXEC_P		/* Object flags.  */
985   | HAS_LINENO | HAS_DEBUG
986   | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
987
988  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
989#if defined(COFF_WITH_PE)
990   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
991#endif
992   | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
993
994#ifdef TARGET_UNDERSCORE
995  TARGET_UNDERSCORE,		/* Leading underscore.  */
996#else
997  0,				/* Leading underscore.  */
998#endif
999  '/',				/* Ar_pad_char.  */
1000  15,				/* Ar_max_namelen.  */
1001  0,				/* match priority.  */
1002  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
1003
1004  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1005     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1006     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
1007  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
1008     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
1009     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
1010
1011  /* Note that we allow an object file to be treated as a core file as well.  */
1012  {				/* bfd_check_format.  */
1013    _bfd_dummy_target,
1014    amd64coff_object_p,
1015    bfd_generic_archive_p,
1016    amd64coff_object_p
1017  },
1018  {				/* bfd_set_format.  */
1019    _bfd_bool_bfd_false_error,
1020    coff_mkobject,
1021    _bfd_generic_mkarchive,
1022    _bfd_bool_bfd_false_error
1023  },
1024  {				/* bfd_write_contents.  */
1025    _bfd_bool_bfd_false_error,
1026    coff_write_object_contents,
1027    _bfd_write_archive_contents,
1028    _bfd_bool_bfd_false_error
1029  },
1030
1031  BFD_JUMP_TABLE_GENERIC (coff),
1032  BFD_JUMP_TABLE_COPY (coff),
1033  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1034  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
1035  BFD_JUMP_TABLE_SYMBOLS (coff),
1036  BFD_JUMP_TABLE_RELOCS (coff),
1037  BFD_JUMP_TABLE_WRITE (coff),
1038  BFD_JUMP_TABLE_LINK (coff),
1039  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1040
1041  NULL,
1042
1043  &bigobj_swap_table
1044};
1045#endif
1046