2010-09-14 Kai Tietz <kai.tietz@onevision.com>
[external/binutils.git] / bfd / pei-x86_64.c
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
79 static 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
84 static void
85 pex64_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
97 static void
98 pex64_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_EHANDLER:
118       ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
119       break;
120     case UNW_FLAG_UHANDLER:
121       ui->rva_TerminationHandler = bfd_get_32 (abfd, ex_dta);
122       break;
123     case UNW_FLAG_FHANDLER:
124       ui->rva_FrameHandler = bfd_get_32 (abfd, ex_dta);
125       ui->FrameHandlerArgument = bfd_get_32 (abfd, ex_dta + 4);
126       ui->SizeOfBlock += 8;
127       return;
128     case UNW_FLAG_CHAININFO:
129       ui->rva_FunctionEntry = bfd_get_32 (abfd, ex_dta);
130       ui->SizeOfBlock += 4;
131       return;
132     default:
133       return;
134     }
135   ex_dta += 4;
136   ui->SizeOfBlock += 8;
137   ui->CountOfScopes = bfd_get_32 (abfd, ex_dta);
138   ex_dta += 4;
139   ui->rawScopeEntries = ex_dta;
140   ui->SizeOfBlock += (ui->CountOfScopes * PEX64_SCOPE_ENTRY_SIZE);
141 }
142
143 static void
144 pex64_get_scope_entry (bfd *abfd, struct pex64_scope_entry *se,
145                        bfd_vma idx, const bfd_byte *x)
146 {
147   const struct external_pex64_scope_entry *ex_se;
148   x += (idx * PEX64_SCOPE_ENTRY_SIZE);
149   ex_se = (const struct external_pex64_scope_entry *) x;
150   memset (se, 0, sizeof (struct pex64_scope_entry));
151   se->rva_BeginAddress = bfd_get_32 (abfd, ex_se->rva_BeginAddress);
152   se->rva_EndAddress = bfd_get_32 (abfd, ex_se->rva_EndAddress);
153   se->rva_HandlerAddress = bfd_get_32 (abfd, ex_se->rva_HandlerAddress);
154   se->rva_JumpAddress = bfd_get_32 (abfd, ex_se->rva_JumpAddress);
155 }
156
157 static void
158 pex64_xdata_print_uwd_codes (FILE *file, struct pex64_unwind_info *ui,
159                              bfd_vma pc_addr)
160 {
161   bfd_vma i;
162   bfd_vma tmp = 0;
163   const bfd_byte *insns[256];
164   bfd_vma insns_count = 0;
165   const bfd_byte *dta = ui->rawUnwindCodes;
166
167   if (ui->CountOfCodes == 0 || !dta)
168     return;
169
170   /* Sort array ascending. Note: it is stored in reversed order.  */
171   for (i = 0; i < ui->CountOfCodes; i++)
172     {
173       const bfd_byte *t;
174
175       t = insns[insns_count++] = &dta[i * 2];
176       switch (PEX64_UNWCODE_CODE (t[1]))
177         {
178         case UWOP_PUSH_NONVOL:
179         case UWOP_ALLOC_SMALL:
180         case UWOP_SET_FPREG:
181         case UWOP_PUSH_MACHFRAME:
182           break;
183         case UWOP_ALLOC_LARGE:
184           if (PEX64_UNWCODE_INFO (t[1]) == 0)
185             {
186               i += 1;
187               break;
188             }
189           else if (PEX64_UNWCODE_INFO (t[1]) == 1)
190             {
191               i += 2;
192               break;
193             }
194           /* fall through.  */
195         default:
196           fprintf (file, "\t contains unknown code (%u).\n",
197                    (unsigned int) PEX64_UNWCODE_CODE (t[1]));
198           return;
199         case UWOP_SAVE_NONVOL:
200         case UWOP_SAVE_XMM:
201         case UWOP_SAVE_XMM128:
202           i++;
203           break;
204         case UWOP_SAVE_NONVOL_FAR:
205         case UWOP_SAVE_XMM_FAR:
206         case UWOP_SAVE_XMM128_FAR:
207           i += 2;
208           break;
209         }
210     }
211   fprintf (file, "\t At pc 0x");
212   fprintf_vma (file, pc_addr);
213   fprintf (file, " there are the following saves (in logical order).\n");
214   for (i = insns_count; i > 0;)
215     {
216       --i;
217       dta = insns[i];
218       fprintf (file, "\t  insn ends at pc+0x%02x: ", (unsigned int) dta[0]);
219       switch (PEX64_UNWCODE_CODE (dta[1]))
220         {
221         case UWOP_PUSH_NONVOL:
222           fprintf (file, "push %s.\n", pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
223           break;
224         case UWOP_ALLOC_LARGE:
225           if (PEX64_UNWCODE_INFO (dta[1]) == 0)
226             {
227               tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
228               tmp *= 8;
229             }
230           else
231             tmp = (bfd_vma) (*((unsigned int *)&dta[2]));
232           fprintf (file, "save stack region of size 0x");
233           fprintf_vma (file, tmp);
234           fprintf (file,".\n");
235           break;
236         case UWOP_ALLOC_SMALL:
237           tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]);
238           tmp += 1;
239           tmp *= 8;
240           fprintf (file, "save stack region of size 0x");
241           fprintf_vma (file, tmp);
242           fprintf (file,".\n");
243           break;
244         case UWOP_SET_FPREG:
245           tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]);
246           tmp *= 16;
247           fprintf (file, "FPReg = (FrameReg) + 0x");
248           fprintf_vma (file, tmp);
249           fprintf (file, ".\n");
250           break;
251         case UWOP_SAVE_NONVOL:
252           fprintf (file, "mov %s at 0x",
253                    pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
254           tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
255           tmp *= 8;
256           fprintf_vma (file, tmp);
257           fprintf (file, ".\n");
258           break;
259         case UWOP_SAVE_NONVOL_FAR:
260           fprintf (file, "mov %s at 0x",
261                    pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
262           tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
263           fprintf_vma (file, tmp);
264           fprintf (file, ".\n");
265           break;
266         case UWOP_SAVE_XMM:
267           tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
268           tmp *= 8;
269           fprintf (file, "mov mm%u at 0x",
270                    (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
271           fprintf_vma (file, tmp);
272           fprintf (file, ".\n");
273           break;
274         case UWOP_SAVE_XMM_FAR:
275           tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
276           fprintf (file, "mov mm%u at 0x",
277                    (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
278           fprintf_vma (file, tmp);
279           fprintf (file, ".\n");
280           break;
281         case UWOP_SAVE_XMM128:
282           tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
283           tmp *= 16;
284           fprintf (file, "mov xmm%u at 0x",
285                    (unsigned int) PEX64_UNWCODE_INFO ( dta[1]));
286           fprintf_vma (file, tmp);
287           fprintf (file, ".\n");
288           break;
289         case UWOP_SAVE_XMM128_FAR:
290           tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
291           fprintf (file, "mov xmm%u at 0x",
292                    (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
293           fprintf_vma (file, tmp);
294           fprintf (file, ".\n");
295           break;
296         case UWOP_PUSH_MACHFRAME:
297           fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
298           if (PEX64_UNWCODE_INFO (dta[1]) == 0)
299             {
300               fprintf (file, ")");
301             }
302           else if (PEX64_UNWCODE_INFO (dta[1]) == 1)
303             {
304               fprintf (file, ",ErrorCode)");
305             }
306           else
307             fprintf (file, ", unknown(%u))",
308                      (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
309           fprintf (file,".\n");
310           break;
311         default:
312           fprintf (file, "unknown code %u.\n",
313                    (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
314           break;
315       }
316     }
317 }
318
319 static asection *
320 pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
321 {
322   asection *section = bfd_get_section_by_name (abfd, sec_name);
323   bfd_vma vsize;
324   bfd_size_type datasize = 0;
325
326   if (section == NULL
327       || coff_section_data (abfd, section) == NULL
328       || pei_section_data (abfd, section) == NULL)
329     return NULL;
330   vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
331   datasize = section->size;
332   if (!datasize || vsize > addr || (vsize + datasize) < addr)
333     return NULL;
334   return section;
335 }
336
337 static void
338 pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr)
339 {
340   asection *section = pex64_get_section_by_rva (abfd, addr, ".rdata");
341   bfd_vma vsize;
342   bfd_byte *data = NULL;
343   bfd_vma i;
344
345   if (!section)
346     section = pex64_get_section_by_rva (abfd, addr, ".data");
347   if (!section)
348     section = pex64_get_section_by_rva (abfd, addr, ".xdata");
349   if (!section)
350     {
351       section = pex64_get_section_by_rva (abfd, addr, ".pdata");
352       if (section)
353         {
354           fprintf (file, "\t Shares information with pdata element at 0x");
355           fprintf_vma (file, addr + pe_data (abfd)->pe_opthdr.ImageBase);
356           fprintf (file, ".\n");
357         }
358     }
359   if (!section)
360     return;
361   vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
362   addr -= vsize;
363   if (bfd_malloc_and_get_section (abfd, section, &data))
364     {
365       struct pex64_unwind_info ui;
366
367       if (!data)
368         return;
369
370       pex64_get_unwind_info (abfd, &ui, &data[addr]);
371
372       if (ui.Version != 1)
373         {
374           fprintf (file, "\tVersion %u (unknown).\n", (unsigned int) ui.Version);
375           return;
376         }
377
378       fprintf (file, "\tFlags: ");
379       switch (ui.Flags)
380         {
381         case UNW_FLAG_NHANDLER:
382           fprintf (file, "UNW_FLAG_NHANDLER");
383           break;
384         case UNW_FLAG_EHANDLER:
385           fprintf (file, "UNW_FLAG_EHANDLER");
386           break;
387         case UNW_FLAG_UHANDLER:
388           fprintf (file, "UNW_FLAG_UHANDLER");
389           break;
390         case UNW_FLAG_FHANDLER:
391           fprintf (file, "UNW_FLAG_FHANDLER = (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)");
392           break;
393         case UNW_FLAG_CHAININFO:
394           fprintf (file, "UNW_FLAG_CHAININFO");
395           break;
396         default:
397           fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
398           break;
399         }
400       fprintf (file, ".\n");
401       if (ui.CountOfCodes != 0)
402         fprintf (file, "\tEntry has %u codes.", (unsigned int) ui.CountOfCodes);
403       fprintf (file, "\tPrologue size: %u, Frame offset = 0x%x.\n",
404                (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
405       fprintf (file, "\tFrame register is %s.\n",
406         ui.FrameRegister == 0 ? "CFA"
407                               : pex_regs[(unsigned int) ui.FrameRegister]);
408
409       pex64_xdata_print_uwd_codes (file, &ui, pc_addr);
410       
411       switch (ui.Flags)
412         {
413         case UNW_FLAG_NHANDLER:
414           return;
415         case UNW_FLAG_EHANDLER:
416           fprintf (file, "\texception_handler at 0x%x.\n", (unsigned int) ui.rva_ExceptionHandler);
417           break;
418         case UNW_FLAG_UHANDLER:
419           fprintf (file, "\ttermination_handler at 0x%x.\n", (unsigned int) ui.rva_TerminationHandler);
420         case UNW_FLAG_FHANDLER:
421           fprintf (file, "\tframe_handler at 0x%x.\n", (unsigned int) ui.rva_FrameHandler);
422           fprintf (file, "\t Argument for FrameHandler: 0x%x.\n",
423                    (unsigned int) ui.FrameHandlerArgument);
424           return;
425         case UNW_FLAG_CHAININFO:
426           fprintf (file, "\t Function Entry: 0x%x\n", (unsigned int) ui.rva_FunctionEntry);
427           return;
428         default:
429           fprintf (file, "\t Unknown flag value of 0x%x\n", (unsigned int) ui.Flags);
430           return;
431         }
432       fprintf (file, "\t 0x%x # of scope(s)\n", (unsigned int) ui.CountOfScopes);
433       for (i = 0; i < ui.CountOfScopes; i++)
434         {
435           struct pex64_scope_entry se;
436           pex64_get_scope_entry (abfd, &se, i, ui.rawScopeEntries);
437           fprintf (file, "\t scope #%u: BeginAddress: 0x%x, EndAddress: 0x%x,"
438                    "\n\t\tHandlerAddress:0x%x, JumpTarget:0x%x\n",
439                    (unsigned int) (i + 1),
440                    (unsigned int) se.rva_BeginAddress,
441                    (unsigned int) se.rva_EndAddress,
442                    (unsigned int) se.rva_HandlerAddress,
443                    (unsigned int) se.rva_JumpAddress);
444         }
445     }
446   if (data != NULL)
447     free (data);
448 }
449
450 static bfd_boolean
451 pex64_bfd_print_pdata (bfd *abfd, void *vfile)
452 {
453   FILE *file = (FILE *) vfile;
454   bfd_byte *data = NULL;
455   asection *section = bfd_get_section_by_name (abfd, ".pdata");
456   bfd_size_type datasize = 0;
457   bfd_size_type i;
458   bfd_size_type start, stop;
459   int onaline = PDATA_ROW_SIZE;
460
461   if (section == NULL
462       || coff_section_data (abfd, section) == NULL
463       || pei_section_data (abfd, section) == NULL)
464     return TRUE;
465
466   stop = pei_section_data (abfd, section)->virt_size;
467   if ((stop % onaline) != 0)
468     fprintf (file,
469              _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
470              (long) stop, onaline);
471
472   fprintf (file,
473            _("\nThe Function Table (interpreted .pdata section contents)\n"));
474
475   fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));
476
477   datasize = section->size;
478   if (datasize == 0)
479     return TRUE;
480
481   if (!bfd_malloc_and_get_section (abfd, section, &data))
482     {
483       if (data != NULL)
484         free (data);
485       return FALSE;
486     }
487
488   start = 0;
489
490   for (i = start; i < stop; i += onaline)
491     {
492       struct pex64_runtime_function rf;
493
494       if (i + PDATA_ROW_SIZE > stop)
495         break;
496       pex64_get_runtime_function (abfd, &rf, &data[i]);
497
498       if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
499           && rf.rva_UnwindData == 0)
500         /* We are probably into the padding of the section now.  */
501         break;
502
503       fputc (' ', file);
504       fprintf_vma (file, i + section->vma);
505       fprintf (file, ":\t");
506       rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase;
507       fprintf_vma (file, rf.rva_BeginAddress);
508       fputc (' ', file);
509       rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase;
510       fprintf_vma (file, rf.rva_EndAddress);
511       fputc (' ', file);
512       fprintf_vma (file, rf.rva_UnwindData);
513       fprintf (file, "\n");
514
515       if (rf.rva_UnwindData != 0)
516         {
517           if (rf.isChained)
518             {
519               fprintf (file, "\t shares information with pdata element at 0x");
520               fprintf_vma (file, rf.rva_UnwindData + pe_data (abfd)->pe_opthdr.ImageBase);
521               fprintf (file, ".\n");
522             }
523           else
524             pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress);
525         }
526     }
527
528   free (data);
529
530   return TRUE;
531 }
532
533 #define bfd_pe_print_pdata   pex64_bfd_print_pdata
534
535 #include "coff-x86_64.c"