1a1ba9ba4Schristos /* BFD back-end for Intel 386 PE IMAGE COFF files. 2*b2396a7bSchristos Copyright (C) 2006-2016 Free Software Foundation, Inc. 3a1ba9ba4Schristos 4a1ba9ba4Schristos This file is part of BFD, the Binary File Descriptor library. 5a1ba9ba4Schristos 6a1ba9ba4Schristos This program is free software; you can redistribute it and/or modify 7a1ba9ba4Schristos it under the terms of the GNU General Public License as published by 8a1ba9ba4Schristos the Free Software Foundation; either version 3 of the License, or 9a1ba9ba4Schristos (at your option) any later version. 10a1ba9ba4Schristos 11a1ba9ba4Schristos This program is distributed in the hope that it will be useful, 12a1ba9ba4Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 13a1ba9ba4Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14a1ba9ba4Schristos GNU General Public License for more details. 15a1ba9ba4Schristos 16a1ba9ba4Schristos You should have received a copy of the GNU General Public License 17a1ba9ba4Schristos along with this program; if not, write to the Free Software 18a1ba9ba4Schristos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19a1ba9ba4Schristos MA 02110-1301, USA. 20a1ba9ba4Schristos 21a1ba9ba4Schristos Written by Kai Tietz, OneVision Software GmbH&CoKg. */ 22a1ba9ba4Schristos 23a1ba9ba4Schristos #include "sysdep.h" 24a1ba9ba4Schristos #include "bfd.h" 25a1ba9ba4Schristos 26a1ba9ba4Schristos #define TARGET_SYM x86_64_pei_vec 27a1ba9ba4Schristos #define TARGET_NAME "pei-x86-64" 28a1ba9ba4Schristos #define COFF_IMAGE_WITH_PE 29a1ba9ba4Schristos #define COFF_WITH_PE 30a1ba9ba4Schristos #define COFF_WITH_pex64 31a1ba9ba4Schristos #define PCRELOFFSET TRUE 32a1ba9ba4Schristos #if defined (USE_MINGW64_LEADING_UNDERSCORES) 33a1ba9ba4Schristos #define TARGET_UNDERSCORE '_' 34a1ba9ba4Schristos #else 35a1ba9ba4Schristos #define TARGET_UNDERSCORE 0 36a1ba9ba4Schristos #endif 37a1ba9ba4Schristos /* Long section names not allowed in executable images, only object files. */ 38a1ba9ba4Schristos #define COFF_LONG_SECTION_NAMES 0 39a1ba9ba4Schristos #define COFF_SUPPORT_GNU_LINKONCE 40a1ba9ba4Schristos #define COFF_LONG_FILENAMES 41a1ba9ba4Schristos #define PDATA_ROW_SIZE (3 * 4) 42a1ba9ba4Schristos 43a1ba9ba4Schristos #define COFF_SECTION_ALIGNMENT_ENTRIES \ 44a1ba9ba4Schristos { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \ 45a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ 46a1ba9ba4Schristos { COFF_SECTION_NAME_PARTIAL_MATCH (".data"), \ 47a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ 48a1ba9ba4Schristos { COFF_SECTION_NAME_PARTIAL_MATCH (".rdata"), \ 49a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ 50a1ba9ba4Schristos { COFF_SECTION_NAME_PARTIAL_MATCH (".text"), \ 51a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ 52a1ba9ba4Schristos { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \ 53a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ 54a1ba9ba4Schristos { COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \ 55a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ 56a1ba9ba4Schristos { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \ 57a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \ 58a1ba9ba4Schristos { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \ 59a1ba9ba4Schristos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 } 60a1ba9ba4Schristos 61a1ba9ba4Schristos /* Note we have to make sure not to include headers twice. 62a1ba9ba4Schristos Not all headers are wrapped in #ifdef guards, so we define 63a1ba9ba4Schristos PEI_HEADERS to prevent double including in coff-x86_64.c */ 64a1ba9ba4Schristos #define PEI_HEADERS 65a1ba9ba4Schristos #include "sysdep.h" 66a1ba9ba4Schristos #include "bfd.h" 67a1ba9ba4Schristos #include "libbfd.h" 68a1ba9ba4Schristos #include "coff/x86_64.h" 69a1ba9ba4Schristos #include "coff/internal.h" 70a1ba9ba4Schristos #include "coff/pe.h" 71a1ba9ba4Schristos #include "libcoff.h" 72a1ba9ba4Schristos #include "libpei.h" 73a1ba9ba4Schristos #include "libiberty.h" 74a1ba9ba4Schristos 75a1ba9ba4Schristos #undef AOUTSZ 76a1ba9ba4Schristos #define AOUTSZ PEPAOUTSZ 77a1ba9ba4Schristos #define PEAOUTHDR PEPAOUTHDR 78a1ba9ba4Schristos 79a1ba9ba4Schristos /* Name of registers according to SEH conventions. */ 80a1ba9ba4Schristos 81a1ba9ba4Schristos static const char * const pex_regs[16] = { 82a1ba9ba4Schristos "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 83a1ba9ba4Schristos "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" 84a1ba9ba4Schristos }; 85a1ba9ba4Schristos 86a1ba9ba4Schristos /* Swap in a runtime function. */ 87a1ba9ba4Schristos 88a1ba9ba4Schristos static void 89a1ba9ba4Schristos pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf, 90a1ba9ba4Schristos const void *data) 91a1ba9ba4Schristos { 92a1ba9ba4Schristos const struct external_pex64_runtime_function *ex_rf = 93a1ba9ba4Schristos (const struct external_pex64_runtime_function *) data; 94a1ba9ba4Schristos rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress); 95a1ba9ba4Schristos rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress); 96a1ba9ba4Schristos rf->rva_UnwindData = bfd_get_32 (abfd, ex_rf->rva_UnwindData); 97a1ba9ba4Schristos } 98a1ba9ba4Schristos 99a1ba9ba4Schristos /* Swap in unwind info header. */ 100a1ba9ba4Schristos 101a1ba9ba4Schristos static void 102a1ba9ba4Schristos pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data) 103a1ba9ba4Schristos { 104a1ba9ba4Schristos struct external_pex64_unwind_info *ex_ui = 105a1ba9ba4Schristos (struct external_pex64_unwind_info *) data; 106a1ba9ba4Schristos bfd_byte *ex_dta = (bfd_byte *) data; 107a1ba9ba4Schristos 108a1ba9ba4Schristos memset (ui, 0, sizeof (struct pex64_unwind_info)); 109a1ba9ba4Schristos ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags); 110a1ba9ba4Schristos ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags); 111a1ba9ba4Schristos ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue; 112a1ba9ba4Schristos ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes; 113a1ba9ba4Schristos ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset); 114a1ba9ba4Schristos ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset); 115a1ba9ba4Schristos ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes); 116a1ba9ba4Schristos ui->SizeOfBlock = ui->sizeofUnwindCodes + 4; 117a1ba9ba4Schristos ui->rawUnwindCodes = &ex_dta[4]; 118a1ba9ba4Schristos 119a1ba9ba4Schristos ex_dta += ui->SizeOfBlock; 120a1ba9ba4Schristos switch (ui->Flags) 121a1ba9ba4Schristos { 122a1ba9ba4Schristos case UNW_FLAG_CHAININFO: 123a1ba9ba4Schristos ui->rva_BeginAddress = bfd_get_32 (abfd, ex_dta + 0); 124a1ba9ba4Schristos ui->rva_EndAddress = bfd_get_32 (abfd, ex_dta + 4); 125a1ba9ba4Schristos ui->rva_UnwindData = bfd_get_32 (abfd, ex_dta + 8); 126a1ba9ba4Schristos ui->SizeOfBlock += 12; 127a1ba9ba4Schristos return; 128a1ba9ba4Schristos case UNW_FLAG_EHANDLER: 129a1ba9ba4Schristos case UNW_FLAG_UHANDLER: 130a1ba9ba4Schristos case UNW_FLAG_FHANDLER: 131a1ba9ba4Schristos ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta); 132a1ba9ba4Schristos ui->SizeOfBlock += 4; 133a1ba9ba4Schristos return; 134a1ba9ba4Schristos default: 135a1ba9ba4Schristos return; 136a1ba9ba4Schristos } 137a1ba9ba4Schristos } 138a1ba9ba4Schristos 139a1ba9ba4Schristos /* Display unwind codes. */ 140a1ba9ba4Schristos 141a1ba9ba4Schristos static void 142a1ba9ba4Schristos pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd, 143a1ba9ba4Schristos struct pex64_unwind_info *ui, 144a1ba9ba4Schristos struct pex64_runtime_function *rf) 145a1ba9ba4Schristos { 146a1ba9ba4Schristos unsigned int i; 147a1ba9ba4Schristos unsigned int tmp; /* At least 32 bits. */ 148a1ba9ba4Schristos int save_allowed; 149a1ba9ba4Schristos 150a1ba9ba4Schristos if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL) 151a1ba9ba4Schristos return; 152a1ba9ba4Schristos 153a1ba9ba4Schristos /* According to UNWIND_CODE documentation: 154a1ba9ba4Schristos If an FP reg is used, the any unwind code taking an offset must only be 155a1ba9ba4Schristos used after the FP reg is established in the prolog. 156a1ba9ba4Schristos But there are counter examples of that in system dlls... */ 157a1ba9ba4Schristos save_allowed = TRUE; 158a1ba9ba4Schristos 159a1ba9ba4Schristos i = 0; 160a1ba9ba4Schristos 161a1ba9ba4Schristos if (ui->Version == 2 162a1ba9ba4Schristos && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == UWOP_EPILOG) 163a1ba9ba4Schristos { 164a1ba9ba4Schristos /* Display epilog opcode (whose docoding is not fully documented). 165a1ba9ba4Schristos Looks to be designed to speed-up unwinding, as there is no need 166a1ba9ba4Schristos to decode instruction flow if outside an epilog. */ 167a1ba9ba4Schristos unsigned int func_size = rf->rva_EndAddress - rf->rva_BeginAddress; 168a1ba9ba4Schristos 169a1ba9ba4Schristos fprintf (file, "\tv2 epilog (length: %02x) at pc+:", 170a1ba9ba4Schristos ui->rawUnwindCodes[0]); 171a1ba9ba4Schristos if (PEX64_UNWCODE_INFO (ui->rawUnwindCodes[1])) 172a1ba9ba4Schristos fprintf (file, " 0x%x", func_size - ui->rawUnwindCodes[0]); 173a1ba9ba4Schristos i++; 174a1ba9ba4Schristos for (; i < ui->CountOfCodes; i++) 175a1ba9ba4Schristos { 176a1ba9ba4Schristos const bfd_byte *dta = ui->rawUnwindCodes + 2 * i; 177a1ba9ba4Schristos unsigned int off; 178a1ba9ba4Schristos 179a1ba9ba4Schristos if (PEX64_UNWCODE_CODE (dta[1]) != UWOP_EPILOG) 180a1ba9ba4Schristos break; 181a1ba9ba4Schristos off = dta[0] | (PEX64_UNWCODE_INFO (dta[1]) << 8); 182a1ba9ba4Schristos if (off == 0) 183a1ba9ba4Schristos fprintf (file, " [pad]"); 184a1ba9ba4Schristos else 185a1ba9ba4Schristos fprintf (file, " 0x%x", func_size - off); 186a1ba9ba4Schristos } 187a1ba9ba4Schristos fputc ('\n', file); 188a1ba9ba4Schristos } 189a1ba9ba4Schristos 190a1ba9ba4Schristos for (; i < ui->CountOfCodes; i++) 191a1ba9ba4Schristos { 192a1ba9ba4Schristos const bfd_byte *dta = ui->rawUnwindCodes + 2 * i; 193a1ba9ba4Schristos unsigned int info = PEX64_UNWCODE_INFO (dta[1]); 194a1ba9ba4Schristos int unexpected = FALSE; 195a1ba9ba4Schristos 196a1ba9ba4Schristos fprintf (file, "\t pc+0x%02x: ", (unsigned int) dta[0]); 197a1ba9ba4Schristos switch (PEX64_UNWCODE_CODE (dta[1])) 198a1ba9ba4Schristos { 199a1ba9ba4Schristos case UWOP_PUSH_NONVOL: 200a1ba9ba4Schristos fprintf (file, "push %s", pex_regs[info]); 201a1ba9ba4Schristos break; 202a1ba9ba4Schristos case UWOP_ALLOC_LARGE: 203a1ba9ba4Schristos if (info == 0) 204a1ba9ba4Schristos { 205a1ba9ba4Schristos tmp = bfd_get_16 (abfd, &dta[2]) * 8; 206a1ba9ba4Schristos i++; 207a1ba9ba4Schristos } 208a1ba9ba4Schristos else 209a1ba9ba4Schristos { 210a1ba9ba4Schristos tmp = bfd_get_32 (abfd, &dta[2]); 211a1ba9ba4Schristos i += 2; 212a1ba9ba4Schristos } 213a1ba9ba4Schristos fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp); 214a1ba9ba4Schristos break; 215a1ba9ba4Schristos case UWOP_ALLOC_SMALL: 216a1ba9ba4Schristos fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8); 217a1ba9ba4Schristos break; 218a1ba9ba4Schristos case UWOP_SET_FPREG: 219a1ba9ba4Schristos /* According to the documentation, info field is unused. */ 220a1ba9ba4Schristos fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)", 221a1ba9ba4Schristos pex_regs[ui->FrameRegister], 222a1ba9ba4Schristos (unsigned int) ui->FrameOffset * 16, info); 223a1ba9ba4Schristos unexpected = ui->FrameRegister == 0; 224a1ba9ba4Schristos save_allowed = FALSE; 225a1ba9ba4Schristos break; 226a1ba9ba4Schristos case UWOP_SAVE_NONVOL: 227a1ba9ba4Schristos tmp = bfd_get_16 (abfd, &dta[2]) * 8; 228a1ba9ba4Schristos i++; 229a1ba9ba4Schristos fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp); 230a1ba9ba4Schristos unexpected = !save_allowed; 231a1ba9ba4Schristos break; 232a1ba9ba4Schristos case UWOP_SAVE_NONVOL_FAR: 233a1ba9ba4Schristos tmp = bfd_get_32 (abfd, &dta[2]); 234a1ba9ba4Schristos i += 2; 235a1ba9ba4Schristos fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp); 236a1ba9ba4Schristos unexpected = !save_allowed; 237a1ba9ba4Schristos break; 238a1ba9ba4Schristos case UWOP_SAVE_XMM: 239a1ba9ba4Schristos if (ui->Version == 1) 240a1ba9ba4Schristos { 241a1ba9ba4Schristos tmp = bfd_get_16 (abfd, &dta[2]) * 8; 242a1ba9ba4Schristos i++; 243a1ba9ba4Schristos fprintf (file, "save mm%u at rsp + 0x%x", info, tmp); 244a1ba9ba4Schristos unexpected = !save_allowed; 245a1ba9ba4Schristos } 246a1ba9ba4Schristos else if (ui->Version == 2) 247a1ba9ba4Schristos { 248a1ba9ba4Schristos fprintf (file, "epilog %02x %01x", dta[0], info); 249a1ba9ba4Schristos unexpected = TRUE; 250a1ba9ba4Schristos } 251a1ba9ba4Schristos break; 252a1ba9ba4Schristos case UWOP_SAVE_XMM_FAR: 253a1ba9ba4Schristos tmp = bfd_get_32 (abfd, &dta[2]) * 8; 254a1ba9ba4Schristos i += 2; 255a1ba9ba4Schristos fprintf (file, "save mm%u at rsp + 0x%x", info, tmp); 256a1ba9ba4Schristos unexpected = !save_allowed; 257a1ba9ba4Schristos break; 258a1ba9ba4Schristos case UWOP_SAVE_XMM128: 259a1ba9ba4Schristos tmp = bfd_get_16 (abfd, &dta[2]) * 16; 260a1ba9ba4Schristos i++; 261a1ba9ba4Schristos fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp); 262a1ba9ba4Schristos unexpected = !save_allowed; 263a1ba9ba4Schristos break; 264a1ba9ba4Schristos case UWOP_SAVE_XMM128_FAR: 265a1ba9ba4Schristos tmp = bfd_get_32 (abfd, &dta[2]) * 16; 266a1ba9ba4Schristos i += 2; 267a1ba9ba4Schristos fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp); 268a1ba9ba4Schristos unexpected = !save_allowed; 269a1ba9ba4Schristos break; 270a1ba9ba4Schristos case UWOP_PUSH_MACHFRAME: 271a1ba9ba4Schristos fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP"); 272a1ba9ba4Schristos if (info == 0) 273a1ba9ba4Schristos fprintf (file, ")"); 274a1ba9ba4Schristos else if (info == 1) 275a1ba9ba4Schristos fprintf (file, ",ErrorCode)"); 276a1ba9ba4Schristos else 277a1ba9ba4Schristos fprintf (file, ", unknown(%u))", info); 278a1ba9ba4Schristos break; 279a1ba9ba4Schristos default: 280a1ba9ba4Schristos /* PR 17512: file: 2245-7442-0.004. */ 281a1ba9ba4Schristos fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1])); 282a1ba9ba4Schristos break; 283a1ba9ba4Schristos } 284a1ba9ba4Schristos if (unexpected) 285a1ba9ba4Schristos fprintf (file, " [Unexpected!]"); 286a1ba9ba4Schristos fputc ('\n', file); 287a1ba9ba4Schristos } 288a1ba9ba4Schristos } 289a1ba9ba4Schristos 290a1ba9ba4Schristos /* Check wether section SEC_NAME contains the xdata at address ADDR. */ 291a1ba9ba4Schristos 292a1ba9ba4Schristos static asection * 293a1ba9ba4Schristos pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name) 294a1ba9ba4Schristos { 295a1ba9ba4Schristos asection *section = bfd_get_section_by_name (abfd, sec_name); 296a1ba9ba4Schristos bfd_vma vsize; 297a1ba9ba4Schristos bfd_size_type datasize = 0; 298a1ba9ba4Schristos 299a1ba9ba4Schristos if (section == NULL 300a1ba9ba4Schristos || coff_section_data (abfd, section) == NULL 301a1ba9ba4Schristos || pei_section_data (abfd, section) == NULL) 302a1ba9ba4Schristos return NULL; 303a1ba9ba4Schristos vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase; 304a1ba9ba4Schristos datasize = section->size; 305a1ba9ba4Schristos if (!datasize || vsize > addr || (vsize + datasize) < addr) 306a1ba9ba4Schristos return NULL; 307a1ba9ba4Schristos return section; 308a1ba9ba4Schristos } 309a1ba9ba4Schristos 310a1ba9ba4Schristos /* Dump xdata at for function RF to FILE. The argument XDATA_SECTION 311a1ba9ba4Schristos designate the bfd section containing the xdata, XDATA is its content, 312a1ba9ba4Schristos and ENDX the size if known (or NULL). */ 313a1ba9ba4Schristos 314a1ba9ba4Schristos static void 315a1ba9ba4Schristos pex64_dump_xdata (FILE *file, bfd *abfd, 316a1ba9ba4Schristos asection *xdata_section, bfd_byte *xdata, bfd_vma *endx, 317a1ba9ba4Schristos struct pex64_runtime_function *rf) 318a1ba9ba4Schristos { 319a1ba9ba4Schristos bfd_vma vaddr; 320a1ba9ba4Schristos bfd_vma end_addr; 321a1ba9ba4Schristos bfd_vma addr = rf->rva_UnwindData; 322a1ba9ba4Schristos bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size; 323a1ba9ba4Schristos struct pex64_unwind_info ui; 324a1ba9ba4Schristos 325a1ba9ba4Schristos vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase; 326a1ba9ba4Schristos addr -= vaddr; 327a1ba9ba4Schristos 328a1ba9ba4Schristos /* PR 17512: file: 2245-7442-0.004. */ 329a1ba9ba4Schristos if (addr >= sec_size) 330a1ba9ba4Schristos { 331a1ba9ba4Schristos fprintf (file, _("warning: xdata section corrupt\n")); 332a1ba9ba4Schristos return; 333a1ba9ba4Schristos } 334a1ba9ba4Schristos 335a1ba9ba4Schristos if (endx) 336a1ba9ba4Schristos { 337a1ba9ba4Schristos end_addr = endx[0] - vaddr; 338a1ba9ba4Schristos /* PR 17512: file: 2245-7442-0.004. */ 339a1ba9ba4Schristos if (end_addr > sec_size) 340a1ba9ba4Schristos { 341a1ba9ba4Schristos fprintf (file, _("warning: xdata section corrupt")); 342a1ba9ba4Schristos end_addr = sec_size; 343a1ba9ba4Schristos } 344a1ba9ba4Schristos } 345a1ba9ba4Schristos else 346a1ba9ba4Schristos end_addr = sec_size; 347a1ba9ba4Schristos 348a1ba9ba4Schristos pex64_get_unwind_info (abfd, &ui, &xdata[addr]); 349a1ba9ba4Schristos 350a1ba9ba4Schristos if (ui.Version != 1 && ui.Version != 2) 351a1ba9ba4Schristos { 352a1ba9ba4Schristos unsigned int i; 353a1ba9ba4Schristos fprintf (file, "\tVersion %u (unknown).\n", 354a1ba9ba4Schristos (unsigned int) ui.Version); 355a1ba9ba4Schristos for (i = 0; addr < end_addr; addr += 1, i++) 356a1ba9ba4Schristos { 357a1ba9ba4Schristos if ((i & 15) == 0) 358a1ba9ba4Schristos fprintf (file, "\t %03x:", i); 359a1ba9ba4Schristos fprintf (file, " %02x", xdata[addr]); 360a1ba9ba4Schristos if ((i & 15) == 15) 361a1ba9ba4Schristos fprintf (file, "\n"); 362a1ba9ba4Schristos } 363a1ba9ba4Schristos if ((i & 15) != 0) 364a1ba9ba4Schristos fprintf (file, "\n"); 365a1ba9ba4Schristos return; 366a1ba9ba4Schristos } 367a1ba9ba4Schristos 368a1ba9ba4Schristos fprintf (file, "\tVersion: %d, Flags: ", ui.Version); 369a1ba9ba4Schristos switch (ui.Flags) 370a1ba9ba4Schristos { 371a1ba9ba4Schristos case UNW_FLAG_NHANDLER: 372a1ba9ba4Schristos fprintf (file, "none"); 373a1ba9ba4Schristos break; 374a1ba9ba4Schristos case UNW_FLAG_EHANDLER: 375a1ba9ba4Schristos fprintf (file, "UNW_FLAG_EHANDLER"); 376a1ba9ba4Schristos break; 377a1ba9ba4Schristos case UNW_FLAG_UHANDLER: 378a1ba9ba4Schristos fprintf (file, "UNW_FLAG_UHANDLER"); 379a1ba9ba4Schristos break; 380a1ba9ba4Schristos case UNW_FLAG_FHANDLER: 381a1ba9ba4Schristos fprintf 382a1ba9ba4Schristos (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER"); 383a1ba9ba4Schristos break; 384a1ba9ba4Schristos case UNW_FLAG_CHAININFO: 385a1ba9ba4Schristos fprintf (file, "UNW_FLAG_CHAININFO"); 386a1ba9ba4Schristos break; 387a1ba9ba4Schristos default: 388a1ba9ba4Schristos fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags); 389a1ba9ba4Schristos break; 390a1ba9ba4Schristos } 391a1ba9ba4Schristos fputc ('\n', file); 392a1ba9ba4Schristos fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes); 393a1ba9ba4Schristos fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ", 394a1ba9ba4Schristos (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset); 395a1ba9ba4Schristos fprintf (file, "Frame reg: %s\n", 396a1ba9ba4Schristos ui.FrameRegister == 0 ? "none" 397a1ba9ba4Schristos : pex_regs[(unsigned int) ui.FrameRegister]); 398a1ba9ba4Schristos 399a1ba9ba4Schristos /* PR 17512: file: 2245-7442-0.004. */ 400a1ba9ba4Schristos if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size) 401a1ba9ba4Schristos fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes); 402a1ba9ba4Schristos else 403a1ba9ba4Schristos pex64_xdata_print_uwd_codes (file, abfd, &ui, rf); 404a1ba9ba4Schristos 405a1ba9ba4Schristos switch (ui.Flags) 406a1ba9ba4Schristos { 407a1ba9ba4Schristos case UNW_FLAG_EHANDLER: 408a1ba9ba4Schristos case UNW_FLAG_UHANDLER: 409a1ba9ba4Schristos case UNW_FLAG_FHANDLER: 410a1ba9ba4Schristos fprintf (file, "\tHandler: "); 411a1ba9ba4Schristos fprintf_vma (file, (ui.rva_ExceptionHandler 412a1ba9ba4Schristos + pe_data (abfd)->pe_opthdr.ImageBase)); 413a1ba9ba4Schristos fprintf (file, ".\n"); 414a1ba9ba4Schristos break; 415a1ba9ba4Schristos case UNW_FLAG_CHAININFO: 416a1ba9ba4Schristos fprintf (file, "\tChain: start: "); 417a1ba9ba4Schristos fprintf_vma (file, ui.rva_BeginAddress); 418a1ba9ba4Schristos fprintf (file, ", end: "); 419a1ba9ba4Schristos fprintf_vma (file, ui.rva_EndAddress); 420a1ba9ba4Schristos fprintf (file, "\n\t unwind data: "); 421a1ba9ba4Schristos fprintf_vma (file, ui.rva_UnwindData); 422a1ba9ba4Schristos fprintf (file, ".\n"); 423a1ba9ba4Schristos break; 424a1ba9ba4Schristos } 425a1ba9ba4Schristos 426a1ba9ba4Schristos /* Now we need end of this xdata block. */ 427a1ba9ba4Schristos addr += ui.SizeOfBlock; 428a1ba9ba4Schristos if (addr < end_addr) 429a1ba9ba4Schristos { 430a1ba9ba4Schristos unsigned int i; 431a1ba9ba4Schristos fprintf (file,"\tUser data:\n"); 432a1ba9ba4Schristos for (i = 0; addr < end_addr; addr += 1, i++) 433a1ba9ba4Schristos { 434a1ba9ba4Schristos if ((i & 15) == 0) 435a1ba9ba4Schristos fprintf (file, "\t %03x:", i); 436a1ba9ba4Schristos fprintf (file, " %02x", xdata[addr]); 437a1ba9ba4Schristos if ((i & 15) == 15) 438a1ba9ba4Schristos fprintf (file, "\n"); 439a1ba9ba4Schristos } 440a1ba9ba4Schristos if ((i & 15) != 0) 441a1ba9ba4Schristos fprintf (file, "\n"); 442a1ba9ba4Schristos } 443a1ba9ba4Schristos } 444a1ba9ba4Schristos 445a1ba9ba4Schristos /* Helper function to sort xdata. The entries of xdata are sorted to know 446a1ba9ba4Schristos the size of each entry. */ 447a1ba9ba4Schristos 448a1ba9ba4Schristos static int 449a1ba9ba4Schristos sort_xdata_arr (const void *l, const void *r) 450a1ba9ba4Schristos { 451a1ba9ba4Schristos const bfd_vma *lp = (const bfd_vma *) l; 452a1ba9ba4Schristos const bfd_vma *rp = (const bfd_vma *) r; 453a1ba9ba4Schristos 454a1ba9ba4Schristos if (*lp == *rp) 455a1ba9ba4Schristos return 0; 456a1ba9ba4Schristos return (*lp < *rp ? -1 : 1); 457a1ba9ba4Schristos } 458a1ba9ba4Schristos 459a1ba9ba4Schristos /* Display unwind tables for x86-64. */ 460a1ba9ba4Schristos 461a1ba9ba4Schristos static bfd_boolean 462a1ba9ba4Schristos pex64_bfd_print_pdata_section (bfd *abfd, void *vfile, asection *pdata_section) 463a1ba9ba4Schristos { 464a1ba9ba4Schristos FILE *file = (FILE *) vfile; 465a1ba9ba4Schristos bfd_byte *pdata = NULL; 466a1ba9ba4Schristos bfd_byte *xdata = NULL; 467a1ba9ba4Schristos asection *xdata_section = NULL; 468a1ba9ba4Schristos bfd_vma xdata_base; 469a1ba9ba4Schristos bfd_size_type i; 470a1ba9ba4Schristos bfd_size_type datasize; 471a1ba9ba4Schristos bfd_size_type stop; 472a1ba9ba4Schristos bfd_vma prev_beginaddress = (bfd_vma) -1; 473a1ba9ba4Schristos bfd_vma prev_unwinddata_rva = (bfd_vma) -1; 474a1ba9ba4Schristos bfd_vma imagebase; 475a1ba9ba4Schristos int onaline = PDATA_ROW_SIZE; 476a1ba9ba4Schristos int seen_error = 0; 477a1ba9ba4Schristos bfd_vma *xdata_arr = NULL; 478a1ba9ba4Schristos int xdata_arr_cnt; 479a1ba9ba4Schristos bfd_boolean virt_size_is_zero = FALSE; 480a1ba9ba4Schristos 481a1ba9ba4Schristos /* Sanity checks. */ 482a1ba9ba4Schristos if (pdata_section == NULL 483a1ba9ba4Schristos || coff_section_data (abfd, pdata_section) == NULL 484a1ba9ba4Schristos || pei_section_data (abfd, pdata_section) == NULL) 485a1ba9ba4Schristos return TRUE; 486a1ba9ba4Schristos 487a1ba9ba4Schristos stop = pei_section_data (abfd, pdata_section)->virt_size; 488a1ba9ba4Schristos if ((stop % onaline) != 0) 489a1ba9ba4Schristos fprintf (file, 490a1ba9ba4Schristos _("Warning: %s section size (%ld) is not a multiple of %d\n"), 491a1ba9ba4Schristos pdata_section->name, (long) stop, onaline); 492a1ba9ba4Schristos 493a1ba9ba4Schristos datasize = pdata_section->size; 494a1ba9ba4Schristos if (datasize == 0) 495a1ba9ba4Schristos { 496a1ba9ba4Schristos if (stop) 497a1ba9ba4Schristos fprintf (file, _("Warning: %s section size is zero\n"), 498a1ba9ba4Schristos pdata_section->name); 499a1ba9ba4Schristos return TRUE; 500a1ba9ba4Schristos } 501a1ba9ba4Schristos 502a1ba9ba4Schristos /* virt_size might be zero for objects. */ 503a1ba9ba4Schristos if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0) 504a1ba9ba4Schristos { 505a1ba9ba4Schristos stop = (datasize / onaline) * onaline; 506a1ba9ba4Schristos virt_size_is_zero = TRUE; 507a1ba9ba4Schristos } 508a1ba9ba4Schristos else if (datasize < stop) 509a1ba9ba4Schristos { 510a1ba9ba4Schristos fprintf (file, 511a1ba9ba4Schristos _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"), 512a1ba9ba4Schristos pdata_section->name, (unsigned long) datasize, 513a1ba9ba4Schristos (unsigned long) stop); 514a1ba9ba4Schristos /* Be sure not to read passed datasize. */ 515a1ba9ba4Schristos stop = datasize / onaline; 516a1ba9ba4Schristos } 517a1ba9ba4Schristos 518a1ba9ba4Schristos /* Display functions table. */ 519a1ba9ba4Schristos fprintf (file, 520a1ba9ba4Schristos _("\nThe Function Table (interpreted %s section contents)\n"), 521a1ba9ba4Schristos pdata_section->name); 522a1ba9ba4Schristos 523a1ba9ba4Schristos fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); 524a1ba9ba4Schristos 525a1ba9ba4Schristos if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata)) 526a1ba9ba4Schristos goto done; 527a1ba9ba4Schristos 528a1ba9ba4Schristos /* Table of xdata entries. */ 529a1ba9ba4Schristos xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1)); 530a1ba9ba4Schristos xdata_arr_cnt = 0; 531a1ba9ba4Schristos 532a1ba9ba4Schristos if (strcmp (abfd->xvec->name, "pei-x86-64") == 0) 533a1ba9ba4Schristos imagebase = pe_data (abfd)->pe_opthdr.ImageBase; 534a1ba9ba4Schristos else 535a1ba9ba4Schristos imagebase = 0; 536a1ba9ba4Schristos 537a1ba9ba4Schristos for (i = 0; i < stop; i += onaline) 538a1ba9ba4Schristos { 539a1ba9ba4Schristos struct pex64_runtime_function rf; 540a1ba9ba4Schristos 541a1ba9ba4Schristos if (i + PDATA_ROW_SIZE > stop) 542a1ba9ba4Schristos break; 543a1ba9ba4Schristos 544a1ba9ba4Schristos pex64_get_runtime_function (abfd, &rf, &pdata[i]); 545a1ba9ba4Schristos 546a1ba9ba4Schristos if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 547a1ba9ba4Schristos && rf.rva_UnwindData == 0) 548a1ba9ba4Schristos /* We are probably into the padding of the section now. */ 549a1ba9ba4Schristos break; 550a1ba9ba4Schristos fputc (' ', file); 551a1ba9ba4Schristos fprintf_vma (file, i + pdata_section->vma); 552a1ba9ba4Schristos fprintf (file, ":\t"); 553a1ba9ba4Schristos fprintf_vma (file, imagebase + rf.rva_BeginAddress); 554a1ba9ba4Schristos fprintf (file, " "); 555a1ba9ba4Schristos fprintf_vma (file, imagebase + rf.rva_EndAddress); 556a1ba9ba4Schristos fprintf (file, " "); 557a1ba9ba4Schristos fprintf_vma (file, imagebase + rf.rva_UnwindData); 558a1ba9ba4Schristos fprintf (file, "\n"); 559a1ba9ba4Schristos if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress) 560a1ba9ba4Schristos { 561a1ba9ba4Schristos seen_error = 1; 562a1ba9ba4Schristos fprintf (file, " has %s begin address as predecessor\n", 563a1ba9ba4Schristos (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same")); 564a1ba9ba4Schristos } 565a1ba9ba4Schristos prev_beginaddress = rf.rva_BeginAddress; 566a1ba9ba4Schristos /* Now we check for negative addresses. */ 567a1ba9ba4Schristos if ((prev_beginaddress & 0x80000000) != 0) 568a1ba9ba4Schristos { 569a1ba9ba4Schristos seen_error = 1; 570a1ba9ba4Schristos fprintf (file, " has negative begin address\n"); 571a1ba9ba4Schristos } 572a1ba9ba4Schristos if ((rf.rva_EndAddress & 0x80000000) != 0) 573a1ba9ba4Schristos { 574a1ba9ba4Schristos seen_error = 1; 575a1ba9ba4Schristos fprintf (file, " has negative end address\n"); 576a1ba9ba4Schristos } 577a1ba9ba4Schristos if ((rf.rva_UnwindData & 0x80000000) != 0) 578a1ba9ba4Schristos { 579a1ba9ba4Schristos seen_error = 1; 580a1ba9ba4Schristos fprintf (file, " has negative unwind address\n"); 581a1ba9ba4Schristos } 582a1ba9ba4Schristos else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) 583a1ba9ba4Schristos || virt_size_is_zero) 584a1ba9ba4Schristos xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; 585a1ba9ba4Schristos } 586a1ba9ba4Schristos 587a1ba9ba4Schristos if (seen_error) 588a1ba9ba4Schristos goto done; 589a1ba9ba4Schristos 590a1ba9ba4Schristos /* Add end of list marker. */ 591a1ba9ba4Schristos xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0); 592a1ba9ba4Schristos 593a1ba9ba4Schristos /* Sort start RVAs of xdata. */ 594a1ba9ba4Schristos if (xdata_arr_cnt > 1) 595a1ba9ba4Schristos qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma), 596a1ba9ba4Schristos sort_xdata_arr); 597a1ba9ba4Schristos 598a1ba9ba4Schristos /* Find the section containing the unwind data (.xdata). */ 599a1ba9ba4Schristos xdata_base = xdata_arr[0]; 600a1ba9ba4Schristos /* For sections with long names, first look for the same 601a1ba9ba4Schristos section name, replacing .pdata by .xdata prefix. */ 602a1ba9ba4Schristos if (strcmp (pdata_section->name, ".pdata") != 0) 603a1ba9ba4Schristos { 604a1ba9ba4Schristos size_t len = strlen (pdata_section->name); 605*b2396a7bSchristos char *xdata_name = xmalloc (len + 1); 606a1ba9ba4Schristos 607a1ba9ba4Schristos xdata_name = memcpy (xdata_name, pdata_section->name, len + 1); 608a1ba9ba4Schristos /* Transform .pdata prefix into .xdata prefix. */ 609a1ba9ba4Schristos if (len > 1) 610a1ba9ba4Schristos xdata_name [1] = 'x'; 611a1ba9ba4Schristos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, 612a1ba9ba4Schristos xdata_name); 613*b2396a7bSchristos free (xdata_name); 614a1ba9ba4Schristos } 615a1ba9ba4Schristos /* Second, try the .xdata section itself. */ 616a1ba9ba4Schristos if (!xdata_section) 617a1ba9ba4Schristos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata"); 618a1ba9ba4Schristos /* Otherwise, if xdata_base is non zero, search also inside 619a1ba9ba4Schristos other standard sections. */ 620a1ba9ba4Schristos if (!xdata_section && xdata_base) 621a1ba9ba4Schristos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata"); 622a1ba9ba4Schristos if (!xdata_section && xdata_base) 623a1ba9ba4Schristos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data"); 624a1ba9ba4Schristos if (!xdata_section && xdata_base) 625a1ba9ba4Schristos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata"); 626a1ba9ba4Schristos if (!xdata_section && xdata_base) 627a1ba9ba4Schristos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text"); 628a1ba9ba4Schristos /* Transfer xdata section into xdata array. */ 629a1ba9ba4Schristos if (!xdata_section 630a1ba9ba4Schristos || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata)) 631a1ba9ba4Schristos goto done; 632a1ba9ba4Schristos 633a1ba9ba4Schristos /* Avoid "also used "... ouput for single unwind info 634a1ba9ba4Schristos in object file. */ 635a1ba9ba4Schristos prev_unwinddata_rva = (bfd_vma) -1; 636a1ba9ba4Schristos 637a1ba9ba4Schristos /* Do dump of pdata related xdata. */ 638a1ba9ba4Schristos for (i = 0; i < stop; i += onaline) 639a1ba9ba4Schristos { 640a1ba9ba4Schristos struct pex64_runtime_function rf; 641a1ba9ba4Schristos 642a1ba9ba4Schristos if (i + PDATA_ROW_SIZE > stop) 643a1ba9ba4Schristos break; 644a1ba9ba4Schristos 645a1ba9ba4Schristos pex64_get_runtime_function (abfd, &rf, &pdata[i]); 646a1ba9ba4Schristos 647a1ba9ba4Schristos if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 648a1ba9ba4Schristos && rf.rva_UnwindData == 0) 649a1ba9ba4Schristos /* We are probably into the padding of the section now. */ 650a1ba9ba4Schristos break; 651a1ba9ba4Schristos if (i == 0) 652a1ba9ba4Schristos fprintf (file, _("\nDump of %s\n"), xdata_section->name); 653a1ba9ba4Schristos 654a1ba9ba4Schristos fputc (' ', file); 655a1ba9ba4Schristos fprintf_vma (file, rf.rva_UnwindData + imagebase); 656a1ba9ba4Schristos 657a1ba9ba4Schristos if (prev_unwinddata_rva == rf.rva_UnwindData) 658a1ba9ba4Schristos { 659a1ba9ba4Schristos /* Do not dump again the xdata for the same entry. */ 660a1ba9ba4Schristos fprintf (file, " also used for function at "); 661a1ba9ba4Schristos fprintf_vma (file, rf.rva_BeginAddress + imagebase); 662a1ba9ba4Schristos fputc ('\n', file); 663a1ba9ba4Schristos continue; 664a1ba9ba4Schristos } 665a1ba9ba4Schristos else 666a1ba9ba4Schristos prev_unwinddata_rva = rf.rva_UnwindData; 667a1ba9ba4Schristos 668a1ba9ba4Schristos fprintf (file, " (rva: %08x): ", 669a1ba9ba4Schristos (unsigned int) rf.rva_UnwindData); 670a1ba9ba4Schristos fprintf_vma (file, rf.rva_BeginAddress + imagebase); 671a1ba9ba4Schristos fprintf (file, " - "); 672a1ba9ba4Schristos fprintf_vma (file, rf.rva_EndAddress + imagebase); 673a1ba9ba4Schristos fputc ('\n', file); 674a1ba9ba4Schristos 675a1ba9ba4Schristos if (rf.rva_UnwindData != 0 || virt_size_is_zero) 676a1ba9ba4Schristos { 677a1ba9ba4Schristos if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) 678a1ba9ba4Schristos { 679a1ba9ba4Schristos bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf); 680a1ba9ba4Schristos bfd_vma pdata_vma = bfd_get_section_vma (abfd, pdata_section); 681a1ba9ba4Schristos struct pex64_runtime_function arf; 682a1ba9ba4Schristos 683a1ba9ba4Schristos fprintf (file, "\t shares information with "); 684a1ba9ba4Schristos altent += imagebase; 685a1ba9ba4Schristos 686a1ba9ba4Schristos if (altent >= pdata_vma 687a1ba9ba4Schristos && (altent + PDATA_ROW_SIZE <= pdata_vma 688a1ba9ba4Schristos + pei_section_data (abfd, pdata_section)->virt_size)) 689a1ba9ba4Schristos { 690a1ba9ba4Schristos pex64_get_runtime_function 691a1ba9ba4Schristos (abfd, &arf, &pdata[altent - pdata_vma]); 692a1ba9ba4Schristos fprintf (file, "pdata element at 0x"); 693a1ba9ba4Schristos fprintf_vma (file, arf.rva_UnwindData); 694a1ba9ba4Schristos } 695a1ba9ba4Schristos else 696a1ba9ba4Schristos fprintf (file, "unknown pdata element"); 697a1ba9ba4Schristos fprintf (file, ".\n"); 698a1ba9ba4Schristos } 699a1ba9ba4Schristos else 700a1ba9ba4Schristos { 701a1ba9ba4Schristos bfd_vma *p; 702a1ba9ba4Schristos 703a1ba9ba4Schristos /* Search for the current entry in the sorted array. */ 704a1ba9ba4Schristos p = (bfd_vma *) 705a1ba9ba4Schristos bsearch (&rf.rva_UnwindData, xdata_arr, 706a1ba9ba4Schristos (size_t) xdata_arr_cnt, sizeof (bfd_vma), 707a1ba9ba4Schristos sort_xdata_arr); 708a1ba9ba4Schristos 709a1ba9ba4Schristos /* Advance to the next pointer into the xdata section. We may 710a1ba9ba4Schristos have shared xdata entries, which will result in a string of 711a1ba9ba4Schristos identical pointers in the array; advance past all of them. */ 712a1ba9ba4Schristos while (p[0] <= rf.rva_UnwindData) 713a1ba9ba4Schristos ++p; 714a1ba9ba4Schristos 715a1ba9ba4Schristos if (p[0] == ~((bfd_vma) 0)) 716a1ba9ba4Schristos p = NULL; 717a1ba9ba4Schristos 718a1ba9ba4Schristos pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf); 719a1ba9ba4Schristos } 720a1ba9ba4Schristos } 721a1ba9ba4Schristos } 722a1ba9ba4Schristos 723a1ba9ba4Schristos done: 724a1ba9ba4Schristos free (pdata); 725a1ba9ba4Schristos free (xdata_arr); 726a1ba9ba4Schristos free (xdata); 727a1ba9ba4Schristos 728a1ba9ba4Schristos return TRUE; 729a1ba9ba4Schristos } 730a1ba9ba4Schristos 731a1ba9ba4Schristos /* Static counter of number of found pdata sections. */ 732a1ba9ba4Schristos static bfd_boolean pdata_count; 733a1ba9ba4Schristos 734a1ba9ba4Schristos /* Functionn prototype. */ 735a1ba9ba4Schristos bfd_boolean pex64_bfd_print_pdata (bfd *, void *); 736a1ba9ba4Schristos 737a1ba9ba4Schristos /* Helper function for bfd_map_over_section. */ 738a1ba9ba4Schristos static void 739a1ba9ba4Schristos pex64_print_all_pdata_sections (bfd *abfd, asection *pdata, void *obj) 740a1ba9ba4Schristos { 741a1ba9ba4Schristos if (CONST_STRNEQ (pdata->name, ".pdata")) 742a1ba9ba4Schristos { 743a1ba9ba4Schristos if (pex64_bfd_print_pdata_section (abfd, obj, pdata)) 744a1ba9ba4Schristos pdata_count++; 745a1ba9ba4Schristos } 746a1ba9ba4Schristos } 747a1ba9ba4Schristos 748a1ba9ba4Schristos bfd_boolean 749a1ba9ba4Schristos pex64_bfd_print_pdata (bfd *abfd, void *vfile) 750a1ba9ba4Schristos { 751a1ba9ba4Schristos asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata"); 752a1ba9ba4Schristos 753a1ba9ba4Schristos if (pdata_section) 754a1ba9ba4Schristos return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section); 755a1ba9ba4Schristos 756a1ba9ba4Schristos pdata_count = 0; 757a1ba9ba4Schristos bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, vfile); 758a1ba9ba4Schristos return (pdata_count > 0); 759a1ba9ba4Schristos } 760a1ba9ba4Schristos 761a1ba9ba4Schristos #define bfd_pe_print_pdata pex64_bfd_print_pdata 762a1ba9ba4Schristos #define bfd_coff_std_swap_table bfd_coff_pei_swap_table 763a1ba9ba4Schristos 764a1ba9ba4Schristos #include "coff-x86_64.c" 765