VirtualBox

Ignore:
Timestamp:
Apr 8, 2013 1:38:35 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
84833
Message:

ntBldSymDb.cpp: back to the os version info detection code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/nt/ntBldSymDb.cpp

    r45383 r45405  
    8383} MYSTRUCT;
    8484
     85/** Architecture. */
     86typedef enum MYARCH
     87{
     88    MYARCH_X86,
     89    MYARCH_AMD64,
     90    MYARCH_DETECT
     91} MYARCH;
     92
    8593/** Set of structures for one kernel. */
    8694typedef struct MYSET
     
    92100    /** The OS version we've harvested structs for */
    93101    RTNTSDBOSVER    OsVerInfo;
     102    /** The architecture. */
     103    MYARCH          enmArch;
    94104    /** The structures and their member. */
    95105    MYSTRUCT        aStructs[1];
     
    268278    RTListForEach(&g_SetList, pSet, MYSET, ListEntry)
    269279    {
     280        const char *pszArch = pSet->enmArch == MYARCH_AMD64 ? "AMD64" : "X86";
    270281        RTStrmPrintf(pOut,
     282                     "#ifdef RT_ARCH_%s\n"
    271283                     "    {   /* Source: %s */\n"
    272284                     "        /*.OsVerInfo = */\n"
     
    279291                     "            /* .uBuildNo  = */ %u,\n"
    280292                     "        },\n",
     293                     pszArch,
    281294                     pSet->pszPdb,
    282295                     pSet->OsVerInfo.uMajorVer,
     
    306319        }
    307320        RTStrmPrintf(pOut,
    308                      "    },\n");
     321                     "    },\n"
     322                     "#endif\n"
     323                     );
    309324    }
    310325
     
    325340 * @param   pOsVerInfo      The OS version info.
    326341 */
    327 static RTEXITCODE saveStructures(PRTNTSDBOSVER pOsVerInfo, const char *pszPdb)
     342static RTEXITCODE saveStructures(PRTNTSDBOSVER pOsVerInfo, MYARCH enmArch, const char *pszPdb)
    328343{
    329344    /*
     
    346361     * Copy over the data.
    347362     */
     363    pSet->enmArch = enmArch;
    348364    memcpy(&pSet->OsVerInfo, pOsVerInfo, sizeof(pSet->OsVerInfo));
    349365    memcpy(&pSet->aStructs[0], g_aStructs, sizeof(g_aStructs));
     
    666682
    667683
    668 #if 0
    669 /** @name Path properties returned by RTPathParse and RTPathSplit.
    670  * @{ */
    671 /** Indicates that there is a filename.
    672  * If not set, a directory was specified using a trailing slash or a volume
    673  * was specified without any file/dir name following it. */
    674 #define RTPATH_PROP_FILENAME        UINT16_C(0x0001)
    675 /** The filename has a suffix (extension). */
    676 #define RTPATH_PROP_SUFFIX          UINT16_C(0x0002)
    677 /** Indicates that this is an UNC path (Windows and OS/2 only). */
    678 #define RTPATH_PROP_UNC             UINT16_C(0x0010)
    679 /** A root is specified. The path is relative if not set. */
    680 #define RTPATH_PROP_ROOT            UINT16_C(0x0020)
    681 /** A volume (drive) is specified. */
    682 #define RTPATH_PROP_VOLSPEC         UINT16_C(0x0040)
    683 /** The path is absolute. */
    684 #define RTPATH_PROP_ABSOLUTE        UINT16_C(0x0100)
    685 /** @} */
    686 
    687 
    688 /**
    689  * Parsed path.
    690  *
    691  * The first component is the root and volume specifier. If UNC, the first
    692  * component does not include the share/service name, that is found as the
    693  * second component if present.
    694  */
    695 typedef struct RTPATHPARSED
    696 {
    697     /** Number of path components. */
    698     uint16_t    cComponents;
    699     /** The offset of the filename suffix, offset of the NUL char if none. */
    700     uint16_t    offSuffix;
    701     /** Path property flags, RTPATH_PROP_XXX */
    702     uint16_t    fProps;
    703     /** The number of bytes used (on success) or needed (on buffer overflow). */
    704     uint16_t    cbUsed;
    705     /** Array of component descriptors (variable size). */
    706     struct
    707     {
    708         /** The offset of the component. */
    709         uint16_t    off;
    710         /** The  */
    711         uint16_t    cch;
    712     } aComponents[1];
    713 } RTPATHPARSED;
    714 /** Pointer to to a parsed path result. */
    715 typedef RTPATHPARSED *PRTPATHPARSED;
    716 /** Pointer to to a const parsed path result. */
    717 typedef RTPATHPARSED *PCRTPATHPARSED;
    718 
    719 
    720 int RTPathParse(const char *pszPath, PRTPATHPARSED pOutput, size_t cbOutput)
    721 {
    722     AssertReturn(cbOutput >= sizeof(*pOutput), VERR_INVALID_PARAMETER);
    723     AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    724     AssertPtrReturn(pOutput, VERR_INVALID_POINTER);
    725 
    726 }
    727 
    728 
    729 
    730 
    731 typedef struct RTPATHSPLIT
    732 {
    733     /** Number of path components. */
    734     uint32_t    cComponents;
    735     /** The first directory.  */
    736     uint8_t     iFirstDir;
    737     uint8_t     fReserved1; /**< Reserved */
    738     /** Path property flags, RTPATHSPLIT_PROP_XXX */
    739     uint16_t    fProps;
    740     /** Pointer to the dot in the filename suffix. If no suffix, this points to
    741      * the terminator character. */
    742     const char *pszSuffix;
    743     /** Array of pointers to components.
    744      * @remarks This is variable sized and is followed by the strings it points to.
    745      *          It's set to 8 instead of the usual 1 as that's the minimum size of
    746      *          the RTPathSplit buffer. */
    747     const char *apszComponents[8];
    748 } RTPATHSPLIT;
    749 /** Pointer to to a path split result. */
    750 typedef RTPATHSPLIT *PRTPATHSPLIT;
    751 /** Pointer to to a const path split result. */
    752 typedef RTPATHSPLIT *PCRTPATHSPLIT;
    753 
    754 
    755 int RTPathSplit(const char *pszPath, PRTPATHSPLIT pOutput, size_t cbOutput)
    756 {
    757     AssertReturn(cbOutput >= sizeof(*pOutput), VERR_BUFFER_UNDERFLOW);
    758     AssertPtr(pszPath);
    759     AsserPtr(pOutput);
    760 
    761     /*
    762      * Parse the path, we're using apszComponents to store offset + length of
    763      * each component while parsing to avoid duplicating code and effort.
    764      */
    765     struct TMPOFFSIZE
    766     {
    767         uint16_t    off;
    768         uint16_t    cch;
    769     }          *paComponents   = (struct TMPOFFSIZE *)&pOutput->apszComponents;
    770     uint32_t    cMaxComponents = (cbOutput - RT_OFFSETOF(RTPATHSPLIT, apszComponents)) / sizeof(paComponents[0]);
    771     uint32_t    iComponent     = 0;
    772     size_t      cbStrings      = 0;
    773     uint16_t    fFlags         = 0;
    774     size_t      off            = 0;
    775 
    776     paComponents[0].off = 0;
    777 
    778     /* The volume specifier bit first, it's special. */
    779     if (RTPATH_IS_SLASH(pszPath[0]))
    780     {
    781 #if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    782         if (   RTPATH_IS_SLASH(pszPath[1])
    783             && !RTPATH_IS_SLASH(pszPath[2])
    784             && pszPath[2])
    785         {
    786             fFlags |= RTPATHSPLIT_PROP_UNC;
    787 
    788             /* UNC server name */
    789             off = 2;
    790             while (!RTPATH_IS_SLASH(pszPath[off]) && pszPath[off])
    791                 off++;
    792             paComponents[0].cch = off;
    793             size_t      cbStrings      = 0;
    794 
    795 
    796             while (RTPATH_IS_SLASH(pszPath[off]))
    797                 off++;
    798 
    799             /* UNC share */
    800             while (!RTPATH_IS_SLASH(pszPath[off]) && pszPath[off])
    801                 off++;
    802         }
    803         else
    804 #endif
    805         {
    806             fFlags |= RTPATHSPLIT_PROP_ROOT;
    807             cbString = sizeof("/");
    808             iComponent = 1;
    809             off = 1;
    810         }
    811         while (RTPATH_IS_SLASH(pszPath[off]))
    812             off++;
    813     }
    814 #if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    815     else if (RT_C_IS_ALPHA(pszPath[0]) && pszPath[1] == ':')
    816     {
    817         off = 2;
    818         while (RTPATH_IS_SLASH(pszPath[off]))
    819             off++;
    820     }
    821 #endif
    822     Assert(!RTPATH_IS_SLASH(pszPath[off]));
    823 
    824 
    825 }
    826 
    827 #endif
    828 
    829684/**
    830685 * Use various hysterics to figure out the OS version details from the PDB path.
     
    839694 * @param   pszPdb              The path to the PDB.
    840695 * @param   pVerInfo            Where to return the version info.
    841  */
    842 static RTEXITCODE FigurePdbVersionInfo(const char *pszPdb, PRTNTSDBOSVER pVerInfo)
    843 {
    844     const char *pszFilename = RTPathFilename(pszPdb);
    845 
     696 * @param   penmArch            Where to return the architecture.
     697 */
     698static RTEXITCODE FigurePdbVersionInfo(const char *pszPdb, PRTNTSDBOSVER pVerInfo, MYARCH *penmArch)
     699{
     700    /*
     701     * Split the path.
     702     */
     703    union
     704    {
     705        RTPATHSPLIT Split;
     706        uint8_t     abPad[RTPATH_MAX + 1024];
     707    } u;
     708    int rc = RTPathSplit(pszPdb, &u.Split, sizeof(u), 0);
     709    if (RT_FAILURE(rc))
     710        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathSplit failed on '%s': %Rrc", pszPdb, rc);
     711    if (!(u.Split.fProps & RTPATH_PROP_FILENAME))
     712        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPATH_PROP_FILENAME not set for: '%s'", pszPdb);
     713    const char *pszFilename = u.Split.apszComps[u.Split.cComps - 1];
     714
     715    /*
     716     * SMP or UNI kernel?
     717     */
    846718    if (!RTStrICmp(pszFilename, "ntkrnlmp.pdb"))
    847719        pVerInfo->fSmp = true;
     
    851723        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Doesn't recognize the filename '%s'...", pszFilename);
    852724
    853     /* testing only */
     725    /*
     726     * Look for symbol pack names in the path. This is stuff like:
     727     *  - WindowsVista.6002.090410-1830.x86fre
     728     *  - WindowsVista.6002.090410-1830.amd64chk
     729     *  - Windows_Win7.7600.16385.090713-1255.X64CHK
     730     *  - Windows_Win7SP1.7601.17514.101119-1850.AMD64FRE
     731     *  - Windows_Win8.9200.16384.120725-1247.X86CHK
     732     */
     733    bool fFound = false;
     734    uint32_t i = u.Split.cComps - 1;
     735    while (i-- > 0)
     736    {
     737        static struct
     738        {
     739            const char *pszPrefix;
     740            size_t      cchPrefix;
     741            uint8_t     uMajorVer;
     742            uint8_t     uMinorVer;
     743            uint8_t     uCsdNo;
     744            uint8_t     uChecked;   /**< */
     745            MYARCH      enmArch;
     746            uint32_t    uBuildNo;   /**< UINT32_MAX means the number immediately after the prefix. */
     747        } const s_aSymPacks[] =
     748        {
     749            { RT_STR_TUPLE("Windows2003."),           5, 2, 0, UINT8_MAX, MYARCH_DETECT, UINT32_MAX },
     750            { RT_STR_TUPLE("WindowsVista.6000."),     6, 0, 0, UINT8_MAX, MYARCH_DETECT, 6000 },
     751            { RT_STR_TUPLE("Windows_Longhorn.6001."), 6, 0, 1, UINT8_MAX, MYARCH_DETECT, 6001 }, /* server 2008 */
     752            { RT_STR_TUPLE("WindowsVista.6002."),     6, 0, 2, UINT8_MAX, MYARCH_DETECT, 6002 },
     753        };
     754
     755        const char *pszComp = u.Split.apszComps[i];
     756        uint32_t j = RT_ELEMENTS(s_aSymPacks);
     757        while (j-- > 0)
     758            if (!RTStrNICmp(pszComp, s_aSymPacks[i].pszPrefix, s_aSymPacks[i].cchPrefix))
     759                break;
     760        if (j >= RT_ELEMENTS(s_aSymPacks))
     761            continue;
     762
     763        pVerInfo->uMajorVer = s_aSymPacks[j].uMajorVer;
     764        pVerInfo->uMinorVer = s_aSymPacks[j].uMinorVer;
     765        pVerInfo->uCsdNo    = s_aSymPacks[j].uCsdNo;
     766        pVerInfo->fChecked  = s_aSymPacks[j].uChecked == 1;
     767        pVerInfo->uBuildNo  = s_aSymPacks[j].uBuildNo;
     768        *penmArch           = s_aSymPacks[j].enmArch;
     769
     770        /* Parse build number if necessary. */
     771        if (s_aSymPacks[j].uBuildNo == UINT32_MAX)
     772        {
     773            char *pszNext;
     774            rc = RTStrToUInt32Ex(pszComp + s_aSymPacks[j].cchPrefix, &pszNext, 10, &pVerInfo->uBuildNo);
     775            if (RT_FAILURE(rc))
     776                return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to decode build number in '%s': %Rrc", pszComp, rc);
     777            if (*pszNext != '.' && *pszNext != '_' && *pszNext != '-')
     778                return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to decode build number in '%s': '%c'", pszComp, *pszNext);
     779        }
     780
     781        /* Look for build arch and checked/free. */
     782        if (   RTStrIStr(pszComp, ".x86.chk.")
     783            || RTStrIStr(pszComp, ".x86chk.")
     784            || RTStrIStr(pszComp, "_x86_chk_")
     785            || RTStrIStr(pszComp, "_x86chk_")
     786            || RTStrIStr(pszComp, "-x86-DEBUG")
     787            || (RTStrIStr(pszComp, "-x86-") && RTStrIStr(pszComp, "-DEBUG"))
     788           )
     789        {
     790            pVerInfo->fChecked = true;
     791            *penmArch = MYARCH_X86;
     792        }
     793        else if (   RTStrIStr(pszComp, ".amd64.chk.")
     794                 || RTStrIStr(pszComp, ".amd64chk.")
     795                 || RTStrIStr(pszComp, ".x64.chk.")
     796                 || RTStrIStr(pszComp, ".x64chk.")
     797                )
     798        {
     799            pVerInfo->fChecked = true;
     800            *penmArch = MYARCH_AMD64;
     801        }
     802        else if (   RTStrIStr(pszComp, ".amd64.fre.")
     803                 || RTStrIStr(pszComp, ".amd64fre.")
     804                 || RTStrIStr(pszComp, ".x64.fre.")
     805                 || RTStrIStr(pszComp, ".x64fre.")
     806                )
     807        {
     808            pVerInfo->fChecked = false;
     809            *penmArch = MYARCH_AMD64;
     810        }
     811        else if (RTStrIStr(pszComp, "DEBUG"))
     812        {
     813            pVerInfo->fChecked = true;
     814            *penmArch = MYARCH_X86;
     815        }
     816        else
     817        {
     818            pVerInfo->fChecked = false;
     819            *penmArch = MYARCH_X86;
     820        }
     821        return RTEXITCODE_SUCCESS;
     822    }
     823
     824
     825    /*
     826     * testing only
     827     */
    854828    if (strIEndsWith(pszPdb, "ntkrnlmp.pdb\\B2DA40502FA744C18B9022FD187ADB592\\ntkrnlmp.pdb"))
    855829    {
     
    888862     * Figure the windows version details for the given PDB.
    889863     */
     864    MYARCH       enmArch;
    890865    RTNTSDBOSVER OsVerInfo;
    891     RTEXITCODE rcExit = FigurePdbVersionInfo(pszPdb, &OsVerInfo);
     866    RTEXITCODE rcExit = FigurePdbVersionInfo(pszPdb, &OsVerInfo, &enmArch);
    892867    if (rcExit != RTEXITCODE_SUCCESS)
    893868        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to figure the OS version info for '%s'.\n'", pszPdb);
     
    922897             * Save the details for later when we produce the header.
    923898             */
    924             rcExit = saveStructures(&OsVerInfo, pszPdb);
     899            rcExit = saveStructures(&OsVerInfo, enmArch, pszPdb);
    925900        }
    926901    }
     
    10871062    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
    10881063                 RTGETOPTINIT_FLAGS_OPTS_FIRST);
    1089     while ((ch = RTGetOpt(&GetState, &ValueUnion)))
     1064    while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
    10901065    {
    10911066        switch (ch)
Note: See TracChangeset for help on using the changeset viewer.

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