xref: /netbsd-src/external/gpl3/binutils/dist/bfd/coff-x86_64.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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 
57 static bfd_reloc_status_type
coff_amd64_reloc(bfd * abfd,arelent * reloc_entry,asymbol * symbol,void * data,asection * input_section ATTRIBUTE_UNUSED,bfd * output_bfd,char ** error_message ATTRIBUTE_UNUSED)58 coff_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 
223 static bool
in_reloc_p(bfd * abfd ATTRIBUTE_UNUSED,reloc_howto_type * howto)224 in_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 
237 static 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 
568 static bool
coff_pe_amd64_relocate_section(bfd * output_bfd,struct bfd_link_info * info,bfd * input_bfd,asection * input_section,bfd_byte * contents,struct internal_reloc * relocs,struct internal_syment * syms,asection ** sections)569 coff_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 
655 static hashval_t
htab_hash_section_index(const void * entry)656 htab_hash_section_index (const void * entry)
657 {
658   const struct bfd_section * sec = entry;
659   return sec->index;
660 }
661 
662 static int
htab_eq_section_index(const void * e1,const void * e2)663 htab_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 
673 static reloc_howto_type *
coff_amd64_rtype_to_howto(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,struct internal_reloc * rel,struct coff_link_hash_entry * h,struct internal_syment * sym,bfd_vma * addendp)674 coff_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 
807 static reloc_howto_type *
coff_amd64_reloc_type_lookup(bfd * abfd ATTRIBUTE_UNUSED,bfd_reloc_code_real_type code)808 coff_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 
848 static reloc_howto_type *
coff_amd64_reloc_name_lookup(bfd * abfd ATTRIBUTE_UNUSED,const char * r_name)849 coff_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 
870 static bool
coff_amd64_is_local_label_name(bfd * abfd,const char * name)871 coff_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 
895 const 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
976 const 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