VirtualBox

Changeset 46025 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
May 13, 2013 3:36:27 PM (12 years ago)
Author:
vboxsync
Message:

RTDbgCfg: Directory and cache searching code.

Location:
trunk/src/VBox/Runtime/common/dbg
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/dbg/dbgcfg.cpp

    r45998 r46025  
    2929*   Header Files                                                               *
    3030*******************************************************************************/
     31#define LOG_GROUP RTLOGGROUP_DBG
    3132#include <iprt/dbg.h>
    3233#include "internal/iprt.h"
     
    3637#include <iprt/critsect.h>
    3738#include <iprt/ctype.h>
     39#include <iprt/dir.h>
    3840#include <iprt/err.h>
    3941#include <iprt/env.h>
     42#include <iprt/file.h>
    4043#include <iprt/list.h>
     44#include <iprt/log.h>
    4145#include <iprt/mem.h>
    4246#include <iprt/path.h>
    4347#include <iprt/semaphore.h>
    4448#include <iprt/string.h>
     49#include <iprt/uuid.h>
    4550#include "internal/magics.h"
    4651
     
    4954*   Structures and Typedefs                                                    *
    5055*******************************************************************************/
    51 /** @name Flags for path search strings
    52  * @{ */
    53 #define RTDBGCCFG_PATH_SRV      UINT16_C(0x0001)
    54 #define RTDBGCCFG_PATH_CACHE    UINT16_C(0x0002)
    55 /** @}*/
    56 
    5756/**
    5857 * String list entry.
     
    7271typedef RTDBGCFGSTR *PRTDBGCFGSTR;
    7372
     73
     74/**
     75 * Log callback.
     76 *
     77 * @param   hDbgCfg         The debug config instance.
     78 * @param   iLevel          The message level.
     79 * @param   pszMsg          The message.
     80 * @param   pvUser          User argument.
     81 */
     82typedef DECLCALLBACK(int) FNRTDBGCFGLOG(RTDBGCFG hDbgCfg, uint32_t iLevel, const char *pszMsg, void *pvUser);
     83/** Pointer to a log callback. */
     84typedef FNRTDBGCFGLOG *PFNRTDBGCFGLOG;
     85
    7486/**
    7587 * Configuration instance.
     
    100112#endif
    101113
     114    /** Log callback function. */
     115    PFNRTDBGCFGLOG      pfnLogCallback;
     116    /** User argument to pass to the log callback. */
     117    void               *pvLogUser;
     118
    102119    /** Critical section protecting the instance data. */
    103120    RTCRITSECTRW        CritSect;
    104121} *PRTDBGCFGINT;
    105 
    106122
    107123/**
     
    124140
    125141
     142/** @name Open flags.
     143 * @{ */
     144/** The operative system mask.  The values are RT_OPSYS_XXX. */
     145#define RTDBGCFG_O_OPSYS_MASK           UINT32_C(0x000000ff)
     146/** Whether to make a recursive search. */
     147#define RTDBGCFG_O_RECURSIVE            RT_BIT_32(27)
     148/** We're looking for a separate debug file. */
     149#define RTDBGCFG_O_EXT_DEBUG_FILE       RT_BIT_32(28)
     150/** We're looking for an executable image. */
     151#define RTDBGCFG_O_EXECUTABLE_IMAGE     RT_BIT_32(29)
     152/** The file search should be done in an case insensitive fashion. */
     153#define RTDBGCFG_O_CASE_INSENSITIVE     RT_BIT_32(30)
     154/** Use Windbg style symbol servers when encountered in the path. */
     155#define RTDBGCFG_O_SYMSRV               RT_BIT_32(31)
     156/** @} */
     157
    126158
    127159/*******************************************************************************
     
    158190
    159191
     192/**
     193 * Runtime logging, level 1.
     194 *
     195 * @param   pThis               The debug config instance data.
     196 * @param   pszFormat           The message format string.
     197 * @param   ...                 Arguments references in the format string.
     198 */
     199static void rtDbgCfgLog1(PRTDBGCFGINT pThis, const char *pszFormat, ...)
     200{
     201    if (LogIsEnabled() || (pThis && pThis->pfnLogCallback))
     202    {
     203        va_list va;
     204        va_start(va, pszFormat);
     205        char *pszMsg = RTStrAPrintf2V(pszFormat, va);
     206        va_end(va);
     207
     208        Log(("RTDbgCfg: %s", pszMsg));
     209        if (pThis && pThis->pfnLogCallback)
     210            pThis->pfnLogCallback(pThis, 1, pszMsg, pThis->pvLogUser);
     211        RTStrFree(pszMsg);
     212    }
     213}
     214
     215
     216/**
     217 * Runtime logging, level 2.
     218 *
     219 * @param   pThis               The debug config instance data.
     220 * @param   pszFormat           The message format string.
     221 * @param   ...                 Arguments references in the format string.
     222 */
     223static void rtDbgCfgLog2(PRTDBGCFGINT pThis, const char *pszFormat, ...)
     224{
     225    if (LogIs2Enabled() || (pThis && pThis->pfnLogCallback))
     226    {
     227        va_list va;
     228        va_start(va, pszFormat);
     229        char *pszMsg = RTStrAPrintf2V(pszFormat, va);
     230        va_end(va);
     231
     232        Log(("RTDbgCfg: %s", pszMsg));
     233        if (pThis && pThis->pfnLogCallback)
     234            pThis->pfnLogCallback(pThis, 2, pszMsg, pThis->pvLogUser);
     235        RTStrFree(pszMsg);
     236    }
     237}
     238
     239
     240/**
     241 * Checks if the file system at the given path is case insensitive or not.
     242 *
     243 * @returns true / false
     244 * @param   pszPath             The path to query about.
     245 */
     246static int rtDbgCfgIsFsCaseInsensitive(const char *pszPath)
     247{
     248    RTFSPROPERTIES Props;
     249    int rc = RTFsQueryProperties(pszPath, &Props);
     250    if (RT_FAILURE(rc))
     251        return RT_OPSYS == RT_OPSYS_DARWIN
     252            || RT_OPSYS == RT_OPSYS_DOS
     253            || RT_OPSYS == RT_OPSYS_OS2
     254            || RT_OPSYS == RT_OPSYS_NT
     255            || RT_OPSYS == RT_OPSYS_WINDOWS;
     256    return !Props.fCaseSensitive;
     257}
     258
     259
     260/**
     261 * Worker that does case sensitive file/dir searching.
     262 *
     263 * @returns true / false.
     264 * @param   pszPath         The path buffer containing an existing directory.
     265 *                          RTPATH_MAX in size.  On success, this will contain
     266 *                          the combined path with @a pszName case correct.
     267 * @param   offLastComp     The offset of the last component (for chopping it
     268 *                          off).
     269 * @param   pszName         What we're looking for.
     270 * @param   enmType         What kind of thing we're looking for.
     271 */
     272static bool rtDbgCfgIsXxxxAndFixCaseWorker(char *pszPath, size_t offLastComp, const char *pszName,
     273                                           RTDIRENTRYTYPE enmType)
     274{
     275    /** @todo IPRT should generalize this so we can use host specific tricks to
     276     *        speed it up. */
     277
     278    /* Return straight away if the name isn't case foldable. */
     279    if (!RTStrIsCaseFoldable(pszName))
     280        return false;
     281
     282    /*
     283     * Open the directory and check each entry in it.
     284     */
     285    pszPath[offLastComp] = '\0';
     286    PRTDIR pDir;
     287    int rc = RTDirOpen(&pDir, pszPath);
     288    if (RT_SUCCESS(rc))
     289        return false;
     290
     291    for (;;)
     292    {
     293        /* Read the next entry. */
     294        union
     295        {
     296            RTDIRENTRY  Entry;
     297            uint8_t     ab[_4K];
     298        } u;
     299        size_t cbBuf = sizeof(u);
     300        rc = RTDirRead(pDir, &u.Entry, &cbBuf);
     301        if (RT_FAILURE(rc))
     302            break;
     303
     304        if (   !RTStrICmp(pszName, u.Entry.szName)
     305            && (   u.Entry.enmType == enmType
     306                || u.Entry.enmType == RTDIRENTRYTYPE_UNKNOWN
     307                || u.Entry.enmType == RTDIRENTRYTYPE_SYMLINK) )
     308        {
     309            pszPath[offLastComp] = '\0';
     310            rc = RTPathAppend(pszPath, RTPATH_MAX, u.Entry.szName);
     311            if (   u.Entry.enmType != enmType
     312                && RT_SUCCESS(rc))
     313                RTDirQueryUnknownType(pszPath, true /*fFollowSymlinks*/, &u.Entry.enmType);
     314
     315            if (   u.Entry.enmType == enmType
     316                || RT_FAILURE(rc))
     317            {
     318                RTDirClose(pDir);
     319                if (RT_FAILURE(rc))
     320                {
     321                    pszPath[offLastComp] = '\0';
     322                    return false;
     323                }
     324                return true;
     325            }
     326        }
     327    }
     328
     329    RTDirClose(pDir);
     330    pszPath[offLastComp] = '\0';
     331
     332    return false;
     333}
     334
     335
     336/**
     337 * Appends @a pszSubDir to @a pszPath and check whether it exists and is a
     338 * directory.
     339 *
     340 * If @a fCaseInsensitive is set, we will do a case insensitive search for a
     341 * matching sub directory.
     342 *
     343 * @returns true / false
     344 * @param   pszPath             The path buffer containing an existing
     345 *                              directory.  RTPATH_MAX in size.
     346 * @param   pszSubDir           The sub directory to append.
     347 * @param   fCaseInsensitive    Whether case insensitive searching is required.
     348 */
     349static bool rtDbgCfgIsDirAndFixCase(char *pszPath, const char *pszSubDir, bool fCaseInsensitive)
     350{
     351    /* Save the length of the input path so we can restore it in the case
     352       insensitive branch further down. */
     353    size_t const cchPath = strlen(pszPath);
     354
     355    /*
     356     * Append the sub directory and check if we got a hit.
     357     */
     358    int rc = RTPathAppend(pszPath, RTPATH_MAX, pszSubDir);
     359    if (RT_FAILURE(rc))
     360        return false;
     361
     362    if (RTDirExists(pszPath))
     363        return true;
     364
     365    /*
     366     * Do case insensitive lookup if requested.
     367     */
     368    if (fCaseInsensitive)
     369        return rtDbgCfgIsXxxxAndFixCaseWorker(pszPath, cchPath, pszSubDir, RTDIRENTRYTYPE_DIRECTORY);
     370    return false;
     371}
     372
     373
     374/**
     375 * Appends @a pszFilename to @a pszPath and check whether it exists and is a
     376 * directory.
     377 *
     378 * If @a fCaseInsensitive is set, we will do a case insensitive search for a
     379 * matching filename.
     380 *
     381 * @returns true / false
     382 * @param   pszPath             The path buffer containing an existing
     383 *                              directory.  RTPATH_MAX in size.
     384 * @param   pszFilename         The file name to append.
     385 * @param   fCaseInsensitive    Whether case insensitive searching is required.
     386 */
     387static bool rtDbgCfgIsFileAndFixCase(char *pszPath, const char *pszFilename, bool fCaseInsensitive)
     388{
     389    /* Save the length of the input path so we can restore it in the case
     390       insensitive branch further down. */
     391    size_t cchPath = strlen(pszPath);
     392
     393    /*
     394     * Append the filename and check if we got a hit.
     395     */
     396    int rc = RTPathAppend(pszPath, RTPATH_MAX, pszFilename);
     397    if (RT_FAILURE(rc))
     398        return false;
     399
     400    if (RTFileExists(pszPath))
     401        return true;
     402
     403    /*
     404     * Do case insensitive lookup if requested.
     405     */
     406    if (fCaseInsensitive)
     407        return rtDbgCfgIsXxxxAndFixCaseWorker(pszPath, cchPath, pszFilename, RTDIRENTRYTYPE_FILE);
     408    return false;
     409}
     410
     411
     412static int rtDbgCfgTryOpenDir(PRTDBGCFGINT pThis, char *pszPath, PRTPATHSPLIT pSplitFn, uint32_t fFlags,
     413                              PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
     414{
     415    int rcRet = VWRN_NOT_FOUND;
     416    int rc2;
     417
     418    /* If the directory doesn't exist, just quit immediately.
     419       Note! Our case insensitivity doesn't extend to the search dirs themselfs,
     420             only to the bits under neath them. */
     421    if (!RTDirExists(pszPath))
     422    {
     423        rtDbgCfgLog2(pThis, "Dir does not exist: '%s'\n", pszPath);
     424        return rcRet;
     425    }
     426
     427    /* Figure out whether we have to do a case sensitive search or not.
     428       Note! As a simplification, we don't ask for case settings in each
     429             directory under the user specified path, we assume the file
     430             systems that mounted there have compatible settings. Faster
     431             that way. */
     432    bool const fCaseInsensitive = (fFlags & RTDBGCFG_O_CASE_INSENSITIVE)
     433                               && rtDbgCfgIsFsCaseInsensitive(pszPath);
     434
     435    size_t const cchPath = strlen(pszPath);
     436
     437    /*
     438     * Look for the file with less and less of the original path given.
     439     */
     440    for (unsigned i = RTPATH_PROP_HAS_ROOT_SPEC(pSplitFn->fProps); i < pSplitFn->cComps; i++)
     441    {
     442        pszPath[cchPath] = '\0';
     443
     444        rc2 = VINF_SUCCESS;
     445        for (unsigned j = i; j < pSplitFn->cComps - 1U && RT_SUCCESS(rc2); j++)
     446            if (!rtDbgCfgIsDirAndFixCase(pszPath, pSplitFn->apszComps[i], fCaseInsensitive))
     447                rc2 = VERR_FILE_NOT_FOUND;
     448
     449        if (RT_SUCCESS(rc2))
     450        {
     451            if (rtDbgCfgIsFileAndFixCase(pszPath, pSplitFn->apszComps[pSplitFn->cComps - 1], fCaseInsensitive))
     452            {
     453                rtDbgCfgLog1(pThis, "Trying '%s'...\n", pszPath);
     454                rc2 = pfnCallback(pThis, pszPath, pvUser1, pvUser2);
     455                if (rc2 == VINF_CALLBACK_RETURN || rc2 == VERR_CALLBACK_RETURN)
     456                {
     457                    if (rc2 == VINF_CALLBACK_RETURN)
     458                        rtDbgCfgLog1(pThis, "Found '%s'.", pszPath);
     459                    else
     460                        rtDbgCfgLog1(pThis, "Error opening '%s'.\n", pszPath);
     461                    return rc2;
     462                }
     463                rtDbgCfgLog1(pThis, "Error %Rrc opening '%s'.\n", rc2, pszPath);
     464                if (RT_FAILURE(rc2) && RT_SUCCESS_NP(rcRet))
     465                    rcRet = rc2;
     466            }
     467        }
     468    }
     469
     470    /*
     471     * Do a recursive search if requested.
     472     */
     473    if (   (fFlags & RTDBGCFG_O_RECURSIVE)
     474        && !(pThis->fFlags & RTDBGCFG_FLAGS_NO_RECURSIV_SEARCH) )
     475    {
     476        /** @todo Recursive searching will be done later. */
     477    }
     478
     479    return rcRet;
     480}
     481
     482
     483static int rtDbgCfgTryDownloadAndOpen(PRTDBGCFGINT pThis, const char *pszServer,
     484                                      char *pszPath, const char *pszCacheSubDir, PRTPATHSPLIT pSplitFn,
     485                                      uint32_t fFlags, PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
     486{
     487    if (pThis->fFlags & RTDBGCFG_FLAGS_NO_SYM_SRV)
     488        return VWRN_NOT_FOUND;
     489
     490
     491    return VERR_NOT_IMPLEMENTED;
     492}
     493
     494
     495static int rtDbgCfgCopyFileToCache(PRTDBGCFGINT pThis, char const *pszSrc, const char *pchCache, size_t cchCache,
     496                                   const char *pszCacheSubDir, PRTPATHSPLIT pSplitFn)
     497{
     498    /** @todo copy to cache */
     499    return VINF_SUCCESS;
     500}
     501
     502
     503static int rtDbgCfgTryOpenCache(PRTDBGCFGINT pThis, char *pszPath, const char *pszCacheSubDir, PRTPATHSPLIT pSplitFn,
     504                                uint32_t fFlags, PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
     505{
     506    /*
     507     * If the cache doesn't exist, fail right away.
     508     */
     509    if (!pszCacheSubDir || !*pszCacheSubDir)
     510        return VWRN_NOT_FOUND;
     511    if (!RTDirExists(pszPath))
     512    {
     513        rtDbgCfgLog2(pThis, "Cache does not exist: '%s'\n", pszPath);
     514        return VWRN_NOT_FOUND;
     515    }
     516
     517    size_t cchPath = strlen(pszPath);
     518
     519    /*
     520     * Carefully construct the cache path with case insensitivity in mind.
     521     */
     522    bool const fCaseInsensitive = (fFlags & RTDBGCFG_O_CASE_INSENSITIVE)
     523                               && rtDbgCfgIsFsCaseInsensitive(pszPath);
     524
     525    if (!rtDbgCfgIsDirAndFixCase(pszPath, pSplitFn->apszComps[pSplitFn->cComps - 1], fCaseInsensitive))
     526        return VWRN_NOT_FOUND;
     527
     528    if (!rtDbgCfgIsDirAndFixCase(pszPath, pszCacheSubDir, fCaseInsensitive))
     529        return VWRN_NOT_FOUND;
     530
     531    if (!rtDbgCfgIsFileAndFixCase(pszPath, pSplitFn->apszComps[pSplitFn->cComps - 1], fCaseInsensitive))
     532        return VWRN_NOT_FOUND;
     533
     534    rtDbgCfgLog1(pThis, "Trying '%s'...\n", pszPath);
     535    int rc2 = pfnCallback(pThis, pszPath, pvUser1, pvUser2);
     536    if (rc2 == VINF_CALLBACK_RETURN)
     537        rtDbgCfgLog1(pThis, "Found '%s'.", pszPath);
     538    else if (rc2 == VERR_CALLBACK_RETURN)
     539        rtDbgCfgLog1(pThis, "Error opening '%s'.\n", pszPath);
     540    else
     541        rtDbgCfgLog1(pThis, "Error %Rrc opening '%s'.\n", rc2, pszPath);
     542    return rc2;
     543}
     544
     545
     546static int rtDbgCfgTryOpenList(PRTDBGCFGINT pThis, PRTLISTANCHOR pList, PRTPATHSPLIT pSplitFn, const char *pszCacheSubDir,
     547                               uint32_t fFlags, char *pszPath, PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
     548{
     549    int rcRet = VWRN_NOT_FOUND;
     550    int rc2;
     551
     552    const char *pchCache = NULL;
     553    size_t      cchCache = 0;
     554
     555    PRTDBGCFGSTR pCur;
     556    RTListForEach(pList, pCur, RTDBGCFGSTR, ListEntry)
     557    {
     558        size_t      cchDir = pCur->cch;
     559        const char *pszDir = pCur->sz;
     560        rtDbgCfgLog2(pThis, "Path list entry: '%s'\n", pszDir);
     561
     562        /* This is very simplistic, but we have a unreasonably large path
     563           buffer, so it'll work just fine and simplify things greatly below. */
     564        if (cchDir >= RTPATH_MAX - 8U)
     565        {
     566            if (RT_SUCCESS_NP(rcRet))
     567                rcRet = VERR_FILENAME_TOO_LONG;
     568            continue;
     569        }
     570
     571        /*
     572         * Process the path according to it's type.
     573         */
     574        if (!strncmp(pszDir, RT_STR_TUPLE("srv*")))
     575        {
     576            /*
     577             * Symbol server.
     578             */
     579            pszDir += sizeof("srv*") - 1;
     580            cchDir -= sizeof("srv*") - 1;
     581            bool        fSearchCache = false;
     582            const char *pszServer = (const char *)memchr(pszDir, '*', cchDir);
     583            if (!pszServer)
     584                pszServer = pszDir;
     585            else if (pszServer == pszDir)
     586                continue;
     587            {
     588                fSearchCache = true;
     589                pchCache = pszDir;
     590                cchCache = pszServer - pszDir;
     591                pszServer++;
     592            }
     593
     594            /* We don't have any default cache directory, so skip if the cache is missing. */
     595            if (cchCache == 0)
     596                continue;
     597
     598            /* Search the cache first (if we haven't already done so). */
     599            if (fSearchCache)
     600            {
     601                memcpy(pszPath, pchCache, cchCache);
     602                pszPath[cchCache] = '\0';
     603                rc2 = rtDbgCfgTryOpenCache(pThis, pszPath, pszCacheSubDir, pSplitFn, fFlags,
     604                                           pfnCallback, pvUser1, pvUser2);
     605                if (rc2 == VINF_CALLBACK_RETURN || rc2 == VERR_CALLBACK_RETURN)
     606                    return rc2;
     607            }
     608
     609            /* Try downloading the file. */
     610            memcpy(pszPath, pchCache, cchCache);
     611            pszPath[cchCache] = '\0';
     612            rc2 = rtDbgCfgTryDownloadAndOpen(pThis, pszServer, pszPath, pszCacheSubDir, pSplitFn, fFlags,
     613                                             pfnCallback, pvUser1, pvUser2);
     614            if (rc2 == VINF_CALLBACK_RETURN || rc2 == VERR_CALLBACK_RETURN)
     615                return rc2;
     616        }
     617        else if (!strncmp(pszDir, RT_STR_TUPLE("cache*")))
     618        {
     619            /*
     620             * Cache directory.
     621             */
     622            pszDir += sizeof("cache*") - 1;
     623            cchDir -= sizeof("cache*") - 1;
     624            if (!cchDir)
     625                continue;
     626            pchCache = pszDir;
     627            cchCache = cchDir;
     628
     629            memcpy(pszPath, pchCache, cchCache);
     630            pszPath[cchCache] = '\0';
     631            rc2 = rtDbgCfgTryOpenCache(pThis, pszPath, pszCacheSubDir, pSplitFn, fFlags,
     632                                       pfnCallback, pvUser1, pvUser2);
     633            if (rc2 == VINF_CALLBACK_RETURN || rc2 == VERR_CALLBACK_RETURN)
     634                return rc2;
     635        }
     636        else
     637        {
     638            /*
     639             * Normal directory. Check for our own 'rec*' and 'norec*' prefix
     640             * flags governing recursive searching.
     641             */
     642            uint32_t fFlagsDir = fFlags;
     643            if (!strncmp(pszDir, RT_STR_TUPLE("rec*")))
     644            {
     645                pszDir += sizeof("rec*") - 1;
     646                cchDir -= sizeof("rec*") - 1;
     647                fFlagsDir |= RTDBGCFG_O_RECURSIVE;
     648            }
     649            else if (!strncmp(pszDir, RT_STR_TUPLE("norec*")))
     650            {
     651                pszDir += sizeof("norec*") - 1;
     652                cchDir -= sizeof("norec*") - 1;
     653                fFlagsDir &= ~RTDBGCFG_O_RECURSIVE;
     654            }
     655
     656            /* Copy the path into the buffer and do the searching. */
     657            memcpy(pszPath, pszDir, cchDir);
     658            pszPath[cchDir] = '\0';
     659
     660            rc2 = rtDbgCfgTryOpenDir(pThis, pszPath, pSplitFn, fFlagsDir, pfnCallback, pvUser1, pvUser2);
     661            if (rc2 == VINF_CALLBACK_RETURN || rc2 == VERR_CALLBACK_RETURN)
     662            {
     663                if (   rc2 == VINF_CALLBACK_RETURN
     664                    && cchCache > 0)
     665                    rtDbgCfgCopyFileToCache(pThis, pszPath, pchCache, cchCache, pszCacheSubDir, pSplitFn);
     666                return rc2;
     667            }
     668        }
     669    }
     670
     671    return rcRet;
     672}
     673
     674
     675/**
     676 * Common worker routine for Image and debug info opening.
     677 *
     678 * This will not search using for suffixes.
     679 *
     680 * @returns IPRT status code.
     681 * @param   hDbgCfg         The debugging configuration handle.  NIL_RTDBGCFG is
     682 *                          accepted, but the result is that no paths will be
     683 *                          searched beyond the given and the current directory.
     684 * @param   pszFilename     The filename to search for.  This may or may not
     685 *                          include a full or partial path.
     686 * @param   pszCacheSubDir  The cache subdirectory to look in.
     687 * @param   fFlags          Flags and hints.
     688 * @param   pfnCallback     The open callback routine.
     689 * @param   pvUser1         User parameter 1.
     690 * @param   pvUser2         User parameter 2.
     691 */
     692static int rtDbgCfgOpenWithSubDir(RTDBGCFG hDbgCfg, const char *pszFilename, const char *pszCacheSubDir,
     693                                  uint32_t fFlags, PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
     694{
     695    int rcRet = VINF_SUCCESS;
     696    int rc2;
     697
     698    /*
     699     * Do a little validating first.
     700     */
     701    PRTDBGCFGINT pThis = hDbgCfg;
     702    if (pThis != NIL_RTDBGCFG)
     703        RTDBGCFG_VALID_RETURN_RC(pThis, VERR_INVALID_HANDLE);
     704    else
     705        pThis = NULL;
     706    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
     707    AssertPtrReturn(pszCacheSubDir, VERR_INVALID_POINTER);
     708    AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
     709
     710    /*
     711     * Do some guessing as to the way we should parse the filename and whether
     712     * it's case exact or not.
     713     */
     714    bool fDosPath = strchr(pszFilename, ':')  != NULL
     715                 || strchr(pszFilename, '\\') != NULL
     716                 || RT_OPSYS_USES_DOS_PATHS(fFlags & RTDBGCFG_O_OPSYS_MASK)
     717                 || (fFlags & RTDBGCFG_O_CASE_INSENSITIVE);
     718    if (fDosPath)
     719        fFlags |= RTDBGCFG_O_CASE_INSENSITIVE;
     720
     721    rtDbgCfgLog2(pThis, "Looking for '%s' w/ cache subdir '%s' and %#x flags\n", pszFilename, pszCacheSubDir, fFlags);
     722
     723    PRTPATHSPLIT pSplitFn;
     724    rc2 = RTPathSplitA(pszFilename, &pSplitFn, fDosPath ? RTPATH_STR_F_STYLE_DOS : RTPATH_STR_F_STYLE_UNIX);
     725    if (RT_FAILURE(rc2))
     726        return rc2;
     727
     728    /*
     729     * Try the stored file name first if it has a kind of absolute path.
     730     */
     731    char szPath[RTPATH_MAX];
     732    if (RTPATH_PROP_HAS_ROOT_SPEC(pSplitFn->fProps))
     733    {
     734        rc2 = RTPathSplitReassemble(pSplitFn, RTPATH_STR_F_STYLE_HOST, szPath, sizeof(szPath));
     735        if (RT_SUCCESS(rc2) && RTFileExists(szPath))
     736            rc2 = pfnCallback(pThis, pszFilename, pvUser1, pvUser2);
     737    }
     738    if (   rc2 != VINF_CALLBACK_RETURN
     739        && rc2 != VERR_CALLBACK_RETURN)
     740    {
     741        /*
     742         * Try the current directory (will take cover relative paths
     743         * skipped above).
     744         */
     745        rc2 = RTPathGetCurrent(szPath, sizeof(szPath));
     746        if (RT_FAILURE(rc2))
     747            strcpy(szPath, ".");
     748        rc2 = rtDbgCfgTryOpenDir(pThis, szPath, pSplitFn, fFlags, pfnCallback, pvUser1, pvUser2);
     749        if (RT_FAILURE(rc2) && RT_SUCCESS_NP(rcRet))
     750            rcRet = rc2;
     751
     752        if (   rc2 != VINF_CALLBACK_RETURN
     753            && rc2 != VERR_CALLBACK_RETURN
     754            && pThis)
     755        {
     756            rc2 = RTCritSectRwEnterShared(&pThis->CritSect);
     757            if (RT_SUCCESS(rc2))
     758            {
     759                /*
     760                 * Run the applicable lists.
     761                 */
     762                rc2 = rtDbgCfgTryOpenList(pThis, &pThis->PathList, pSplitFn, pszCacheSubDir, fFlags, szPath,
     763                                          pfnCallback, pvUser1, pvUser2);
     764                if (RT_FAILURE(rc2) && RT_SUCCESS_NP(rcRet))
     765                    rcRet = rc2;
     766
     767#ifdef RT_OS_WINDOWS
     768                if (   rc2 != VINF_CALLBACK_RETURN
     769                    && rc2 != VERR_CALLBACK_RETURN
     770                    && (fFlags & RTDBGCFG_O_EXECUTABLE_IMAGE)
     771                    && !(pThis->fFlags & RTDBGCFG_FLAGS_NO_SYSTEM_PATHS) )
     772                {
     773                    rc2 = rtDbgCfgTryOpenList(pThis, &pThis->NtExecutablePathList, pSplitFn, pszCacheSubDir, fFlags, szPath,
     774                                              pfnCallback, pvUser1, pvUser2);
     775                    if (RT_FAILURE(rc2) && RT_SUCCESS_NP(rcRet))
     776                        rcRet = rc2;
     777                }
     778
     779                if (   rc2 != VINF_CALLBACK_RETURN
     780                    && rc2 != VERR_CALLBACK_RETURN
     781                    && !(pThis->fFlags & RTDBGCFG_FLAGS_NO_SYSTEM_PATHS) )
     782                {
     783                    rc2 = rtDbgCfgTryOpenList(pThis, &pThis->NtSymbolPathList, pSplitFn, pszCacheSubDir, fFlags, szPath,
     784                                              pfnCallback, pvUser1, pvUser2);
     785                    if (RT_FAILURE(rc2) && RT_SUCCESS_NP(rcRet))
     786                        rcRet = rc2;
     787                }
     788#endif
     789                RTCritSectRwLeaveShared(&pThis->CritSect);
     790            }
     791            else if (RT_SUCCESS(rcRet))
     792                rcRet = rc2;
     793        }
     794    }
     795
     796    RTPathSplitFree(pSplitFn);
     797    if (   rc2 == VINF_CALLBACK_RETURN
     798        || rc2 == VERR_CALLBACK_RETURN)
     799        rcRet = rc2;
     800    else if (RT_SUCCESS(rcRet))
     801        rcRet = VERR_NOT_FOUND;
     802    return rcRet;
     803}
     804
    160805
    161806RTDECL(int) RTDbgCfgOpenPeImage(RTDBGCFG hDbgCfg, const char *pszFilename, uint32_t cbImage, uint32_t uTimestamp,
    162807                                PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
    163808{
    164     int rc = pfnCallback(hDbgCfg, pszFilename, pvUser1, pvUser2);
    165     if (rc == VINF_CALLBACK_RETURN || rc == VERR_CALLBACK_RETURN)
    166         return rc;
    167 
    168     return rc;
    169 }
     809    char szSubDir[32];
     810    RTStrPrintf(szSubDir, sizeof(szSubDir), "%08X%X", uTimestamp, cbImage);
     811    return rtDbgCfgOpenWithSubDir(hDbgCfg, pszFilename, szSubDir,
     812                                  RT_OPSYS_WINDOWS /* approx */ | RTDBGCFG_O_SYMSRV | RTDBGCFG_O_CASE_INSENSITIVE
     813                                  | RTDBGCFG_O_EXECUTABLE_IMAGE,
     814                                  pfnCallback, pvUser1, pvUser2);
     815}
     816
    170817
    171818RTDECL(int) RTDbgCfgOpenPdb70(RTDBGCFG hDbgCfg, const char *pszFilename, PCRTUUID pUuid, uint32_t uAge,
    172819                              PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
    173820{
    174     int rc = pfnCallback(hDbgCfg, pszFilename, pvUser1, pvUser2);
    175     if (rc == VINF_CALLBACK_RETURN || rc == VERR_CALLBACK_RETURN)
    176         return rc;
    177 
    178     return rc;
    179 }
     821    char szSubDir[64];
     822    if (!pUuid)
     823        szSubDir[0] = '\0';
     824    else
     825    {
     826        /* Stringify the UUID and remove the dashes. */
     827        int rc2 = RTUuidToStr(pUuid, szSubDir, sizeof(szSubDir));
     828        AssertRCReturn(rc2, rc2);
     829
     830        char *pszSrc = szSubDir;
     831        char *pszDst = szSubDir;
     832        char ch;
     833        while ((ch = *pszSrc++))
     834            if (ch != '-')
     835                *pszDst++ = ch;
     836            else if (RT_C_IS_LOWER(ch))
     837                *pszDst++ = RT_C_TO_UPPER(ch);
     838
     839        RTStrPrintf(pszDst, &szSubDir[sizeof(szSubDir)] - pszDst, "%X", uAge);
     840    }
     841
     842    return rtDbgCfgOpenWithSubDir(hDbgCfg, pszFilename, szSubDir,
     843                                  RT_OPSYS_WINDOWS /* approx */ | RTDBGCFG_O_SYMSRV | RTDBGCFG_O_CASE_INSENSITIVE
     844                                  | RTDBGCFG_O_EXT_DEBUG_FILE,
     845                                  pfnCallback, pvUser1, pvUser2);
     846}
     847
    180848
    181849RTDECL(int) RTDbgCfgOpenPdb20(RTDBGCFG hDbgCfg, const char *pszFilename, uint32_t cbImage, uint32_t uTimestamp, uint32_t uAge,
    182850                              PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
    183851{
    184     return VERR_NOT_IMPLEMENTED;
     852    /** @todo test this! */
     853    char szSubDir[32];
     854    RTStrPrintf(szSubDir, sizeof(szSubDir), "%08X%X", uTimestamp, uAge);
     855    return rtDbgCfgOpenWithSubDir(hDbgCfg, pszFilename, szSubDir,
     856                                  RT_OPSYS_WINDOWS /* approx */ | RTDBGCFG_O_SYMSRV | RTDBGCFG_O_CASE_INSENSITIVE
     857                                  | RTDBGCFG_O_EXT_DEBUG_FILE,
     858                                  pfnCallback, pvUser1, pvUser2);
    185859}
    186860
     
    189863                            PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
    190864{
    191     return VERR_NOT_IMPLEMENTED;
     865    char szSubDir[32];
     866    RTStrPrintf(szSubDir, sizeof(szSubDir), "%08X%X", uTimestamp, cbImage);
     867    return rtDbgCfgOpenWithSubDir(hDbgCfg, pszFilename, szSubDir,
     868                                  RT_OPSYS_WINDOWS /* approx */ | RTDBGCFG_O_SYMSRV | RTDBGCFG_O_CASE_INSENSITIVE
     869                                  | RTDBGCFG_O_EXT_DEBUG_FILE,
     870                                  pfnCallback, pvUser1, pvUser2);
    192871}
    193872
     
    196875                            PFNDBGCFGOPEN pfnCallback, void *pvUser1, void *pvUser2)
    197876{
    198     return VERR_NOT_IMPLEMENTED;
     877    char szSubDir[32];
     878    RTStrPrintf(szSubDir, sizeof(szSubDir), "%08x", uCrc32);
     879    return rtDbgCfgOpenWithSubDir(hDbgCfg, pszFilename, szSubDir,
     880                                  RT_OPSYS_UNKNOWN | RTDBGCFG_O_EXT_DEBUG_FILE,
     881                                  pfnCallback, pvUser1, pvUser2);
    199882}
    200883
     
    253936            return VERR_FILENAME_TOO_LONG;
    254937
    255         if (enmOp != RTDBGCFGOP_REMOVE)
     938        if (enmOp == RTDBGCFGOP_REMOVE)
    256939        {
    257940            /*
     
    280963            pNew->cch = (uint16_t)cchPath;
    281964            pNew->fFlags = 0;
    282             if (fPaths)
    283             {
    284                 if (!strncmp(pchPath, RT_STR_TUPLE("srv*")))
    285                     pNew->fFlags |= RTDBGCCFG_PATH_SRV;
    286                 else if (!strncmp(pchPath, RT_STR_TUPLE("cache*")))
    287                     pNew->fFlags |= RTDBGCCFG_PATH_CACHE;
    288             }
    289965            memcpy(pNew->sz, pchPath, cchPath);
    290966            pNew->sz[cchPath] = '\0';
     
    7381414                    rc = VINF_SUCCESS;
    7391415            }
     1416
     1417            /*
     1418             * Pick up system specific search paths.
     1419             */
     1420            if (RT_SUCCESS(rc))
     1421            {
     1422                struct
     1423                {
     1424                    PRTLISTANCHOR   pList;
     1425                    const char     *pszVar;
     1426                    char            chSep;
     1427                } aNativePaths[] =
     1428                {
     1429#ifdef RT_OS_WINDOWS
     1430                    { &pThis->NtExecutablePathList, "_NT_EXECUTABLE_PATH",  ';' },
     1431                    { &pThis->NtSymbolPathList,     "_NT_ALT_SYMBOL_PATH",  ';' },
     1432                    { &pThis->NtSymbolPathList,     "_NT_SYMBOL_PATH",      ';' },
     1433                    { &pThis->NtSourcePath,         "_NT_SOURCE_PATH",      ';' },
     1434#endif
     1435                    { NULL, NULL, 0 }
     1436                };
     1437                for (unsigned i = 0; i < RT_ELEMENTS(aNativePaths) - 1U; i++)
     1438                {
     1439                    Assert(aNativePaths[i].chSep == ';'); /* fix when needed */
     1440                    rc = RTEnvGetEx(RTENV_DEFAULT, aNativePaths[i].pszVar, pszEnvVal, cbEnvVal, NULL);
     1441                    if (RT_SUCCESS(rc))
     1442                    {
     1443                        rc = rtDbgCfgChangeStringList(pThis, RTDBGCFGOP_APPEND, pszEnvVal, true, aNativePaths[i].pList);
     1444                        if (RT_FAILURE(rc))
     1445                            break;
     1446                    }
     1447                    else if (rc != VERR_ENV_VAR_NOT_FOUND)
     1448                        break;
     1449                    else
     1450                        rc = VINF_SUCCESS;
     1451                }
     1452            }
    7401453            RTMemTmpFree(pszEnvVar);
    7411454        }
  • trunk/src/VBox/Runtime/common/dbg/dbgmodldr.cpp

    r39327 r46025  
    151151    {
    152152        RTLDRMOD hLdrMod;
    153         rc = RTLdrOpen(pMod->pszImgFile, 0 /*fFlags*/, RTLDRARCH_WHATEVER, &hLdrMod);
     153        rc = RTLdrOpen(pMod->pszImgFile, RTLDR_O_FOR_DEBUG, RTLDRARCH_WHATEVER, &hLdrMod);
    154154        if (RT_SUCCESS(rc))
    155155        {
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