/**
 * Initializes the address space parts of DBGF.
 *
 * @returns VBox status code.
 * @param   pUVM        The user mode VM handle.
 */
int dbgfR3AsInit(PUVM pUVM)
{
    Assert(pUVM->pVM);

    /*
     * Create the semaphore.
     */
    int rc = RTSemRWCreate(&pUVM->dbgf.s.hAsDbLock);
    AssertRCReturn(rc, rc);

    /*
     * Create the debugging config instance and set it up, defaulting to
     * deferred loading in order to keep things fast.
     */
    rc = RTDbgCfgCreate(&pUVM->dbgf.s.hDbgCfg, NULL, true /*fNativePaths*/);
    AssertRCReturn(rc, rc);
    rc = RTDbgCfgChangeUInt(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_FLAGS, RTDBGCFGOP_PREPEND,
                            RTDBGCFG_FLAGS_DEFERRED);
    AssertRCReturn(rc, rc);

    static struct
    {
        RTDBGCFGPROP    enmProp;
        const char     *pszEnvName;
        const char     *pszCfgName;
    } const s_aProps[] =
    {
        { RTDBGCFGPROP_FLAGS,               "VBOXDBG_FLAGS",            "Flags"             },
        { RTDBGCFGPROP_PATH,                "VBOXDBG_PATH",             "Path"              },
        { RTDBGCFGPROP_SUFFIXES,            "VBOXDBG_SUFFIXES",         "Suffixes"          },
        { RTDBGCFGPROP_SRC_PATH,            "VBOXDBG_SRC_PATH",         "SrcPath"           },
    };
    PCFGMNODE pCfgDbgf = CFGMR3GetChild(CFGMR3GetRootU(pUVM), "/DBGF");
    for (unsigned i = 0; i < RT_ELEMENTS(s_aProps); i++)
    {
        char szEnvValue[8192];
        rc = RTEnvGetEx(RTENV_DEFAULT, s_aProps[i].pszEnvName, szEnvValue, sizeof(szEnvValue), NULL);
        if (RT_SUCCESS(rc))
        {
            rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, szEnvValue);
            if (RT_FAILURE(rc))
                return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                    "DBGF Config Error: %s=%s -> %Rrc", s_aProps[i].pszEnvName, szEnvValue, rc);
        }
        else if (rc != VERR_ENV_VAR_NOT_FOUND)
            return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                "DBGF Config Error: Error querying env.var. %s: %Rrc", s_aProps[i].pszEnvName, rc);

        char *pszCfgValue;
        rc = CFGMR3QueryStringAllocDef(pCfgDbgf, s_aProps[i].pszCfgName, &pszCfgValue, NULL);
        if (RT_FAILURE(rc))
            return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                "DBGF Config Error: Querying /DBGF/%s -> %Rrc", s_aProps[i].pszCfgName, rc);
        if (pszCfgValue)
        {
            rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, s_aProps[i].enmProp, RTDBGCFGOP_PREPEND, pszCfgValue);
            if (RT_FAILURE(rc))
                return VMR3SetError(pUVM, rc, RT_SRC_POS,
                                    "DBGF Config Error: /DBGF/%s=%s -> %Rrc", s_aProps[i].pszCfgName, pszCfgValue, rc);
        }
    }

    /*
     * Prepend the NoArch and VBoxDbgSyms directories to the path.
     */
    char szPath[RTPATH_MAX];
    rc = RTPathAppPrivateNoArch(szPath, sizeof(szPath));
    AssertRCReturn(rc, rc);
#ifdef RT_OS_DARWIN
    rc = RTPathAppend(szPath, sizeof(szPath), "../Resources/VBoxDbgSyms/");
#else
    rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath);
    AssertRCReturn(rc, rc);

    rc = RTPathAppend(szPath, sizeof(szPath), "VBoxDbgSyms/");
