Exemple #1
0
/**
 * @interface_method_impl(PDMDRVREG,pfnConstruct)
 */
DECLCALLBACK(int) Nvram::drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    LogFlowFunc(("iInstance/#d, pCfg:%p, fFlags:%x\n", pDrvIns->iInstance, pCfg, fFlags));
    PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);

    if (!CFGMR3AreValuesValid(pCfg, "Object\0"
                                    "PermanentSave\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    void *pv;
    int rc = CFGMR3QueryPtr(pCfg, "Object", &pv);
    AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);
    pThis->pNvram = (Nvram *)pv;

    bool fPermanentSave = false;
    rc = CFGMR3QueryBool(pCfg, "PermanentSave", &fPermanentSave);
    if (   RT_SUCCESS(rc)
        || rc == VERR_CFGM_VALUE_NOT_FOUND)
        pThis->fPermanentSave = fPermanentSave;
    else
        AssertRCReturn(rc, rc);

    pDrvIns->IBase.pfnQueryInterface = Nvram::drvNvram_QueryInterface;
    pThis->INvram.pfnFlushNvramStorage = drvNvram_pfnFlushNvramStorage;
    pThis->INvram.pfnStoreNvramValue = drvNvram_pfnStoreNvramValue;
    pThis->INvram.pfnLoadNvramValue = drvNvram_pfnLoadNvramValue;

    return VINF_SUCCESS;
}
DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
{
    /*
     * Read the /proc/self/exe link, convert to native and return it.
     */
    int cchLink = readlink("/proc/self/exe", pszPath, cchPath - 1);
    if (cchLink > 0 && (size_t)cchLink <= cchPath - 1)
    {
        pszPath[cchLink] = '\0';

        char const *pszTmp;
        int rc = rtPathFromNative(&pszTmp, pszPath, NULL);
        AssertMsgRCReturn(rc, ("rc=%Rrc pszLink=\"%s\"\nhex: %.*Rhxs\n", rc, pszPath, cchLink, pszPath), rc);
        if (pszTmp != pszPath)
        {
            rc = RTStrCopy(pszPath, cchPath, pszTmp);
            rtPathFreeIprt(pszTmp, pszPath);
        }
        return rc;
    }

    int err = errno;
    int rc = RTErrConvertFromErrno(err);
    AssertMsgFailed(("rc=%Rrc err=%d cchLink=%d\n", rc, err, cchLink));
    return rc;
}
Exemple #3
0
/**
 * Detaches a debugger from the specified VM.
 *
 * Caller must be attached to the VM.
 *
 * @returns VBox status code.
 * @param   pVM     Pointer to the VM.
 */
VMMR3DECL(int) DBGFR3Detach(PVM pVM)
{
    LogFlow(("DBGFR3Detach:\n"));
    int rc;

    /*
     * Check if attached.
     */
    AssertReturn(pVM->dbgf.s.fAttached, VERR_DBGF_NOT_ATTACHED);

    /*
     * Try send the detach command.
     * Keep in mind that we might be racing EMT, so, be extra careful.
     */
    DBGFCMD enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACH_DEBUGGER);
    if (RTSemPongIsSpeaker(&pVM->dbgf.s.PingPong))
    {
        rc = RTSemPong(&pVM->dbgf.s.PingPong);
        AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);
        LogRel(("DBGFR3Detach: enmCmd=%d (pong -> ping)\n", enmCmd));
    }

    /*
     * Wait for the OK event.
     */
    rc = RTSemPongWait(&pVM->dbgf.s.PingPong, RT_INDEFINITE_WAIT);
    AssertLogRelMsgRCReturn(rc, ("Wait on detach command failed, rc=%Rrc\n", rc), rc);

    /*
     * Send the notification command indicating that we're really done.
     */
    enmCmd = dbgfR3SetCmd(pVM, DBGFCMD_DETACHED_DEBUGGER);
    rc = RTSemPong(&pVM->dbgf.s.PingPong);
    AssertMsgRCReturn(rc, ("Failed to signal emulation thread. rc=%Rrc\n", rc), rc);

    LogFlowFunc(("returns VINF_SUCCESS\n"));
    return VINF_SUCCESS;
}
Exemple #4
0
int VBoxNetDhcp::fetchAndUpdateDnsInfo()
{
    ComHostPtr host;
    if (SUCCEEDED(virtualbox->COMGETTER(Host)(host.asOutParam())))
    {
        AddressToOffsetMapping mapIp4Addr2Off;
        int rc = localMappings(m_NATNetwork, mapIp4Addr2Off);
        /* XXX: here could be several cases: 1. COM error, 2. not found (empty) 3. ? */
        AssertMsgRCReturn(rc, ("Can't fetch local mappings"), rc);

        RTNETADDRIPV4 address = getIpv4Address();
        RTNETADDRIPV4 netmask = getIpv4Netmask();

        AddressList nameservers;
        rc = hostDnsServers(host, networkid(address, netmask), mapIp4Addr2Off, nameservers);
        AssertMsgRCReturn(rc, ("Debug me!!!"), rc);
        /* XXX: Search strings */

        std::string domain;
        rc = hostDnsDomain(host, domain);
        AssertMsgRCReturn(rc, ("Debug me!!"), rc);

        {
            VBoxNetALock(this);
            ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
            confManager->flushAddressList(RTNET_DHCP_OPT_DNS);

            for (AddressList::iterator it = nameservers.begin(); it != nameservers.end(); ++it)
                confManager->addToAddressList(RTNET_DHCP_OPT_DNS, *it);

            confManager->setString(RTNET_DHCP_OPT_DOMAIN_NAME, domain);
        }
    }

    return VINF_SUCCESS;
}
Exemple #5
0
/**
 * @interface_method_impl{PDMDRVREG,pfnConstruct}
 */
