VirtualBox

vbox的更動 49044 路徑 trunk/src/VBox/Debugger


忽略:
時間撮記:
2013-10-11 上午01:06:28 (11 年 以前)
作者:
vboxsync
訊息:

Darwin guest OS digger hacking in progress. Adding symbol cache util to iprt and started on the Mach-O code that'll make use of it (RTDbgModCreateFromMachOImage++). Updates kStuff from 53 to 55 for UUID query and 64-bit kext loading.

位置:
trunk/src/VBox/Debugger
檔案:
修改 3 筆資料
複製 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Debugger/DBGPlugInDarwin.cpp

    r48854 r49044  
    11/* $Id$ */
    22/** @file
    3  * DBGPlugInLinux - Debugger and Guest OS Digger Plugin For Linux.
     3 * DBGPlugInDarwin - Debugger and Guest OS Digger Plugin For Darwin / OS X.
    44 */
    55
     
    2222#define LOG_GROUP LOG_GROUP_DBGF ///@todo add new log group.
    2323#include "DBGPlugIns.h"
    24 #include "DBGPlugInCommonELF.h"
    2524#include <VBox/vmm/dbgf.h>
    2625#include <iprt/string.h>
    2726#include <iprt/mem.h>
    2827#include <iprt/stream.h>
     28#include <iprt/uuid.h>
    2929#include <iprt/ctype.h>
     30#include <iprt/formats/mach-o.h>
    3031
    3132
     
    3435*******************************************************************************/
    3536
    36 /** @name InternalLinux structures
     37/** @name Internal Darwin structures
    3738 * @{ */
    3839
     
    4445 * Linux guest OS digger instance data.
    4546 */
    46 typedef struct DBGDIGGERLINUX
     47typedef struct DBGDIGGERDARWIN
    4748{
    4849    /** Whether the information is valid or not.
     
    5051    bool fValid;
    5152
    52     /** The address of the linux banner.
     53    /** The address of an kernel version string (there are several).
    5354     * This is set during probing. */
    54     DBGFADDRESS AddrLinuxBanner;
     55    DBGFADDRESS AddrKernelVersion;
    5556    /** Kernel base address.
    5657     * This is set during probing. */
    57     DBGFADDRESS AddrKernelBase;
    58 } DBGDIGGERLINUX;
     58    DBGFADDRESS AddrKernel;
     59} DBGDIGGERDARWIN;
    5960/** Pointer to the linux guest OS digger instance data. */
    60 typedef DBGDIGGERLINUX *PDBGDIGGERLINUX;
     61typedef DBGDIGGERDARWIN *PDBGDIGGERDARWIN;
    6162
    6263
     
    6566*******************************************************************************/
    6667/** Validates a 32-bit linux kernel address */
    67 #define LNX32_VALID_ADDRESS(Addr)       ((Addr) > UINT32_C(0x80000000) && (Addr) < UINT32_C(0xfffff000))
     68#define DARWIN32_VALID_ADDRESS(Addr)    ((Addr) > UINT32_C(0x80000000) && (Addr) < UINT32_C(0xfffff000))
    6869
    6970/** The max kernel size. */
    70 #define LNX_MAX_KERNEL_SIZE         0x0f000000
     71#define DARWIN_MAX_KERNEL_SIZE          0x0f000000
     72
     73/** AppleOsX on little endian ASCII systems. */
     74#define DIG_DARWIN_MOD_TAG              UINT64_C(0x58734f656c707041)
    7175
    7276
     
    7478*   Internal Functions                                                         *
    7579*******************************************************************************/
    76 static DECLCALLBACK(int)  dbgDiggerLinuxInit(PUVM pUVM, void *pvData);
     80static DECLCALLBACK(int)  dbgDiggerDarwinInit(PUVM pUVM, void *pvData);
    7781
    7882
     
    9296 * @copydoc DBGFOSREG::pfnQueryInterface
    9397 */
    94 static DECLCALLBACK(void *) dbgDiggerLinuxQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
     98static DECLCALLBACK(void *) dbgDiggerDarwinQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
    9599{
    96100    return NULL;
     
    101105 * @copydoc DBGFOSREG::pfnQueryVersion
    102106 */
    103 static DECLCALLBACK(int)  dbgDiggerLinuxQueryVersion(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion)
    104 {
    105     PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
     107static DECLCALLBACK(int)  dbgDiggerDarwinQueryVersion(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion)
     108{
     109    PDBGDIGGERDARWIN pThis = (PDBGDIGGERDARWIN)pvData;
    106110    Assert(pThis->fValid);
    107111
     
    109113     * It's all in the linux banner.
    110114     */
    111     int rc = DBGFR3MemReadString(pUVM, 0, &pThis->AddrLinuxBanner, pszVersion, cchVersion);
     115    int rc = DBGFR3MemReadString(pUVM, 0, &pThis->AddrKernelVersion, pszVersion, cchVersion);
    112116    if (RT_SUCCESS(rc))
    113117    {
     
    129133 * @copydoc DBGFOSREG::pfnTerm
    130134 */
    131 static DECLCALLBACK(void)  dbgDiggerLinuxTerm(PUVM pUVM, void *pvData)
    132 {
    133     PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
    134     Assert(pThis->fValid);
     135static DECLCALLBACK(void)  dbgDiggerDarwinTerm(PUVM pUVM, void *pvData)
     136{
     137    PDBGDIGGERDARWIN pThis = (PDBGDIGGERDARWIN)pvData;
    135138
    136139    pThis->fValid = false;
     
    141144 * @copydoc DBGFOSREG::pfnRefresh
    142145 */
    143 static DECLCALLBACK(int)  dbgDiggerLinuxRefresh(PUVM pUVM, void *pvData)
    144 {
    145     PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
     146static DECLCALLBACK(int)  dbgDiggerDarwinRefresh(PUVM pUVM, void *pvData)
     147{
     148    PDBGDIGGERDARWIN pThis = (PDBGDIGGERDARWIN)pvData;
    146149    NOREF(pThis);
    147150    Assert(pThis->fValid);
     
    150153     * For now we'll flush and reload everything.
    151154     */
    152     dbgDiggerLinuxTerm(pUVM, pvData);
    153     return dbgDiggerLinuxInit(pUVM, pvData);
    154 }
    155 
     155    dbgDiggerDarwinTerm(pUVM, pvData);
     156    return dbgDiggerDarwinInit(pUVM, pvData);
     157}
     158
     159
     160/**
     161 * Helper function that validates a segment (or section) name.
     162 *
     163 * @returns true if valid, false if not.
     164 * @param   pszName             The name string.
     165 * @param   cbName              The size of the string, including terminator.
     166 */
     167static bool dbgDiggerDarwinIsValidSegOrSectName(const char *pszName, size_t cbName)
     168{
     169    /* ascii chars */
     170    char ch;
     171    size_t off = 0;
     172    while (off < cbName && (ch = pszName[off]))
     173    {
     174        if (RT_C_IS_CNTRL(ch) || ch > 127)
     175            return false;
     176        off++;
     177    }
     178
     179    /* Not empty nor 100% full. */
     180    if (off == 0 || off == cbName)
     181        return false;
     182
     183    /* remainder should be zeros. */
     184    while (off < cbName)
     185    {
     186        if (pszName[off])
     187            return false;
     188        off++;
     189    }
     190
     191    return true;
     192}
     193
     194
     195static int dbgDiggerDarwinAddModule(PDBGDIGGERDARWIN pThis, PUVM pUVM, uint64_t uModAddr, const char *pszName)
     196{
     197    union
     198    {
     199        uint8_t             ab[2 * X86_PAGE_4K_SIZE];
     200        mach_header_64_t    Hdr64;
     201        mach_header_32_t    Hdr32;
     202    } uBuf;
     203
     204    /* Read the first page of the image. */
     205    DBGFADDRESS ModAddr;
     206    int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &ModAddr, uModAddr), uBuf.ab, X86_PAGE_4K_SIZE);
     207    if (RT_FAILURE(rc))
     208        return rc;
     209
     210    /* Validate the header. */
     211    AssertCompileMembersSameSizeAndOffset(mach_header_64_t, magic,   mach_header_32_t, magic);
     212    if (   uBuf.Hdr64.magic != IMAGE_MACHO64_SIGNATURE
     213        && uBuf.Hdr32.magic != IMAGE_MACHO32_SIGNATURE)
     214        return VERR_INVALID_EXE_SIGNATURE;
     215    AssertCompileMembersSameSizeAndOffset(mach_header_64_t, cputype, mach_header_32_t, cputype);
     216    bool f64Bit = uBuf.Hdr64.magic == IMAGE_MACHO64_SIGNATURE;
     217    if (uBuf.Hdr32.cputype != (f64Bit ? CPU_TYPE_X86_64 : CPU_TYPE_I386))
     218        return VERR_LDR_ARCH_MISMATCH;
     219    AssertCompileMembersSameSizeAndOffset(mach_header_64_t, filetype, mach_header_32_t, filetype);
     220    if (   uBuf.Hdr32.filetype != MH_EXECUTE
     221        && uBuf.Hdr32.filetype != (f64Bit ? MH_KEXT_BUNDLE : MH_OBJECT))
     222        return VERR_BAD_EXE_FORMAT;
     223    AssertCompileMembersSameSizeAndOffset(mach_header_64_t, ncmds, mach_header_32_t, ncmds);
     224    if (uBuf.Hdr32.ncmds > 256)
     225        return VERR_BAD_EXE_FORMAT;
     226    AssertCompileMembersSameSizeAndOffset(mach_header_64_t, sizeofcmds, mach_header_32_t, sizeofcmds);
     227    if (uBuf.Hdr32.sizeofcmds > X86_PAGE_4K_SIZE * 2 - sizeof(mach_header_64_t))
     228        return VERR_BAD_EXE_FORMAT;
     229
     230    /* Do we need to read a 2nd page to get all the load commands? If so, do it. */
     231    if (uBuf.Hdr32.sizeofcmds + (f64Bit ? sizeof(mach_header_64_t) : sizeof(mach_header_32_t)) > X86_PAGE_4K_SIZE)
     232    {
     233        rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &ModAddr, uModAddr + X86_PAGE_4K_SIZE),
     234                           &uBuf.ab[X86_PAGE_4K_SIZE], X86_PAGE_4K_SIZE);
     235        if (RT_FAILURE(rc))
     236            return rc;
     237    }
     238
     239    /*
     240     * Process the load commands.
     241     */
     242    RTDBGSEGMENT    aSegs[12];
     243    uint32_t        cSegs  = 0;
     244    RTUUID          Uuid   = RTUUID_INITIALIZE_NULL;
     245    uint32_t        cLeft  = uBuf.Hdr32.ncmds;
     246    uint32_t        cbLeft = uBuf.Hdr32.sizeofcmds;
     247    union
     248    {
     249        uint8_t const              *pb;
     250        load_command_t const       *pGenric;
     251        segment_command_32_t const *pSeg32;
     252        segment_command_64_t const *pSeg64;
     253        section_32_t const         *pSect32;
     254        section_64_t const         *pSect64;
     255        symtab_command_t const     *pSymTab;
     256        uuid_command_t const       *pUuid;
     257    } uLCmd;
     258    uLCmd.pb = &uBuf.ab[f64Bit ? sizeof(mach_header_64_t) : sizeof(mach_header_32_t)];
     259
     260    while (cLeft-- > 0)
     261    {
     262        uint32_t const cbCmd = uLCmd.pGenric->cmdsize;
     263        if (cbCmd > cbLeft || cbCmd < sizeof(load_command_t))
     264            return VERR_BAD_EXE_FORMAT;
     265
     266        switch (uLCmd.pGenric->cmd)
     267        {
     268            case LC_SEGMENT_32:
     269                if (cbCmd != sizeof(segment_command_32_t) + uLCmd.pSeg32->nsects * sizeof(section_32_t))
     270                    return VERR_BAD_EXE_FORMAT;
     271                if (!dbgDiggerDarwinIsValidSegOrSectName(uLCmd.pSeg32->segname, sizeof(uLCmd.pSeg32->segname)))
     272                    return VERR_INVALID_NAME;
     273                if (!strcmp(uLCmd.pSeg32->segname, "__LINKEDIT"))
     274                    continue; /* This usually is discarded or not loaded at all. */
     275                if (cSegs >= RT_ELEMENTS(aSegs))
     276                    return VERR_BUFFER_OVERFLOW;
     277                aSegs[cSegs].Address = uLCmd.pSeg32->vmaddr;
     278                aSegs[cSegs].uRva    = uLCmd.pSeg32->vmaddr - uModAddr;
     279                aSegs[cSegs].cb      = uLCmd.pSeg32->vmsize;
     280                aSegs[cSegs].fFlags  = uLCmd.pSeg32->flags; /* Abusing the flags field here... */
     281                aSegs[cSegs].iSeg    = cSegs;
     282                AssertCompile(RTDBG_SEGMENT_NAME_LENGTH > sizeof(uLCmd.pSeg32->segname));
     283                strcpy(aSegs[cSegs].szName, uLCmd.pSeg32->segname);
     284                cSegs++;
     285                break;
     286
     287            case LC_SEGMENT_64:
     288                if (cbCmd != sizeof(segment_command_64_t) + uLCmd.pSeg64->nsects * sizeof(section_64_t))
     289                    return VERR_BAD_EXE_FORMAT;
     290                if (!dbgDiggerDarwinIsValidSegOrSectName(uLCmd.pSeg64->segname, sizeof(uLCmd.pSeg64->segname)))
     291                    return VERR_INVALID_NAME;
     292                if (!strcmp(uLCmd.pSeg64->segname, "__LINKEDIT"))
     293                    continue; /* This usually is discarded or not loaded at all. */
     294                if (cSegs >= RT_ELEMENTS(aSegs))
     295                    return VERR_BUFFER_OVERFLOW;
     296                aSegs[cSegs].Address = uLCmd.pSeg64->vmaddr;
     297                aSegs[cSegs].uRva    = uLCmd.pSeg64->vmaddr - uModAddr;
     298                aSegs[cSegs].cb      = uLCmd.pSeg64->vmsize;
     299                aSegs[cSegs].fFlags  = uLCmd.pSeg64->flags; /* Abusing the flags field here... */
     300                aSegs[cSegs].iSeg    = cSegs;
     301                AssertCompile(RTDBG_SEGMENT_NAME_LENGTH > sizeof(uLCmd.pSeg64->segname));
     302                strcpy(aSegs[cSegs].szName, uLCmd.pSeg64->segname);
     303                cSegs++;
     304                break;
     305
     306            case LC_UUID:
     307                if (cbCmd != sizeof(uuid_command_t))
     308                    return VERR_BAD_EXE_FORMAT;
     309                if (RTUuidIsNull((PCRTUUID)&uLCmd.pUuid->uuid[0]))
     310                    return VERR_BAD_EXE_FORMAT;
     311                memcpy(&Uuid, &uLCmd.pUuid->uuid[0], sizeof(uLCmd.pUuid->uuid));
     312                break;
     313
     314            default:
     315                /* Current known max plus a lot of slack. */
     316                if (uLCmd.pGenric->cmd > LC_DYLIB_CODE_SIGN_DRS + 32)
     317                    return VERR_BAD_EXE_FORMAT;
     318                break;
     319        }
     320
     321        /* next */
     322        cbLeft   -= cbCmd;
     323        uLCmd.pb += cbCmd;
     324    }
     325
     326    if (cbLeft != 0)
     327        return VERR_BAD_EXE_FORMAT;
     328
     329    /*
     330     * Some post processing checks.
     331     */
     332    uint32_t iSeg;
     333    for (iSeg = 0; iSeg < cSegs; iSeg++)
     334        if (aSegs[iSeg].Address == uModAddr)
     335            break;
     336    if (iSeg >= cSegs)
     337        return VERR_ADDRESS_CONFLICT;
     338
     339    /*
     340     * Create a debug module.
     341     */
     342    RTDBGMOD hMod;
     343    rc = RTDbgModCreateFromMachOImage(&hMod, pszName, NULL, f64Bit ? RTLDRARCH_AMD64 : RTLDRARCH_X86_32, 0 /*cbImage*/,
     344                                      cSegs, aSegs, &Uuid, DBGFR3AsGetConfig(pUVM), RTDBGMOD_F_NOT_DEFERRED);
     345
     346    if (RT_FAILURE(rc))
     347    {
     348        /*
     349         * Final fallback is a container module.
     350         */
     351        rc = RTDbgModCreate(&hMod, pszName, 0, 0);
     352        if (RT_FAILURE(rc))
     353            return rc;
     354
     355        uint64_t uRvaNext = 0;
     356        for (iSeg = 0; iSeg < cSegs && RT_SUCCESS(rc); iSeg++)
     357        {
     358            if (   aSegs[iSeg].uRva > uRvaNext
     359                && aSegs[iSeg].uRva - uRvaNext < _1M)
     360                uRvaNext = aSegs[iSeg].uRva;
     361            rc = RTDbgModSegmentAdd(hMod, aSegs[iSeg].uRva, aSegs[iSeg].cb, aSegs[iSeg].szName, 0, NULL);
     362            if (aSegs[iSeg].cb > 0 && RT_SUCCESS(rc))
     363            {
     364                char szTmp[RTDBG_SEGMENT_NAME_LENGTH + sizeof("_start")];
     365                strcat(strcpy(szTmp, aSegs[iSeg].szName), "_start");
     366                rc = RTDbgModSymbolAdd(hMod, szTmp, iSeg, 0 /*uRva*/, 0 /*cb*/, 0 /*fFlags*/, NULL);
     367            }
     368            uRvaNext += aSegs[iSeg].cb;
     369        }
     370
     371        if (RT_FAILURE(rc))
     372        {
     373            RTDbgModRelease(hMod);
     374            return rc;
     375        }
     376    }
     377
     378    /* Tag the module. */
     379    rc = RTDbgModSetTag(hMod, DIG_DARWIN_MOD_TAG);
     380    AssertRC(rc);
     381
     382    /*
     383     * Link the module.
     384     */
     385    RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
     386    if (hAs != NIL_RTDBGAS)
     387    {
     388        uint64_t uRvaNext = 0;
     389        uint32_t cLinked  = 0;
     390        for (iSeg = 0; iSeg < cSegs; iSeg++)
     391            if (aSegs[iSeg].cb)
     392            {
     393                int rc2 = RTDbgAsModuleLinkSeg(hAs, hMod, iSeg, aSegs[iSeg].Address, RTDBGASLINK_FLAGS_REPLACE /*fFlags*/);
     394                if (RT_SUCCESS(rc2))
     395                    cLinked++;
     396                else if (RT_SUCCESS(rc))
     397                    rc = rc2;
     398            }
     399        if (RT_FAILURE(rc) && cLinked != 0)
     400            rc = -rc;
     401    }
     402    else
     403        rc = VERR_INTERNAL_ERROR;
     404    RTDbgModRelease(hMod);
     405    RTDbgAsRelease(hAs);
     406
     407    return rc;
     408}
    156409
    157410/**
    158411 * @copydoc DBGFOSREG::pfnInit
    159412 */
    160 static DECLCALLBACK(int)  dbgDiggerLinuxInit(PUVM pUVM, void *pvData)
    161 {
    162     PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
     413static DECLCALLBACK(int)  dbgDiggerDarwinInit(PUVM pUVM, void *pvData)
     414{
     415    PDBGDIGGERDARWIN pThis = (PDBGDIGGERDARWIN)pvData;
    163416    Assert(!pThis->fValid);
    164 #if 0  /* later */
    165     int rc;
    166 
    167     /*
    168      * Algorithm to find the ksymtab:
    169      *  1. Find a known export string in kstrtab ("init_task", "enable_hlt" or something).
    170      *  2. Search for the address its at, this should give you the corresponding ksymtab entry.
    171      *  3. Search backwards assuming that kstrtab is corresponding to ksymtab.
    172      */
    173     DBGFADDRESS AddrKernelKsymTab;
    174 
    175 
    176 #endif
    177     pThis->fValid = true;
     417
     418    /*
     419     * Add the kernel module (and later the other kernel modules we can find).
     420     */
     421    int rc = dbgDiggerDarwinAddModule(pThis, pUVM, pThis->AddrKernel.FlatPtr, "mach_kernel");
     422    if (RT_SUCCESS(rc))
     423    {
     424        /** @todo  */
     425        pThis->fValid = true;
     426        return VINF_SUCCESS;
     427    }
     428
     429    return rc;
     430}
     431
     432
     433/**
     434 * @copydoc DBGFOSREG::pfnProbe
     435 */
     436static DECLCALLBACK(bool)  dbgDiggerDarwinProbe(PUVM pUVM, void *pvData)
     437{
     438    PDBGDIGGERDARWIN pThis = (PDBGDIGGERDARWIN)pvData;
     439
     440    /*
     441     * Look for a section + segment combo that normally only occures in
     442     * mach_kernel.  Follow it up with probing of the rest of the executable
     443     * header.  We must search a largish area because the more recent versions
     444     * of darwin have random load address for security raisins.
     445     */
     446    static struct { uint64_t uStart, uEnd; } const s_aRanges[] =
     447    {
     448        /* 64-bit: */
     449        { UINT64_C(0xffffff8000000000), UINT64_C(0xffffff81ffffffff), },
     450
     451        /* 32-bit - always search for this because of the hybrid 32-bit kernel
     452           with cpu in long mode that darwin used for a number of versions. */
     453        { UINT64_C(0x00001000), UINT64_C(0x0ffff000), }
     454    };
     455    for (unsigned iRange = DBGFR3CpuGetMode(pUVM, 0 /*idCpu*/) != CPUMMODE_LONG;
     456          iRange < RT_ELEMENTS(s_aRanges);
     457          iRange++)
     458    {
     459        DBGFADDRESS     KernelAddr;
     460        for (DBGFR3AddrFromFlat(pUVM, &KernelAddr, s_aRanges[iRange].uStart);
     461             KernelAddr.FlatPtr < s_aRanges[iRange].uEnd;
     462             KernelAddr.FlatPtr += X86_PAGE_4K_SIZE)
     463        {
     464            static const uint8_t s_abNeedle[16 + 16] =
     465            {
     466                '_','_','t','e','x','t',  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, /* section_32_t::sectname */
     467                '_','_','K','L','D',  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, /* section_32_t::segname. */
     468            };
     469
     470            int rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, s_aRanges[iRange].uEnd - KernelAddr.FlatPtr,
     471                                   1, s_abNeedle, sizeof(s_abNeedle), &KernelAddr);
     472            if (RT_FAILURE(rc))
     473                break;
     474            DBGFR3AddrSub(&KernelAddr, KernelAddr.FlatPtr & X86_PAGE_4K_OFFSET_MASK);
     475
     476            /*
     477             * Read the first page of the image and check the headers.
     478             */
     479            union
     480            {
     481                uint8_t             ab[X86_PAGE_4K_SIZE];
     482                mach_header_64_t    Hdr64;
     483                mach_header_32_t    Hdr32;
     484            } uBuf;
     485            rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &KernelAddr, uBuf.ab, X86_PAGE_4K_SIZE);
     486            if (RT_FAILURE(rc))
     487                continue;
     488            AssertCompileMembersSameSizeAndOffset(mach_header_64_t, magic,   mach_header_32_t, magic);
     489            if (   uBuf.Hdr64.magic != IMAGE_MACHO64_SIGNATURE
     490                && uBuf.Hdr32.magic != IMAGE_MACHO32_SIGNATURE)
     491                continue;
     492            AssertCompileMembersSameSizeAndOffset(mach_header_64_t, cputype, mach_header_32_t, cputype);
     493            bool f64Bit = uBuf.Hdr64.magic == IMAGE_MACHO64_SIGNATURE;
     494            if (uBuf.Hdr32.cputype != (f64Bit ? CPU_TYPE_X86_64 : CPU_TYPE_I386))
     495                continue;
     496            AssertCompileMembersSameSizeAndOffset(mach_header_64_t, filetype, mach_header_32_t, filetype);
     497            if (uBuf.Hdr32.filetype != MH_EXECUTE)
     498                continue;
     499            AssertCompileMembersSameSizeAndOffset(mach_header_64_t, ncmds, mach_header_32_t, ncmds);
     500            if (uBuf.Hdr32.ncmds > 256)
     501                continue;
     502            AssertCompileMembersSameSizeAndOffset(mach_header_64_t, sizeofcmds, mach_header_32_t, sizeofcmds);
     503            if (uBuf.Hdr32.sizeofcmds > X86_PAGE_4K_SIZE - sizeof(mach_header_64_t))
     504                continue;
     505
     506            /* Seems good enough for now.
     507
     508               If the above causes false positives, check the segments and make
     509               sure there is a kernel version string in the right one. */
     510            pThis->AddrKernel = KernelAddr;
     511
     512            /*
     513             * Finally, find the kernel version string.
     514             */
     515            rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, 32*_1M, 1, RT_STR_TUPLE("Darwin Kernel Version"),
     516                               &pThis->AddrKernelVersion);
     517            if (RT_FAILURE(rc))
     518                DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelVersion, 0);
     519            return true;
     520        }
     521    }
     522    return false;
     523}
     524
     525
     526/**
     527 * @copydoc DBGFOSREG::pfnDestruct
     528 */
     529static DECLCALLBACK(void)  dbgDiggerDarwinDestruct(PUVM pUVM, void *pvData)
     530{
     531
     532}
     533
     534
     535/**
     536 * @copydoc DBGFOSREG::pfnConstruct
     537 */
     538static DECLCALLBACK(int)  dbgDiggerDarwinConstruct(PUVM pUVM, void *pvData)
     539{
    178540    return VINF_SUCCESS;
    179541}
    180542
    181543
    182 /**
    183  * @copydoc DBGFOSREG::pfnProbe
    184  */
    185 static DECLCALLBACK(bool)  dbgDiggerLinuxProbe(PUVM pUVM, void *pvData)
    186 {
    187     PDBGDIGGERLINUX pThis = (PDBGDIGGERLINUX)pvData;
    188 
    189     /*
    190      * Look for "Linux version " at the start of the rodata segment.
    191      * Hope that this comes before any message buffer or other similar string.
    192      *                                                                       .
    193      * Note! Only Linux version 2.x.y, where x in {0..6}.                                                                      .
    194      */
    195     for (unsigned i = 0; i < RT_ELEMENTS(g_au64LnxKernelAddresses); i++)
    196     {
    197         DBGFADDRESS KernelAddr;
    198         DBGFR3AddrFromFlat(pUVM, &KernelAddr, g_au64LnxKernelAddresses[i]);
    199         DBGFADDRESS HitAddr;
    200         static const uint8_t s_abLinuxVersion[] = "Linux version 2.";
    201         int rc = DBGFR3MemScan(pUVM, 0, &KernelAddr, LNX_MAX_KERNEL_SIZE, 1,
    202                                s_abLinuxVersion, sizeof(s_abLinuxVersion) - 1, &HitAddr);
    203         if (RT_SUCCESS(rc))
    204         {
    205             char szTmp[128];
    206             char const *pszY = &szTmp[sizeof(s_abLinuxVersion) - 1];
    207             rc = DBGFR3MemReadString(pUVM, 0, &HitAddr, szTmp, sizeof(szTmp));
    208             if (    RT_SUCCESS(rc)
    209                 &&  *pszY >= '0'
    210                 &&  *pszY <= '6')
    211             {
    212                 pThis->AddrKernelBase  = KernelAddr;
    213                 pThis->AddrLinuxBanner = HitAddr;
    214                 return true;
    215             }
    216         }
    217     }
    218     return false;
    219 }
    220 
    221 
    222 /**
    223  * @copydoc DBGFOSREG::pfnDestruct
    224  */
    225 static DECLCALLBACK(void)  dbgDiggerLinuxDestruct(PUVM pUVM, void *pvData)
    226 {
    227 
    228 }
    229 
    230 
    231 /**
    232  * @copydoc DBGFOSREG::pfnConstruct
    233  */
    234 static DECLCALLBACK(int)  dbgDiggerLinuxConstruct(PUVM pUVM, void *pvData)
    235 {
    236     return VINF_SUCCESS;
    237 }
    238 
    239 
    240 const DBGFOSREG g_DBGDiggerLinux =
     544const DBGFOSREG g_DBGDiggerDarwin =
    241545{
    242546    /* .u32Magic = */           DBGFOSREG_MAGIC,
    243547    /* .fFlags = */             0,
    244     /* .cbData = */             sizeof(DBGDIGGERLINUX),
    245     /* .szName = */             "Linux",
    246     /* .pfnConstruct = */       dbgDiggerLinuxConstruct,
    247     /* .pfnDestruct = */        dbgDiggerLinuxDestruct,
    248     /* .pfnProbe = */           dbgDiggerLinuxProbe,
    249     /* .pfnInit = */            dbgDiggerLinuxInit,
    250     /* .pfnRefresh = */         dbgDiggerLinuxRefresh,
    251     /* .pfnTerm = */            dbgDiggerLinuxTerm,
    252     /* .pfnQueryVersion = */    dbgDiggerLinuxQueryVersion,
    253     /* .pfnQueryInterface = */  dbgDiggerLinuxQueryInterface,
     548    /* .cbData = */             sizeof(DBGDIGGERDARWIN),
     549    /* .szName = */             "Darwin",
     550    /* .pfnConstruct = */       dbgDiggerDarwinConstruct,
     551    /* .pfnDestruct = */        dbgDiggerDarwinDestruct,
     552    /* .pfnProbe = */           dbgDiggerDarwinProbe,
     553    /* .pfnInit = */            dbgDiggerDarwinInit,
     554    /* .pfnRefresh = */         dbgDiggerDarwinRefresh,
     555    /* .pfnTerm = */            dbgDiggerDarwinTerm,
     556    /* .pfnQueryVersion = */    dbgDiggerDarwinQueryVersion,
     557    /* .pfnQueryInterface = */  dbgDiggerDarwinQueryInterface,
    254558    /* .u32EndMagic = */        DBGFOSREG_MAGIC
    255559};
  • trunk/src/VBox/Debugger/DBGPlugInDiggers.cpp

    r44528 r49044  
    3232    static PCDBGFOSREG s_aPlugIns[] =
    3333    {
     34        &g_DBGDiggerDarwin,
    3435        //&g_DBGDiggerFreeBSD,
    3536        &g_DBGDiggerLinux,
  • trunk/src/VBox/Debugger/DBGPlugIns.h

    r35346 r49044  
    88
    99/*
    10  * Copyright (C) 2008-2010 Oracle Corporation
     10 * Copyright (C) 2008-2013 Oracle Corporation
    1111 *
    1212 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2626RT_C_DECLS_BEGIN
    2727
    28 extern const DBGFOSREG g_DBGDiggerFreeBSD;
     28//extern const DBGFOSREG g_DBGDiggerFreeBSD;
     29extern const DBGFOSREG g_DBGDiggerDarwin;
    2930extern const DBGFOSREG g_DBGDiggerLinux;
    3031extern const DBGFOSREG g_DBGDiggerOS2;
  • trunk/src/VBox/Debugger/Makefile.kmk

    r46474 r49044  
    6161DBGCPlugInDiggers_SOURCES = \
    6262        DBGPlugInDiggers.cpp \
     63        DBGPlugInDarwin.cpp \
    6364        DBGPlugInLinux.cpp \
    6465        DBGPlugInSolaris.cpp \
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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