VirtualBox

Changeset 83081 in vbox for trunk/src/VBox/Debugger


Ignore:
Timestamp:
Feb 15, 2020 2:22:58 AM (5 years ago)
Author:
vboxsync
Message:

DBGC/dumpimage: Started on a Mach-O dumper.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGCDumpImage.cpp

    r82968 r83081  
    4040#include <iprt/formats/elf64.h>
    4141#include <iprt/formats/codeview.h>
     42#include <iprt/formats/mach-o.h>
    4243
    4344#include "DBGCInternal.h"
     
    7980
    8081
     82/** Helper for translating flags. */
     83typedef struct
     84{
     85    uint32_t        fFlag;
     86    const char     *pszNm;
     87} DBGCDUMPFLAGENTRY;
     88#define FLENT(a_Define) { a_Define, #a_Define }
     89
     90
    8191/*********************************************************************************************************************************
    8292*   Internal Functions                                                                                                           *
     
    8494extern FNDBGCCMD dbgcCmdDumpImage; /* See DBGCCommands.cpp. */
    8595
     96
     97/** Stringifies a 32-bit flag value. */
     98static 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*********************************************************************************************************************************/
    86109
    87110static const char *dbgcPeMachineName(uint16_t uMachine)
     
    406429
    407430
     431/*********************************************************************************************************************************
     432*   ELF                                                                                                                          *
     433*********************************************************************************************************************************/
     434
    408435static int dbgcDumpImageElf(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PCDBGCVAR pImageBase)
    409436{
     
    411438    DBGCCmdHlpPrintf(pCmdHlp, "%Dv: ELF image dumping not implemented yet.\n", pImageBase);
    412439    return VINF_SUCCESS;
     440}
     441
     442
     443/*********************************************************************************************************************************
     444*   Mach-O                                                                                                                       *
     445*********************************************************************************************************************************/
     446
     447static 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
     467static 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
     494static 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
     554static 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
     571static 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
    413712}
    414713
     
    431730                IMAGE_FILE_HEADER   FileHdr;
    432731            } Nt;
     732            mach_header_64_t    MachO64;
    433733        } uBuf;
    434734        DBGCVAR const ImageBase = paArgs[iArg];
     
    476776                rc = dbgcDumpImageElf(pCmd, pCmdHlp, &ImageBase);
    477777            /*
     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            /*
    478784             * Dunno.
    479785             */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette