1/* BFD back-end for Intel 386 PE IMAGE COFF files.
2   Copyright 2006, 2007, 2009 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
26#define TARGET_SYM 		x86_64pei_vec
27#define TARGET_NAME 		"pei-x86-64"
28#define COFF_IMAGE_WITH_PE
29#define COFF_WITH_PE
30#define COFF_WITH_pex64
31#define PCRELOFFSET 		TRUE
32#if defined (USE_MINGW64_LEADING_UNDERSCORES)
33#define TARGET_UNDERSCORE 	'_'
34#else
35#define TARGET_UNDERSCORE 	0
36#endif
37/* Long section names not allowed in executable images, only object files.  */
38#define COFF_LONG_SECTION_NAMES 0
39#define COFF_SUPPORT_GNU_LINKONCE
40#define COFF_LONG_FILENAMES
41#define PDATA_ROW_SIZE	(3 * 4)
42
43#define COFF_SECTION_ALIGNMENT_ENTRIES \
44{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
45  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
46{ COFF_SECTION_NAME_PARTIAL_MATCH (".data"), \
47  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
48{ COFF_SECTION_NAME_PARTIAL_MATCH (".rdata"), \
49  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
50{ COFF_SECTION_NAME_PARTIAL_MATCH (".text"), \
51  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
52{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
53  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
54{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
55  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
56{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
57  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
58{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
59  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
60
61/* Note we have to make sure not to include headers twice.
62   Not all headers are wrapped in #ifdef guards, so we define
63   PEI_HEADERS to prevent double including in coff-x86_64.c  */
64#define PEI_HEADERS
65#include "sysdep.h"
66#include "bfd.h"
67#include "libbfd.h"
68#include "coff/x86_64.h"
69#include "coff/internal.h"
70#include "coff/pe.h"
71#include "libcoff.h"
72#include "libpei.h"
73#include "libiberty.h"
74
75#undef AOUTSZ
76#define AOUTSZ		PEPAOUTSZ
77#define PEAOUTHDR	PEPAOUTHDR
78
79static const char *pex_regs[16] = {
80  "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
81  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
82};
83
84static void
85pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf,
86			    const void *data)
87{
88  const struct external_pex64_runtime_function *ex_rf =
89    (const struct external_pex64_runtime_function *) data;
90  rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
91  rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
92  rf->rva_UnwindData =	bfd_get_32 (abfd, ex_rf->rva_UnwindData);
93  rf->isChained = PEX64_IS_RUNTIME_FUNCTION_CHAINED (rf);
94  rf->rva_UnwindData = PEX64_GET_UNWINDDATA_UNIFIED_RVA (rf);
95}
96
97static void
98pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data)
99{
100  struct external_pex64_unwind_info *ex_ui =
101    (struct external_pex64_unwind_info *) data;
102  bfd_byte *ex_dta = (bfd_byte *) data;
103
104  memset (ui, 0, sizeof (struct pex64_unwind_info));
105  ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
106  ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
107  ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
108  ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes;
109  ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset);
110  ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
111  ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
112  ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
113  ui->rawUnwindCodes = &ex_dta[4];
114  ex_dta += ui->SizeOfBlock;
115  switch (ui->Flags)
116    {
117    case UNW_FLAG_CHAININFO:
118      ui->rva_FunctionEntry = bfd_get_32 (abfd, ex_dta);
119      ui->SizeOfBlock += 4;
120      return;
121    default:
122      return;
123    }
124}
125
126static void
127pex64_xdata_print_uwd_codes (FILE *file, struct pex64_unwind_info *ui,
128			     bfd_vma pc_addr)
129{
130  bfd_vma i;
131  bfd_vma tmp = 0;
132  const bfd_byte *insns[256];
133  bfd_vma insns_count = 0;
134  const bfd_byte *dta = ui->rawUnwindCodes;
135
136  if (ui->CountOfCodes == 0 || !dta)
137    return;
138
139  /* Sort array ascending. Note: it is stored in reversed order.  */
140  for (i = 0; i < ui->CountOfCodes; i++)
141    {
142      const bfd_byte *t;
143
144      t = insns[insns_count++] = &dta[i * 2];
145      switch (PEX64_UNWCODE_CODE (t[1]))
146	{
147	case UWOP_PUSH_NONVOL:
148	case UWOP_ALLOC_SMALL:
149	case UWOP_SET_FPREG:
150	case UWOP_PUSH_MACHFRAME:
151	  break;
152	case UWOP_ALLOC_LARGE:
153	  if (PEX64_UNWCODE_INFO (t[1]) == 0)
154	    {
155	      i += 1;
156	      break;
157	    }
158	  else if (PEX64_UNWCODE_INFO (t[1]) == 1)
159	    {
160	      i += 2;
161	      break;
162	    }
163	  /* fall through.  */
164	default:
165	  fprintf (file, "\t contains unknown code (%u).\n",
166		   (unsigned int) PEX64_UNWCODE_CODE (t[1]));
167	  return;
168	case UWOP_SAVE_NONVOL:
169	case UWOP_SAVE_XMM:
170	case UWOP_SAVE_XMM128:
171	  i++;
172	  break;
173	case UWOP_SAVE_NONVOL_FAR:
174	case UWOP_SAVE_XMM_FAR:
175	case UWOP_SAVE_XMM128_FAR:
176	  i += 2;
177	  break;
178	}
179    }
180  fprintf (file, "\t At pc 0x");
181  fprintf_vma (file, pc_addr);
182  fprintf (file, " there are the following saves (in logical order).\n");
183  for (i = insns_count; i > 0;)
184    {
185      --i;
186      dta = insns[i];
187      fprintf (file, "\t  insn ends at pc+0x%02x: ", (unsigned int) dta[0]);
188      switch (PEX64_UNWCODE_CODE (dta[1]))
189	{
190	case UWOP_PUSH_NONVOL:
191	  fprintf (file, "push %s.\n", pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
192	  break;
193	case UWOP_ALLOC_LARGE:
194	  if (PEX64_UNWCODE_INFO (dta[1]) == 0)
195	    {
196	      tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
197	      tmp *= 8;
198	    }
199	  else
200	    tmp = (bfd_vma) (*((unsigned int *)&dta[2]));
201	  fprintf (file, "save stack region of size 0x");
202	  fprintf_vma (file, tmp);
203	  fprintf (file,".\n");
204	  break;
205	case UWOP_ALLOC_SMALL:
206	  tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]);
207	  tmp += 1;
208	  tmp *= 8;
209	  fprintf (file, "save stack region of size 0x");
210	  fprintf_vma (file, tmp);
211	  fprintf (file,".\n");
212	  break;
213	case UWOP_SET_FPREG:
214	  tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]);
215	  tmp *= 16;
216	  fprintf (file, "FPReg = (FrameReg) + 0x");
217	  fprintf_vma (file, tmp);
218	  fprintf (file, ".\n");
219	  break;
220	case UWOP_SAVE_NONVOL:
221	  fprintf (file, "mov %s at 0x",
222		   pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
223	  tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
224	  tmp *= 8;
225	  fprintf_vma (file, tmp);
226	  fprintf (file, ".\n");
227	  break;
228	case UWOP_SAVE_NONVOL_FAR:
229	  fprintf (file, "mov %s at 0x",
230		   pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
231	  tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
232	  fprintf_vma (file, tmp);
233	  fprintf (file, ".\n");
234	  break;
235	case UWOP_SAVE_XMM:
236	  tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
237	  tmp *= 8;
238	  fprintf (file, "mov mm%u at 0x",
239		   (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
240	  fprintf_vma (file, tmp);
241	  fprintf (file, ".\n");
242	  break;
243	case UWOP_SAVE_XMM_FAR:
244	  tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
245	  fprintf (file, "mov mm%u at 0x",
246		   (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
247	  fprintf_vma (file, tmp);
248	  fprintf (file, ".\n");
249	  break;
250	case UWOP_SAVE_XMM128:
251	  tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
252	  tmp *= 16;
253	  fprintf (file, "mov xmm%u at 0x",
254		   (unsigned int) PEX64_UNWCODE_INFO ( dta[1]));
255	  fprintf_vma (file, tmp);
256	  fprintf (file, ".\n");
257	  break;
258	case UWOP_SAVE_XMM128_FAR:
259	  tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
260	  fprintf (file, "mov xmm%u at 0x",
261		   (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
262	  fprintf_vma (file, tmp);
263	  fprintf (file, ".\n");
264	  break;
265	case UWOP_PUSH_MACHFRAME:
266	  fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
267	  if (PEX64_UNWCODE_INFO (dta[1]) == 0)
268	    {
269	      fprintf (file, ")");
270	    }
271	  else if (PEX64_UNWCODE_INFO (dta[1]) == 1)
272	    {
273	      fprintf (file, ",ErrorCode)");
274	    }
275	  else
276	    fprintf (file, ", unknown(%u))",
277		     (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
278	  fprintf (file,".\n");
279	  break;
280	default:
281	  fprintf (file, "unknown code %u.\n",
282		   (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
283	  break;
284      }
285    }
286}
287
288static asection *
289pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
290{
291  asection *section = bfd_get_section_by_name (abfd, sec_name);
292  bfd_vma vsize;
293  bfd_size_type datasize = 0;
294
295  if (section == NULL
296      || coff_section_data (abfd, section) == NULL
297      || pei_section_data (abfd, section) == NULL)
298    return NULL;
299  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
300  datasize = section->size;
301  if (!datasize || vsize > addr || (vsize + datasize) < addr)
302    return NULL;
303  return section;
304}
305
306static void
307pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr,
308		  bfd_vma *endx)
309{
310  asection *section = pex64_get_section_by_rva (abfd, addr, ".rdata");
311  bfd_vma vsize;
312  bfd_byte *data = NULL;
313  bfd_vma end_addr;
314
315  if (!section)
316    section = pex64_get_section_by_rva (abfd, addr, ".data");
317  if (!section)
318    section = pex64_get_section_by_rva (abfd, addr, ".xdata");
319  if (!section)
320    {
321      section = pex64_get_section_by_rva (abfd, addr, ".pdata");
322      if (section)
323	{
324	  fprintf (file, "\t Shares information with pdata element at 0x");
325	  fprintf_vma (file, addr + pe_data (abfd)->pe_opthdr.ImageBase);
326	  fprintf (file, ".\n");
327	}
328    }
329  if (!section)
330    return;
331
332  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
333  addr -= vsize;
334
335  if (endx)
336    end_addr = endx[0] - vsize;
337  else
338    end_addr = (section->rawsize != 0 ? section->rawsize : section->size);
339
340  if (bfd_malloc_and_get_section (abfd, section, &data))
341    {
342      struct pex64_unwind_info ui;
343
344      if (!data)
345	return;
346
347      pex64_get_unwind_info (abfd, &ui, &data[addr]);
348
349      if (ui.Version != 1)
350	{
351	  fprintf (file, "\tVersion %u (unknown).\n", (unsigned int) ui.Version);
352	  return;
353	}
354
355      fprintf (file, "\tFlags: ");
356      switch (ui.Flags)
357	{
358	case UNW_FLAG_NHANDLER:
359	  fprintf (file, "UNW_FLAG_NHANDLER");
360	  break;
361	case UNW_FLAG_EHANDLER:
362	  fprintf (file, "UNW_FLAG_EHANDLER");
363	  break;
364	case UNW_FLAG_UHANDLER:
365	  fprintf (file, "UNW_FLAG_UHANDLER");
366	  break;
367	case UNW_FLAG_FHANDLER:
368	  fprintf (file, "UNW_FLAG_FHANDLER = (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)");
369	  break;
370	case UNW_FLAG_CHAININFO:
371	  fprintf (file, "UNW_FLAG_CHAININFO");
372	  break;
373	default:
374	  fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
375	  break;
376	}
377      fprintf (file, ".\n");
378      if (ui.CountOfCodes != 0)
379	fprintf (file, "\tEntry has %u codes.", (unsigned int) ui.CountOfCodes);
380      fprintf (file, "\tPrologue size: %u, Frame offset = 0x%x.\n",
381	       (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
382      fprintf (file, "\tFrame register is %s.\n",
383	ui.FrameRegister == 0 ? "none"
384			      : pex_regs[(unsigned int) ui.FrameRegister]);
385
386      pex64_xdata_print_uwd_codes (file, &ui, pc_addr);
387
388      /* Now we need end of this xdata block.  */
389      addr += ui.SizeOfBlock;
390      if (addr < end_addr)
391        {
392	  unsigned int i;
393	  fprintf (file,"\tUser data:\n");
394	  for (i = 0; addr < end_addr; addr += 1, i++)
395	    {
396	      if ((i & 15) == 0)
397	        fprintf (file, "\t  %03x:", i);
398	      fprintf (file, " %02x", data[addr]);
399	      if ((i & 15) == 15)
400	        fprintf (file, "\n");
401	    }
402	  if ((i & 15) != 0)
403	    fprintf (file, "\n");
404        }
405    }
406  if (data != NULL)
407    free (data);
408}
409
410static int
411sort_xdata_arr (const void *l, const void *r)
412{
413  const bfd_vma *lp = (const bfd_vma *) l;
414  const bfd_vma *rp = (const bfd_vma *) r;
415
416  if (*lp == *rp)
417    return 0;
418  return (*lp < *rp ? -1 : 1);
419}
420
421static bfd_boolean
422pex64_bfd_print_pdata (bfd *abfd, void *vfile)
423{
424  FILE *file = (FILE *) vfile;
425  bfd_byte *data = NULL;
426  asection *section = bfd_get_section_by_name (abfd, ".pdata");
427  bfd_size_type datasize = 0;
428  bfd_size_type i;
429  bfd_size_type stop;
430  bfd_vma prev_beginaddress = 0;
431  int onaline = PDATA_ROW_SIZE;
432  int seen_error = 0;
433  bfd_vma *xdata_arr;
434  int xdata_arr_cnt;
435
436  if (section == NULL
437      || coff_section_data (abfd, section) == NULL
438      || pei_section_data (abfd, section) == NULL)
439    return TRUE;
440
441  stop = pei_section_data (abfd, section)->virt_size;
442  if ((stop % onaline) != 0)
443    fprintf (file,
444	     _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
445	     (long) stop, onaline);
446
447  fprintf (file,
448	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
449
450  fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));
451
452  datasize = section->size;
453  if (datasize == 0)
454    return TRUE;
455
456  if (!bfd_malloc_and_get_section (abfd, section, &data))
457    {
458      if (data != NULL)
459	free (data);
460      return FALSE;
461    }
462
463  xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
464  xdata_arr_cnt = 0;
465  /* Do sanity check of pdata.  */
466  for (i = 0; i < stop; i += onaline)
467    {
468      struct pex64_runtime_function rf;
469
470      if (i + PDATA_ROW_SIZE > stop)
471	break;
472      pex64_get_runtime_function (abfd, &rf, &data[i]);
473
474      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
475	  && rf.rva_UnwindData == 0)
476	/* We are probably into the padding of the section now.  */
477	break;
478      fputc (' ', file);
479      fprintf_vma (file, i + section->vma);
480      fprintf (file, ":\t");
481      fprintf_vma (file, rf.rva_BeginAddress);
482      fputc (' ', file);
483      fprintf_vma (file, rf.rva_EndAddress);
484      fputc (' ', file);
485      fprintf_vma (file, rf.rva_UnwindData);
486      fprintf (file, "\n");
487      if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
488	{
489	  seen_error = 1;
490	  fprintf (file, "  has %s begin address as predecessor\n",
491	    (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
492        }
493      prev_beginaddress = rf.rva_BeginAddress;
494      /* Now we check for negative addresses.  */
495      if ((prev_beginaddress & 0x80000000) != 0)
496	{
497	  seen_error = 1;
498	  fprintf (file, "  has negative begin address\n");
499	}
500      if ((rf.rva_EndAddress & 0x80000000) != 0)
501	{
502	  seen_error = 1;
503	  fprintf (file, "  has negative end address\n");
504	}
505      if ((rf.rva_UnwindData & 0x80000000) != 0)
506	{
507	  seen_error = 1;
508	  fprintf (file, "  has negative unwind address\n");
509	}
510      if (rf.rva_UnwindData && !rf.isChained)
511        xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
512    }
513
514  if (seen_error)
515    {
516      free (data);
517      free (xdata_arr);
518
519      return TRUE;
520    }
521
522  /* Add end of list marker.  */
523  xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
524
525  /* Sort start RVAs of xdata.  */
526  if (xdata_arr_cnt > 1)
527    qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
528	   sort_xdata_arr);
529
530  /* Do dump of pdata related xdata.  */
531
532  for (i = 0; i < stop; i += onaline)
533    {
534      struct pex64_runtime_function rf;
535
536      if (i + PDATA_ROW_SIZE > stop)
537	break;
538      pex64_get_runtime_function (abfd, &rf, &data[i]);
539
540      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
541	  && rf.rva_UnwindData == 0)
542	/* We are probably into the padding of the section now.  */
543	break;
544      if (i == 0)
545        fprintf (file, "\nDump of .xdata\n");
546      fputc (' ', file);
547      fprintf_vma (file, rf.rva_UnwindData);
548      fprintf (file, ":\n");
549
550      rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase;
551      rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase;
552
553      if (rf.rva_UnwindData != 0)
554	{
555	  if (rf.isChained)
556	    {
557	      fprintf (file, "\t shares information with pdata element at 0x");
558	      fprintf_vma (file, rf.rva_UnwindData);
559	      fprintf (file, ".\n");
560	    }
561	  else
562	    {
563	      bfd_vma *p;
564
565	      /* Search for the current entry in the sorted array.  */
566	      p = (bfd_vma *)
567	          bsearch (&rf.rva_UnwindData, xdata_arr,
568			   (size_t) xdata_arr_cnt, sizeof (bfd_vma),
569			   sort_xdata_arr);
570
571	      /* Advance to the next pointer into the xdata section.  We may
572		 have shared xdata entries, which will result in a string of
573		 identical pointers in the array; advance past all of them.  */
574	      while (p[0] <= rf.rva_UnwindData)
575		++p;
576	      if (p[0] == ~((bfd_vma) 0))
577		p = NULL;
578
579	      pex64_dump_xdata (file, abfd, rf.rva_UnwindData,
580				rf.rva_BeginAddress, p);
581	    }
582	}
583    }
584
585  free (data);
586  free (xdata_arr);
587
588  return TRUE;
589}
590
591#define bfd_pe_print_pdata   pex64_bfd_print_pdata
592
593#include "coff-x86_64.c"
594