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