#endif
    AssertRCReturn(rc, rc);
    rc = RTDbgCfgChangeString(pUVM->dbgf.s.hDbgCfg, RTDBGCFGPROP_PATH, RTDBGCFGOP_PREPEND, szPath);
    AssertRCReturn(rc, rc);

    /*
     * Create the standard address spaces.
     */
    RTDBGAS hDbgAs;
    rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPTR_MAX, "Global");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_GLOBAL)] = hDbgAs;

    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_KERNEL)] = hDbgAs;

    rc = RTDbgAsCreate(&hDbgAs, 0, RTGCPHYS_MAX, "Physical");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_PHYS)] = hDbgAs;

    rc = RTDbgAsCreate(&hDbgAs, 0, RTRCPTR_MAX, "HyperRawMode");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC)] = hDbgAs;
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_RC_AND_GC_GLOBAL)] = hDbgAs;

    rc = RTDbgAsCreate(&hDbgAs, 0, RTR0PTR_MAX, "HyperRing0");
    AssertRCReturn(rc, rc);
    rc = DBGFR3AsAdd(pUVM, hDbgAs, NIL_RTPROCESS);
    AssertRCReturn(rc, rc);
    RTDbgAsRetain(hDbgAs);
    pUVM->dbgf.s.ahAsAliases[DBGF_AS_ALIAS_2_INDEX(DBGF_AS_R0)] = hDbgAs;

    return VINF_SUCCESS;
}
コード例 #2
0
ファイル: RTLdrFlt.cpp プロジェクト: bringhurst/vbox
int main(int argc, char **argv)
{
    int rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);

    /*
     * Create an empty address space that we can load modules and stuff into
     * as we parse the parameters.
     */
    RTDBGAS hDbgAs;
    rc = RTDbgAsCreate(&hDbgAs, 0, RTUINTPTR_MAX, "");
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDBgAsCreate -> %Rrc", rc);

    /*
     * Create a debugging configuration instance to work with so that we can
     * make use of (i.e. test) path searching and such.
     */
    RTDBGCFG hDbgCfg;
    rc = RTDbgCfgCreate(&hDbgCfg, "IPRT", true /*fNativePaths*/);
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDbgCfgCreate -> %Rrc", rc);

    /*
     * Parse arguments.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--input",        'i', RTGETOPT_REQ_STRING },
        { "--local-file",   'l', RTGETOPT_REQ_NOTHING },
        { "--cache-file",   'c', RTGETOPT_REQ_NOTHING },
        { "--pe-image",     'p', RTGETOPT_REQ_NOTHING },
        { "--verbose",      'v', RTGETOPT_REQ_NOTHING },
        { "--x86",          '8', RTGETOPT_REQ_NOTHING },
        { "--amd64",        '6', RTGETOPT_REQ_NOTHING },
        { "--whatever",     '*', RTGETOPT_REQ_NOTHING },
    };

    PRTSTREAM       pInput          = g_pStdIn;
    PRTSTREAM       pOutput         = g_pStdOut;
    unsigned        cVerbosityLevel = 0;
    enum {
        kOpenMethod_FromImage,
        kOpenMethod_FromPeImage
    }               enmOpenMethod   = kOpenMethod_FromImage;
    bool            fCacheFile      = false;
    RTLDRARCH       enmArch         = RTLDRARCH_WHATEVER;

    RTGETOPTUNION   ValueUnion;
    RTGETOPTSTATE   GetState;
    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
    {
        switch (rc)
        {
            case 'i':
                rc = RTStrmOpen(ValueUnion.psz, "r", &pInput);
                if (RT_FAILURE(rc))
                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to open '%s' for reading: %Rrc", ValueUnion.psz, rc);
                break;

            case 'c':
                fCacheFile = true;
                break;

            case 'l':
                fCacheFile = false;
                break;

            case 'p':
                enmOpenMethod = kOpenMethod_FromPeImage;
                break;

            case 'v':
                cVerbosityLevel++;
                break;

            case '8':
                enmArch = RTLDRARCH_X86_32;
                break;

            case '6':
                enmArch = RTLDRARCH_AMD64;
                break;

            case '*':
                enmArch = RTLDRARCH_WHATEVER;
                break;

            case 'h':
                RTPrintf("Usage: %s [options] <module> <address> [<module> <address> [..]]\n"
                         "\n"
                         "Options:\n"
                         "  -i,--input=file\n"
                         "      Specify a input file instead of standard input.\n"
                         "  --pe-image\n"
                         "      Use RTDbgModCreateFromPeImage to open the file."
                         "  -v, --verbose\n"
                         "      Display the address space before doing the filtering.\n"
                         "  --amd64,--x86,--whatever\n"
                         "      Selects the desired architecture.\n"
                         "  -h, -?, --help\n"
                         "      Display this help text and exit successfully.\n"
                         "  -V, --version\n"
                         "      Display the revision and exit successfully.\n"
                         , RTPathFilename(argv[0]));
                return RTEXITCODE_SUCCESS;

            case 'V':
                RTPrintf("$Revision$\n");
                return RTEXITCODE_SUCCESS;

            case VINF_GETOPT_NOT_OPTION:
            {
                /* <module> <address> */
                const char *pszModule = ValueUnion.psz;

                rc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_HEX);
                if (RT_FAILURE(rc))
                    return RTGetOptPrintError(rc, &ValueUnion);
                uint64_t u64Address = ValueUnion.u64;

                uint32_t cbImage    = 0;
                uint32_t uTimestamp = 0;
                if (fCacheFile)
                {
                    rc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX);
                    if (RT_FAILURE(rc))
                        return RTGetOptPrintError(rc, &ValueUnion);
                    cbImage = ValueUnion.u32;

                    rc = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_HEX);
                    if (RT_FAILURE(rc))
                        return RTGetOptPrintError(rc, &ValueUnion);
                    uTimestamp = ValueUnion.u32;
                }

                RTDBGMOD hMod;
                if (enmOpenMethod == kOpenMethod_FromImage)
                    rc = RTDbgModCreateFromImage(&hMod, pszModule, NULL, enmArch, hDbgCfg);
                else
                    rc = RTDbgModCreateFromPeImage(&hMod, pszModule, NULL, NIL_RTLDRMOD, cbImage, uTimestamp, hDbgCfg);
                if (RT_FAILURE(rc))
                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDbgModCreateFromImage(,%s,,) -> %Rrc", pszModule, rc);

                rc = RTDbgAsModuleLink(hDbgAs, hMod, u64Address, 0 /* fFlags */);
                if (RT_FAILURE(rc))
                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTDbgAsModuleLink(,%s,%llx,) -> %Rrc", pszModule, u64Address, rc);
                break;
            }

            default:
                return RTGetOptPrintError(rc, &ValueUnion);
        }
    }

    /*
     * Display the address space.
     */
    if (cVerbosityLevel)
    {
        RTPrintf("*** Address Space Dump ***\n");
        uint32_t cModules = RTDbgAsModuleCount(hDbgAs);
        for (uint32_t iModule = 0; iModule < cModules; iModule++)
        {
            RTDBGMOD        hDbgMod = RTDbgAsModuleByIndex(hDbgAs, iModule);
            RTPrintf("Module #%u: %s\n", iModule, RTDbgModName(hDbgMod));

            RTDBGASMAPINFO  aMappings[128];
            uint32_t        cMappings = RT_ELEMENTS(aMappings);
            rc = RTDbgAsModuleQueryMapByIndex(hDbgAs, iModule, &aMappings[0], &cMappings, 0 /*fFlags*/);
            if (RT_SUCCESS(rc))
            {
                for (uint32_t iMapping = 0; iMapping < cMappings; iMapping++)
                {
                    if (aMappings[iMapping].iSeg == NIL_RTDBGSEGIDX)
                        RTPrintf("  mapping #%u: %RTptr-%RTptr\n",
                                 iMapping,
                                 aMappings[iMapping].Address,
                                 aMappings[iMapping].Address + RTDbgModImageSize(hDbgMod) - 1);
                    else
                    {
                        RTDBGSEGMENT SegInfo;
                        rc = RTDbgModSegmentByIndex(hDbgMod, aMappings[iMapping].iSeg, &SegInfo);
                        if (RT_SUCCESS(rc))
                            RTPrintf("  mapping #%u: %RTptr-%RTptr (segment #%u - '%s')",
                                     iMapping,
                                     aMappings[iMapping].Address,
                                     aMappings[iMapping].Address + SegInfo.cb,
                                     SegInfo.iSeg, SegInfo.szName);
                        else
                            RTPrintf("  mapping #%u: %RTptr-???????? (segment #%u)", iMapping, aMappings[iMapping].Address);
                    }

                    if (cVerbosityLevel > 1)
                    {
                        uint32_t cSymbols = RTDbgModSymbolCount(hDbgMod);
                        RTPrintf("    %u symbols\n", cSymbols);
                        for (uint32_t iSymbol = 0; iSymbol < cSymbols; iSymbol++)
                        {
                            RTDBGSYMBOL SymInfo;
                            rc = RTDbgModSymbolByOrdinal(hDbgMod, iSymbol, &SymInfo);
                            if (RT_SUCCESS(rc))
                                RTPrintf("    #%04u at %08x:%RTptr %05llx %s\n",
                                         SymInfo.iOrdinal, SymInfo.iSeg, SymInfo.offSeg,
                                         (uint64_t)SymInfo.cb, SymInfo.szName);
                        }
                    }
                }
            }
            else
                RTMsgError("RTDbgAsModuleQueryMapByIndex failed: %Rrc", rc);
            RTDbgModRelease(hDbgMod);
        }
        RTPrintf("*** End of Address Space Dump ***\n");
    }

    /*
     * Read text from standard input and see if there is anything we can translate.
     */
    for (;;)
    {
        /* Get a line. */
        char szLine[_64K];
        rc = RTStrmGetLine(pInput, szLine, sizeof(szLine));
        if (rc == VERR_EOF)
            break;
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTStrmGetLine() -> %Rrc\n", rc);

        /*
         * Search the line for potential addresses and replace them with
         * symbols+offset.
         */
        const char *pszStart = szLine;
        const char *psz      = szLine;
        char        ch;
        while ((ch = *psz) != '\0')
        {
            size_t      cchAddress;
            uint64_t    u64Address;

            if (   (   ch == '0'
                    && (psz[1] == 'x' || psz[1] == 'X')
                    && TryParseAddress(psz, &cchAddress, &u64Address))
                || (   RT_C_IS_XDIGIT(ch)
                    && TryParseAddress(psz, &cchAddress, &u64Address))
               )
            {
                /* Print. */
                psz += cchAddress;
                if (pszStart != psz)
                    RTStrmWrite(pOutput, pszStart, psz - pszStart);
                pszStart = psz;

                /* Try get the module. */
                RTUINTPTR   uAddr;
                RTDBGSEGIDX iSeg;
                RTDBGMOD    hDbgMod;
                rc = RTDbgAsModuleByAddr(hDbgAs, u64Address, &hDbgMod, &uAddr, &iSeg);
                if (RT_SUCCESS(rc))
                {
                    if (iSeg != UINT32_MAX)
                        RTStrmPrintf(pOutput, "=[%s:%u", RTDbgModName(hDbgMod), iSeg);
                    else
                        RTStrmPrintf(pOutput, "=[%s", RTDbgModName(hDbgMod), iSeg);

                    /*
                     * Do we have symbols?
                     */
                    RTDBGSYMBOL Symbol;
                    RTINTPTR    offSym;
                    rc = RTDbgAsSymbolByAddr(hDbgAs, u64Address, RTDBGSYMADDR_FLAGS_LESS_OR_EQUAL, &offSym, &Symbol, NULL);
                    if (RT_SUCCESS(rc))
                    {
                        if (!offSym)
                            RTStrmPrintf(pOutput, "!%s", Symbol.szName);
                        else if (offSym > 0)
                            RTStrmPrintf(pOutput, "!%s+%#llx", Symbol.szName, offSym);
                        else
                            RTStrmPrintf(pOutput, "!%s-%#llx", Symbol.szName, -offSym);
                    }
                    else
                        RTStrmPrintf(pOutput, "+%#llx", u64Address - uAddr);

                    /*
                     * Do we have line numbers?
                     */
                    RTDBGLINE   Line;
                    RTINTPTR    offLine;
                    rc = RTDbgAsLineByAddr(hDbgAs, u64Address, &offLine, &Line, NULL);
                    if (RT_SUCCESS(rc))
                        RTStrmPrintf(pOutput, " %Rbn(%u)", Line.szFilename, Line.uLineNo);

                    RTStrmPrintf(pOutput, "]");
                    RTDbgModRelease(hDbgMod);
                }
            }
            else
                psz++;
        }

        if (pszStart != psz)
            RTStrmWrite(pOutput, pszStart, psz - pszStart);
        RTStrmPutCh(pOutput, '\n');

    }

    return RTEXITCODE_SUCCESS;
}