VirtualBox

Changeset 75039 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Oct 24, 2018 1:47:40 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
126082
Message:

IPRT/r0drv/darwin: Split out RTFile* from dbgkrnlinfo. Added RTFileRead and RTFileGetSize. bugref:9232

Location:
trunk/src/VBox/Runtime
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r74742 r75039  
    29422942        r0drv/darwin/initterm-r0drv-darwin.cpp \
    29432943        r0drv/darwin/dbgkrnlinfo-r0drv-darwin.cpp \
     2944        r0drv/darwin/fileio-r0drv-darwin.cpp \
    29442945        r0drv/darwin/memobj-r0drv-darwin.cpp \
    29452946        r0drv/darwin/mp-r0drv-darwin.cpp \
  • trunk/src/VBox/Runtime/r0drv/darwin/dbgkrnlinfo-r0drv-darwin.cpp

    r72691 r75039  
    191191#ifdef DEBUG
    192192static bool g_fBreakpointOnError = false;
    193 #endif
    194 
    195 
    196 #ifdef IN_RING0
    197 
    198 /** Default file permissions for newly created files. */
    199 #if defined(S_IRUSR) && defined(S_IWUSR)
    200 # define RT_FILE_PERMISSION  (S_IRUSR | S_IWUSR)
    201 #else
    202 # define RT_FILE_PERMISSION  (00600)
    203 #endif
    204 
    205 /**
    206  * Darwin kernel file handle data.
    207  */
    208 typedef struct RTFILEINT
    209 {
    210     /** Magic value (RTFILE_MAGIC). */
    211     uint32_t        u32Magic;
    212     /** The open mode flags passed to the kernel API. */
    213     int             fOpenMode;
    214     /** The open flags passed to RTFileOpen. */
    215     uint64_t        fOpen;
    216     /** The VFS context in which the file was opened. */
    217     vfs_context_t   hVfsCtx;
    218     /** The vnode returned by vnode_open. */
    219     vnode_t         hVnode;
    220 } RTFILEINT;
    221 /** Magic number for RTFILEINT::u32Magic (To Be Determined). */
    222 #define RTFILE_MAGIC                    UINT32_C(0x01020304)
    223 
    224 
    225 RTDECL(int) RTFileOpen(PRTFILE phFile, const char *pszFilename, uint64_t fOpen)
    226 {
    227     RTFILEINT *pThis = (RTFILEINT *)RTMemAllocZ(sizeof(*pThis));
    228     if (!pThis)
    229         return VERR_NO_MEMORY;
    230     IPRT_DARWIN_SAVE_EFL_AC();
    231 
    232     errno_t rc;
    233     pThis->u32Magic = RTFILE_MAGIC;
    234     pThis->fOpen    = fOpen;
    235     pThis->hVfsCtx  = vfs_context_current();
    236     if (pThis->hVfsCtx != NULL)
    237     {
    238         int             fCMode    = (fOpen & RTFILE_O_CREATE_MODE_MASK)
    239                                   ? (fOpen & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT
    240                                   : RT_FILE_PERMISSION;
    241         int             fVnFlags  = 0; /* VNODE_LOOKUP_XXX */
    242         int             fOpenMode = 0;
    243         if (fOpen & RTFILE_O_NON_BLOCK)
    244             fOpenMode |= O_NONBLOCK;
    245         if (fOpen & RTFILE_O_WRITE_THROUGH)
    246             fOpenMode |= O_SYNC;
    247 
    248         /* create/truncate file */
    249         switch (fOpen & RTFILE_O_ACTION_MASK)
    250         {
    251             case RTFILE_O_OPEN:             break;
    252             case RTFILE_O_OPEN_CREATE:      fOpenMode |= O_CREAT; break;
    253             case RTFILE_O_CREATE:           fOpenMode |= O_CREAT | O_EXCL; break;
    254             case RTFILE_O_CREATE_REPLACE:   fOpenMode |= O_CREAT | O_TRUNC; break; /** @todo replacing needs fixing, this is *not* a 1:1 mapping! */
    255         }
    256         if (fOpen & RTFILE_O_TRUNCATE)
    257             fOpenMode |= O_TRUNC;
    258 
    259         switch (fOpen & RTFILE_O_ACCESS_MASK)
    260         {
    261             case RTFILE_O_READ:
    262                 fOpenMode |= FREAD;
    263                 break;
    264             case RTFILE_O_WRITE:
    265                 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | FWRITE : FWRITE;
    266                 break;
    267             case RTFILE_O_READWRITE:
    268                 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | FWRITE | FREAD : FWRITE | FREAD;
    269                 break;
    270             default:
    271                 AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#x\n", fOpen));
    272                 IPRT_DARWIN_RESTORE_EFL_AC();
    273                 return VERR_INVALID_PARAMETER;
    274         }
    275 
    276         pThis->fOpenMode = fOpenMode;
    277         rc = vnode_open(pszFilename, fOpenMode, fCMode, fVnFlags, &pThis->hVnode, pThis->hVfsCtx);
    278         if (rc == 0)
    279         {
    280             *phFile = pThis;
    281             IPRT_DARWIN_RESTORE_EFL_AC();
    282             return VINF_SUCCESS;
    283         }
    284 
    285         rc = RTErrConvertFromErrno(rc);
    286     }
    287     else
    288         rc = VERR_INTERNAL_ERROR_5;
    289     RTMemFree(pThis);
    290 
    291     IPRT_DARWIN_RESTORE_EFL_AC();
    292     return rc;
    293 }
    294 
    295 
    296 RTDECL(int) RTFileClose(RTFILE hFile)
    297 {
    298     if (hFile == NIL_RTFILE)
    299         return VINF_SUCCESS;
    300 
    301     RTFILEINT *pThis = hFile;
    302     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    303     AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
    304     pThis->u32Magic = ~RTFILE_MAGIC;
    305 
    306     IPRT_DARWIN_SAVE_EFL_AC();
    307     errno_t rc = vnode_close(pThis->hVnode, pThis->fOpenMode & (FREAD | FWRITE), pThis->hVfsCtx);
    308     IPRT_DARWIN_RESTORE_EFL_AC();
    309 
    310     RTMemFree(pThis);
    311     return RTErrConvertFromErrno(rc);
    312 }
    313 
    314 
    315 RTDECL(int) RTFileReadAt(RTFILE hFile, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead)
    316 {
    317     RTFILEINT *pThis = hFile;
    318     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    319     AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
    320 
    321     off_t offNative = (off_t)off;
    322     AssertReturn((RTFOFF)offNative == off, VERR_OUT_OF_RANGE);
    323     IPRT_DARWIN_SAVE_EFL_AC();
    324 
    325 #if 0 /* Added in 10.6, grr. */
    326     errno_t rc;
    327     if (!pcbRead)
    328         rc = vn_rdwr(UIO_READ, pThis->hVnode, (char *)pvBuf, cbToRead, offNative, UIO_SYSSPACE, 0 /*ioflg*/,
    329                      vfs_context_ucred(pThis->hVfsCtx), NULL, vfs_context_proc(pThis->hVfsCtx));
    330     else
    331     {
    332         int cbLeft = 0;
    333         rc = vn_rdwr(UIO_READ, pThis->hVnode, (char *)pvBuf, cbToRead, offNative, UIO_SYSSPACE, 0 /*ioflg*/,
    334                      vfs_context_ucred(pThis->hVfsCtx), &cbLeft, vfs_context_proc(pThis->hVfsCtx));
    335         *pcbRead = cbToRead - cbLeft;
    336     }
    337     IPRT_DARWIN_RESTORE_EFL_AC();
    338     return !rc ? VINF_SUCCESS : RTErrConvertFromErrno(rc);
    339 
    340 #else
    341     uio_t hUio = uio_create(1, offNative, UIO_SYSSPACE, UIO_READ);
    342     if (!hUio)
    343     {
    344         IPRT_DARWIN_RESTORE_EFL_AC();
    345         return VERR_NO_MEMORY;
    346     }
    347     errno_t rc;
    348     if (uio_addiov(hUio, (user_addr_t)(uintptr_t)pvBuf, cbToRead) == 0)
    349     {
    350         rc = VNOP_READ(pThis->hVnode, hUio, 0 /*ioflg*/, pThis->hVfsCtx);
    351         if (pcbRead)
    352             *pcbRead = cbToRead - uio_resid(hUio);
    353         else if (!rc && uio_resid(hUio))
    354             rc = VERR_FILE_IO_ERROR;
    355     }
    356     else
    357         rc = VERR_INTERNAL_ERROR_3;
    358     uio_free(hUio);
    359     IPRT_DARWIN_RESTORE_EFL_AC();
    360     return rc;
    361 
    362 #endif
    363 }
    364 
    365193#endif
    366194
  • trunk/src/VBox/Runtime/r0drv/darwin/fileio-r0drv-darwin.cpp

    r75037 r75039  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Kernel Debug Information, R0 Driver, Darwin.
     3 * IPRT - File I/O, R0 Driver, Darwin.
    44 */
    55
    66/*
    7  * Copyright (C) 2011-2017 Oracle Corporation
     7 * Copyright (C) 2011-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2929*   Header Files                                                                                                                 *
    3030*********************************************************************************************************************************/
    31 #ifdef IN_RING0
    32 # include "the-darwin-kernel.h"
    33 # include <sys/kauth.h>
    34 RT_C_DECLS_BEGIN /* Buggy 10.4 headers, fixed in 10.5. */
    35 # include <sys/kpi_mbuf.h>
    36 # include <net/kpi_interfacefilter.h>
    37 # include <sys/kpi_socket.h>
    38 # include <sys/kpi_socketfilter.h>
    39 RT_C_DECLS_END
    40 # include <sys/buf.h>
    41 # include <sys/vm.h>
    42 # include <sys/vnode_if.h>
    43 /*# include <sys/sysctl.h>*/
    44 # include <sys/systm.h>
    45 # include <vfs/vfs_support.h>
    46 /*# include <miscfs/specfs/specdev.h>*/
    47 #else
    48 # include <stdio.h> /* for printf */
    49 #endif
    50 
    51 #if !defined(IN_RING0) && !defined(DOXYGEN_RUNNING) /* A linking tweak for the testcase: */
    52 # include <iprt/cdefs.h>
    53 # undef  RTR0DECL
    54 # define RTR0DECL(type) DECLHIDDEN(type) RTCALL
    55 #endif
    56 
     31#include "the-darwin-kernel.h"
     32
     33#include <iprt/file.h>
    5734#include "internal/iprt.h"
    58 #include <iprt/dbg.h>
    5935
    6036#include <iprt/asm.h>
    6137#include <iprt/assert.h>
    6238#include <iprt/err.h>
    63 #include <iprt/assert.h>
    64 #include <iprt/file.h>
    6539#include <iprt/log.h>
    6640#include <iprt/mem.h>
    6741#include <iprt/string.h>
    68 #include <iprt/formats/mach-o.h>
    6942#include "internal/magics.h"
    7043
    71 /** @def MY_CPU_TYPE
    72  * The CPU type targeted by the compiler. */
    73 /** @def MY_CPU_TYPE
    74  * The "ALL" CPU subtype targeted by the compiler. */
    75 /** @def MY_MACHO_HEADER
    76  * The Mach-O header targeted by the compiler.  */
    77 /** @def MY_MACHO_MAGIC
    78  * The Mach-O header magic we're targeting.  */
    79 /** @def MY_SEGMENT_COMMAND
    80  * The segment command targeted by the compiler.  */
    81 /** @def MY_SECTION
    82  * The section struture targeted by the compiler.  */
    83 /** @def MY_NLIST
    84  * The symbol table entry targeted by the compiler.  */
    85 #ifdef RT_ARCH_X86
    86 # define MY_CPU_TYPE            CPU_TYPE_I386
    87 # define MY_CPU_SUBTYPE_ALL     CPU_SUBTYPE_I386_ALL
    88 # define MY_MACHO_HEADER        mach_header_32_t
    89 # define MY_MACHO_MAGIC         IMAGE_MACHO32_SIGNATURE
    90 # define MY_SEGMENT_COMMAND     segment_command_32_t
    91 # define MY_SECTION             section_32_t
    92 # define MY_NLIST               macho_nlist_32_t
    93 
    94 #elif defined(RT_ARCH_AMD64)
    95 # define MY_CPU_TYPE            CPU_TYPE_X86_64
    96 # define MY_CPU_SUBTYPE_ALL     CPU_SUBTYPE_X86_64_ALL
    97 # define MY_MACHO_HEADER        mach_header_64_t
    98 # define MY_MACHO_MAGIC         IMAGE_MACHO64_SIGNATURE
    99 # define MY_SEGMENT_COMMAND     segment_command_64_t
    100 # define MY_SECTION             section_64_t
    101 # define MY_NLIST               macho_nlist_64_t
    102 
    103 #else
    104 # error "Port me!"
    105 #endif
    106 
    107 /** @name Return macros for make it simpler to track down too paranoid code.
    108  * @{
    109  */
    110 #ifdef DEBUG
    111 # define RETURN_VERR_BAD_EXE_FORMAT \
    112     do { Assert(!g_fBreakpointOnError);         return VERR_BAD_EXE_FORMAT; } while (0)
    113 # define RETURN_VERR_LDR_UNEXPECTED \
    114     do { Assert(!g_fBreakpointOnError);         return VERR_LDR_UNEXPECTED; } while (0)
    115 # define RETURN_VERR_LDR_ARCH_MISMATCH \
    116     do { Assert(!g_fBreakpointOnError);         return VERR_LDR_ARCH_MISMATCH; } while (0)
    117 #else
    118 # define RETURN_VERR_BAD_EXE_FORMAT     do {    return VERR_BAD_EXE_FORMAT; } while (0)
    119 # define RETURN_VERR_LDR_UNEXPECTED     do {    return VERR_LDR_UNEXPECTED; } while (0)
    120 # define RETURN_VERR_LDR_ARCH_MISMATCH  do {    return VERR_LDR_ARCH_MISMATCH; } while (0)
    121 #endif
    122 /** @} */
    123 
    124 #define VERR_LDR_UNEXPECTED     (-641)
    125 
    126 #ifndef RT_OS_DARWIN
    127 # define MAC_OS_X_VERSION_MIN_REQUIRED 1050
    128 #endif
    129 
    13044
    13145/*********************************************************************************************************************************
    132 *   Structures and Typedefs                                                                                                      *
     46*   Global Variables                                                                                                             *
    13347*********************************************************************************************************************************/
    134 /**
    135  * Our internal representation of the mach_kernel after loading it's symbols
    136  * and successfully resolving their addresses.
    137  */
    138 typedef struct RTDBGKRNLINFOINT
    139 {
    140     /** Magic value (RTDBGKRNLINFO_MAGIC). */
    141     uint32_t            u32Magic;
    142     /** Reference counter.  */
    143     uint32_t volatile   cRefs;
    144 
    145     /** @name Result.
    146      * @{ */
    147     /** Pointer to the string table. */
    148     char               *pachStrTab;
    149     /** The size of the string table. */
    150     uint32_t            cbStrTab;
    151     /** The file offset of the string table. */
    152     uint32_t            offStrTab;
    153     /** Pointer to the symbol table. */
    154     MY_NLIST           *paSyms;
    155     /** The size of the symbol table. */
    156     uint32_t            cSyms;
    157     /** The file offset of the symbol table. */
    158     uint32_t            offSyms;
    159     /** Offset between link address and actual load address. */
    160     uintptr_t           offLoad;
    161     /** @} */
    162 
    163     /** @name Used during loading.
    164      * @{ */
    165     /** The file handle.  */
    166     RTFILE              hFile;
    167     /** The architecture image offset (fat_arch_t::offset). */
    168     uint64_t            offArch;
    169     /** The architecture image size (fat_arch_t::size). */
    170     uint32_t            cbArch;
    171     /** The number of load commands (mach_header_XX_t::ncmds). */
    172     uint32_t            cLoadCmds;
    173     /** The size of the load commands. */
    174     uint32_t            cbLoadCmds;
    175     /** The load commands. */
    176     load_command_t     *pLoadCmds;
    177     /** Section pointer table (points into the load commands). */
    178     MY_SECTION const   *apSections[MACHO_MAX_SECT];
    179     /** The number of sections. */
    180     uint32_t            cSections;
    181     /** @} */
    182 
    183     /** Buffer space. */
    184     char                abBuf[_4K];
    185 } RTDBGKRNLINFOINT;
    186 
    187 
    188 /*********************************************************************************************************************************
    189 *   Structures and Typedefs                                                                                                      *
    190 *********************************************************************************************************************************/
    191 #ifdef DEBUG
    192 static bool g_fBreakpointOnError = false;
    193 #endif
    194 
    195 
    196 #ifdef IN_RING0
    197 
    19848/** Default file permissions for newly created files. */
    19949#if defined(S_IRUSR) && defined(S_IWUSR)
     
    20353#endif
    20454
     55
     56/*********************************************************************************************************************************
     57*   Structures and Typedefs                                                                                                      *
     58*********************************************************************************************************************************/
    20559/**
    20660 * Darwin kernel file handle data.
     
    21872    /** The vnode returned by vnode_open. */
    21973    vnode_t         hVnode;
     74    /** The current file offset. */
     75    uint64_t        offFile;
    22076} RTFILEINT;
    22177/** Magic number for RTFILEINT::u32Magic (To Be Determined). */
     
    349205    {
    350206        rc = VNOP_READ(pThis->hVnode, hUio, 0 /*ioflg*/, pThis->hVfsCtx);
     207        off_t const cbActual = cbToRead - uio_resid(hUio);
    351208        if (pcbRead)
    352             *pcbRead = cbToRead - uio_resid(hUio);
    353         else if (!rc && uio_resid(hUio))
    354             rc = VERR_FILE_IO_ERROR;
     209            *pcbRead = cbActual;
     210        if (rc == 0)
     211        {
     212            pThis->offFile += (uint64_t)cbActual;
     213            if (cbToRead != (uint64_t)cbActual)
     214                rc = VERR_FILE_IO_ERROR;
     215        }
     216        else
     217            rc = RTErrConvertFromErrno(rc);
    355218    }
    356219    else
     
    359222    IPRT_DARWIN_RESTORE_EFL_AC();
    360223    return rc;
    361 
    362224#endif
    363225}
    364226
    365 #endif
    366 
    367 
    368 /**
    369  * Close and free up resources we no longer needs.
    370  *
    371  * @param   pThis               The internal scratch data.
    372  */
    373 static void rtR0DbgKrnlDarwinLoadDone(RTDBGKRNLINFOINT *pThis)
    374 {
    375     RTFileClose(pThis->hFile);
    376     pThis->hFile = NIL_RTFILE;
    377 
    378     RTMemFree(pThis->pLoadCmds);
    379     pThis->pLoadCmds = NULL;
    380     memset((void *)&pThis->apSections[0], 0, sizeof(pThis->apSections[0]) * MACHO_MAX_SECT);
    381 }
    382 
    383 
    384 /**
    385  * Looks up a kernel symbol.
    386  *
    387  * @returns The symbol address on success, 0 on failure.
    388  * @param   pThis               The internal scratch data.
    389  * @param   pszSymbol           The symbol to resolve.  Automatically prefixed
    390  *                              with an underscore.
    391  */
    392 static uintptr_t rtR0DbgKrnlDarwinLookup(RTDBGKRNLINFOINT *pThis, const char *pszSymbol)
    393 {
    394     uint32_t const  cSyms = pThis->cSyms;
    395     MY_NLIST const *pSym = pThis->paSyms;
    396 
    397 #if 1
    398     /* linear search. */
    399     for (uint32_t iSym = 0; iSym < cSyms; iSym++, pSym++)
    400     {
    401         if (pSym->n_type & MACHO_N_STAB)
    402             continue;
    403 
    404         const char *pszTabName= &pThis->pachStrTab[(uint32_t)pSym->n_un.n_strx];
    405         if (   *pszTabName == '_'
    406             && strcmp(pszTabName + 1, pszSymbol) == 0)
    407             return pSym->n_value + pThis->offLoad;
    408     }
    409 #else
    410     /** @todo binary search. */
    411 
    412 #endif
    413     return 0;
    414 }
    415 
    416 
    417 /* Rainy day: Find the right headers for these symbols ... if there are any. */
    418 extern "C" void ev_try_lock(void);
    419 extern "C" void OSMalloc(void);
    420 extern "C" void OSlibkernInit(void);
    421 extern "C" void kdp_set_interface(void);
    422 
    423 
    424 /**
    425  * Check the symbol table against symbols we known symbols.
    426  *
    427  * This is done to detect whether the on disk image and the in
    428  * memory images matches.  Mismatches could stem from user
    429  * replacing the default kernel image on disk.
    430  *
    431  * @returns IPRT status code.
    432  * @param   pThis               The internal scratch data.
    433  */
    434 static int rtR0DbgKrnlDarwinCheckStandardSymbols(RTDBGKRNLINFOINT *pThis)
    435 {
    436     static struct
    437     {
    438         const char *pszName;
    439         uintptr_t   uAddr;
    440     } const s_aStandardCandles[] =
    441     {
    442 #ifdef IN_RING0
    443 # define KNOWN_ENTRY(a_Sym)  { #a_Sym, (uintptr_t)&a_Sym }
    444 #else
    445 # define KNOWN_ENTRY(a_Sym)  { #a_Sym, 0 }
    446 #endif
    447         /* IOKit: */
    448         KNOWN_ENTRY(IOMalloc),
    449         KNOWN_ENTRY(IOFree),
    450         KNOWN_ENTRY(IOSleep),
    451         KNOWN_ENTRY(IORWLockAlloc),
    452         KNOWN_ENTRY(IORecursiveLockLock),
    453         KNOWN_ENTRY(IOSimpleLockAlloc),
    454         KNOWN_ENTRY(PE_cpu_halt),
    455         KNOWN_ENTRY(gIOKitDebug),
    456         KNOWN_ENTRY(gIOServicePlane),
    457         KNOWN_ENTRY(ev_try_lock),
    458 
    459         /* Libkern: */
    460         KNOWN_ENTRY(OSAddAtomic),
    461         KNOWN_ENTRY(OSBitAndAtomic),
    462         KNOWN_ENTRY(OSBitOrAtomic),
    463         KNOWN_ENTRY(OSBitXorAtomic),
    464         KNOWN_ENTRY(OSCompareAndSwap),
    465         KNOWN_ENTRY(OSMalloc),
    466         KNOWN_ENTRY(OSlibkernInit),
    467         KNOWN_ENTRY(bcmp),
    468         KNOWN_ENTRY(copyout),
    469         KNOWN_ENTRY(copyin),
    470         KNOWN_ENTRY(kprintf),
    471         KNOWN_ENTRY(printf),
    472         KNOWN_ENTRY(lck_grp_alloc_init),
    473         KNOWN_ENTRY(lck_mtx_alloc_init),
    474         KNOWN_ENTRY(lck_rw_alloc_init),
    475         KNOWN_ENTRY(lck_spin_alloc_init),
    476         KNOWN_ENTRY(osrelease),
    477         KNOWN_ENTRY(ostype),
    478         KNOWN_ENTRY(panic),
    479         KNOWN_ENTRY(strprefix),
    480         //KNOWN_ENTRY(sysctlbyname), - we get kernel_sysctlbyname from the 10.10+ kernels.
    481         KNOWN_ENTRY(vsscanf),
    482         KNOWN_ENTRY(page_mask),
    483 
    484         /* Mach: */
    485         KNOWN_ENTRY(absolutetime_to_nanoseconds),
    486         KNOWN_ENTRY(assert_wait),
    487         KNOWN_ENTRY(clock_delay_until),
    488         KNOWN_ENTRY(clock_get_uptime),
    489         KNOWN_ENTRY(current_task),
    490         KNOWN_ENTRY(current_thread),
    491         KNOWN_ENTRY(kernel_task),
    492         KNOWN_ENTRY(lck_mtx_sleep),
    493         KNOWN_ENTRY(lck_rw_sleep),
    494         KNOWN_ENTRY(lck_spin_sleep),
    495         KNOWN_ENTRY(mach_absolute_time),
    496         KNOWN_ENTRY(semaphore_create),
    497         KNOWN_ENTRY(task_reference),
    498         KNOWN_ENTRY(thread_block),
    499         KNOWN_ENTRY(thread_reference),
    500         KNOWN_ENTRY(thread_terminate),
    501         KNOWN_ENTRY(thread_wakeup_prim),
    502 
    503         /* BSDKernel: */
    504         KNOWN_ENTRY(buf_size),
    505         KNOWN_ENTRY(copystr),
    506         KNOWN_ENTRY(current_proc),
    507         KNOWN_ENTRY(ifnet_hdrlen),
    508         KNOWN_ENTRY(ifnet_set_promiscuous),
    509         KNOWN_ENTRY(kauth_getuid),
    510 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
    511         KNOWN_ENTRY(kauth_cred_unref),
    512 #else
    513         KNOWN_ENTRY(kauth_cred_rele),
    514 #endif
    515         KNOWN_ENTRY(mbuf_data),
    516         KNOWN_ENTRY(msleep),
    517         KNOWN_ENTRY(nanotime),
    518         KNOWN_ENTRY(nop_close),
    519         KNOWN_ENTRY(proc_pid),
    520         KNOWN_ENTRY(sock_accept),
    521         KNOWN_ENTRY(sockopt_name),
    522         //KNOWN_ENTRY(spec_write),
    523         KNOWN_ENTRY(suword),
    524         //KNOWN_ENTRY(sysctl_int),
    525         KNOWN_ENTRY(uio_rw),
    526         KNOWN_ENTRY(vfs_flags),
    527         KNOWN_ENTRY(vfs_name),
    528         KNOWN_ENTRY(vfs_statfs),
    529         KNOWN_ENTRY(VNOP_READ),
    530         KNOWN_ENTRY(uio_create),
    531         KNOWN_ENTRY(uio_addiov),
    532         KNOWN_ENTRY(uio_free),
    533         KNOWN_ENTRY(vnode_get),
    534         KNOWN_ENTRY(vnode_open),
    535         KNOWN_ENTRY(vnode_ref),
    536         KNOWN_ENTRY(vnode_rele),
    537         KNOWN_ENTRY(vnop_close_desc),
    538         KNOWN_ENTRY(wakeup),
    539         KNOWN_ENTRY(wakeup_one),
    540 
    541         /* Unsupported: */
    542         KNOWN_ENTRY(kdp_set_interface),
    543         KNOWN_ENTRY(pmap_find_phys),
    544         KNOWN_ENTRY(vm_map),
    545         KNOWN_ENTRY(vm_protect),
    546         KNOWN_ENTRY(vm_region),
    547         KNOWN_ENTRY(vm_map_unwire), /* vm_map_wire has an alternative symbol, vm_map_wire_external, in 10.11  */
    548         KNOWN_ENTRY(PE_kputc),
    549         KNOWN_ENTRY(kernel_map),
    550         KNOWN_ENTRY(kernel_pmap),
    551     };
    552 
    553     for (unsigned i = 0; i < RT_ELEMENTS(s_aStandardCandles); i++)
    554     {
    555         uintptr_t uAddr = rtR0DbgKrnlDarwinLookup(pThis, s_aStandardCandles[i].pszName);
    556 #ifdef IN_RING0
    557         if (uAddr != s_aStandardCandles[i].uAddr)
    558 #else
    559         if (uAddr == 0)
    560 #endif
    561         {
    562             AssertLogRelMsgFailed(("%s (%p != %p)\n", s_aStandardCandles[i].pszName, uAddr, s_aStandardCandles[i].uAddr));
    563             return VERR_INTERNAL_ERROR_2;
    564         }
    565     }
    566     return VINF_SUCCESS;
    567 }
    568 
    569 
    570 /**
    571  * Loads and validates the symbol and string tables.
    572  *
    573  * @returns IPRT status code.
    574  * @param   pThis               The internal scratch data.
    575  * @param   pszKernelFile       The name of the kernel file.
    576  */
    577 static int rtR0DbgKrnlDarwinLoadSymTab(RTDBGKRNLINFOINT *pThis, const char *pszKernelFile)
    578 {
     227
     228RTDECL(int) RTFileRead(RTFILE hFile, void *pvBuf, size_t cbToRead, size_t *pcbRead)
     229{
     230    RTFILEINT *pThis = hFile;
     231    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     232    AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
     233
     234    return RTFileReadAt(hFile, pThis->offFile, pvBuf, cbToRead, pcbRead);
     235}
     236
     237
     238RTDECL(int) RTFileGetSize(RTFILE hFile, uint64_t *pcbSize)
     239{
     240    RTFILEINT *pThis = hFile;
     241    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     242    AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
     243
    579244    /*
    580      * Load the tables.
     245     * Query the data size attribute.
     246     * Note! Allocate extra attribute buffer space to be on the safe side.
    581247     */
    582     pThis->paSyms = (MY_NLIST *)RTMemAllocZ(pThis->cSyms * sizeof(MY_NLIST));
    583     if (!pThis->paSyms)
    584         return VERR_NO_MEMORY;
    585 
    586     int rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offSyms,
    587                           pThis->paSyms, pThis->cSyms * sizeof(MY_NLIST), NULL);
    588     if (RT_FAILURE(rc))
    589         return rc;
    590 
    591     pThis->pachStrTab = (char *)RTMemAllocZ(pThis->cbStrTab + 1);
    592     if (!pThis->pachStrTab)
    593         return VERR_NO_MEMORY;
    594 
    595     rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offStrTab,
    596                       pThis->pachStrTab, pThis->cbStrTab, NULL);
    597     if (RT_FAILURE(rc))
    598         return rc;
    599 
    600     /*
    601      * The first string table symbol must be a zero length name.
    602      */
    603     if (pThis->pachStrTab[0] != '\0')
    604         RETURN_VERR_BAD_EXE_FORMAT;
    605 
    606     /*
    607      * Validate the symbol table.
    608      */
    609     const char     *pszPrev = "";
    610     uint32_t const  cSyms   = pThis->cSyms;
    611     MY_NLIST const  *pSym   = pThis->paSyms;
    612     for (uint32_t iSym = 0; iSym < cSyms; iSym++, pSym++)
    613     {
    614         if ((uint32_t)pSym->n_un.n_strx >= pThis->cbStrTab)
    615         {
    616             printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u has a bad string table index: %#x vs cbStrTab=%#x\n",
    617                    pszKernelFile, iSym, pSym->n_un.n_strx, pThis->cbStrTab);
    618             RETURN_VERR_BAD_EXE_FORMAT;
    619         }
    620         const char *pszSym = &pThis->pachStrTab[(uint32_t)pSym->n_un.n_strx];
    621 #ifdef IN_RING3
    622         RTAssertMsg2("%05i: %02x:%08llx %02x %04x %s\n", iSym, pSym->n_sect, (uint64_t)pSym->n_value, pSym->n_type, pSym->n_desc, pszSym);
    623 #endif
    624 
    625         if (strcmp(pszSym, pszPrev) < 0)
    626             RETURN_VERR_BAD_EXE_FORMAT; /* not sorted */
    627 
    628         if (!(pSym->n_type & MACHO_N_STAB))
    629         {
    630             switch (pSym->n_type & MACHO_N_TYPE)
    631             {
    632                 case MACHO_N_SECT:
    633                     if (pSym->n_sect == MACHO_NO_SECT)
    634                     {
    635                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_sect = MACHO_NO_SECT\n",
    636                                pszKernelFile, iSym, pszSym);
    637                         RETURN_VERR_BAD_EXE_FORMAT;
    638                     }
    639                     if (pSym->n_sect > pThis->cSections)
    640                     {
    641                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_sect (%u) is higher than cSections (%u)\n",
    642                                pszKernelFile, iSym, pszSym, pSym->n_sect, pThis->cSections);
    643                         RETURN_VERR_BAD_EXE_FORMAT;
    644                     }
    645                     if (pSym->n_desc & ~(REFERENCED_DYNAMICALLY | N_WEAK_DEF))
    646                     {
    647                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: Unexpected value n_desc=%#x\n",
    648                                pszKernelFile, iSym, pszSym, pSym->n_desc);
    649                         RETURN_VERR_BAD_EXE_FORMAT;
    650                     }
    651                     if (   pSym->n_value < pThis->apSections[pSym->n_sect - 1]->addr
    652                         && strcmp(pszSym, "__mh_execute_header"))    /* in 10.8 it's no longer absolute (PIE?). */
    653                     {
    654                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_value (%#llx) < section addr (%#llx)\n",
    655                                pszKernelFile, iSym, pszSym, pSym->n_value, pThis->apSections[pSym->n_sect - 1]->addr);
    656                         RETURN_VERR_BAD_EXE_FORMAT;
    657                     }
    658                     if (      pSym->n_value - pThis->apSections[pSym->n_sect - 1]->addr
    659                            > pThis->apSections[pSym->n_sect - 1]->size
    660                         && strcmp(pszSym, "__mh_execute_header"))    /* see above. */
    661                     {
    662                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_value (%#llx) >= end of section (%#llx + %#llx)\n",
    663                                pszKernelFile, iSym, pszSym, pSym->n_value, pThis->apSections[pSym->n_sect - 1]->addr,
    664                                pThis->apSections[pSym->n_sect - 1]->size);
    665                         RETURN_VERR_BAD_EXE_FORMAT;
    666                     }
    667                     break;
    668 
    669                 case MACHO_N_ABS:
    670                     if (   pSym->n_sect != MACHO_NO_SECT
    671                         && (   strcmp(pszSym, "__mh_execute_header") /* n_sect=1 in 10.7/amd64 */
    672                             || pSym->n_sect > pThis->cSections) )
    673                     {
    674                         printf("RTR0DbgKrnlInfoOpen: %s: Abs symbol #%u '%s' problem: n_sect (%u) is not MACHO_NO_SECT (cSections is %u)\n",
    675                                pszKernelFile, iSym, pszSym, pSym->n_sect, pThis->cSections);
    676                         RETURN_VERR_BAD_EXE_FORMAT;
    677                     }
    678                     if (pSym->n_desc & ~(REFERENCED_DYNAMICALLY | N_WEAK_DEF))
    679                     {
    680                         printf("RTR0DbgKrnlInfoOpen: %s: Abs symbol #%u '%s' problem: Unexpected value n_desc=%#x\n",
    681                                pszKernelFile, iSym, pszSym, pSym->n_desc);
    682                         RETURN_VERR_BAD_EXE_FORMAT;
    683                     }
    684                     break;
    685 
    686                 case MACHO_N_UNDF:
    687                     /* No undefined or common symbols in the kernel. */
    688                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected undefined symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
    689                     RETURN_VERR_BAD_EXE_FORMAT;
    690 
    691                 case MACHO_N_INDR:
    692                     /* No indirect symbols in the kernel. */
    693                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected indirect symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
    694                     RETURN_VERR_BAD_EXE_FORMAT;
    695 
    696                 case MACHO_N_PBUD:
    697                     /* No prebound symbols in the kernel. */
    698                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected prebound symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
    699                     RETURN_VERR_BAD_EXE_FORMAT;
    700 
    701                 default:
    702                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected symbol n_type %#x for symbol #%u '%s'\n",
    703                            pszKernelFile, pSym->n_type, iSym, pszSym);
    704                     RETURN_VERR_BAD_EXE_FORMAT;
    705             }
    706         }
    707         /* else: Ignore debug symbols. */
    708     }
    709 
    710     return VINF_SUCCESS;
    711 }
    712 
    713 
    714 /**
    715  * Loads the load commands and validates them.
    716  *
    717  * @returns IPRT status code.
    718  * @param   pThis               The internal scratch data.
    719  */
    720 static int rtR0DbgKrnlDarwinLoadCommands(RTDBGKRNLINFOINT *pThis)
    721 {
    722     pThis->offStrTab = 0;
    723     pThis->cbStrTab  = 0;
    724     pThis->offSyms   = 0;
    725     pThis->cSyms     = 0;
    726     pThis->cSections = 0;
    727 
    728     pThis->pLoadCmds = (load_command_t *)RTMemAlloc(pThis->cbLoadCmds);
    729     if (!pThis->pLoadCmds)
    730         return VERR_NO_MEMORY;
    731 
    732     int rc = RTFileReadAt(pThis->hFile, pThis->offArch + sizeof(MY_MACHO_HEADER),
    733                           pThis->pLoadCmds, pThis->cbLoadCmds, NULL);
    734     if (RT_FAILURE(rc))
    735         return rc;
    736 
    737     /*
    738      * Validate the relevant commands, picking up sections and the symbol
    739      * table location.
    740      */
    741     load_command_t const   *pCmd = pThis->pLoadCmds;
    742     for (uint32_t iCmd = 0; ; iCmd++)
    743     {
    744         /* cmd index & offset. */
    745         uintptr_t offCmd = (uintptr_t)pCmd - (uintptr_t)pThis->pLoadCmds;
    746         if (offCmd == pThis->cbLoadCmds && iCmd == pThis->cLoadCmds)
    747             break;
    748         if (offCmd + sizeof(*pCmd) > pThis->cbLoadCmds)
    749             RETURN_VERR_BAD_EXE_FORMAT;
    750         if (iCmd >= pThis->cLoadCmds)
    751             RETURN_VERR_BAD_EXE_FORMAT;
    752 
    753         /* cmdsize */
    754         if (pCmd->cmdsize < sizeof(*pCmd))
    755             RETURN_VERR_BAD_EXE_FORMAT;
    756         if (pCmd->cmdsize > pThis->cbLoadCmds)
    757             RETURN_VERR_BAD_EXE_FORMAT;
    758         if (RT_ALIGN_32(pCmd->cmdsize, 4) != pCmd->cmdsize)
    759             RETURN_VERR_BAD_EXE_FORMAT;
    760 
    761         /* cmd */
    762         switch (pCmd->cmd & ~LC_REQ_DYLD)
    763         {
    764             /* Validate and store the symbol table details. */
    765             case LC_SYMTAB:
    766             {
    767                 struct symtab_command const *pSymTab = (struct symtab_command const *)pCmd;
    768                 if (pSymTab->cmdsize != sizeof(*pSymTab))
    769                     RETURN_VERR_BAD_EXE_FORMAT;
    770                 if (pSymTab->nsyms > _1M)
    771                     RETURN_VERR_BAD_EXE_FORMAT;
    772                 if (pSymTab->strsize > _2M)
    773                     RETURN_VERR_BAD_EXE_FORMAT;
    774 
    775                 pThis->offStrTab = pSymTab->stroff;
    776                 pThis->cbStrTab  = pSymTab->strsize;
    777                 pThis->offSyms   = pSymTab->symoff;
    778                 pThis->cSyms     = pSymTab->nsyms;
    779                 break;
    780             }
    781 
    782             /* Validate the segment. */
    783 #if ARCH_BITS == 32
    784             case LC_SEGMENT_32:
    785 #elif ARCH_BITS == 64
    786             case LC_SEGMENT_64:
    787 #else
    788 # error ARCH_BITS
    789 #endif
    790             {
    791                 MY_SEGMENT_COMMAND const *pSeg = (MY_SEGMENT_COMMAND const *)pCmd;
    792                 if (pSeg->cmdsize < sizeof(*pSeg))
    793                     RETURN_VERR_BAD_EXE_FORMAT;
    794 
    795                 if (pSeg->segname[0] == '\0')
    796                     RETURN_VERR_BAD_EXE_FORMAT;
    797 
    798                 if (pSeg->nsects > MACHO_MAX_SECT)
    799                     RETURN_VERR_BAD_EXE_FORMAT;
    800                 if (pSeg->nsects * sizeof(MY_SECTION) + sizeof(*pSeg) != pSeg->cmdsize)
    801                     RETURN_VERR_BAD_EXE_FORMAT;
    802 
    803                 if (pSeg->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1))
    804                     RETURN_VERR_BAD_EXE_FORMAT;
    805 
    806                 if (   pSeg->vmaddr != 0
    807                     || !strcmp(pSeg->segname, "__PAGEZERO"))
    808                 {
    809                     if (pSeg->vmaddr + RT_ALIGN_Z(pSeg->vmsize, RT_BIT_32(12)) < pSeg->vmaddr)
    810                         RETURN_VERR_BAD_EXE_FORMAT;
    811                 }
    812                 else if (pSeg->vmsize)
    813                     RETURN_VERR_BAD_EXE_FORMAT;
    814 
    815                 if (pSeg->maxprot & ~VM_PROT_ALL)
    816                     RETURN_VERR_BAD_EXE_FORMAT;
    817                 if (pSeg->initprot & ~VM_PROT_ALL)
    818                     RETURN_VERR_BAD_EXE_FORMAT;
    819 
    820                 /* Validate the sections. */
    821                 uint32_t            uAlignment = 0;
    822                 MY_SECTION const   *paSects    = (MY_SECTION const *)(pSeg + 1);
    823                 for (uint32_t i = 0; i < pSeg->nsects; i++)
    824                 {
    825                     if (paSects[i].sectname[0] == '\0')
    826                         RETURN_VERR_BAD_EXE_FORMAT;
    827                     if (memcmp(paSects[i].segname, pSeg->segname, sizeof(pSeg->segname)))
    828                         RETURN_VERR_BAD_EXE_FORMAT;
    829 
    830                     switch (paSects[i].flags & SECTION_TYPE)
    831                     {
    832                         case S_REGULAR:
    833                         case S_CSTRING_LITERALS:
    834                         case S_NON_LAZY_SYMBOL_POINTERS:
    835                         case S_MOD_INIT_FUNC_POINTERS:
    836                         case S_MOD_TERM_FUNC_POINTERS:
    837                         case S_COALESCED:
    838                         case S_4BYTE_LITERALS:
    839                             if (  pSeg->filesize != 0
    840                                 ? paSects[i].offset - pSeg->fileoff >= pSeg->filesize
    841                                 : paSects[i].offset - pSeg->fileoff != pSeg->filesize)
    842                                 RETURN_VERR_BAD_EXE_FORMAT;
    843                             if (   paSects[i].addr != 0
    844                                 && paSects[i].offset - pSeg->fileoff != paSects[i].addr - pSeg->vmaddr)
    845                                 RETURN_VERR_BAD_EXE_FORMAT;
    846                             break;
    847 
    848                         case S_ZEROFILL:
    849                             if (paSects[i].offset != 0)
    850                                 RETURN_VERR_BAD_EXE_FORMAT;
    851                             break;
    852 
    853                         /* not observed */
    854                         case S_SYMBOL_STUBS:
    855                         case S_INTERPOSING:
    856                         case S_8BYTE_LITERALS:
    857                         case S_16BYTE_LITERALS:
    858                         case S_DTRACE_DOF:
    859                         case S_LAZY_SYMBOL_POINTERS:
    860                         case S_LAZY_DYLIB_SYMBOL_POINTERS:
    861                             RETURN_VERR_LDR_UNEXPECTED;
    862                         case S_GB_ZEROFILL:
    863                             RETURN_VERR_LDR_UNEXPECTED;
    864                         default:
    865                             RETURN_VERR_BAD_EXE_FORMAT;
    866                     }
    867 
    868                     if (paSects[i].align > 12)
    869                         RETURN_VERR_BAD_EXE_FORMAT;
    870                     if (paSects[i].align > uAlignment)
    871                         uAlignment = paSects[i].align;
    872 
    873                     /* Add to the section table. */
    874                     if (pThis->cSections == MACHO_MAX_SECT)
    875                         RETURN_VERR_BAD_EXE_FORMAT;
    876                     pThis->apSections[pThis->cSections++] = &paSects[i];
    877                 }
    878 
    879                 if (RT_ALIGN_Z(pSeg->vmaddr, RT_BIT_32(uAlignment)) != pSeg->vmaddr)
    880                     RETURN_VERR_BAD_EXE_FORMAT;
    881                 if (   pSeg->filesize > RT_ALIGN_Z(pSeg->vmsize, RT_BIT_32(uAlignment))
    882                     && pSeg->vmsize != 0)
    883                     RETURN_VERR_BAD_EXE_FORMAT;
    884                 break;
    885             }
    886 
    887             case LC_UUID:
    888                 if (pCmd->cmdsize != sizeof(uuid_command))
    889                     RETURN_VERR_BAD_EXE_FORMAT;
    890                 break;
    891 
    892             case LC_DYSYMTAB:
    893             case LC_UNIXTHREAD:
    894             case LC_CODE_SIGNATURE:
    895             case LC_VERSION_MIN_MACOSX:
    896             case LC_FUNCTION_STARTS:
    897             case LC_MAIN:
    898             case LC_DATA_IN_CODE:
    899             case LC_SOURCE_VERSION:
    900             case LC_ENCRYPTION_INFO_64:
    901             case LC_LINKER_OPTION:
    902             case LC_LINKER_OPTIMIZATION_HINT:
    903             case LC_VERSION_MIN_TVOS:
    904             case LC_VERSION_MIN_WATCHOS:
    905             case LC_NOTE:
    906             case LC_BUILD_VERSION:
    907                 break;
    908 
    909             /* not observed */
    910             case LC_SYMSEG:
    911 #if ARCH_BITS == 32
    912             case LC_SEGMENT_64:
    913 #elif ARCH_BITS == 64
    914             case LC_SEGMENT_32:
    915 #endif
    916             case LC_ROUTINES_64:
    917             case LC_ROUTINES:
    918             case LC_THREAD:
    919             case LC_LOADFVMLIB:
    920             case LC_IDFVMLIB:
    921             case LC_IDENT:
    922             case LC_FVMFILE:
    923             case LC_PREPAGE:
    924             case LC_TWOLEVEL_HINTS:
    925             case LC_PREBIND_CKSUM:
    926             case LC_SEGMENT_SPLIT_INFO:
    927             case LC_ENCRYPTION_INFO:
    928                 RETURN_VERR_LDR_UNEXPECTED;
    929 
    930             /* no phones here yet */
    931             case LC_VERSION_MIN_IPHONEOS:
    932                 RETURN_VERR_LDR_UNEXPECTED;
    933 
    934             /* dylib */
    935             case LC_LOAD_DYLIB:
    936             case LC_ID_DYLIB:
    937             case LC_LOAD_DYLINKER:
    938             case LC_ID_DYLINKER:
    939             case LC_PREBOUND_DYLIB:
    940             case LC_LOAD_WEAK_DYLIB & ~LC_REQ_DYLD:
    941             case LC_SUB_FRAMEWORK:
    942             case LC_SUB_UMBRELLA:
    943             case LC_SUB_CLIENT:
    944             case LC_SUB_LIBRARY:
    945             case LC_RPATH:
    946             case LC_REEXPORT_DYLIB:
    947             case LC_LAZY_LOAD_DYLIB:
    948             case LC_DYLD_INFO:
    949             case LC_DYLD_INFO_ONLY:
    950             case LC_LOAD_UPWARD_DYLIB:
    951             case LC_DYLD_ENVIRONMENT:
    952             case LC_DYLIB_CODE_SIGN_DRS:
    953                 RETURN_VERR_LDR_UNEXPECTED;
    954 
    955             default:
    956                 RETURN_VERR_BAD_EXE_FORMAT;
    957         }
    958 
    959         /* next */
    960         pCmd = (load_command_t *)((uintptr_t)pCmd + pCmd->cmdsize);
    961     }
    962 
    963     return VINF_SUCCESS;
    964 }
    965 
    966 
    967 /**
    968  * Loads the FAT and MACHO headers, noting down the relevant info.
    969  *
    970  * @returns IPRT status code.
    971  * @param   pThis               The internal scratch data.
    972  */
    973 static int rtR0DbgKrnlDarwinLoadFileHeaders(RTDBGKRNLINFOINT *pThis)
    974 {
    975     uint32_t i;
    976 
    977     pThis->offArch = 0;
    978     pThis->cbArch  = 0;
    979 
    980     /*
    981      * Read the first bit of the file, parse the FAT if found there.
    982      */
    983     int rc = RTFileReadAt(pThis->hFile, 0, pThis->abBuf, sizeof(fat_header_t) + sizeof(fat_arch_t) * 16, NULL);
    984     if (RT_FAILURE(rc))
    985         return rc;
    986 
    987     fat_header_t   *pFat        = (fat_header *)pThis->abBuf;
    988     fat_arch_t     *paFatArches = (fat_arch_t *)(pFat + 1);
    989 
    990     /* Correct FAT endian first. */
    991     if (pFat->magic == IMAGE_FAT_SIGNATURE_OE)
    992     {
    993         pFat->magic     = RT_BSWAP_U32(pFat->magic);
    994         pFat->nfat_arch = RT_BSWAP_U32(pFat->nfat_arch);
    995         i = RT_MIN(pFat->nfat_arch, 16);
    996         while (i-- > 0)
    997         {
    998             paFatArches[i].cputype    = RT_BSWAP_U32(paFatArches[i].cputype);
    999             paFatArches[i].cpusubtype = RT_BSWAP_U32(paFatArches[i].cpusubtype);
    1000             paFatArches[i].offset     = RT_BSWAP_U32(paFatArches[i].offset);
    1001             paFatArches[i].size       = RT_BSWAP_U32(paFatArches[i].size);
    1002             paFatArches[i].align      = RT_BSWAP_U32(paFatArches[i].align);
    1003         }
    1004     }
    1005 
    1006     /* Lookup our architecture in the FAT. */
    1007     if (pFat->magic == IMAGE_FAT_SIGNATURE)
    1008     {
    1009         if (pFat->nfat_arch > 16)
    1010             RETURN_VERR_BAD_EXE_FORMAT;
    1011 
    1012         for (i = 0; i < pFat->nfat_arch; i++)
    1013         {
    1014             if (   paFatArches[i].cputype == MY_CPU_TYPE
    1015                 && paFatArches[i].cpusubtype == MY_CPU_SUBTYPE_ALL)
    1016             {
    1017                 pThis->offArch = paFatArches[i].offset;
    1018                 pThis->cbArch  = paFatArches[i].size;
    1019                 if (!pThis->cbArch)
    1020                     RETURN_VERR_BAD_EXE_FORMAT;
    1021                 if (pThis->offArch < sizeof(fat_header_t) + sizeof(fat_arch_t) * pFat->nfat_arch)
    1022                     RETURN_VERR_BAD_EXE_FORMAT;
    1023                 if (pThis->offArch + pThis->cbArch <= pThis->offArch)
    1024                     RETURN_VERR_LDR_ARCH_MISMATCH;
    1025                 break;
    1026             }
    1027         }
    1028         if (i >= pFat->nfat_arch)
    1029             RETURN_VERR_LDR_ARCH_MISMATCH;
    1030     }
    1031 
    1032     /*
    1033      * Read the Mach-O header and validate it.
    1034      */
    1035     rc = RTFileReadAt(pThis->hFile, pThis->offArch, pThis->abBuf, sizeof(MY_MACHO_HEADER), NULL);
    1036     if (RT_FAILURE(rc))
    1037         return rc;
    1038     MY_MACHO_HEADER const *pHdr = (MY_MACHO_HEADER const *)pThis->abBuf;
    1039     if (pHdr->magic != MY_MACHO_MAGIC)
    1040     {
    1041         if (   pHdr->magic == IMAGE_MACHO32_SIGNATURE
    1042             || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
    1043             || pHdr->magic == IMAGE_MACHO64_SIGNATURE
    1044             || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE)
    1045             RETURN_VERR_LDR_ARCH_MISMATCH;
    1046         RETURN_VERR_BAD_EXE_FORMAT;
    1047     }
    1048 
    1049     if (pHdr->cputype    != MY_CPU_TYPE)
    1050         RETURN_VERR_LDR_ARCH_MISMATCH;
    1051     if (pHdr->cpusubtype != MY_CPU_SUBTYPE_ALL)
    1052         RETURN_VERR_LDR_ARCH_MISMATCH;
    1053     if (pHdr->filetype   != MH_EXECUTE)
    1054         RETURN_VERR_LDR_UNEXPECTED;
    1055     if (pHdr->ncmds      < 4)
    1056         RETURN_VERR_LDR_UNEXPECTED;
    1057     if (pHdr->ncmds      > 256)
    1058         RETURN_VERR_LDR_UNEXPECTED;
    1059     if (pHdr->sizeofcmds <= pHdr->ncmds * sizeof(load_command_t))
    1060         RETURN_VERR_LDR_UNEXPECTED;
    1061     if (pHdr->sizeofcmds >= _1M)
    1062         RETURN_VERR_LDR_UNEXPECTED;
    1063     if (pHdr->flags & ~MH_VALID_FLAGS)
    1064         RETURN_VERR_LDR_UNEXPECTED;
    1065 
    1066     pThis->cLoadCmds  = pHdr->ncmds;
    1067     pThis->cbLoadCmds = pHdr->sizeofcmds;
    1068     return VINF_SUCCESS;
    1069 }
    1070 
    1071 
    1072 /**
    1073  * Destructor.
    1074  *
    1075  * @param   pThis               The instance to destroy.
    1076  */
    1077 static void rtR0DbgKrnlDarwinDtor(RTDBGKRNLINFOINT *pThis)
    1078 {
    1079     pThis->u32Magic = ~RTDBGKRNLINFO_MAGIC;
    1080 
    1081     RTMemFree(pThis->pachStrTab);
    1082     pThis->pachStrTab = NULL;
    1083 
    1084     RTMemFree(pThis->paSyms);
    1085     pThis->paSyms = NULL;
    1086 
    1087     RTMemFree(pThis);
    1088 }
    1089 
    1090 
    1091 static int rtR0DbgKrnlDarwinOpen(PRTDBGKRNLINFO phKrnlInfo, const char *pszKernelFile)
    1092 {
    1093     RTDBGKRNLINFOINT *pThis = (RTDBGKRNLINFOINT *)RTMemAllocZ(sizeof(*pThis));
    1094     if (!pThis)
    1095         return VERR_NO_MEMORY;
    1096     pThis->hFile = NIL_RTFILE;
    1097 
    1098     int rc = RTFileOpen(&pThis->hFile, pszKernelFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
    1099     if (RT_SUCCESS(rc))
    1100         rc = rtR0DbgKrnlDarwinLoadFileHeaders(pThis);
    1101     if (RT_SUCCESS(rc))
    1102         rc = rtR0DbgKrnlDarwinLoadCommands(pThis);
    1103     if (RT_SUCCESS(rc))
    1104         rc = rtR0DbgKrnlDarwinLoadSymTab(pThis, pszKernelFile);
    1105     if (RT_SUCCESS(rc))
    1106     {
    1107 #ifdef IN_RING0
    1108         /*
    1109          * Determine the load displacement (10.8 kernels are PIE).
    1110          */
    1111         uintptr_t uLinkAddr = rtR0DbgKrnlDarwinLookup(pThis, "kernel_map");
    1112         if (uLinkAddr != 0)
    1113             pThis->offLoad = (uintptr_t)&kernel_map - uLinkAddr;
    1114 #endif
    1115         rc = rtR0DbgKrnlDarwinCheckStandardSymbols(pThis);
    1116     }
    1117 
    1118     rtR0DbgKrnlDarwinLoadDone(pThis);
    1119     if (RT_SUCCESS(rc))
    1120     {
    1121         pThis->u32Magic = RTDBGKRNLINFO_MAGIC;
    1122         pThis->cRefs    = 1;
    1123         *phKrnlInfo = pThis;
    1124     }
    1125     else
    1126         rtR0DbgKrnlDarwinDtor(pThis);
    1127     return rc;
    1128 }
    1129 
    1130 
    1131 RTR0DECL(int) RTR0DbgKrnlInfoOpen(PRTDBGKRNLINFO phKrnlInfo, uint32_t fFlags)
    1132 {
    1133     AssertPtrReturn(phKrnlInfo, VERR_INVALID_POINTER);
    1134     *phKrnlInfo = NIL_RTDBGKRNLINFO;
    1135     AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
    1136 
    1137     /*
    1138      * Go thru likely kernel locations
    1139      *
    1140      * Note! Check the OS X version and reorder the list?
    1141      * Note! We should try fish kcsuffix out of bootargs or somewhere one day.
    1142      */
    1143     static bool s_fFirstCall = true;
    1144 #ifdef IN_RING3
    1145     extern const char *g_pszTestKernel;
    1146 #endif
    1147     struct
    1148     {
    1149         const char *pszLocation;
    1150         int         rc;
    1151     } aKernels[] =
    1152     {
    1153 #ifdef IN_RING3
    1154         { g_pszTestKernel, VERR_WRONG_ORDER },
    1155 #endif
    1156         { "/System/Library/Kernels/kernel", VERR_WRONG_ORDER },
    1157         { "/System/Library/Kernels/kernel.development", VERR_WRONG_ORDER },
    1158         { "/System/Library/Kernels/kernel.debug", VERR_WRONG_ORDER },
    1159         { "/mach_kernel", VERR_WRONG_ORDER },
    1160     };
    1161     int rc = VERR_WRONG_ORDER; /* shut up stupid MSC */
    1162     for (uint32_t i = 0; i < RT_ELEMENTS(aKernels); i++)
    1163     {
    1164         aKernels[i].rc = rc = rtR0DbgKrnlDarwinOpen(phKrnlInfo, aKernels[i].pszLocation);
    1165         if (RT_SUCCESS(rc))
    1166         {
    1167             if (s_fFirstCall)
    1168             {
    1169                 printf("RTR0DbgKrnlInfoOpen: Using kernel file '%s'\n", aKernels[i].pszLocation);
    1170                 s_fFirstCall = false;
    1171             }
    1172             return rc;
    1173         }
    1174     }
    1175 
    1176     /*
    1177      * Failed.
    1178      */
    1179     /* Pick the best error code. */
    1180     for (uint32_t i = 0; rc == VERR_FILE_NOT_FOUND && i < RT_ELEMENTS(aKernels); i++)
    1181         if (aKernels[i].rc != VERR_FILE_NOT_FOUND)
    1182             rc = aKernels[i].rc;
    1183 
    1184     /* Bitch about it. */
    1185     printf("RTR0DbgKrnlInfoOpen: failed to find matching kernel file! rc=%d\n", rc);
    1186     if (s_fFirstCall)
    1187     {
    1188         for (uint32_t i = 0; i < RT_ELEMENTS(aKernels); i++)
    1189             printf("RTR0DbgKrnlInfoOpen: '%s' -> %d\n", aKernels[i].pszLocation, aKernels[i].rc);
    1190         s_fFirstCall = false;
    1191     }
    1192 
    1193     return rc;
    1194 }
    1195 
    1196 
    1197 RTR0DECL(uint32_t) RTR0DbgKrnlInfoRetain(RTDBGKRNLINFO hKrnlInfo)
    1198 {
    1199     RTDBGKRNLINFOINT *pThis = hKrnlInfo;
    1200     AssertPtrReturn(pThis, UINT32_MAX);
    1201     AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), UINT32_MAX);
    1202 
    1203     uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
    1204     Assert(cRefs && cRefs < 100000);
    1205     return cRefs;
    1206 }
    1207 
    1208 
    1209 RTR0DECL(uint32_t) RTR0DbgKrnlInfoRelease(RTDBGKRNLINFO hKrnlInfo)
    1210 {
    1211     RTDBGKRNLINFOINT *pThis = hKrnlInfo;
    1212     if (pThis == NIL_RTDBGKRNLINFO)
    1213         return 0;
    1214     AssertPtrReturn(pThis, UINT32_MAX);
    1215     AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), UINT32_MAX);
    1216 
    1217     uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
    1218     if (cRefs == 0)
    1219         rtR0DbgKrnlDarwinDtor(pThis);
    1220     return cRefs;
    1221 }
    1222 
    1223 
    1224 RTR0DECL(int) RTR0DbgKrnlInfoQueryMember(RTDBGKRNLINFO hKrnlInfo, const char *pszModule, const char *pszStructure,
    1225                                          const char *pszMember, size_t *poffMember)
    1226 {
    1227     RTDBGKRNLINFOINT *pThis = hKrnlInfo;
    1228     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    1229     AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    1230     AssertPtrReturn(pszMember, VERR_INVALID_POINTER);
    1231     AssertPtrReturn(pszModule, VERR_INVALID_POINTER);
    1232     AssertPtrReturn(pszStructure, VERR_INVALID_POINTER);
    1233     AssertPtrReturn(poffMember, VERR_INVALID_POINTER);
    1234     return VERR_NOT_FOUND;
    1235 }
    1236 
    1237 
    1238 RTR0DECL(int) RTR0DbgKrnlInfoQuerySymbol(RTDBGKRNLINFO hKrnlInfo, const char *pszModule,
    1239                                          const char *pszSymbol, void **ppvSymbol)
    1240 {
    1241     RTDBGKRNLINFOINT *pThis = hKrnlInfo;
    1242     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    1243     AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    1244     AssertPtrReturn(pszSymbol, VERR_INVALID_PARAMETER);
    1245     AssertPtrNullReturn(ppvSymbol, VERR_INVALID_PARAMETER);
    1246     AssertReturn(!pszModule, VERR_MODULE_NOT_FOUND);
    1247 
    1248     uintptr_t uValue = rtR0DbgKrnlDarwinLookup(pThis, pszSymbol);
    1249     if (ppvSymbol)
    1250         *ppvSymbol = (void *)uValue;
    1251     if (uValue)
     248    union
     249    {
     250        struct vnode_attr VAttr;
     251        uint8_t             abPadding[sizeof(struct vnode_attr) * 2];
     252    } uBuf;
     253    RT_ZERO(uBuf);
     254    struct vnode_attr *pVAttr = &uBuf.VAttr;
     255
     256    VATTR_INIT(pVAttr);
     257    VATTR_WANTED(pVAttr, va_data_size);
     258
     259    errno_t rc = vnode_getattr(pThis->hVnode, pVAttr, pThis->hVfsCtx);
     260    if (!rc)
     261    {
     262        *pcbSize = pVAttr->va_data_size;
    1252263        return VINF_SUCCESS;
    1253     return VERR_SYMBOL_NOT_FOUND;
    1254 }
    1255 
     264    }
     265    return RTErrConvertFromErrno(rc);
     266}
     267
Note: See TracChangeset for help on using the changeset viewer.

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