DECLCALLBACK(int) Nvram::drvNvram_Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    RT_NOREF(fFlags);
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
    LogFlowFunc(("iInstance/#%d pCfg=%p fFlags=%x\n", pDrvIns->iInstance, pCfg, fFlags));
    PNVRAM pThis = PDMINS_2_DATA(pDrvIns, PNVRAM);

    /*
     * Initalize instance data variables first.
     */
    //pThis->pNvram                               = NULL;
    //pThis->cLoadedVariables                     = 0;
    //pThis->fPermanentSave                       = false;
    pThis->pCfgVarRoot                          = CFGMR3GetChild(pCfg, "Vars");
    //pThis->pLastVarNode                         = NULL;
    pThis->idxLastVar                           = UINT32_MAX / 2;

    pDrvIns->IBase.pfnQueryInterface            = Nvram::drvNvram_QueryInterface;
    pThis->INvramConnector.pfnVarQueryByIndex   = drvNvram_VarQueryByIndex;
    pThis->INvramConnector.pfnVarStoreSeqBegin  = drvNvram_VarStoreSeqBegin;
    pThis->INvramConnector.pfnVarStoreSeqPut    = drvNvram_VarStoreSeqPut;
    pThis->INvramConnector.pfnVarStoreSeqEnd    = drvNvram_VarStoreSeqEnd;

    /*
     * Validate and read configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "Object\0"
                              "PermanentSave\0"))
        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
    AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
                    ("Configuration error: Not possible to attach anything to this driver!\n"),
                    VERR_PDM_DRVINS_NO_ATTACH);

    int rc = CFGMR3QueryPtr(pCfg, "Object", (void **)&pThis->pNvram);
    AssertMsgRCReturn(rc, ("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc), rc);

    rc = CFGMR3QueryBoolDef(pCfg, "PermanentSave", &pThis->fPermanentSave, false);
    AssertRCReturn(rc, rc);

    /*
     * Let the associated class instance know about us.
     */
    pThis->pNvram->mpDrv = pThis;

    return VINF_SUCCESS;
}
DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
{
    /*
     * Query the image name from the dynamic linker, convert and return it.
     */
    _execname(pszPath, cchPath);

    char const *pszTmp;
    int rc = rtPathFromNative(&pszTmp, pszPath, NULL);
    AssertMsgRCReturn(rc, ("rc=%Rrc pszLink=\"%s\"\nhex: %.*Rhxs\n", rc, pszPath, cchPath, pszPath), rc);
    if (pszTmp != pszPath)
    {
        rc = RTStrCopy(pszPath, cchPath, pszTmp);
        rtPathFreeIprt(pszTmp, pszPath);
    }
    return rc;
}
DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
{
    /*
     * Query the image name from the dynamic linker, convert and return it.
     */
    const char *pszImageName = _dyld_get_image_name(0);
    AssertReturn(pszImageName, VERR_INTERNAL_ERROR);

    char szTmpPath[PATH_MAX + 1];
    const char *psz = realpath(pszImageName, szTmpPath);
    int rc;
    if (psz)
        rc = rtPathFromNativeCopy(pszPath, cchPath, szTmpPath, NULL);
    else
        rc = RTErrConvertFromErrno(errno);
    AssertMsgRCReturn(rc, ("rc=%Rrc pszLink=\"%s\"\nhex: %.*Rhxs\n", rc, pszPath, strlen(pszImageName), pszPath), rc);

    return VINF_SUCCESS;
}
RTR3DECL(bool) RTProcIsRunningByName(const char *pszName)
{
    /*
     * Quick validation.
     */
    if (!pszName)
        return false;

    bool const fWithPath = RTPathHavePath(pszName);

    /*
     * Enumerate /proc.
     */
    RTDIR hDir;
    int rc = RTDirOpen(&hDir, "/proc");
    AssertMsgRCReturn(rc, ("RTDirOpen on /proc failed: rc=%Rrc\n", rc), false);
    if (RT_SUCCESS(rc))
    {
        RTDIRENTRY DirEntry;
        while (RT_SUCCESS(RTDirRead(hDir, &DirEntry, NULL)))
        {
            /*
             * Filter numeric directory entries only.
             */
            if (   (   DirEntry.enmType == RTDIRENTRYTYPE_DIRECTORY
                    || DirEntry.enmType == RTDIRENTRYTYPE_UNKNOWN)
                && RTStrToUInt32(DirEntry.szName) > 0)
            {
                /*
                 * Try readlink on exe first since it's more faster and reliable.
                 * Fall back on reading the first line in cmdline if that fails
                 * (access errors typically). cmdline is unreliable as it might
                 * contain whatever the execv caller passes as argv[0].
                 */
                char szName[RTPATH_MAX];
                RTStrPrintf(szName, sizeof(szName), "/proc/%s/exe", &DirEntry.szName[0]);
                char szExe[RTPATH_MAX];
                int cchLink = readlink(szName, szExe, sizeof(szExe) - 1);
                if (    cchLink > 0
                    &&  (size_t)cchLink < sizeof(szExe))
                {
                    szExe[cchLink] = '\0';
                    rc = VINF_SUCCESS;
                }
                else
                {
                    RTStrPrintf(szName, sizeof(szName), "/proc/%s/cmdline", &DirEntry.szName[0]);
                    PRTSTREAM pStream;
                    rc = RTStrmOpen(szName, "r", &pStream);
                    if (RT_SUCCESS(rc))
                    {
                        rc = RTStrmGetLine(pStream, szExe, sizeof(szExe));
                        RTStrmClose(pStream);
                    }
                }
                if (RT_SUCCESS(rc))
                {
                    /*
                     * We are interested on the file name part only.
                     */
                    char const *pszProcName = fWithPath ? szExe : RTPathFilename(szExe);
                    if (RTStrCmp(pszProcName, pszName) == 0)
                    {
                        /* Found it! */
                        RTDirClose(hDir);
                        return true;
                    }
                }
            }
        }
        RTDirClose(hDir);
    }

    return false;
}
Exemple #9
0
int VBoxNetDhcp::initWithMain()
{
    /* ok, here we should initiate instance of dhcp server
     * and listener for Dhcp configuration events
     */
    AssertRCReturn(virtualbox.isNull(), VERR_INTERNAL_ERROR);
    std::string networkName = getNetwork();

    int rc = findDhcpServer(virtualbox, networkName, m_DhcpServer);
    AssertRCReturn(rc, rc);

    rc = findNatNetwork(virtualbox, networkName, m_NATNetwork);
    AssertRCReturn(rc, rc);

    BOOL fNeedDhcpServer = isDhcpRequired(m_NATNetwork);
    if (!fNeedDhcpServer)
        return VERR_CANCELLED;

    RTNETADDRIPV4 gateway;
    com::Bstr strGateway;
    HRESULT hrc = m_NATNetwork->COMGETTER(Gateway)(strGateway.asOutParam());
    AssertComRCReturn(hrc, VERR_INTERNAL_ERROR);
    RTNetStrToIPv4Addr(com::Utf8Str(strGateway).c_str(), &gateway);

    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();
    AssertPtrReturn(confManager, VERR_INTERNAL_ERROR);
    confManager->addToAddressList(RTNET_DHCP_OPT_ROUTERS, gateway);

    rc = fetchAndUpdateDnsInfo();
    AssertMsgRCReturn(rc, ("Wasn't able to fetch Dns info"), rc);

    ComEventTypeArray aVBoxEvents;
    aVBoxEvents.push_back(VBoxEventType_OnHostNameResolutionConfigurationChange);
    rc = createNatListener(m_vboxListener, virtualbox, this, aVBoxEvents);
    AssertRCReturn(rc, rc);

    RTNETADDRIPV4 LowerAddress;
    rc = configGetBoundryAddress(m_DhcpServer, false, LowerAddress);
    AssertMsgRCReturn(rc, ("can't get lower boundrary adderss'"),rc);

    RTNETADDRIPV4 UpperAddress;
    rc = configGetBoundryAddress(m_DhcpServer, true, UpperAddress);
    AssertMsgRCReturn(rc, ("can't get upper boundrary adderss'"),rc);

    RTNETADDRIPV4 address = getIpv4Address();
    RTNETADDRIPV4 netmask = getIpv4Netmask();
    RTNETADDRIPV4 networkId = networkid(address, netmask);
    std::string name = std::string("default");

    confManager->addNetwork(unconst(g_RootConfig),
                            networkId,
                            netmask,
                            LowerAddress,
                            UpperAddress);

    com::Bstr bstr;
    hrc = virtualbox->COMGETTER(HomeFolder)(bstr.asOutParam());
    com::Utf8StrFmt strXmlLeaseFile("%ls%c%s.leases",
                                    bstr.raw(), RTPATH_DELIMITER, networkName.c_str());
    confManager->loadFromFile(strXmlLeaseFile);

    return VINF_SUCCESS;
}
/**
 * rtR3Init worker.
 */
