Changeset 83081 in vbox for trunk/src/VBox/Debugger
- Timestamp:
- Feb 15, 2020 2:22:58 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGCDumpImage.cpp
r82968 r83081 40 40 #include <iprt/formats/elf64.h> 41 41 #include <iprt/formats/codeview.h> 42 #include <iprt/formats/mach-o.h> 42 43 43 44 #include "DBGCInternal.h" … … 79 80 80 81 82 /** Helper for translating flags. */ 83 typedef struct 84 { 85 uint32_t fFlag; 86 const char *pszNm; 87 } DBGCDUMPFLAGENTRY; 88 #define FLENT(a_Define) { a_Define, #a_Define } 89 90 81 91 /********************************************************************************************************************************* 82 92 * Internal Functions * … … 84 94 extern FNDBGCCMD dbgcCmdDumpImage; /* See DBGCCommands.cpp. */ 85 95 96 97 /** Stringifies a 32-bit flag value. */ 98 static void dbgcDumpImageFlags32(PDBGCCMDHLP pCmdHlp, uint32_t fFlags, DBGCDUMPFLAGENTRY const *paEntries, size_t cEntries) 99 { 100 for (size_t i = 0; i < cEntries; i++) 101 if (fFlags & paEntries[i].fFlag) 102 DBGCCmdHlpPrintf(pCmdHlp, " %s", paEntries[i].pszNm); 103 } 104 105 106 /********************************************************************************************************************************* 107 * PE * 108 *********************************************************************************************************************************/ 86 109 87 110 static const char *dbgcPeMachineName(uint16_t uMachine) … … 406 429 407 430 431 /********************************************************************************************************************************* 432 * ELF * 433 *********************************************************************************************************************************/ 434 408 435 static int dbgcDumpImageElf(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pImageBase) 409 436 { … … 411 438 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: ELF image dumping not implemented yet.\n", pImageBase); 412 439 return VINF_SUCCESS; 440 } 441 442 443 /********************************************************************************************************************************* 444 * Mach-O * 445 *********************************************************************************************************************************/ 446 447 static const char *dbgcMachoFileType(uint32_t uType) 448 { 449 switch (uType) 450 { 451 case MH_OBJECT: return "MH_OBJECT"; 452 case MH_EXECUTE: return "MH_EXECUTE"; 453 case MH_FVMLIB: return "MH_FVMLIB"; 454 case MH_CORE: return "MH_CORE"; 455 case MH_PRELOAD: return "MH_PRELOAD"; 456 case MH_DYLIB: return "MH_DYLIB"; 457 case MH_DYLINKER: return "MH_DYLINKER"; 458 case MH_BUNDLE: return "MH_BUNDLE"; 459 case MH_DYLIB_STUB: return "MH_DYLIB_STUB"; 460 case MH_DSYM: return "MH_DSYM"; 461 case MH_KEXT_BUNDLE: return "MH_KEXT_BUNDLE"; 462 } 463 return "??"; 464 } 465 466 467 static const char *dbgcMachoCpuType(uint32_t uType, uint32_t uSubType) 468 { 469 switch (uType) 470 { 471 case CPU_TYPE_ANY: return "CPU_TYPE_ANY"; 472 case CPU_TYPE_VAX: return "VAX"; 473 case CPU_TYPE_MC680x0: return "MC680x0"; 474 case CPU_TYPE_X86: return "X86"; 475 case CPU_TYPE_X86_64: 476 switch (uSubType) 477 { 478 case CPU_SUBTYPE_X86_64_ALL: return "X86_64/ALL64"; 479 } 480 return "X86_64"; 481 case CPU_TYPE_MC98000: return "MC98000"; 482 case CPU_TYPE_HPPA: return "HPPA"; 483 case CPU_TYPE_MC88000: return "MC88000"; 484 case CPU_TYPE_SPARC: return "SPARC"; 485 case CPU_TYPE_I860: return "I860"; 486 case CPU_TYPE_POWERPC: return "POWERPC"; 487 case CPU_TYPE_POWERPC64: return "POWERPC64"; 488 489 } 490 return "??"; 491 } 492 493 494 static const char *dbgcMachoLoadCommand(uint32_t uCmd) 495 { 496 switch (uCmd) 497 { 498 RT_CASE_RET_STR(LC_SEGMENT_32); 499 RT_CASE_RET_STR(LC_SYMTAB); 500 RT_CASE_RET_STR(LC_SYMSEG); 501 RT_CASE_RET_STR(LC_THREAD); 502 RT_CASE_RET_STR(LC_UNIXTHREAD); 503 RT_CASE_RET_STR(LC_LOADFVMLIB); 504 RT_CASE_RET_STR(LC_IDFVMLIB); 505 RT_CASE_RET_STR(LC_IDENT); 506 RT_CASE_RET_STR(LC_FVMFILE); 507 RT_CASE_RET_STR(LC_PREPAGE); 508 RT_CASE_RET_STR(LC_DYSYMTAB); 509 RT_CASE_RET_STR(LC_LOAD_DYLIB); 510 RT_CASE_RET_STR(LC_ID_DYLIB); 511 RT_CASE_RET_STR(LC_LOAD_DYLINKER); 512 RT_CASE_RET_STR(LC_ID_DYLINKER); 513 RT_CASE_RET_STR(LC_PREBOUND_DYLIB); 514 RT_CASE_RET_STR(LC_ROUTINES); 515 RT_CASE_RET_STR(LC_SUB_FRAMEWORK); 516 RT_CASE_RET_STR(LC_SUB_UMBRELLA); 517 RT_CASE_RET_STR(LC_SUB_CLIENT); 518 RT_CASE_RET_STR(LC_SUB_LIBRARY); 519 RT_CASE_RET_STR(LC_TWOLEVEL_HINTS); 520 RT_CASE_RET_STR(LC_PREBIND_CKSUM); 521 RT_CASE_RET_STR(LC_LOAD_WEAK_DYLIB); 522 RT_CASE_RET_STR(LC_SEGMENT_64); 523 RT_CASE_RET_STR(LC_ROUTINES_64); 524 RT_CASE_RET_STR(LC_UUID); 525 RT_CASE_RET_STR(LC_RPATH); 526 RT_CASE_RET_STR(LC_CODE_SIGNATURE); 527 RT_CASE_RET_STR(LC_SEGMENT_SPLIT_INFO); 528 RT_CASE_RET_STR(LC_REEXPORT_DYLIB); 529 RT_CASE_RET_STR(LC_LAZY_LOAD_DYLIB); 530 RT_CASE_RET_STR(LC_ENCRYPTION_INFO); 531 RT_CASE_RET_STR(LC_DYLD_INFO); 532 RT_CASE_RET_STR(LC_DYLD_INFO_ONLY); 533 RT_CASE_RET_STR(LC_LOAD_UPWARD_DYLIB); 534 RT_CASE_RET_STR(LC_VERSION_MIN_MACOSX); 535 RT_CASE_RET_STR(LC_VERSION_MIN_IPHONEOS); 536 RT_CASE_RET_STR(LC_FUNCTION_STARTS); 537 RT_CASE_RET_STR(LC_DYLD_ENVIRONMENT); 538 RT_CASE_RET_STR(LC_MAIN); 539 RT_CASE_RET_STR(LC_DATA_IN_CODE); 540 RT_CASE_RET_STR(LC_SOURCE_VERSION); 541 RT_CASE_RET_STR(LC_DYLIB_CODE_SIGN_DRS); 542 RT_CASE_RET_STR(LC_ENCRYPTION_INFO_64); 543 RT_CASE_RET_STR(LC_LINKER_OPTION); 544 RT_CASE_RET_STR(LC_LINKER_OPTIMIZATION_HINT); 545 RT_CASE_RET_STR(LC_VERSION_MIN_TVOS); 546 RT_CASE_RET_STR(LC_VERSION_MIN_WATCHOS); 547 RT_CASE_RET_STR(LC_NOTE); 548 RT_CASE_RET_STR(LC_BUILD_VERSION); 549 } 550 return "??"; 551 } 552 553 554 static const char *dbgcMachoProt(uint32_t fProt) 555 { 556 switch (fProt) 557 { 558 case VM_PROT_NONE: return "---"; 559 case VM_PROT_READ: return "r--"; 560 case VM_PROT_READ | VM_PROT_WRITE: return "rw-"; 561 case VM_PROT_READ | VM_PROT_EXECUTE: return "r-x"; 562 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: return "rwx"; 563 case VM_PROT_WRITE: return "-w-"; 564 case VM_PROT_WRITE | VM_PROT_EXECUTE: return "-wx"; 565 case VM_PROT_EXECUTE: return "-w-"; 566 } 567 return "???"; 568 } 569 570 571 static int dbgcDumpImageMachO(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pImageBase, mach_header_64_t const *pHdr) 572 { 573 #define ENTRY(a_Define) { a_Define, #a_Define } 574 RT_NOREF_PV(pCmd); 575 576 /* 577 * Header: 578 */ 579 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: Mach-O image (%s bit) - %s (%u) - %s (%#x / %#x)\n", 580 pImageBase, pHdr->magic == IMAGE_MACHO64_SIGNATURE ? "64" : "32", 581 dbgcMachoFileType(pHdr->filetype), pHdr->filetype, 582 dbgcMachoCpuType(pHdr->cputype, pHdr->cpusubtype), pHdr->cputype, pHdr->cpusubtype); 583 584 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: Flags: %#x", pImageBase, pHdr->flags); 585 static DBGCDUMPFLAGENTRY const s_aHdrFlags[] = 586 { 587 FLENT(MH_NOUNDEFS), FLENT(MH_INCRLINK), 588 FLENT(MH_DYLDLINK), FLENT(MH_BINDATLOAD), 589 FLENT(MH_PREBOUND), FLENT(MH_SPLIT_SEGS), 590 FLENT(MH_LAZY_INIT), FLENT(MH_TWOLEVEL), 591 FLENT(MH_FORCE_FLAT), FLENT(MH_NOMULTIDEFS), 592 FLENT(MH_NOFIXPREBINDING), FLENT(MH_PREBINDABLE), 593 FLENT(MH_ALLMODSBOUND), FLENT(MH_SUBSECTIONS_VIA_SYMBOLS), 594 FLENT(MH_CANONICAL), FLENT(MH_WEAK_DEFINES), 595 FLENT(MH_BINDS_TO_WEAK), FLENT(MH_ALLOW_STACK_EXECUTION), 596 FLENT(MH_ROOT_SAFE), FLENT(MH_SETUID_SAFE), 597 FLENT(MH_NO_REEXPORTED_DYLIBS), FLENT(MH_PIE), 598 FLENT(MH_DEAD_STRIPPABLE_DYLIB), FLENT(MH_HAS_TLV_DESCRIPTORS), 599 FLENT(MH_NO_HEAP_EXECUTION), 600 }; 601 dbgcDumpImageFlags32(pCmdHlp, pHdr->flags, s_aHdrFlags, RT_ELEMENTS(s_aHdrFlags)); 602 DBGCCmdHlpPrintf(pCmdHlp, "\n"); 603 if (pHdr->reserved != 0 && pHdr->magic == IMAGE_MACHO64_SIGNATURE) 604 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: Reserved header field: %#x\n", pImageBase, pHdr->reserved); 605 606 /* 607 * And now the load commands. 608 */ 609 const uint32_t cCmds = pHdr->ncmds; 610 const uint32_t cbCmds = pHdr->sizeofcmds; 611 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: %u load commands covering %#x bytes:\n", pImageBase, cCmds, cbCmds); 612 if (cbCmds > _16M) 613 return DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_OUT_OF_RANGE, 614 "%Dv: Commands too big: %#x bytes, max 16MiB\n", pImageBase, cbCmds); 615 616 /* Calc address of the first command: */ 617 const uint32_t cbHdr = pHdr->magic == IMAGE_MACHO64_SIGNATURE ? sizeof(mach_header_64_t) : sizeof(mach_header_32_t); 618 DBGCVAR Addr; 619 int rc = DBGCCmdHlpEval(pCmdHlp, &Addr, "%DV + %#RX32", pImageBase, cbHdr); 620 AssertRCReturn(rc, rc); 621 622 /* Read them into a temp buffer: */ 623 uint8_t *pbCmds = (uint8_t *)RTMemTmpAllocZ(cbCmds); 624 if (!pbCmds) 625 return VERR_NO_TMP_MEMORY; 626 627 rc = DBGCCmdHlpMemRead(pCmdHlp, pbCmds, cbCmds, &Addr, NULL); 628 if (RT_SUCCESS(rc)) 629 { 630 static const DBGCDUMPFLAGENTRY s_aSegFlags[] = 631 { FLENT(SG_HIGHVM), FLENT(SG_FVMLIB), FLENT(SG_NORELOC), FLENT(SG_PROTECTED_VERSION_1), }; 632 633 /* 634 * Iterate the commands. 635 */ 636 uint32_t offCmd = 0; 637 for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++) 638 { 639 load_command_t const *pCurCmd = (load_command_t const *)&pbCmds[offCmd]; 640 const uint32_t cbCurCmd = offCmd + sizeof(*pCurCmd) <= cbCmds ? pCurCmd->cmdsize : sizeof(*pCurCmd); 641 if (offCmd + cbCurCmd > cbCmds) 642 { 643 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_OUT_OF_RANGE, 644 "%Dv: Load command #%u (offset %#x + %#x) is out of bounds! cmdsize=%u (%#x) cmd=%u\n", 645 pImageBase, iCmd, offCmd, cbHdr, cbCurCmd, cbCurCmd, 646 offCmd + RT_UOFFSET_AFTER(load_command_t, cmd) <= cbCmds ? pCurCmd->cmd : UINT32_MAX); 647 break; 648 } 649 650 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: Load command #%u (offset %#x + %#x): %s (%u) LB %u\n", 651 pImageBase, iCmd, offCmd, cbHdr, dbgcMachoLoadCommand(pCurCmd->cmd), pCurCmd->cmd, cbCurCmd); 652 switch (pCurCmd->cmd) 653 { 654 case LC_SEGMENT_64: 655 if (cbCurCmd < sizeof(segment_command_64_t)) 656 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_LDRMACHO_BAD_LOAD_COMMAND, 657 "%Dv: LC_SEGMENT64 is too short!\n", pImageBase); 658 else 659 { 660 segment_command_64_t const *pSeg = (segment_command_64_t const *)pCurCmd; 661 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: vmaddr: %016RX64 LB %08RX64 prot: %s(%x) maxprot: %s(%x) name: %.16s\n", 662 pImageBase, pSeg->vmaddr, pSeg->vmsize, dbgcMachoProt(pSeg->initprot), pSeg->initprot, 663 dbgcMachoProt(pSeg->maxprot), pSeg->maxprot, pSeg->segname); 664 DBGCCmdHlpPrintf(pCmdHlp, "%Dv: file: %016RX64 LB %08RX64 sections: %2u flags: %#x", 665 pImageBase, pSeg->fileoff, pSeg->filesize, pSeg->nsects, pSeg->flags); 666 dbgcDumpImageFlags32(pCmdHlp, pSeg->flags, s_aSegFlags, RT_ELEMENTS(s_aSegFlags)); 667 DBGCCmdHlpPrintf(pCmdHlp, "\n"); 668 if ( pSeg->nsects > _64K 669 || pSeg->nsects * sizeof(section_64_t) + sizeof(pSeg) > cbCurCmd) 670 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, VERR_LDRMACHO_BAD_LOAD_COMMAND, 671 "%Dv: LC_SEGMENT64 is too short for all the sections!\n", pImageBase); 672 else 673 { 674 section_64_t const *paSec = (section_64_t const *)(pSeg + 1); 675 for (uint32_t iSec = 0; iSec < pSeg->nsects; iSec++) 676 { 677 DBGCCmdHlpPrintf(pCmdHlp, 678 "%Dv: Section #%u: %016RX64 LB %08RX64 align: 2**%-2u name: %.16s", 679 pImageBase, iSec, paSec[iSec].addr, paSec[iSec].size, paSec[iSec].align, 680 paSec[iSec].sectname); 681 if (strncmp(pSeg->segname, paSec[iSec].segname, sizeof(pSeg->segname))) 682 DBGCCmdHlpPrintf(pCmdHlp, "(in %.16s)", paSec[iSec].segname); 683 DBGCCmdHlpPrintf(pCmdHlp, "\n"); 684 685 /// @todo Good night! 686 /// uint32_t offset; 687 /// uint32_t reloff; 688 /// uint32_t nreloc; 689 /// uint32_t flags; 690 /// /** For S_LAZY_SYMBOL_POINTERS, S_NON_LAZY_SYMBOL_POINTERS and S_SYMBOL_STUBS 691 /// * this is the index into the indirect symbol table. */ 692 /// uint32_t reserved1; 693 /// uint32_t reserved2; 694 /// uint32_t reserved3; 695 /// 696 } 697 } 698 } 699 break; 700 } 701 702 /* Advance: */ 703 offCmd += cbCurCmd; 704 } 705 } 706 else 707 rc = DBGCCmdHlpFailRc(pCmdHlp, pCmd, rc, "%Dv: Error reading load commands %Dv LB %#x\n", 708 pImageBase, &Addr, cbCmds); 709 RTMemTmpFree(pbCmds); 710 return rc; 711 #undef ENTRY 413 712 } 414 713 … … 431 730 IMAGE_FILE_HEADER FileHdr; 432 731 } Nt; 732 mach_header_64_t MachO64; 433 733 } uBuf; 434 734 DBGCVAR const ImageBase = paArgs[iArg]; … … 476 776 rc = dbgcDumpImageElf(pCmd, pCmdHlp, &ImageBase); 477 777 /* 778 * Mach-O. 779 */ 780 else if ( uBuf.MachO64.magic == IMAGE_MACHO64_SIGNATURE 781 || uBuf.MachO64.magic == IMAGE_MACHO32_SIGNATURE ) 782 rc = dbgcDumpImageMachO(pCmd, pCmdHlp, &ImageBase, &uBuf.MachO64); 783 /* 478 784 * Dunno. 479 785 */
Note:
See TracChangeset
for help on using the changeset viewer.