VirtualBox

Changeset 49044 in vbox for trunk/src


Ignore:
Timestamp:
Oct 11, 2013 1:06:28 AM (11 years ago)
Author:
vboxsync
Message:

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.

Location:
trunk/src
Files:
1 added
17 edited
1 copied

Legend:

Unmodified
Added
Removed
  • 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 \
  • trunk/src/VBox/Runtime/common/dbg/dbgcfg.cpp

    r46161 r49044  
    14251425    int rc2;
    14261426
    1427     //RTStrPrintf(szFile, sizeof(szFile), "%s.dSYM/Contents/Resources/DWARF/%s", pszFilename, pszFilename);
    1428 
    14291427    /*
    14301428     * Do a little validating first.
     
    15431541        rcRet = VERR_NOT_FOUND;
    15441542    return rcRet;
    1545 
    1546 
    15471543}
    15481544
  • trunk/src/VBox/Runtime/common/dbg/dbgmod.cpp

    r49040 r49044  
    4747#include <iprt/strcache.h>
    4848#include <iprt/string.h>
     49#include <iprt/uuid.h>
    4950#include "internal/dbgmod.h"
    5051#include "internal/magics.h"
     
    326327    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    327328    AssertReturn(*pszName, VERR_INVALID_PARAMETER);
    328     AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
     329    AssertReturn(fFlags == 0 || fFlags == RTDBGMOD_F_NOT_DEFERRED, VERR_INVALID_PARAMETER);
    329330
    330331    int rc = rtDbgModLazyInit();
     
    11351136                    {
    11361137                        PRTDBGMODDEFERRED pDeferred;
    1137                         rc = rtDbgModDeferredCreate(pDbgMod, rtDbgModFromPeImageDeferredCallback, cbImage, hDbgCfg, &pDeferred);
     1138                        rc = rtDbgModDeferredCreate(pDbgMod, rtDbgModFromPeImageDeferredCallback, cbImage, hDbgCfg, 0,
     1139                                                    &pDeferred);
    11381140                        if (RT_SUCCESS(rc))
    11391141                            pDeferred->u.PeImage.uTimestamp = uTimestamp;
     
    11701172
    11711173
     1174
     1175
     1176/*
     1177 *
     1178 *  M a c h - O   I M A G E
     1179 *  M a c h - O   I M A G E
     1180 *  M a c h - O   I M A G E
     1181 *
     1182 */
     1183
     1184/** @callback_method_impl{FNRTDBGCFGOPEN} */
     1185static DECLCALLBACK(int)
     1186rtDbgModFromMachOImageOpenMachOCallback(RTDBGCFG hDbgCfg, const char *pszFilename, void *pvUser1, void *pvUser2)
     1187{
     1188    PRTDBGMODINT        pDbgMod   = (PRTDBGMODINT)pvUser1;
     1189    PCRTDBGDWARFSEGPKG  pSegPkg   = (PCRTDBGDWARFSEGPKG)pvUser2;
     1190
     1191    /** @todo  */
     1192
     1193    return VERR_OPEN_FAILED;
     1194}
     1195
     1196
     1197/** @callback_method_impl{FNRTDBGCFGOPEN} */
     1198static DECLCALLBACK(int)
     1199rtDbgModFromMachOImageOpenDsymCallback(RTDBGCFG hDbgCfg, const char *pszFilename, void *pvUser1, void *pvUser2)
     1200{
     1201    PRTDBGMODINT        pDbgMod   = (PRTDBGMODINT)pvUser1;
     1202    PCRTDBGDWARFSEGPKG  pSegPkg   = (PCRTDBGDWARFSEGPKG)pvUser2;
     1203
     1204    Assert(!pDbgMod->pDbgVt);
     1205    Assert(!pDbgMod->pvDbgPriv);
     1206    Assert(!pDbgMod->pszDbgFile);
     1207    Assert(!pDbgMod->pImgVt);
     1208    Assert(!pDbgMod->pvDbgPriv);
     1209    Assert(pDbgMod->pszImgFile);
     1210    Assert(pDbgMod->pszImgFileSpecified);
     1211
     1212    const char *pszImgFileOrg = pDbgMod->pszImgFile;
     1213    pDbgMod->pszImgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
     1214    if (!pDbgMod->pszImgFile)
     1215        return VERR_NO_STR_MEMORY;
     1216    RTStrCacheRetain(pDbgMod->pszImgFile);
     1217    pDbgMod->pszDbgFile = pDbgMod->pszImgFile;
     1218
     1219    /*
     1220     * Try image interpreters as the dwarf file inside the dSYM bundle is a
     1221     * Mach-O file with dwarf debug sections insides it and no code or data.
     1222     */
     1223    int rc = RTSemRWRequestRead(g_hDbgModRWSem, RT_INDEFINITE_WAIT);
     1224    if (RT_SUCCESS(rc))
     1225    {
     1226        rc = VERR_DBG_NO_MATCHING_INTERPRETER;
     1227        PRTDBGMODREGIMG pImg;
     1228        for (pImg = g_pImgHead; pImg; pImg = pImg->pNext)
     1229        {
     1230            pDbgMod->pImgVt    = pImg->pVt;
     1231            pDbgMod->pvImgPriv = NULL;
     1232            rc = pImg->pVt->pfnTryOpen(pDbgMod, pSegPkg->enmArch);
     1233            if (RT_SUCCESS(rc))
     1234                break;
     1235            pDbgMod->pImgVt    = NULL;
     1236            Assert(pDbgMod->pvImgPriv == NULL);
     1237        }
     1238
     1239        if (RT_SUCCESS(rc))
     1240        {
     1241            /*
     1242             * Check the UUID if one was given.
     1243             */
     1244            if (pSegPkg->pUuid)
     1245            {
     1246                RTUUID UuidOpened;
     1247                rc = pDbgMod->pImgVt->pfnQueryProp(pDbgMod, RTLDRPROP_UUID, &UuidOpened, sizeof(UuidOpened));
     1248                if (RT_SUCCESS(rc))
     1249                {
     1250                    if (RTUuidCompare(&UuidOpened, pSegPkg->pUuid) != 0)
     1251                        rc = VERR_DBG_FILE_MISMATCH;
     1252                }
     1253                else if (rc == VERR_NOT_FOUND || rc == VERR_NOT_IMPLEMENTED)
     1254                    rc = VERR_DBG_FILE_MISMATCH;
     1255            }
     1256            if (RT_SUCCESS(rc))
     1257            {
     1258                /*
     1259                 * Pass it to the DWARF reader(s).
     1260                 */
     1261                for (PRTDBGMODREGDBG pDbg = g_pDbgHead; pDbg; pDbg = pDbg->pNext)
     1262                {
     1263                    if (pDbg->pVt->fSupports & RT_DBGTYPE_DWARF)
     1264                    {
     1265                        pDbgMod->pDbgVt    = pDbg->pVt;
     1266                        pDbgMod->pvDbgPriv = pSegPkg->cSegs ? (void *)pSegPkg : NULL;
     1267                        rc = pDbg->pVt->pfnTryOpen(pDbgMod, pDbgMod->pImgVt->pfnGetArch(pDbgMod));
     1268                        if (RT_SUCCESS(rc))
     1269                        {
     1270                            /*
     1271                             * Got it!
     1272                             */
     1273                            ASMAtomicIncU32(&pDbg->cUsers);
     1274                            RTSemRWReleaseRead(g_hDbgModRWSem);
     1275                            RTStrCacheRelease(g_hDbgModStrCache, pszImgFileOrg);
     1276                            return VINF_CALLBACK_RETURN;
     1277                        }
     1278                        pDbgMod->pDbgVt    = NULL;
     1279                        Assert(pDbgMod->pvDbgPriv == NULL);
     1280                    }
     1281                }
     1282            }
     1283
     1284            pDbgMod->pImgVt->pfnClose(pDbgMod);
     1285            pDbgMod->pImgVt    = NULL;
     1286            pDbgMod->pvImgPriv = NULL;
     1287        }
     1288    }
     1289
     1290    /* No joy. */
     1291    RTSemRWReleaseRead(g_hDbgModRWSem);
     1292    RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
     1293    pDbgMod->pszImgFile = pszImgFileOrg;
     1294    RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszDbgFile);
     1295    pDbgMod->pszDbgFile = NULL;
     1296    return rc;
     1297}
     1298
     1299
     1300static int rtDbgModFromMachOImageWorker(PRTDBGMODINT pDbgMod, RTLDRARCH enmArch, uint32_t cbImage,
     1301                                        uint32_t cSegs, PCRTDBGSEGMENT paSegs, PCRTUUID pUuid, RTDBGCFG hDbgCfg)
     1302{
     1303    RTDBGDWARFSEGPKG SegPkg;
     1304    SegPkg.cSegs    = cSegs;
     1305    SegPkg.paSegs   = paSegs;
     1306    SegPkg.enmArch  = enmArch;
     1307    SegPkg.pUuid    = pUuid && RTUuidIsNull(pUuid) ? pUuid : NULL;
     1308
     1309    /*
     1310     * Search for the .dSYM bundle first, since that's generally all we need.
     1311     */
     1312    int rc = RTDbgCfgOpenDsymBundle(hDbgCfg, pDbgMod->pszImgFile, pUuid,
     1313                                    rtDbgModFromMachOImageOpenDsymCallback, pDbgMod, &SegPkg);
     1314    if (RT_FAILURE(rc))
     1315    {
     1316        /*
     1317         * If we cannot get at the .dSYM, try the executable image.
     1318         */
     1319        //rc = RTDbgCfgOpenMachOImage(hDbgCfg, pDbgMod->pszImgFile, pUuid,
     1320        //                            rtDbgModFromMachOImageOpenMachOCallback, pDbgMod, &SegPkg);
     1321    }
     1322    return rc;
     1323}
     1324
     1325
     1326/** @callback_method_impl{FNRTDBGMODDEFERRED}  */
     1327static DECLCALLBACK(int) rtDbgModFromMachOImageDeferredCallback(PRTDBGMODINT pDbgMod, PRTDBGMODDEFERRED pDeferred)
     1328{
     1329    return rtDbgModFromMachOImageWorker(pDbgMod, pDeferred->u.MachO.enmArch, pDeferred->cbImage,
     1330                                        pDeferred->u.MachO.cSegs, pDeferred->u.MachO.aSegs,
     1331                                        &pDeferred->u.MachO.Uuid, pDeferred->hDbgCfg);
     1332}
     1333
     1334
     1335RTDECL(int) RTDbgModCreateFromMachOImage(PRTDBGMOD phDbgMod, const char *pszFilename, const char *pszName,
     1336                                         RTLDRARCH enmArch, uint32_t cbImage, uint32_t cSegs, PCRTDBGSEGMENT paSegs,
     1337                                         PCRTUUID pUuid, RTDBGCFG hDbgCfg, uint32_t fFlags)
     1338{
     1339    /*
     1340     * Input validation and lazy initialization.
     1341     */
     1342    AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER);
     1343    *phDbgMod = NIL_RTDBGMOD;
     1344    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
     1345    AssertReturn(*pszFilename, VERR_INVALID_PARAMETER);
     1346    if (!pszName)
     1347        pszName = RTPathFilenameEx(pszFilename, RTPATH_STR_F_STYLE_HOST);
     1348    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
     1349    if (cSegs)
     1350    {
     1351        AssertReturn(cSegs < 1024, VERR_INVALID_PARAMETER);
     1352        AssertPtrReturn(paSegs, VERR_INVALID_POINTER);
     1353        AssertReturn(!cbImage, VERR_INVALID_PARAMETER);
     1354    }
     1355    AssertReturn(cbImage || cSegs, VERR_INVALID_PARAMETER);
     1356    AssertPtrNullReturn(pUuid, VERR_INVALID_POINTER);
     1357    AssertReturn(!(fFlags & ~(RTDBGMOD_F_NOT_DEFERRED)), VERR_INVALID_PARAMETER);
     1358
     1359    int rc = rtDbgModLazyInit();
     1360    if (RT_FAILURE(rc))
     1361        return rc;
     1362
     1363    uint64_t fDbgCfg = 0;
     1364    if (hDbgCfg)
     1365    {
     1366        rc = RTDbgCfgQueryUInt(hDbgCfg, RTDBGCFGPROP_FLAGS, &fDbgCfg);
     1367        AssertRCReturn(rc, rc);
     1368    }
     1369
     1370    /*
     1371     * Allocate a new module instance.
     1372     */
     1373    PRTDBGMODINT pDbgMod = (PRTDBGMODINT)RTMemAllocZ(sizeof(*pDbgMod));
     1374    if (!pDbgMod)
     1375        return VERR_NO_MEMORY;
     1376    pDbgMod->u32Magic = RTDBGMOD_MAGIC;
     1377    pDbgMod->cRefs = 1;
     1378    rc = RTCritSectInit(&pDbgMod->CritSect);
     1379    if (RT_SUCCESS(rc))
     1380    {
     1381        pDbgMod->pszName = RTStrCacheEnterLower(g_hDbgModStrCache, pszName);
     1382        if (pDbgMod->pszName)
     1383        {
     1384            pDbgMod->pszImgFile = RTStrCacheEnter(g_hDbgModStrCache, pszFilename);
     1385            if (pDbgMod->pszImgFile)
     1386            {
     1387                RTStrCacheRetain(pDbgMod->pszImgFile);
     1388                pDbgMod->pszImgFileSpecified = pDbgMod->pszImgFile;
     1389
     1390                /*
     1391                 * Load it immediately?
     1392                 */
     1393                if (   !(fDbgCfg & RTDBGCFG_FLAGS_DEFERRED)
     1394                    || (!cbImage && !cSegs)
     1395                    || (fFlags & RTDBGMOD_F_NOT_DEFERRED) )
     1396                    rc = rtDbgModFromMachOImageWorker(pDbgMod, enmArch, cbImage, cSegs, paSegs, pUuid, hDbgCfg);
     1397                else
     1398                {
     1399                    /*
     1400                     * Procrastinate.  Need image size atm.
     1401                     */
     1402                    uint32_t uRvaMax = cbImage;
     1403                    if (!uRvaMax)
     1404                        for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
     1405                        {
     1406                            if (   paSegs[iSeg].uRva > uRvaMax
     1407                                && paSegs[iSeg].uRva - uRvaMax < _1M)
     1408                                uRvaMax = paSegs[iSeg].uRva;
     1409                            uRvaMax += paSegs[iSeg].cb;
     1410                        }
     1411
     1412                    PRTDBGMODDEFERRED pDeferred;
     1413                    rc = rtDbgModDeferredCreate(pDbgMod, rtDbgModFromMachOImageDeferredCallback, uRvaMax, hDbgCfg,
     1414                                                RT_OFFSETOF(RTDBGMODDEFERRED, u.MachO.aSegs[cSegs]),
     1415                                                &pDeferred);
     1416                    if (RT_SUCCESS(rc))
     1417                    {
     1418                        pDeferred->u.MachO.Uuid    = *pUuid;
     1419                        pDeferred->u.MachO.enmArch = enmArch;
     1420                        pDeferred->u.MachO.cSegs   = cSegs;
     1421                        if (cSegs)
     1422                        {
     1423                            memcpy(&pDeferred->u.MachO.aSegs, paSegs, cSegs * sizeof(paSegs[0]));
     1424                            if (!cbImage)
     1425                            {
     1426                                /* If we calculated a cbImage above, do corresponding RVA adjustments. */
     1427                                uRvaMax = 0;
     1428                                for (uint32_t iSeg = 0; iSeg < cSegs; iSeg++)
     1429                                {
     1430                                    if (   paSegs[iSeg].uRva > uRvaMax
     1431                                        && paSegs[iSeg].uRva - uRvaMax < _1M)
     1432                                        uRvaMax = paSegs[iSeg].uRva;
     1433                                    else
     1434                                        pDeferred->u.MachO.aSegs[iSeg].uRva = uRvaMax;
     1435                                    uRvaMax += paSegs[iSeg].cb;
     1436                                }
     1437                            }
     1438                        }
     1439                    }
     1440                }
     1441                if (RT_SUCCESS(rc))
     1442                {
     1443                    *phDbgMod = pDbgMod;
     1444                    return VINF_SUCCESS;
     1445                }
     1446
     1447                /* Failed, bail out. */
     1448                RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszName);
     1449            }
     1450            else
     1451                rc = VERR_NO_STR_MEMORY;
     1452            RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFileSpecified);
     1453            RTStrCacheRelease(g_hDbgModStrCache, pDbgMod->pszImgFile);
     1454        }
     1455        else
     1456            rc = VERR_NO_STR_MEMORY;
     1457        RTCritSectDelete(&pDbgMod->CritSect);
     1458    }
     1459
     1460    RTMemFree(pDbgMod);
     1461    return rc;
     1462}
     1463
     1464
     1465
     1466RT_EXPORT_SYMBOL(RTDbgModCreateFromMachOImage);
     1467
     1468
     1469
    11721470/**
    11731471 * Destroys an module after the reference count has reached zero.
  • trunk/src/VBox/Runtime/common/dbg/dbgmoddeferred.cpp

    r46281 r49044  
    439439 *
    440440 */
     441
     442/** @interface_method_impl{RTDBGMODVTIMG,pfnQueryProp} */
     443static DECLCALLBACK(int ) rtDbgModDeferredImg_QueryProp(PRTDBGMODINT pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf)
     444{
     445    int rc = rtDbgModDeferredDoIt(pMod, false /*fForceRetry*/);
     446    if (RT_SUCCESS(rc))
     447        rc = pMod->pImgVt->pfnQueryProp(pMod, enmProp, pvBuf, cbBuf);
     448    return rc;
     449}
    441450
    442451
     
    593602    /*.pfnGetFormat = */                rtDbgModDeferredImg_GetFormat,
    594603    /*.pfnGetArch = */                  rtDbgModDeferredImg_GetArch,
     604    /*.pfnQueryProp = */                rtDbgModDeferredImg_QueryProp,
    595605
    596606    /*.u32EndMagic = */                 RTDBGMODVTIMG_MAGIC
     
    608618 * @param   hDbgCfg             The debug config handle.  Can be NIL.  A
    609619 *                              reference will be retained.
     620 * @param   cbDeferred          The size of the deferred instance data, 0 if the
     621 *                              default structure is good enough.
    610622 * @param   ppDeferred          Where to return the instance data. Can be NULL.
    611623 */
    612624DECLHIDDEN(int) rtDbgModDeferredCreate(PRTDBGMODINT pDbgMod, PFNRTDBGMODDEFERRED pfnDeferred, RTUINTPTR cbImage,
    613                                        RTDBGCFG hDbgCfg, PRTDBGMODDEFERRED *ppDeferred)
     625                                       RTDBGCFG hDbgCfg, size_t cbDeferred, PRTDBGMODDEFERRED *ppDeferred)
    614626{
    615627    AssertReturn(!pDbgMod->pDbgVt, VERR_DBG_MOD_IPE);
    616628
    617     PRTDBGMODDEFERRED pDeferred = (PRTDBGMODDEFERRED)RTMemAllocZ(sizeof(*pDeferred));
     629    if (cbDeferred < sizeof(RTDBGMODDEFERRED))
     630        cbDeferred = sizeof(RTDBGMODDEFERRED);
     631    PRTDBGMODDEFERRED pDeferred = (PRTDBGMODDEFERRED)RTMemAllocZ(cbDeferred);
    618632    if (!pDeferred)
    619633        return VERR_NO_MEMORY;
  • trunk/src/VBox/Runtime/common/dbg/dbgmodldr.cpp

    r46266 r49044  
    55
    66/*
    7  * Copyright (C) 2011 Oracle Corporation
     7 * Copyright (C) 2011-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5959typedef RTDBGMODLDR *PRTDBGMODLDR;
    6060
     61
     62
     63/** @interface_method_impl{RTDBGMODVTIMG,pfnQueryProp} */
     64static DECLCALLBACK(int) rtDbgModLdr_QueryProp(PRTDBGMODINT pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf)
     65{
     66    PRTDBGMODLDR pThis = (PRTDBGMODLDR)pMod->pvImgPriv;
     67    return RTLdrQueryProp(pThis->hLdrMod, enmProp, pvBuf, cbBuf);
     68}
    6169
    6270
     
    216224    /*.pfnGetFormat = */                rtDbgModLdr_GetFormat,
    217225    /*.pfnGetArch = */                  rtDbgModLdr_GetArch,
     226    /*.pfnQueryProp = */                rtDbgModLdr_QueryProp,
    218227
    219228    /*.u32EndMagic = */                 RTDBGMODVTIMG_MAGIC
  • trunk/src/VBox/Runtime/common/ldr/ldr.cpp

    r48935 r49044  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    148148     * Validate input.
    149149     */
     150    if (hLdrMod == NIL_RTLDRMOD)
     151        return VINF_SUCCESS;
    150152    AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), VERR_INVALID_HANDLE);
    151153    PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
  • trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h

    r47290 r49044  
    14011401    RTLDRELF_NAME(RvaToSegOffset),
    14021402    RTLDRELF_NAME(ReadDbgInfo),
     1403    NULL /*pfnQueryProp*/,
    14031404    42
    14041405};
  • trunk/src/VBox/Runtime/common/ldr/ldrEx.cpp

    r48935 r49044  
    55
    66/*
    7  * Copyright (C) 2006-2011 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    540540
    541541
     542RTDECL(int) RTLdrQueryProp(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf)
     543{
     544    AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), RTLDRENDIAN_INVALID);
     545    PRTLDRMODINTERNAL pMod = (PRTLDRMODINTERNAL)hLdrMod;
     546
     547    /*
     548     * Do some pre screening of the input
     549     */
     550    switch (enmProp)
     551    {
     552        case RTLDRPROP_UUID:
     553            AssertReturn(cbBuf == sizeof(RTUUID), VERR_INVALID_PARAMETER);
     554            break;
     555        case RTLDRPROP_TIMESTAMP_SECONDS:
     556            AssertReturn(cbBuf == sizeof(int32_t) || cbBuf == sizeof(int64_t), VERR_INVALID_PARAMETER);
     557            break;
     558        default:
     559            AssertFailedReturn(VERR_INVALID_FUNCTION);
     560    }
     561    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
     562
     563    /*
     564     * Call the image specific worker, if there is one.
     565     */
     566    if (!pMod->pOps->pfnQueryProp)
     567        return VERR_NOT_SUPPORTED;
     568    return pMod->pOps->pfnQueryProp(pMod, enmProp, pvBuf, cbBuf);
     569}
     570RT_EXPORT_SYMBOL(RTLdrQueryProp);
     571
     572
    542573/**
    543574 * Internal method used by the IPRT debug bits.
  • trunk/src/VBox/Runtime/common/ldr/ldrNative.cpp

    r49040 r49044  
    7171    rtldrNativeEnumSymbols,
    7272    /* ext: */
     73    NULL,
    7374    NULL,
    7475    NULL,
  • trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp

    r48935 r49044  
    14901490
    14911491
     1492/** @interface_method_impl{RTLDROPS,pfnQueryProp} */
     1493static DECLCALLBACK(int) rtldrPE_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf)
     1494{
     1495    PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod;
     1496    switch (enmProp)
     1497    {
     1498        case RTLDRPROP_TIMESTAMP_SECONDS:
     1499            if (cbBuf == sizeof(int32_t))
     1500                *(int32_t *)pvBuf = pModPe->uTimestamp;
     1501            else if (cbBuf == sizeof(int64_t))
     1502                *(int64_t *)pvBuf = pModPe->uTimestamp;
     1503            else
     1504                return VERR_INVALID_PARAMETER;
     1505            break;
     1506
     1507        default:
     1508            return VERR_NOT_FOUND;
     1509    }
     1510    return VINF_SUCCESS;
     1511}
     1512
     1513
    14921514/** @copydoc RTLDROPS::pfnDone */
    14931515static DECLCALLBACK(int) rtldrPEDone(PRTLDRMODINTERNAL pMod)
     
    15431565        rtldrPE_RvaToSegOffset,
    15441566        NULL,
     1567        rtldrPE_QueryProp,
    15451568        42
    15461569    },
     
    15731596        rtldrPE_RvaToSegOffset,
    15741597        NULL,
     1598        rtldrPE_QueryProp,
    15751599        42
    15761600    },
  • trunk/src/VBox/Runtime/common/ldr/ldrkStuff.cpp

    r48935 r49044  
    149149        case KLDR_ERR_NOT_DLL:
    150150        case KLDR_ERR_NOT_EXE:
    151             AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
     151            AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_LDR_GENERAL_FAILURE);
    152152
    153153
     
    160160        case KLDR_ERR_PE_BAD_FIXUP:
    161161        case KLDR_ERR_PE_BAD_IMPORT:
    162             AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
     162            AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_LDR_GENERAL_FAILURE);
    163163
    164164        case KLDR_ERR_LX_BAD_HEADER:
     
    174174        case KLDR_ERR_LX_BAD_FORWARDER:
    175175        case KLDR_ERR_LX_NRICHAIN_NOT_SUPPORTED:
    176             AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
    177 
     176            AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_LDR_GENERAL_FAILURE);
     177
     178        case KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE:          return VERR_LDR_GENERAL_FAILURE;
    178179        case KLDR_ERR_MACHO_OTHER_ENDIAN_NOT_SUPPORTED:
    179180        case KLDR_ERR_MACHO_BAD_HEADER:
    180         case KLDR_ERR_MACHO_UNSUPPORTED_FILE_TYPE:
    181181        case KLDR_ERR_MACHO_UNSUPPORTED_MACHINE:
    182182        case KLDR_ERR_MACHO_BAD_LOAD_COMMAND:
     
    195195        case KLDR_ERR_MACHO_BAD_SYMBOL:
    196196        case KLDR_ERR_MACHO_UNSUPPORTED_FIXUP_TYPE:
    197             AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_GENERAL_FAILURE);
     197            AssertMsgFailedReturn(("krc=%d (%#x): %s\n", krc, krc, kErrName(krc)), VERR_LDR_GENERAL_FAILURE);
    198198
    199199        default:
     
    837837
    838838
     839/** @interface_method_impl{RTLDROPS,pfnQueryProp} */
     840static DECLCALLBACK(int) rtkldr_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf)
     841{
     842    PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
     843    int           rc;
     844    switch (enmProp)
     845    {
     846        case RTLDRPROP_UUID:
     847            rc = kLdrModQueryImageUuid(pThis->pMod, /*pvBits*/ NULL, (uint8_t *)pvBuf, cbBuf);
     848            if (rc == KLDR_ERR_NO_IMAGE_UUID)
     849                return VERR_NOT_FOUND;
     850            AssertReturn(rc == 0, VERR_INVALID_PARAMETER);
     851            break;
     852
     853        default:
     854            return VERR_NOT_FOUND;
     855    }
     856    return VINF_SUCCESS;
     857}
     858
     859
    839860/**
    840861 * Operations for a kLdr module.
     
    859880    rtkldr_RvaToSegOffset,
    860881    rtkldr_ReadDbgInfo,
     882    rtkldr_QueryProp,
    861883    42
    862884};
  • trunk/src/VBox/Runtime/include/internal/dbgmod.h

    r46266 r49044  
    227227     */
    228228    DECLCALLBACKMEMBER(RTLDRARCH, pfnGetArch)(PRTDBGMODINT pMod);
     229
     230    /**
     231     * Generic method for querying image properties.
     232     *
     233     * @returns IPRT status code.
     234     * @param   pMod            Pointer to the module structure.
     235     * @param   enmLdrProp      The property to query.
     236     * @param   pvBuf           Pointer to the return buffer.
     237     * @param   cbBuf           The size of the return buffer.
     238     * @sa      RTLdrQueryProp
     239     */
     240    DECLCALLBACKMEMBER(int, pfnQueryProp)(PRTDBGMODINT pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf);
    229241
    230242    /** For catching initialization errors (RTDBGMODVTIMG_MAGIC). */
     
    559571            uint32_t    uCrc32;
    560572        }   GnuDebugLink;
     573
     574        struct
     575        {
     576            /** The image UUID. */
     577            RTUUID          Uuid;
     578            /** Image architecture. */
     579            RTLDRARCH       enmArch;
     580            /** Number of segment mappings. */
     581            uint32_t        cSegs;
     582            /** Segment mappings. */
     583            RTDBGSEGMENT    aSegs[1];
     584        }   MachO;
    561585    } u;
    562586} RTDBGMODDEFERRED;
     
    617641
    618642
     643/**
     644 * Special segment package used passing segment order information for mach-o
     645 * images (mainly mach_kernel, really).
     646 *
     647 * Passes to rtDbgModDwarf_TryOpen via RTDBGMODINF::pvDbgPriv.
     648 */
     649typedef struct RTDBGDWARFSEGPKG
     650{
     651    /** Pointer to the segment array. */
     652    PCRTDBGSEGMENT      paSegs;
     653    /** Number of segments. */
     654    uint32_t            cSegs;
     655    /** For use more internal use in file locator callbacks. */
     656    RTLDRARCH           enmArch;
     657    /** For use more internal use in file locator callbacks. */
     658    PCRTUUID            pUuid;
     659} RTDBGDWARFSEGPKG;
     660/** Pointer to a const segment package. */
     661typedef RTDBGDWARFSEGPKG const *PCRTDBGDWARFSEGPKG;
     662
     663
    619664extern DECLHIDDEN(RTSTRCACHE)           g_hDbgModStrCache;
    620665extern DECLHIDDEN(RTDBGMODVTDBG const)  g_rtDbgModVtDbgCodeView;
     
    637682DECLHIDDEN(int) rtDbgModCreateForExports(PRTDBGMODINT pDbgMod);
    638683DECLHIDDEN(int) rtDbgModDeferredCreate(PRTDBGMODINT pDbgMod, PFNRTDBGMODDEFERRED pfnDeferred, RTUINTPTR cbImage,
    639                                        RTDBGCFG hDbgCfg, PRTDBGMODDEFERRED *ppDeferred);
     684                                       RTDBGCFG hDbgCfg, size_t cbDeferred, PRTDBGMODDEFERRED *ppDeferred);
    640685
    641686DECLHIDDEN(int) rtDbgModLdrOpenFromHandle(PRTDBGMODINT pDbgMod, RTLDRMOD hLdrMod);
  • trunk/src/VBox/Runtime/include/internal/ldr.h

    r46593 r49044  
    312312     * @returns IPRT status code.
    313313     *
     314     * @param   pMod            Pointer to the loader module structure.
    314315     * @param   pvBuf           The buffer to read into.
    315316     * @param   iDbgInfo        The debug info ordinal number if the request
     
    321322     */
    322323    DECLCALLBACKMEMBER(int, pfnReadDbgInfo)(PRTLDRMODINTERNAL pMod, uint32_t iDbgInfo, RTFOFF off, size_t cb, void *pvBuf);
     324
     325
     326
     327    /**
     328     * Generic method for querying image properties.
     329     *
     330     * @returns IPRT status code.
     331     * @retval  VERR_NOT_SUPPORTED if the property query isn't supported (either all
     332     *          or that specific property).
     333     * @retval  VERR_NOT_FOUND the property was not found in the module.
     334     *
     335     * @param   pMod            Pointer to the loader module structure.
     336     * @param   enmLdrProp      The property to query (valid).
     337     * @param   pvBuf           Pointer to the return buffer (valid).
     338     * @param   cbBuf           The size of the return buffer (valid as per
     339     *                          property).
     340     */
     341    DECLCALLBACKMEMBER(int, pfnQueryProp)(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf);
    323342
    324343    /** Dummy entry to make sure we've initialized it all. */
  • trunk/src/VBox/Runtime/tools/Makefile.kmk

    r45929 r49044  
    7171 RTNtDbgHelp_SOURCES = RTNtDbgHelp.cpp
    7272
     73 # RTDbgSymCache - Symbol cache manager.
     74 PROGRAMS += RTDbgSymCache
     75 RTDbgSymCache_TEMPLATE = VBOXR3TSTEXE
     76 RTDbgSymCache_SOURCES = RTDbgSymCache.cpp
     77
    7378endif # !VBOX_ONLY_EXTPACKS_USE_IMPLIBS
    7479
  • trunk/src/libs/kStuff

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