static int rtR3InitBody(uint32_t fFlags, int cArgs, char ***papszArgs, const char *pszProgramPath)
{
    /*
     * Early native initialization.
     */
    int rc = rtR3InitNativeFirst(fFlags);
    AssertMsgRCReturn(rc, ("rtR3InitNativeFirst failed with %Rrc\n", rc), rc);

    /*
     * Disable error popups.
     */
#if defined(RT_OS_OS2) /** @todo move to private code. */
    DosError(FERR_DISABLEHARDERR);
#endif

    /*
     * Init C runtime locale before we do anything that may end up converting
     * paths or we'll end up using the "C" locale for path conversion.
     */
    setlocale(LC_CTYPE, "");

    /*
     * The Process ID.
     */
#ifdef _MSC_VER
    g_ProcessSelf = _getpid(); /* crappy ansi compiler */
#else
    g_ProcessSelf = getpid();
#endif

    /*
     * Save the init flags.
     */
    g_fInitFlags |= fFlags;

#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
# ifdef VBOX
    /*
     * This MUST be done as the very first thing, before any file is opened.
     * The log is opened on demand, but the first log entries may be caused
     * by rtThreadInit() below.
     */
    const char *pszDisableHostCache = getenv("VBOX_DISABLE_HOST_DISK_CACHE");
    if (    pszDisableHostCache != NULL
        &&  *pszDisableHostCache
        &&  strcmp(pszDisableHostCache, "0") != 0)
    {
        RTFileSetForceFlags(RTFILE_O_WRITE, RTFILE_O_WRITE_THROUGH, 0);
        RTFileSetForceFlags(RTFILE_O_READWRITE, RTFILE_O_WRITE_THROUGH, 0);
    }
# endif  /* VBOX */
#endif /* !IN_GUEST && !RT_NO_GIP */

    /*
     * Thread Thread database and adopt the caller thread as 'main'.
     * This must be done before everything else or else we'll call into threading
     * without having initialized TLS entries and suchlike.
     */
    rc = rtThreadInit();
    AssertMsgRCReturn(rc, ("Failed to initialize threads, rc=%Rrc!\n", rc), rc);

#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
    if (fFlags & RTR3INIT_FLAGS_SUPLIB)
    {
        /*
         * Init GIP first.
         * (The more time for updates before real use, the better.)
         */
        rc = SUPR3Init(NULL);
        AssertMsgRCReturn(rc, ("Failed to initializable the support library, rc=%Rrc!\n", rc), rc);
    }
#endif

    /*
     * The executable path, name and directory.  Convert arguments.
     */
    rc = rtR3InitProgramPath(pszProgramPath);
    AssertLogRelMsgRCReturn(rc, ("Failed to get executable directory path, rc=%Rrc!\n", rc), rc);

    rc = rtR3InitArgv(fFlags, cArgs, papszArgs);
    AssertLogRelMsgRCReturn(rc, ("Failed to convert the arguments, rc=%Rrc!\n", rc), rc);

#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
    /*
     * The threading is initialized we can safely sleep a bit if GIP
     * needs some time to update itself updating.
     */
    if ((fFlags & RTR3INIT_FLAGS_SUPLIB) && g_pSUPGlobalInfoPage)
    {
        RTThreadSleep(20);
        RTTimeNanoTS();
    }
#endif

    /*
     * Init the program start TSes.
     * Do that here to be sure that the GIP time was properly updated the 1st time.
     */
    g_u64ProgramStartNanoTS = RTTimeNanoTS();
    g_u64ProgramStartMicroTS = g_u64ProgramStartNanoTS / 1000;
    g_u64ProgramStartMilliTS = g_u64ProgramStartNanoTS / 1000000;

    /*
     * The remainder cannot easily be undone, so it has to go last.
     */

    /* Fork and exit callbacks. */
#if !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
    rc = pthread_atfork(NULL, NULL, rtR3ForkChildCallback);
    AssertMsg(rc == 0, ("%d\n", rc));
#endif
    atexit(rtR3ExitCallback);

#ifdef IPRT_USE_SIG_CHILD_DUMMY
    /*
     * SIGCHLD must not be ignored (that's default), otherwise posix compliant waitpid
     * implementations won't work right.
     */
    for (;;)
    {
        struct sigaction saOld;
        rc = sigaction(SIGCHLD, 0, &saOld);         AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
        if (    rc != 0
            ||  (saOld.sa_flags & SA_SIGINFO)
            || (   saOld.sa_handler != SIG_IGN
                && saOld.sa_handler != SIG_DFL)
           )
            break;

        /* Try install dummy handler. */
        struct sigaction saNew = saOld;
        saNew.sa_flags   = SA_NOCLDSTOP | SA_RESTART;
        saNew.sa_handler = rtR3SigChildHandler;
        rc = sigemptyset(&saNew.sa_mask);           AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
        struct sigaction saOld2;
        rc = sigaction(SIGCHLD, &saNew, &saOld2);   AssertMsg(rc == 0, ("%d/%d\n", rc, errno));
        if (    rc != 0
            ||  (   saOld2.sa_handler == saOld.sa_handler
                 && !(saOld2.sa_flags & SA_SIGINFO))
           )
            break;

        /* Race during dynamic load, restore and try again... */
        sigaction(SIGCHLD, &saOld2, NULL);
        RTThreadYield();
    }
#endif /* IPRT_USE_SIG_CHILD_DUMMY */

#ifdef IPRT_WITH_ALIGNMENT_CHECKS
    /*
     * Enable alignment checks.
     */
    const char *pszAlignmentChecks = getenv("IPRT_ALIGNMENT_CHECKS");
    g_fRTAlignmentChecks = pszAlignmentChecks != NULL
                        && pszAlignmentChecks[0] == '1'
                        && pszAlignmentChecks[1] == '\0';
    if (g_fRTAlignmentChecks)
        IPRT_ALIGNMENT_CHECKS_ENABLE();
#endif

    /*
     * Final native initialization.
     */
    rc = rtR3InitNativeFinal(fFlags);
    AssertMsgRCReturn(rc, ("rtR3InitNativeFinal failed with %Rrc\n", rc), rc);

    return VINF_SUCCESS;
}
/**
 * Initialize the debug info for a VM.
 *
 * This will check the CFGM for any symbols or symbol files
 * which needs loading.
 *
 * @returns VBox status code.
 * @param   pVM     The VM handle.
 */
