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