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