VirtualBox

Changeset 82806 in vbox


Ignore:
Timestamp:
Jan 21, 2020 1:45:13 AM (5 years ago)
Author:
vboxsync
Message:

IPRT/dbgkrnlinfo-r0drv-darwin.cpp: Implemented using the loaded kernel as it is in memory before falling back on the kernel files on disk. Also, don't assert in rtR0DbgKrnlDarwinCheckStandardSymbols because that wasts time every time someone sets up kernel debugging and uses a non-release kernel.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/darwin/dbgkrnlinfo-r0drv-darwin.cpp

    r76553 r82806  
    120120# define RETURN_VERR_LDR_ARCH_MISMATCH  do {    return VERR_LDR_ARCH_MISMATCH; } while (0)
    121121#endif
     122#if defined(DEBUG_bird) && !defined(IN_RING3)
     123# define LOG_MISMATCH(...)                      kprintf(__VA_ARGS__)
     124# define LOG_NOT_PRESENT(...)                   kprintf(__VA_ARGS__)
     125# define LOG_BAD_SYM(...)                       kprintf(__VA_ARGS__)
     126# define LOG_SUCCESS(...)                       kprintf(__VA_ARGS__)
     127#else
     128# define LOG_MISMATCH(...)                      Log((__VA_ARGS__))
     129# define LOG_NOT_PRESENT(...)                   Log((__VA_ARGS__))
     130# define LOG_BAD_SYM(...)                       printf(__VA_ARGS__)
     131# define LOG_SUCCESS(...)                       printf(__VA_ARGS__)
     132#endif
    122133/** @} */
    123134
     
    142153    /** Reference counter.  */
    143154    uint32_t volatile   cRefs;
     155
     156    /** Set if this is an in-memory rather than on-disk instance. */
     157    bool                fIsInMem;
     158    bool                afAlignment[7];
    144159
    145160    /** @name Result.
     
    151166    /** The file offset of the string table. */
    152167    uint32_t            offStrTab;
     168    /** The link address of the string table. */
     169    uintptr_t           uStrTabLinkAddr;
    153170    /** Pointer to the symbol table. */
    154171    MY_NLIST           *paSyms;
     
    157174    /** The file offset of the symbol table. */
    158175    uint32_t            offSyms;
     176    /** The link address of the symbol table. */
     177    uintptr_t           uSymTabLinkAddr;
     178    /** The link address of the text segment. */
     179    uintptr_t           uTextSegLinkAddr;
     180    /** Size of the text segment. */
     181    uintptr_t           cbTextSeg;
    159182    /** Offset between link address and actual load address. */
    160183    uintptr_t           offLoad;
     184    /** The minimum OS version (A.B.C; A is 16 bits, B & C each 8 bits). */
     185    uint32_t            uMinOsVer;
     186    /** The SDK version (A.B.C; A is 16 bits, B & C each 8 bits). */
     187    uint32_t            uSdkVer;
     188    /** The source version (A.B.C.D.E; A is 24 bits, the rest 10 each). */
     189    uint64_t            uSrcVer;
    161190    /** @} */
    162191
     
    175204    /** The load commands. */
    176205    load_command_t     *pLoadCmds;
     206    /** The number of segments. */
     207    uint32_t            cSegments;
     208    /** The number of sections. */
     209    uint32_t            cSections;
     210    /** Section pointer table (points into the load commands). */
     211    MY_SEGMENT_COMMAND const *apSegments[MACHO_MAX_SECT / 2];
    177212    /** Section pointer table (points into the load commands). */
    178213    MY_SECTION const   *apSections[MACHO_MAX_SECT];
    179     /** The number of sections. */
    180     uint32_t            cSections;
    181214    /** @} */
    182215
     
    201234static void rtR0DbgKrnlDarwinLoadDone(RTDBGKRNLINFOINT *pThis)
    202235{
    203     RTFileClose(pThis->hFile);
     236    if (!pThis->fIsInMem)
     237        RTFileClose(pThis->hFile);
    204238    pThis->hFile = NIL_RTFILE;
    205239
    206     RTMemFree(pThis->pLoadCmds);
     240    if (!pThis->fIsInMem)
     241        RTMemFree(pThis->pLoadCmds);
    207242    pThis->pLoadCmds = NULL;
    208     memset((void *)&pThis->apSections[0], 0, sizeof(pThis->apSections[0]) * MACHO_MAX_SECT);
     243    RT_ZERO(pThis->apSections);
     244    RT_ZERO(pThis->apSegments);
    209245}
    210246
     
    259295 * @returns IPRT status code.
    260296 * @param   pThis               The internal scratch data.
    261  */
    262 static int rtR0DbgKrnlDarwinCheckStandardSymbols(RTDBGKRNLINFOINT *pThis)
     297 * @param   pszKernelFile       The name of the kernel file.
     298 */
     299static int rtR0DbgKrnlDarwinCheckStandardSymbols(RTDBGKRNLINFOINT *pThis, const char *pszKernelFile)
    263300{
    264301    static struct
     
    388425#endif
    389426        {
    390             AssertLogRelMsgFailed(("%s (%p != %p)\n", s_aStandardCandles[i].pszName, uAddr, s_aStandardCandles[i].uAddr));
     427#if defined(IN_RING0) && defined(DEBUG_bird)
     428            kprintf("RTR0DbgKrnlInfoOpen: error: %s (%p != %p) in %s\n",
     429                    s_aStandardCandles[i].pszName, (void *)uAddr, (void *)s_aStandardCandles[i].uAddr, pszKernelFile);
     430#endif
     431            printf("RTR0DbgKrnlInfoOpen: error: %s (%p != %p) in %s\n",
     432                   s_aStandardCandles[i].pszName, (void *)uAddr, (void *)s_aStandardCandles[i].uAddr, pszKernelFile);
    391433            return VERR_INTERNAL_ERROR_2;
    392434        }
     
    403445 * @param   pszKernelFile       The name of the kernel file.
    404446 */
    405 static int rtR0DbgKrnlDarwinLoadSymTab(RTDBGKRNLINFOINT *pThis, const char *pszKernelFile)
    406 {
    407     /*
    408      * Load the tables.
    409      */
    410     pThis->paSyms = (MY_NLIST *)RTMemAllocZ(pThis->cSyms * sizeof(MY_NLIST));
    411     if (!pThis->paSyms)
    412         return VERR_NO_MEMORY;
    413 
    414     int rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offSyms,
    415                           pThis->paSyms, pThis->cSyms * sizeof(MY_NLIST), NULL);
    416     if (RT_FAILURE(rc))
    417         return rc;
    418 
    419     pThis->pachStrTab = (char *)RTMemAllocZ(pThis->cbStrTab + 1);
    420     if (!pThis->pachStrTab)
    421         return VERR_NO_MEMORY;
    422 
    423     rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offStrTab,
    424                       pThis->pachStrTab, pThis->cbStrTab, NULL);
    425     if (RT_FAILURE(rc))
    426         return rc;
    427 
     447static int rtR0DbgKrnlDarwinParseSymTab(RTDBGKRNLINFOINT *pThis, const char *pszKernelFile)
     448{
    428449    /*
    429450     * The first string table symbol must be a zero length name.
     
    442463        if ((uint32_t)pSym->n_un.n_strx >= pThis->cbStrTab)
    443464        {
    444             printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u has a bad string table index: %#x vs cbStrTab=%#x\n",
    445                    pszKernelFile, iSym, pSym->n_un.n_strx, pThis->cbStrTab);
     465            LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Symbol #%u has a bad string table index: %#x vs cbStrTab=%#x\n",
     466                        pszKernelFile, iSym, pSym->n_un.n_strx, pThis->cbStrTab);
    446467            RETURN_VERR_BAD_EXE_FORMAT;
    447468        }
     
    461482                    if (pSym->n_sect == MACHO_NO_SECT)
    462483                    {
    463                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_sect = MACHO_NO_SECT\n",
    464                                pszKernelFile, iSym, pszSym);
     484                        LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_sect = MACHO_NO_SECT\n",
     485                                    pszKernelFile, iSym, pszSym);
    465486                        RETURN_VERR_BAD_EXE_FORMAT;
    466487                    }
    467488                    if (pSym->n_sect > pThis->cSections)
    468489                    {
    469                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_sect (%u) is higher than cSections (%u)\n",
    470                                pszKernelFile, iSym, pszSym, pSym->n_sect, pThis->cSections);
     490                        LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_sect (%u) is higher than cSections (%u)\n",
     491                                    pszKernelFile, iSym, pszSym, pSym->n_sect, pThis->cSections);
    471492                        RETURN_VERR_BAD_EXE_FORMAT;
    472493                    }
    473494                    if (pSym->n_desc & ~(REFERENCED_DYNAMICALLY | N_WEAK_DEF))
    474495                    {
    475                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: Unexpected value n_desc=%#x\n",
    476                                pszKernelFile, iSym, pszSym, pSym->n_desc);
     496                        LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: Unexpected value n_desc=%#x\n",
     497                                    pszKernelFile, iSym, pszSym, pSym->n_desc);
    477498                        RETURN_VERR_BAD_EXE_FORMAT;
    478499                    }
     
    480501                        && strcmp(pszSym, "__mh_execute_header"))    /* in 10.8 it's no longer absolute (PIE?). */
    481502                    {
    482                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_value (%#llx) < section addr (%#llx)\n",
    483                                pszKernelFile, iSym, pszSym, pSym->n_value, pThis->apSections[pSym->n_sect - 1]->addr);
     503                        LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_value (%#llx) < section addr (%#llx)\n",
     504                                    pszKernelFile, iSym, pszSym, pSym->n_value, pThis->apSections[pSym->n_sect - 1]->addr);
    484505                        RETURN_VERR_BAD_EXE_FORMAT;
    485506                    }
     
    488509                        && strcmp(pszSym, "__mh_execute_header"))    /* see above. */
    489510                    {
    490                         printf("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_value (%#llx) >= end of section (%#llx + %#llx)\n",
    491                                pszKernelFile, iSym, pszSym, pSym->n_value, pThis->apSections[pSym->n_sect - 1]->addr,
    492                                pThis->apSections[pSym->n_sect - 1]->size);
     511                        LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Symbol #%u '%s' problem: n_value (%#llx) >= end of section (%#llx + %#llx)\n",
     512                                    pszKernelFile, iSym, pszSym, pSym->n_value, pThis->apSections[pSym->n_sect - 1]->addr,
     513                                    pThis->apSections[pSym->n_sect - 1]->size);
    493514                        RETURN_VERR_BAD_EXE_FORMAT;
    494515                    }
     
    500521                            || pSym->n_sect > pThis->cSections) )
    501522                    {
    502                         printf("RTR0DbgKrnlInfoOpen: %s: Abs symbol #%u '%s' problem: n_sect (%u) is not MACHO_NO_SECT (cSections is %u)\n",
    503                                pszKernelFile, iSym, pszSym, pSym->n_sect, pThis->cSections);
     523                        LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Abs symbol #%u '%s' problem: n_sect (%u) is not MACHO_NO_SECT (cSections is %u)\n",
     524                                    pszKernelFile, iSym, pszSym, pSym->n_sect, pThis->cSections);
    504525                        RETURN_VERR_BAD_EXE_FORMAT;
    505526                    }
    506527                    if (pSym->n_desc & ~(REFERENCED_DYNAMICALLY | N_WEAK_DEF))
    507528                    {
    508                         printf("RTR0DbgKrnlInfoOpen: %s: Abs symbol #%u '%s' problem: Unexpected value n_desc=%#x\n",
    509                                pszKernelFile, iSym, pszSym, pSym->n_desc);
     529                        LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Abs symbol #%u '%s' problem: Unexpected value n_desc=%#x\n",
     530                                    pszKernelFile, iSym, pszSym, pSym->n_desc);
    510531                        RETURN_VERR_BAD_EXE_FORMAT;
    511532                    }
     
    514535                case MACHO_N_UNDF:
    515536                    /* No undefined or common symbols in the kernel. */
    516                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected undefined symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
     537                    LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Unexpected undefined symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
    517538                    RETURN_VERR_BAD_EXE_FORMAT;
    518539
    519540                case MACHO_N_INDR:
    520541                    /* No indirect symbols in the kernel. */
    521                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected indirect symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
     542                    LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Unexpected indirect symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
    522543                    RETURN_VERR_BAD_EXE_FORMAT;
    523544
    524545                case MACHO_N_PBUD:
    525546                    /* No prebound symbols in the kernel. */
    526                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected prebound symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
     547                    LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Unexpected prebound symbol #%u '%s'\n", pszKernelFile, iSym, pszSym);
    527548                    RETURN_VERR_BAD_EXE_FORMAT;
    528549
    529550                default:
    530                     printf("RTR0DbgKrnlInfoOpen: %s: Unexpected symbol n_type %#x for symbol #%u '%s'\n",
    531                            pszKernelFile, pSym->n_type, iSym, pszSym);
     551                    LOG_BAD_SYM("RTR0DbgKrnlInfoOpen: %s: Unexpected symbol n_type %#x for symbol #%u '%s'\n",
     552                                pszKernelFile, pSym->n_type, iSym, pszSym);
    532553                    RETURN_VERR_BAD_EXE_FORMAT;
    533554            }
     
    541562
    542563/**
    543  * Loads the load commands and validates them.
     564 * Uses the segment table to translate a file offset into a virtual memory
     565 * address.
     566 *
     567 * @returns The virtual memory address on success, 0 if not found.
     568 * @param   pThis               The instance.
     569 * @param   offFile             The file offset to translate.
     570 */
     571static uintptr_t rtR0DbgKrnlDarwinFileOffToVirtAddr(RTDBGKRNLINFOINT *pThis, uint64_t offFile)
     572{
     573    uint32_t iSeg = pThis->cSegments;
     574    while (iSeg-- > 0)
     575    {
     576        uint64_t offSeg = offFile - pThis->apSegments[iSeg]->fileoff;
     577        if (offSeg < pThis->apSegments[iSeg]->vmsize)
     578            return pThis->apSegments[iSeg]->vmaddr + (uintptr_t)offSeg;
     579    }
     580    return 0;
     581}
     582
     583
     584/**
     585 * Parses and validates the load commands.
    544586 *
    545587 * @returns IPRT status code.
    546588 * @param   pThis               The internal scratch data.
    547589 */
    548 static int rtR0DbgKrnlDarwinLoadCommands(RTDBGKRNLINFOINT *pThis)
    549 {
    550     pThis->offStrTab = 0;
    551     pThis->cbStrTab  = 0;
    552     pThis->offSyms   = 0;
    553     pThis->cSyms     = 0;
    554     pThis->cSections = 0;
    555 
    556     pThis->pLoadCmds = (load_command_t *)RTMemAlloc(pThis->cbLoadCmds);
    557     if (!pThis->pLoadCmds)
    558         return VERR_NO_MEMORY;
    559 
    560     int rc = RTFileReadAt(pThis->hFile, pThis->offArch + sizeof(MY_MACHO_HEADER),
    561                           pThis->pLoadCmds, pThis->cbLoadCmds, NULL);
    562     if (RT_FAILURE(rc))
    563         return rc;
     590static int rtR0DbgKrnlDarwinParseCommands(RTDBGKRNLINFOINT *pThis)
     591{
     592    Assert(pThis->pLoadCmds);
     593
     594    /*
     595     * Reset the state.
     596     */
     597    pThis->offStrTab        = 0;
     598    pThis->cbStrTab         = 0;
     599    pThis->offSyms          = 0;
     600    pThis->cSyms            = 0;
     601    pThis->cSections        = 0;
     602    pThis->uTextSegLinkAddr = 0;
     603    pThis->cbTextSeg        = 0;
     604    pThis->uMinOsVer        = 0;
     605    pThis->uSdkVer          = 0;
     606    pThis->uSrcVer          = 0;
    564607
    565608    /*
     
    700743
    701744                    /* Add to the section table. */
    702                     if (pThis->cSections == MACHO_MAX_SECT)
     745                    if (pThis->cSections >= RT_ELEMENTS(pThis->apSections))
    703746                        RETURN_VERR_BAD_EXE_FORMAT;
    704747                    pThis->apSections[pThis->cSections++] = &paSects[i];
     
    710753                    && pSeg->vmsize != 0)
    711754                    RETURN_VERR_BAD_EXE_FORMAT;
     755
     756                /*
     757                 * Add to the segment table.
     758                 */
     759                if (pThis->cSegments >= RT_ELEMENTS(pThis->apSegments))
     760                    RETURN_VERR_BAD_EXE_FORMAT;
     761                pThis->apSegments[pThis->cSegments++] = pSeg;
     762
     763                /*
     764                 * Take down the text segment size and link address (for in-mem variant):
     765                 */
     766                if (!strcmp(pSeg->segname, "__TEXT"))
     767                {
     768                    if (pThis->cbTextSeg != 0)
     769                        RETURN_VERR_BAD_EXE_FORMAT;
     770                    pThis->uTextSegLinkAddr = pSeg->vmaddr;
     771                    pThis->cbTextSeg        = pSeg->vmsize;
     772                }
    712773                break;
    713774            }
     
    725786            case LC_MAIN:
    726787            case LC_DATA_IN_CODE:
    727             case LC_SOURCE_VERSION:
    728788            case LC_ENCRYPTION_INFO_64:
    729789            case LC_LINKER_OPTION:
     
    732792            case LC_VERSION_MIN_WATCHOS:
    733793            case LC_NOTE:
     794                break;
     795
    734796            case LC_BUILD_VERSION:
     797                if (pCmd->cmdsize >= RT_UOFFSETOF(build_version_command_t, aTools))
     798                {
     799                    build_version_command_t *pBldVerCmd = (build_version_command_t *)pCmd;
     800                    pThis->uMinOsVer = pBldVerCmd->minos;
     801                    pThis->uSdkVer   = pBldVerCmd->sdk;
     802                }
     803                break;
     804
     805            case LC_SOURCE_VERSION:
     806                if (pCmd->cmdsize == sizeof(source_version_command_t))
     807                {
     808                    source_version_command_t *pSrcVerCmd = (source_version_command_t *)pCmd;
     809                    pThis->uSrcVer = pSrcVerCmd->version;
     810                }
    735811                break;
    736812
     
    789865    }
    790866
     867    /*
     868     * Try figure out the virtual addresses for the symbol and string tables.
     869     */
     870    if (pThis->cbStrTab > 0)
     871        pThis->uStrTabLinkAddr = rtR0DbgKrnlDarwinFileOffToVirtAddr(pThis, pThis->offStrTab);
     872    if (pThis->cSyms > 0)
     873        pThis->uSymTabLinkAddr = rtR0DbgKrnlDarwinFileOffToVirtAddr(pThis, pThis->offSyms);
     874
    791875    return VINF_SUCCESS;
     876}
     877
     878
     879/**
     880 * Loads and validates the symbol and string tables.
     881 *
     882 * @returns IPRT status code.
     883 * @param   pThis               The internal scratch data.
     884 * @param   pszKernelFile       The name of the kernel file.
     885 */
     886static int rtR0DbgKrnlDarwinLoadSymTab(RTDBGKRNLINFOINT *pThis, const char *pszKernelFile)
     887{
     888    /*
     889     * Load the tables.
     890     */
     891    int rc;
     892    pThis->paSyms = (MY_NLIST *)RTMemAllocZ(pThis->cSyms * sizeof(MY_NLIST));
     893    if (pThis->paSyms)
     894    {
     895        rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offSyms, pThis->paSyms, pThis->cSyms * sizeof(MY_NLIST), NULL);
     896        if (RT_SUCCESS(rc))
     897        {
     898            pThis->pachStrTab = (char *)RTMemAllocZ(pThis->cbStrTab + 1);
     899            if (pThis->pachStrTab)
     900            {
     901                rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offStrTab, pThis->pachStrTab, pThis->cbStrTab, NULL);
     902                if (RT_SUCCESS(rc))
     903                {
     904                    /*
     905                     * Join paths with the in-memory code path.
     906                     */
     907                    rc = rtR0DbgKrnlDarwinParseSymTab(pThis, pszKernelFile);
     908                }
     909            }
     910            else
     911                rc = VERR_NO_MEMORY;
     912        }
     913    }
     914    else
     915        rc = VERR_NO_MEMORY;
     916    return rc;
     917}
     918
     919
     920/**
     921 * Loads the load commands and validates them.
     922 *
     923 * @returns IPRT status code.
     924 * @param   pThis               The internal scratch data.
     925 */
     926static int rtR0DbgKrnlDarwinLoadCommands(RTDBGKRNLINFOINT *pThis)
     927{
     928    int rc;
     929    pThis->pLoadCmds = (load_command_t *)RTMemAlloc(pThis->cbLoadCmds);
     930    if (pThis->pLoadCmds)
     931    {
     932        rc = RTFileReadAt(pThis->hFile, pThis->offArch + sizeof(MY_MACHO_HEADER), pThis->pLoadCmds, pThis->cbLoadCmds, NULL);
     933        if (RT_SUCCESS(rc))
     934            rc = rtR0DbgKrnlDarwinParseCommands(pThis);
     935    }
     936    else
     937        rc = VERR_NO_MEMORY;
     938   return rc;
    792939}
    793940
     
    9071054    pThis->u32Magic = ~RTDBGKRNLINFO_MAGIC;
    9081055
    909     RTMemFree(pThis->pachStrTab);
     1056    if (!pThis->fIsInMem)
     1057        RTMemFree(pThis->pachStrTab);
    9101058    pThis->pachStrTab = NULL;
    9111059
    912     RTMemFree(pThis->paSyms);
     1060    if (!pThis->fIsInMem)
     1061        RTMemFree(pThis->paSyms);
    9131062    pThis->paSyms = NULL;
    9141063
    9151064    RTMemFree(pThis);
     1065}
     1066
     1067
     1068/**
     1069 * Completes a handle, logging details.
     1070 *
     1071 * @returns VINF_SUCCESS
     1072 * @param   phKrnlInfo      Where to return the handle.
     1073 * @param   pThis           The instance to complete.
     1074 * @param   pszKernelFile   What kernel file it's based on.
     1075 */
     1076static int rtR0DbgKrnlDarwinSuccess(PRTDBGKRNLINFO phKrnlInfo, RTDBGKRNLINFOINT *pThis, const char *pszKernelFile)
     1077{
     1078    pThis->u32Magic = RTDBGKRNLINFO_MAGIC;
     1079    pThis->cRefs    = 1;
     1080
     1081#if defined(DEBUG) || defined(IN_RING3)
     1082    LOG_SUCCESS("RTR0DbgKrnlInfoOpen: Found: %#zx + %#zx - %s\n", pThis->uTextSegLinkAddr, pThis->offLoad, pszKernelFile);
     1083#else
     1084    LOG_SUCCESS("RTR0DbgKrnlInfoOpen: Found: %s\n", pThis->uTextSegLinkAddr, pThis->offLoad, pszKernelFile);
     1085#endif
     1086    LOG_SUCCESS("RTR0DbgKrnlInfoOpen: SDK version: %u.%u.%u  MinOS version: %u.%u.%u  Source version: %u.%u.%u.%u.%u\n",
     1087                pThis->uSdkVer   >> 16, (pThis->uSdkVer   >> 8) & 0xff, pThis->uSdkVer   & 0xff,
     1088                pThis->uMinOsVer >> 16, (pThis->uMinOsVer >> 8) & 0xff, pThis->uMinOsVer & 0xff,
     1089                (uint32_t)(pThis->uSrcVer >> 40),
     1090                (uint32_t)(pThis->uSrcVer >> 30) & 0x3ff,
     1091                (uint32_t)(pThis->uSrcVer >> 20) & 0x3ff,
     1092                (uint32_t)(pThis->uSrcVer >> 10) & 0x3ff,
     1093                (uint32_t)(pThis->uSrcVer)       & 0x3ff);
     1094
     1095    *phKrnlInfo = pThis;
     1096    return VINF_SUCCESS;
    9161097}
    9171098
     
    9411122            pThis->offLoad = (uintptr_t)&kernel_map - uLinkAddr;
    9421123#endif
    943         rc = rtR0DbgKrnlDarwinCheckStandardSymbols(pThis);
     1124        rc = rtR0DbgKrnlDarwinCheckStandardSymbols(pThis, pszKernelFile);
    9441125    }
    9451126
    9461127    rtR0DbgKrnlDarwinLoadDone(pThis);
    9471128    if (RT_SUCCESS(rc))
    948     {
    949         pThis->u32Magic = RTDBGKRNLINFO_MAGIC;
    950         pThis->cRefs    = 1;
    951         *phKrnlInfo = pThis;
    952     }
     1129        rtR0DbgKrnlDarwinSuccess(phKrnlInfo, pThis, pszKernelFile);
    9531130    else
    9541131        rtR0DbgKrnlDarwinDtor(pThis);
     
    9571134
    9581135
     1136#ifdef IN_RING0
     1137
     1138/**
     1139 * Checks if a page is present.
     1140 * @returns true if it is, false if it isn't.
     1141 * @param   uPageAddr   The address of/in the page to check.
     1142 */
     1143static bool rtR0DbgKrnlDarwinIsPagePresent(uintptr_t uPageAddr)
     1144{
     1145    /** @todo the dtrace code subjects the result to pmap_is_valid, but that
     1146     *        isn't exported, so we'll have to make to with != 0 here. */
     1147    return pmap_find_phys(kernel_pmap, uPageAddr) != 0;
     1148}
     1149
     1150
     1151/**
     1152 * Used to check whether a memory range is present or not.
     1153 *
     1154 * This is applied to the to the load commands and selected portions of the link
     1155 * edit segment.
     1156 *
     1157 * @returns true if all present, false if not.
     1158 * @param   uAddress    The start address.
     1159 * @param   cb          Number of bytes to check.
     1160 * @param   pszWhat     What we're checking, for logging.
     1161 * @param   pHdr        The header address (for logging).
     1162 */
     1163static bool rtR0DbgKrnlDarwinIsRangePresent(uintptr_t uAddress, size_t cb,
     1164                                            const char *pszWhat, MY_MACHO_HEADER const volatile *pHdr)
     1165{
     1166    uintptr_t const uStartAddress = uAddress;
     1167    intptr_t        cPages        = RT_ALIGN_Z(cb + (uAddress & PAGE_OFFSET_MASK), PAGE_SIZE);
     1168    for (;;)
     1169    {
     1170        if (!rtR0DbgKrnlDarwinIsPagePresent(uAddress))
     1171        {
     1172            LOG_NOT_PRESENT("RTR0DbgInfo: %p: Page in %s is not present: %#zx - rva %#zx; in structure %#zx (%#zx LB %#zx)\n",
     1173                            pHdr, pszWhat, uAddress, uAddress - (uintptr_t)pHdr, uAddress - uStartAddress, uStartAddress, cb);
     1174            return false;
     1175        }
     1176
     1177        cPages -= 1;
     1178        if (cPages <= 0)
     1179            uAddress += PAGE_SIZE;
     1180        else
     1181            return true;
     1182    }
     1183}
     1184
     1185
     1186/**
     1187 * Try "open" the in-memory kernel image
     1188 *
     1189 * @returns IPRT stauts code
     1190 * @param   phKrnlInfo          Where to return the info instance on success.
     1191 */
     1192static int rtR0DbgKrnlDarwinOpenInMemory(PRTDBGKRNLINFO phKrnlInfo)
     1193{
     1194    RTDBGKRNLINFOINT *pThis = (RTDBGKRNLINFOINT *)RTMemAllocZ(sizeof(*pThis));
     1195    if (!pThis)
     1196        return VERR_NO_MEMORY;
     1197    pThis->hFile    = NIL_RTFILE;
     1198    pThis->fIsInMem = true;
     1199
     1200    /*
     1201     * Figure the search range based on a symbol that is supposed to be in
     1202     * kernel text segment, using it as the upper boundrary.  The lower boundary
     1203     * is determined by subtracting a max kernel size of 64MB (the largest kernel
     1204     * file, kernel.kasan, is around 45MB, but the end of __TEXT is about 27 MB,
     1205     * which means we should still have plenty of room for future growth with 64MB).
     1206     */
     1207    uintptr_t  const    uSomeKernelAddr   = (uintptr_t)&absolutetime_to_nanoseconds;
     1208    uintptr_t  const    uLowestKernelAddr = uSomeKernelAddr - _64M;
     1209
     1210    /*
     1211     * The kernel is probably aligned at some boundrary larger than a page size,
     1212     * so to speed things up we start by assuming the alignment is page directory
     1213     * sized.  In case we're wrong and it's smaller, we decrease the alignment till
     1214     * we've reach the page size.
     1215     */
     1216    uintptr_t           fPrevAlignMask    = ~(uintptr_t)0;
     1217    uintptr_t           uCurAlign         = _2M;                    /* ASSUMES the kernel is typically 2MB aligned. */
     1218    while (uCurAlign >= PAGE_SIZE)
     1219    {
     1220        /*
     1221         * Search down from the symbol address looking for a mach-O header that
     1222         * looks like it might belong to the kernel.
     1223         */
     1224        for (uintptr_t uCur = uSomeKernelAddr & ~(uCurAlign - 1); uCur >= uLowestKernelAddr; uCur -= uCurAlign)
     1225        {
     1226            /* Skip pages we've checked in previous iterations and pages that aren't present: */
     1227            /** @todo This is a little bogus in case the header is paged out. */
     1228            if (   (uCur & fPrevAlignMask)
     1229                && rtR0DbgKrnlDarwinIsPagePresent(uCur))
     1230            {
     1231                /*
     1232                 * Look for valid mach-o header (we skip cpusubtype on purpose here).
     1233                 */
     1234                MY_MACHO_HEADER const volatile *pHdr = (MY_MACHO_HEADER const volatile *)uCur;
     1235                if (   pHdr->magic    == MY_MACHO_MAGIC
     1236                    && pHdr->filetype == MH_EXECUTE
     1237                    && pHdr->cputype  == MY_CPU_TYPE)
     1238                {
     1239                    /* More header validation: */
     1240                    pThis->cLoadCmds  = pHdr->ncmds;
     1241                    pThis->cbLoadCmds = pHdr->sizeofcmds;
     1242                    if (pHdr->ncmds < 4)
     1243                        LOG_MISMATCH("RTR0DbgInfo: %p: ncmds=%u is too small\n", pHdr, pThis->cLoadCmds);
     1244                    else if (pThis->cLoadCmds > 256)
     1245                        LOG_MISMATCH("RTR0DbgInfo: %p: ncmds=%u is too big\n", pHdr, pThis->cLoadCmds);
     1246                    else if (pThis->cbLoadCmds <= pThis->cLoadCmds * sizeof(load_command_t))
     1247                        LOG_MISMATCH("RTR0DbgInfo: %p: sizeofcmds=%u is too small for ncmds=%u\n",
     1248                                     pHdr, pThis->cbLoadCmds, pThis->cLoadCmds);
     1249                    else if (pThis->cbLoadCmds >= _1M)
     1250                        LOG_MISMATCH("RTR0DbgInfo: %p: sizeofcmds=%u is too big\n", pHdr, pThis->cbLoadCmds);
     1251                    else if (pHdr->flags & ~MH_VALID_FLAGS)
     1252                        LOG_MISMATCH("RTR0DbgInfo: %p: invalid flags=%#x\n", pHdr, pHdr->flags);
     1253                    /*
     1254                     * Check that we can safely read the load commands, then parse & validate them.
     1255                     */
     1256                    else if (rtR0DbgKrnlDarwinIsRangePresent((uintptr_t)(pHdr + 1), pThis->cbLoadCmds, "load commands", pHdr))
     1257                    {
     1258                        pThis->pLoadCmds = (load_command_t *)(pHdr + 1);
     1259                        int rc = rtR0DbgKrnlDarwinParseCommands(pThis);
     1260                        if (RT_SUCCESS(rc))
     1261                        {
     1262                            /* Calculate the slide value.  This is typically zero as the
     1263                               load commands has been relocated (the case with 10.14.0 at least). */
     1264                            /** @todo ASSUMES that the __TEXT segment comes first and includes the
     1265                             *        mach-o header and load commands and all that. */
     1266                            pThis->offLoad = uCur - pThis->uTextSegLinkAddr;
     1267
     1268                            /* Check that the kernel symbol is in the text segment: */
     1269                            uintptr_t const offSomeKernAddr = uSomeKernelAddr - uCur;
     1270                            if (offSomeKernAddr >= pThis->cbTextSeg)
     1271                                LOG_MISMATCH("RTR0DbgInfo: %p: Our symbol at %zx (off %zx) isn't within the text segment (size %#zx)\n",
     1272                                             pHdr, uSomeKernelAddr, offSomeKernAddr, pThis->cbTextSeg);
     1273                            /*
     1274                             * Parse the symbol+string tables.
     1275                             */
     1276                            else if (pThis->uSymTabLinkAddr == 0)
     1277                                LOG_MISMATCH("RTR0DbgInfo: %p: No symbol table VA (off %#x L %#x)\n",
     1278                                             pHdr, pThis->offSyms, pThis->cSyms);
     1279                            else if (pThis->uStrTabLinkAddr == 0)
     1280                                LOG_MISMATCH("RTR0DbgInfo: %p: No string table VA (off %#x LB %#x)\n",
     1281                                             pHdr, pThis->offSyms, pThis->cbStrTab);
     1282                            else if (   rtR0DbgKrnlDarwinIsRangePresent(pThis->uStrTabLinkAddr + pThis->offLoad,
     1283                                                                        pThis->cbStrTab, "string table", pHdr)
     1284                                     && rtR0DbgKrnlDarwinIsRangePresent(pThis->uSymTabLinkAddr + pThis->offLoad,
     1285                                                                        pThis->cSyms * sizeof(pThis->paSyms),
     1286                                                                        "symbol table", pHdr))
     1287                            {
     1288                                pThis->pachStrTab = (char *)pThis->uStrTabLinkAddr + pThis->offLoad;
     1289                                pThis->paSyms = (MY_NLIST *)pThis->uSymTabLinkAddr + pThis->offLoad;
     1290                                rc = rtR0DbgKrnlDarwinParseSymTab(pThis, "in-memory");
     1291                                if (RT_SUCCESS(rc))
     1292                                {
     1293                                    /*
     1294                                     * Finally check the standard candles.
     1295                                     */
     1296                                    rc = rtR0DbgKrnlDarwinCheckStandardSymbols(pThis, "in-memory");
     1297                                    rtR0DbgKrnlDarwinLoadDone(pThis);
     1298                                    if (RT_SUCCESS(rc))
     1299                                        return rtR0DbgKrnlDarwinSuccess(phKrnlInfo, pThis, "in-memory");
     1300                                }
     1301                            }
     1302                        }
     1303
     1304                        RT_ZERO(pThis->apSections);
     1305                        RT_ZERO(pThis->apSegments);
     1306                        pThis->pLoadCmds = NULL;
     1307                    }
     1308                }
     1309            }
     1310        }
     1311
     1312        fPrevAlignMask = uCurAlign - 1;
     1313        uCurAlign >>= 1;
     1314    }
     1315
     1316    RTMemFree(pThis);
     1317    return VERR_GENERAL_FAILURE;
     1318}
     1319
     1320#endif /* IN_RING0 */
     1321
    9591322RTR0DECL(int) RTR0DbgKrnlInfoOpen(PRTDBGKRNLINFO phKrnlInfo, uint32_t fFlags)
    9601323{
     
    9621325    *phKrnlInfo = NIL_RTDBGKRNLINFO;
    9631326    AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
     1327
     1328#ifdef IN_RING0
     1329    /*
     1330     * Try see if we can use the kernel memory directly.  This depends on not
     1331     * having the __LINKEDIT segment jettisoned or swapped out.  For older
     1332     * kernels this is typically the case, unless kallsyms=1 is in boot-args.
     1333     */
     1334    int rc = rtR0DbgKrnlDarwinOpenInMemory(phKrnlInfo);
     1335    if (RT_SUCCESS(rc))
     1336    {
     1337        Log(("RTR0DbgKrnlInfoOpen: Using in-memory kernel.\n"));
     1338        return rc;
     1339    }
     1340#else
     1341    int rc = VERR_WRONG_ORDER; /* shut up stupid MSC */
     1342#endif
    9641343
    9651344    /*
     
    9871366        { "/mach_kernel", VERR_WRONG_ORDER },
    9881367    };
    989     int rc = VERR_WRONG_ORDER; /* shut up stupid MSC */
    9901368    for (uint32_t i = 0; i < RT_ELEMENTS(aKernels); i++)
    9911369    {
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