int dbgfR3SymInit(PVM pVM)
{
    int rc;

    /*
     * Initialize the symbol table.
     */
    pVM->dbgf.s.pSymbolSpace = (PRTSTRSPACE)MMR3HeapAllocZ(pVM, MM_TAG_DBGF_SYMBOL, sizeof(*pVM->dbgf.s.pSymbolSpace));
    AssertReturn(pVM->dbgf.s.pSymbolSpace, VERR_NO_MEMORY);

#ifndef HAVE_DBGHELP
    /* modules & lines later */
    rc = dbgfR3SymbolInit(pVM);
    if (RT_FAILURE(rc))
        return rc;
    pVM->dbgf.s.fSymInited = true;
#endif

    /*
     * Check if there are 'loadsyms' commands in the configuration.
     */
    PCFGMNODE pNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/DBGF/loadsyms/");
    if (pNode)
    {
        /*
         * Enumerate the commands.
         */
        for (PCFGMNODE pCmdNode = CFGMR3GetFirstChild(pNode);
             pCmdNode;
             pCmdNode = CFGMR3GetNextChild(pCmdNode))
        {
            char szCmdName[128];
            CFGMR3GetName(pCmdNode, &szCmdName[0], sizeof(szCmdName));

            /* File */
            char *pszFilename;
            rc = CFGMR3QueryStringAlloc(pCmdNode, "Filename", &pszFilename);
            AssertMsgRCReturn(rc, ("rc=%Rrc querying the 'File' attribute of '/DBGF/loadsyms/%s'!\n", rc, szCmdName), rc);

            /* Delta (optional) */
            RTGCINTPTR offDelta;
            rc = CFGMR3QueryGCPtrS(pNode, "Delta", &offDelta);
            if (rc == VERR_CFGM_VALUE_NOT_FOUND)
                offDelta = 0;
            else
                AssertMsgRCReturn(rc, ("rc=%Rrc querying the 'Delta' attribute of '/DBGF/loadsyms/%s'!\n", rc, szCmdName), rc);

            /* Module (optional) */
            char *pszModule;
            rc = CFGMR3QueryStringAlloc(pCmdNode, "Module", &pszModule);
            if (rc == VERR_CFGM_VALUE_NOT_FOUND)
                pszModule = NULL;
            else
                AssertMsgRCReturn(rc, ("rc=%Rrc querying the 'Module' attribute of '/DBGF/loadsyms/%s'!\n", rc, szCmdName), rc);

            /* Module (optional) */
            RTGCUINTPTR ModuleAddress;
            rc = CFGMR3QueryGCPtrU(pNode, "ModuleAddress", &ModuleAddress);
            if (rc == VERR_CFGM_VALUE_NOT_FOUND)
                ModuleAddress = 0;
            else
                AssertMsgRCReturn(rc, ("rc=%Rrc querying the 'ModuleAddress' attribute of '/DBGF/loadsyms/%s'!\n", rc, szCmdName), rc);

            /* Image size (optional) */
            RTGCUINTPTR cbModule;
            rc = CFGMR3QueryGCPtrU(pNode, "ModuleSize", &cbModule);
            if (rc == VERR_CFGM_VALUE_NOT_FOUND)
                cbModule = 0;
            else
                AssertMsgRCReturn(rc, ("rc=%Rrc querying the 'ModuleAddress' attribute of '/DBGF/loadsyms/%s'!\n", rc, szCmdName), rc);


            /*
             * Execute the command.
             */
            rc = DBGFR3ModuleLoad(pVM, pszFilename, offDelta, pszModule, ModuleAddress, cbModule);
            AssertMsgRCReturn(rc, ("pszFilename=%s offDelta=%RGv pszModule=%s ModuleAddress=%RGv cbModule=%RGv\n",
                                   pszFilename, offDelta, pszModule, ModuleAddress, cbModule), rc);

            MMR3HeapFree(pszModule);
            MMR3HeapFree(pszFilename);
        }
    }

    /*
     * Check if there are any 'symadd' commands in the configuration.
     */

    return VINF_SUCCESS;
}