VirtualBox

Ignore:
Timestamp:
May 26, 2013 10:40:09 PM (12 years ago)
Author:
vboxsync
Message:

dbgmodcodeview.cpp: Added code for parsing microsoft COFF debug information. Current strategy is to parse both CodeView and COFF when present since we don't know which have most details, and COFF are more likely to include line numbers.

File:
1 edited

Legend:

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

    r46271 r46274  
    11/* $Id: dbgmoddeferred.cpp 85864 2013-05-19 16:58:01Z bird $ */
    22/** @file
    3  * IPRT - Debug Module Reader For Microsoft CodeView.
     3 * IPRT - Debug Module Reader For Microsoft CodeView and COFF.
    44 *
    55 * Based on the following documentation (plus guess work and googling):
     
    481481    /** The code view magic (used as format indicator). */
    482482    uint32_t        u32CvMagic;
    483     /** The file type. */
    484     RTCVFILETYPE    enmType;
    485483    /** The offset of the CV debug info in the file. */
    486484    uint32_t        offBase;
     
    491489    /** @}  */
    492490
     491    /** @name COFF details.
     492     * @{ */
     493    /** Offset of the COFF header. */
     494    uint32_t        offCoffDbgInfo;
     495    /** The size of the COFF debug info. */
     496    uint32_t        cbCoffDbgInfo;
     497    /** The COFF debug info header. */
     498    IMAGE_COFF_SYMBOLS_HEADER CoffHdr;
     499    /** @} */
     500
     501    /** The file type. */
     502    RTCVFILETYPE    enmType;
    493503    /** The file handle (if external).  */
    494504    RTFILE          hFile;
     
    502512    bool            fHaveLoadedSegments;
    503513
    504     /** @name Parsing state.
     514    /** @name Codeview Parsing state.
    505515     * @{ */
    506516    /** Number of directory entries. */
     
    575585
    576586
     587/**
     588 * Reads CodeView information.
     589 *
     590 * @returns IPRT status.
     591 * @param   pThis               The CodeView reader instance.
     592 * @param   off                 The offset to start reading at, relative to the
     593 *                              CodeView base header.
     594 * @param   pvBuf               The buffer to read into.
     595 * @param   cb                  How many bytes to read.
     596 */
    577597static int rtDbgModCvReadAt(PRTDBGMODCV pThis, uint32_t off, void *pvBuf, size_t cb)
    578598{
     
    586606
    587607
     608/**
     609 * Reads CodeView information into an allocated buffer.
     610 *
     611 * @returns IPRT status.
     612 * @param   pThis               The CodeView reader instance.
     613 * @param   off                 The offset to start reading at, relative to the
     614 *                              CodeView base header.
     615 * @param   ppvBuf              Where to return the allocated buffer on success.
     616 * @param   cb                  How many bytes to read.
     617 */
    588618static int rtDbgModCvReadAtAlloc(PRTDBGMODCV pThis, uint32_t off, void **ppvBuf, size_t cb)
    589619{
     
    12321262
    12331263
    1234 static int rtDbgModCvLoadInfo(PRTDBGMODCV pThis)
     1264static int rtDbgModCvLoadCodeViewInfo(PRTDBGMODCV pThis)
    12351265{
    12361266    /*
     
    13221352    return rc;
    13231353}
     1354
     1355
     1356/*
     1357 *
     1358 * COFF Debug Info Parsing.
     1359 * COFF Debug Info Parsing.
     1360 * COFF Debug Info Parsing.
     1361 *
     1362 */
     1363
     1364static const char *rtDbgModCvGetCoffStorageClassName(uint8_t bStorageClass)
     1365{
     1366    switch (bStorageClass)
     1367    {
     1368        case IMAGE_SYM_CLASS_END_OF_FUNCTION:   return "END_OF_FUNCTION";
     1369        case IMAGE_SYM_CLASS_NULL:              return "NULL";
     1370        case IMAGE_SYM_CLASS_AUTOMATIC:         return "AUTOMATIC";
     1371        case IMAGE_SYM_CLASS_EXTERNAL:          return "EXTERNAL";
     1372        case IMAGE_SYM_CLASS_STATIC:            return "STATIC";
     1373        case IMAGE_SYM_CLASS_REGISTER:          return "REGISTER";
     1374        case IMAGE_SYM_CLASS_EXTERNAL_DEF:      return "EXTERNAL_DEF";
     1375        case IMAGE_SYM_CLASS_LABEL:             return "LABEL";
     1376        case IMAGE_SYM_CLASS_UNDEFINED_LABEL:   return "UNDEFINED_LABEL";
     1377        case IMAGE_SYM_CLASS_MEMBER_OF_STRUCT:  return "MEMBER_OF_STRUCT";
     1378        case IMAGE_SYM_CLASS_ARGUMENT:          return "ARGUMENT";
     1379        case IMAGE_SYM_CLASS_STRUCT_TAG:        return "STRUCT_TAG";
     1380        case IMAGE_SYM_CLASS_MEMBER_OF_UNION:   return "MEMBER_OF_UNION";
     1381        case IMAGE_SYM_CLASS_UNION_TAG:         return "UNION_TAG";
     1382        case IMAGE_SYM_CLASS_TYPE_DEFINITION:   return "TYPE_DEFINITION";
     1383        case IMAGE_SYM_CLASS_UNDEFINED_STATIC:  return "UNDEFINED_STATIC";
     1384        case IMAGE_SYM_CLASS_ENUM_TAG:          return "ENUM_TAG";
     1385        case IMAGE_SYM_CLASS_MEMBER_OF_ENUM:    return "MEMBER_OF_ENUM";
     1386        case IMAGE_SYM_CLASS_REGISTER_PARAM:    return "REGISTER_PARAM";
     1387        case IMAGE_SYM_CLASS_BIT_FIELD:         return "BIT_FIELD";
     1388        case IMAGE_SYM_CLASS_FAR_EXTERNAL:      return "FAR_EXTERNAL";
     1389        case IMAGE_SYM_CLASS_BLOCK:             return "BLOCK";
     1390        case IMAGE_SYM_CLASS_FUNCTION:          return "FUNCTION";
     1391        case IMAGE_SYM_CLASS_END_OF_STRUCT:     return "END_OF_STRUCT";
     1392        case IMAGE_SYM_CLASS_FILE:              return "FILE";
     1393        case IMAGE_SYM_CLASS_SECTION:           return "SECTION";
     1394        case IMAGE_SYM_CLASS_WEAK_EXTERNAL:     return "WEAK_EXTERNAL";
     1395        case IMAGE_SYM_CLASS_CLR_TOKEN:         return "CLR_TOKEN";
     1396    }
     1397
     1398    static char s_szName[32];
     1399    RTStrPrintf(s_szName, sizeof(s_szName), "Unknown%#04x", bStorageClass);
     1400    return s_szName;
     1401}
     1402
     1403
     1404/**
     1405 * Adds a chunk of COFF line numbers.
     1406 *
     1407 * @param   pThis               The COFF/CodeView reader instance.
     1408 * @param   pszFile             The source file name.
     1409 * @param   iSection            The section number.
     1410 * @param   paLines             Pointer to the first line number table entry.
     1411 * @param   cLines              The number of line number table entries to add.
     1412 */
     1413static void rtDbgModCvAddCoffLineNumbers(PRTDBGMODCV pThis, const char *pszFile, uint32_t iSection,
     1414                                         PCIMAGE_LINENUMBER paLines, uint32_t cLines)
     1415{
     1416    Log4(("Adding %u line numbers in section #%u  for %s\n", cLines, iSection, pszFile));
     1417    PCIMAGE_LINENUMBER pCur = paLines;
     1418    while (cLines-- > 0)
     1419    {
     1420        if (pCur->Linenumber)
     1421        {
     1422            int rc = RTDbgModLineAdd(pThis->hCnt, pszFile, pCur->Linenumber, RTDBGSEGIDX_RVA, pCur->Type.VirtualAddress, NULL);
     1423            Log4(("    %#010x: %u  [%Rrc]\n", pCur->Type.VirtualAddress, pCur->Linenumber, rc));
     1424        }
     1425        pCur++;
     1426    }
     1427}
     1428
     1429
     1430/**
     1431 * Adds a COFF symbol.
     1432 *
     1433 * @returns IPRT status (ignored)
     1434 * @param   pThis               The COFF/CodeView reader instance.
     1435 * @param   idxSeg              IPRT RVA or ABS segment index indicator.
     1436 * @param   uValue              The symbol value.
     1437 * @param   pszName             The symbol name.
     1438 */
     1439static int rtDbgModCvAddCoffSymbol(PRTDBGMODCV pThis, uint32_t idxSeg, uint32_t uValue, const char *pszName)
     1440{
     1441    int rc = RTDbgModSymbolAdd(pThis->hCnt, pszName, idxSeg, uValue, 0, 0 /*fFlags*/, NULL);
     1442    Log(("Symbol: %s:%08x %s [%Rrc]\n", idxSeg == RTDBGSEGIDX_RVA ? "rva" : "abs", uValue, pszName, rc));
     1443    if (rc == VERR_DBG_ADDRESS_CONFLICT || rc == VERR_DBG_DUPLICATE_SYMBOL)
     1444        rc = VINF_SUCCESS;
     1445    return rc;
     1446}
     1447
     1448
     1449/**
     1450 * Processes the COFF symbol table.
     1451 *
     1452 * @returns IPRT status code
     1453 * @param   pThis               The COFF/CodeView reader instance.
     1454 * @param   paSymbols           Pointer to the symbol table.
     1455 * @param   cSymbols            The number of entries in the symbol table.
     1456 * @param   paLines             Pointer to the line number table.
     1457 * @param   cLines              The number of entires in the line number table.
     1458 * @param   pszzStrTab          Pointer to the string table.
     1459 * @param   cbStrTab            Size of the string table.
     1460 */
     1461static int rtDbgModCvProcessCoffSymbolTable(PRTDBGMODCV pThis,
     1462                                            PCIMAGE_SYMBOL      paSymbols,  uint32_t cSymbols,
     1463                                            PCIMAGE_LINENUMBER  paLines,    uint32_t cLines,
     1464                                            const char         *pszzStrTab, uint32_t cbStrTab)
     1465{
     1466    Log3(("Processing COFF symbol table with %#x symbols\n", cSymbols));
     1467
     1468    /*
     1469     * Making some bold assumption that the line numbers for the section in
     1470     * the file are allocated sequentially, we do multiple passes until we've
     1471     * gathered them all.
     1472     */
     1473    int      rc        = VINF_SUCCESS;
     1474    uint32_t cSections = 1;
     1475    uint32_t iLineSect = 1;
     1476    uint32_t iLine     = 0;
     1477    do
     1478    {
     1479        /*
     1480         * Process the symbols.
     1481         */
     1482        char        szShort[9];
     1483        char        szFile[RTPATH_MAX];
     1484        uint32_t    iSymbol  = 0;
     1485        szFile[0] = '\0';
     1486        szShort[8] = '\0'; /* avoid having to terminate it all the time. */
     1487
     1488        while (iSymbol < cSymbols && RT_SUCCESS(rc))
     1489        {
     1490            /* Copy the symbol in and hope it works around the misalignment
     1491               issues everywhere. */
     1492            IMAGE_SYMBOL Sym;
     1493            memcpy(&Sym, &paSymbols[iSymbol], sizeof(Sym));
     1494            RTDBGMODCV_CHECK_NOMSG_RET_BF(Sym.NumberOfAuxSymbols < cSymbols);
     1495
     1496            /* Calc a zero terminated symbol name. */
     1497            const char  *pszName;
     1498            if (Sym.N.Name.Short)
     1499                pszName = (const char *)memcpy(szShort, &Sym.N, 8);
     1500            else
     1501            {
     1502                RTDBGMODCV_CHECK_NOMSG_RET_BF(Sym.N.Name.Long < cbStrTab);
     1503                pszName = pszzStrTab + Sym.N.Name.Long;
     1504            }
     1505
     1506            /* Only log stuff and count sections the in the first pass.*/
     1507            if (iLineSect == 1)
     1508            {
     1509                Log3(("%04x: s=%#06x v=%#010x t=%#06x a=%#04x c=%#04x (%s) name='%s'\n",
     1510                      iSymbol, Sym.SectionNumber, Sym.Value, Sym.Type, Sym.NumberOfAuxSymbols,
     1511                      Sym.StorageClass, rtDbgModCvGetCoffStorageClassName(Sym.StorageClass), pszName));
     1512                if ((int16_t)cSections <= Sym.SectionNumber && Sym.SectionNumber > 0)
     1513                    cSections = Sym.SectionNumber + 1;
     1514            }
     1515
     1516            /*
     1517             * Use storage class to pick what we need (which isn't much because,
     1518             * MS only provides a very restricted set of symbols).
     1519             */
     1520            IMAGE_AUX_SYMBOL Aux;
     1521            switch (Sym.StorageClass)
     1522            {
     1523                case IMAGE_SYM_CLASS_NULL:
     1524                    /* a NOP */
     1525                    break;
     1526
     1527                case IMAGE_SYM_CLASS_FILE:
     1528                {
     1529                    /* Change the current file name (for line numbers). Pretend
     1530                       ANSI and ISO-8859-1 are similar enough for out purposes... */
     1531                    RTDBGMODCV_CHECK_NOMSG_RET_BF(Sym.NumberOfAuxSymbols > 0);
     1532                    const char *pszFile = (const char *)&paSymbols[iSymbol + 1];
     1533                    char *pszDst = szFile;
     1534                    rc = RTLatin1ToUtf8Ex(pszFile, Sym.NumberOfAuxSymbols * sizeof(IMAGE_SYMBOL), &pszDst, sizeof(szFile), NULL);
     1535                    if (RT_FAILURE(rc))
     1536                        Log(("Error converting COFF filename: %Rrc\n", rc));
     1537                    else if (iLineSect == 1)
     1538                        Log3(("    filename='%s'\n", szFile));
     1539                    break;
     1540                }
     1541
     1542                case IMAGE_SYM_CLASS_STATIC:
     1543                    if (   Sym.NumberOfAuxSymbols == 1
     1544                        && (   iLineSect == 1
     1545                            || Sym.SectionNumber == iLineSect) )
     1546                    {
     1547                        memcpy(&Aux, &paSymbols[iSymbol + 1], sizeof(Aux));
     1548                        if (iLineSect == 1)
     1549                            Log3(("    section: cb=%#010x #relocs=%#06x #lines=%#06x csum=%#x num=%#x sel=%x rvd=%u\n",
     1550                                  Aux.Section.Length, Aux.Section.NumberOfRelocations,
     1551                                  Aux.Section.NumberOfLinenumbers,
     1552                                  Aux.Section.CheckSum,
     1553                                  RT_MAKE_U32(Aux.Section.Number, Aux.Section.HighNumber),
     1554                                  Aux.Section.Selection,
     1555                                  Aux.Section.bReserved));
     1556                        if (   Sym.SectionNumber == iLineSect
     1557                            && Aux.Section.NumberOfLinenumbers > 0)
     1558                        {
     1559                            uint32_t cLinesToAdd = RT_MIN(Aux.Section.NumberOfLinenumbers, cLines - iLine);
     1560                            if (iLine < cLines && szFile[0])
     1561                                rtDbgModCvAddCoffLineNumbers(pThis, szFile, iLineSect, &paLines[iLine], cLinesToAdd);
     1562                            iLine += cLinesToAdd;
     1563                        }
     1564                    }
     1565                    /* Not so sure about the quality here, but might be useful. */
     1566                    else if (   iLineSect == 1
     1567                             && Sym.NumberOfAuxSymbols == 0
     1568                             && Sym.SectionNumber != IMAGE_SYM_UNDEFINED
     1569                             && Sym.SectionNumber != IMAGE_SYM_ABSOLUTE
     1570                             && Sym.SectionNumber != IMAGE_SYM_DEBUG
     1571                             && Sym.Value > 0
     1572                             && *pszName)
     1573                        rtDbgModCvAddCoffSymbol(pThis, RTDBGSEGIDX_RVA, Sym.Value, pszName);
     1574                    break;
     1575
     1576                case IMAGE_SYM_CLASS_EXTERNAL:
     1577                    /* Add functions (first pass only). */
     1578                    if (   iLineSect == 1
     1579                        && (ISFCN(Sym.Type) || Sym.Type == 0)
     1580                        && Sym.NumberOfAuxSymbols == 0
     1581                        && *pszName )
     1582                    {
     1583                        if (Sym.SectionNumber == IMAGE_SYM_ABSOLUTE)
     1584                            rtDbgModCvAddCoffSymbol(pThis, RTDBGSEGIDX_ABS, Sym.Value, pszName);
     1585                        else if (   Sym.SectionNumber != IMAGE_SYM_UNDEFINED
     1586                                 && Sym.SectionNumber != IMAGE_SYM_DEBUG)
     1587                            rtDbgModCvAddCoffSymbol(pThis, RTDBGSEGIDX_RVA, Sym.Value, pszName);
     1588                    }
     1589                    break;
     1590
     1591                case IMAGE_SYM_CLASS_FUNCTION:
     1592                    /* Not sure this is really used. */
     1593                    break;
     1594
     1595                case IMAGE_SYM_CLASS_END_OF_FUNCTION:
     1596                case IMAGE_SYM_CLASS_AUTOMATIC:
     1597                case IMAGE_SYM_CLASS_REGISTER:
     1598                case IMAGE_SYM_CLASS_EXTERNAL_DEF:
     1599                case IMAGE_SYM_CLASS_LABEL:
     1600                case IMAGE_SYM_CLASS_UNDEFINED_LABEL:
     1601                case IMAGE_SYM_CLASS_MEMBER_OF_STRUCT:
     1602                case IMAGE_SYM_CLASS_ARGUMENT:
     1603                case IMAGE_SYM_CLASS_STRUCT_TAG:
     1604                case IMAGE_SYM_CLASS_MEMBER_OF_UNION:
     1605                case IMAGE_SYM_CLASS_UNION_TAG:
     1606                case IMAGE_SYM_CLASS_TYPE_DEFINITION:
     1607                case IMAGE_SYM_CLASS_UNDEFINED_STATIC:
     1608                case IMAGE_SYM_CLASS_ENUM_TAG:
     1609                case IMAGE_SYM_CLASS_MEMBER_OF_ENUM:
     1610                case IMAGE_SYM_CLASS_REGISTER_PARAM:
     1611                case IMAGE_SYM_CLASS_BIT_FIELD:
     1612                case IMAGE_SYM_CLASS_FAR_EXTERNAL:
     1613                case IMAGE_SYM_CLASS_BLOCK:
     1614                case IMAGE_SYM_CLASS_END_OF_STRUCT:
     1615                case IMAGE_SYM_CLASS_SECTION:
     1616                case IMAGE_SYM_CLASS_WEAK_EXTERNAL:
     1617                case IMAGE_SYM_CLASS_CLR_TOKEN:
     1618                    /* Not used by MS, I think. */
     1619                    break;
     1620
     1621                default:
     1622                    Log(("RTDbgCv: Unexpected COFF storage class %#x (%u)\n", Sym.StorageClass, Sym.StorageClass));
     1623                    break;
     1624            }
     1625
     1626            /* next symbol */
     1627            iSymbol += 1 + Sym.NumberOfAuxSymbols;
     1628        }
     1629
     1630        /* Next section with line numbers. */
     1631        iLineSect++;
     1632    } while (iLine < cLines && iLineSect < cSections && RT_SUCCESS(rc));
     1633
     1634    return rc;
     1635}
     1636
     1637
     1638static int rtDbgModCvLoadCoffInfo(PRTDBGMODCV pThis)
     1639{
     1640    /*
     1641     * Read the whole section into memory.
     1642     * Note! Cannot use rtDbgModCvReadAt or rtDbgModCvReadAtAlloc here.
     1643     */
     1644    int rc;
     1645    uint8_t *pbDbgSect = (uint8_t *)RTMemAlloc(pThis->cbCoffDbgInfo);
     1646    if (pbDbgSect)
     1647    {
     1648        if (pThis->hFile == NIL_RTFILE)
     1649            rc = pThis->pMod->pImgVt->pfnReadAt(pThis->pMod, UINT32_MAX, pThis->offCoffDbgInfo, pbDbgSect, pThis->cbCoffDbgInfo);
     1650        else
     1651            rc = RTFileReadAt(pThis->hFile, pThis->offCoffDbgInfo, pbDbgSect, pThis->cbCoffDbgInfo, NULL);
     1652        if (RT_SUCCESS(rc))
     1653        {
     1654            /* The string table follows after the symbol table. */
     1655            const char *pszzStrTab = (const char *)(  pbDbgSect
     1656                                                    + pThis->CoffHdr.LvaToFirstSymbol
     1657                                                    + pThis->CoffHdr.NumberOfSymbols * sizeof(IMAGE_SYMBOL));
     1658            uint32_t    cbStrTab = (uint32_t)((uintptr_t)(pbDbgSect + pThis->cbCoffDbgInfo) - (uintptr_t)pszzStrTab);
     1659            /** @todo The symbol table starts with a size. Read it and checking. Also verify
     1660             *        that the symtab ends with a terminator character. */
     1661
     1662            rc = rtDbgModCvProcessCoffSymbolTable(pThis,
     1663                                                  (PCIMAGE_SYMBOL)(pbDbgSect + pThis->CoffHdr.LvaToFirstSymbol),
     1664                                                  pThis->CoffHdr.NumberOfSymbols,
     1665                                                  (PCIMAGE_LINENUMBER)(pbDbgSect + pThis->CoffHdr.LvaToFirstLinenumber),
     1666                                                  pThis->CoffHdr.NumberOfLinenumbers,
     1667                                                  pszzStrTab, cbStrTab);
     1668        }
     1669        RTMemFree(pbDbgSect);
     1670    }
     1671    else
     1672        rc = VERR_NO_MEMORY;
     1673    return rc;
     1674}
     1675
     1676
    13241677
    13251678
     
    16231976
    16241977/**
    1625  * Common part of the probing.
     1978 * Instantiates the CV/COFF reader.
     1979 *
     1980 * @returns IPRT status code
     1981 * @param   pDbgMod             The debug module instance.
     1982 * @param   enmFileType         The type of input file.
     1983 * @param   hFile               The file handle, NIL_RTFILE of image.
     1984 * @param   ppThis              Where to return the reader instance.
     1985 */
     1986static int rtDbgModCvCreateInstance(PRTDBGMODINT pDbgMod, RTCVFILETYPE enmFileType, RTFILE hFile, PRTDBGMODCV *ppThis)
     1987{
     1988    /*
     1989     * Do we already have an instance?  Happens if we find multiple debug
     1990     * formats we support.
     1991     */
     1992    PRTDBGMODCV pThis = (PRTDBGMODCV)pDbgMod->pvDbgPriv;
     1993    if (pThis)
     1994    {
     1995        Assert(pThis->enmType == enmFileType);
     1996        Assert(pThis->hFile == hFile);
     1997        Assert(pThis->pMod == pDbgMod);
     1998        *ppThis = pThis;
     1999        return VINF_SUCCESS;
     2000    }
     2001
     2002    /*
     2003     * Create a new instance.
     2004     */
     2005    pThis = (PRTDBGMODCV)RTMemAllocZ(sizeof(RTDBGMODCV));
     2006    if (!pThis)
     2007        return VERR_NO_MEMORY;
     2008    int rc = RTDbgModCreate(&pThis->hCnt, pDbgMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
     2009    if (RT_SUCCESS(rc))
     2010    {
     2011        pDbgMod->pvDbgPriv = pThis;
     2012        pThis->enmType    = enmFileType;
     2013        pThis->hFile      = hFile;
     2014        pThis->pMod       = pDbgMod;
     2015        *ppThis = pThis;
     2016        return VINF_SUCCESS;
     2017    }
     2018    RTMemFree(pThis);
     2019    return rc;
     2020}
     2021
     2022
     2023/**
     2024 * Common part of the COFF probing.
    16262025 *
    16272026 * @returns status code.
     
    16322031 * @param   cb                  The number of bytes of debug info.
    16332032 * @param   enmArch             The desired image architecture.
     2033 * @param   pszFilename         The path to the file (for logging).
     2034 */
     2035static int rtDbgModCvProbeCoff(PRTDBGMODINT pDbgMod, RTCVFILETYPE enmFileType, RTFILE hFile,
     2036                               uint32_t off, uint32_t cb, const char *pszFilename)
     2037{
     2038    /*
     2039     * Check that there is sufficient data for a header, then read it.
     2040     */
     2041    if (cb < sizeof(IMAGE_COFF_SYMBOLS_HEADER))
     2042    {
     2043        Log(("RTDbgModCv: Not enough room for COFF header.\n"));
     2044        return VERR_BAD_EXE_FORMAT;
     2045    }
     2046    if (cb >= UINT32_C(128) * _1M)
     2047    {
     2048        Log(("RTDbgModCv: COFF debug information is to large (%'u bytes), max is 128MB\n", cb));
     2049        return VERR_BAD_EXE_FORMAT;
     2050    }
     2051
     2052    int rc;
     2053    IMAGE_COFF_SYMBOLS_HEADER Hdr;
     2054    if (hFile == NIL_RTFILE)
     2055        rc = pDbgMod->pImgVt->pfnReadAt(pDbgMod, UINT32_MAX, off, &Hdr, sizeof(Hdr));
     2056    else
     2057        rc = RTFileReadAt(hFile, off, &Hdr, sizeof(Hdr), NULL);
     2058    if (RT_FAILURE(rc))
     2059    {
     2060        Log(("RTDbgModCv: Error reading COFF header: %Rrc\n", rc));
     2061        return rc;
     2062    }
     2063
     2064    Log2(("RTDbgModCv: Found COFF debug info header at %#x (LB %#x) in %s\n", off, cb, pszFilename));
     2065    Log2(("    NumberOfSymbols      = %#010x\n", Hdr.NumberOfSymbols));
     2066    Log2(("    LvaToFirstSymbol     = %#010x\n", Hdr.LvaToFirstSymbol));
     2067    Log2(("    NumberOfLinenumbers  = %#010x\n", Hdr.NumberOfLinenumbers));
     2068    Log2(("    LvaToFirstLinenumber = %#010x\n", Hdr.LvaToFirstLinenumber));
     2069    Log2(("    RvaToFirstByteOfCode = %#010x\n", Hdr.RvaToFirstByteOfCode));
     2070    Log2(("    RvaToLastByteOfCode  = %#010x\n", Hdr.RvaToLastByteOfCode));
     2071    Log2(("    RvaToFirstByteOfData = %#010x\n", Hdr.RvaToFirstByteOfData));
     2072    Log2(("    RvaToLastByteOfData  = %#010x\n", Hdr.RvaToLastByteOfData));
     2073
     2074    /*
     2075     * Validate the COFF header.
     2076     */
     2077    if (   (uint64_t)Hdr.LvaToFirstSymbol + (uint64_t)Hdr.NumberOfSymbols * sizeof(IMAGE_SYMBOL) > cb
     2078        || (Hdr.LvaToFirstSymbol < sizeof(Hdr) && Hdr.NumberOfSymbols > 0))
     2079    {
     2080        Log(("RTDbgModCv: Bad COFF symbol count or/and offset: LvaToFirstSymbol=%#x, NumberOfSymbols=%#x cbCoff=%#x\n",
     2081             Hdr.LvaToFirstSymbol, Hdr.NumberOfSymbols, cb));
     2082        return VERR_BAD_EXE_FORMAT;
     2083    }
     2084    if (   (uint64_t)Hdr.LvaToFirstLinenumber + (uint64_t)Hdr.NumberOfLinenumbers * sizeof(IMAGE_LINENUMBER) > cb
     2085        || (Hdr.LvaToFirstLinenumber < sizeof(Hdr) && Hdr.NumberOfLinenumbers > 0))
     2086    {
     2087        Log(("RTDbgModCv: Bad COFF symbol count or/and offset: LvaToFirstSymbol=%#x, NumberOfSymbols=%#x cbCoff=%#x\n",
     2088             Hdr.LvaToFirstSymbol, Hdr.NumberOfSymbols, cb));
     2089        return VERR_BAD_EXE_FORMAT;
     2090    }
     2091    if (Hdr.NumberOfSymbols < 2)
     2092    {
     2093        Log(("RTDbgModCv: The COFF symbol table is too short to be of any worth... (%u syms)\n", Hdr.NumberOfSymbols));
     2094        return VERR_NO_DATA;
     2095    }
     2096
     2097    /*
     2098     * What we care about looks fine, use it.
     2099     */
     2100    PRTDBGMODCV pThis;
     2101    rc = rtDbgModCvCreateInstance(pDbgMod, enmFileType, hFile, &pThis);
     2102    if (RT_SUCCESS(rc))
     2103    {
     2104        pThis->offCoffDbgInfo = off;
     2105        pThis->cbCoffDbgInfo  = cb;
     2106        pThis->CoffHdr        = Hdr;
     2107    }
     2108
     2109    return rc;
     2110}
     2111
     2112
     2113/**
     2114 * Common part of the CodeView probing.
     2115 *
     2116 * @returns status code.
     2117 * @param   pDbgMod             The debug module instance.  On success pvDbgPriv
     2118 *                              will point to a valid RTDBGMODCV.
     2119 * @param   pCvHdr              The CodeView base header.
     2120 * @param   enmFileType         The kind of file this is we're probing.
     2121 * @param   hFile               The file with debug info in it.
     2122 * @param   off                 The offset where to expect CV debug info.
     2123 * @param   cb                  The number of bytes of debug info.
    16342124 * @param   pszFilename         The path to the file (for logging).
    16352125 */
     
    16512141        /* We're assuming it's a base header, so the offset must be within
    16522142           the area defined by the debug info we got from the loader. */
    1653         if (pCvHdr->off < cb)
     2143        if (pCvHdr->off < cb && pCvHdr->off >= sizeof(*pCvHdr))
    16542144        {
    16552145            Log(("RTDbgModCv: Found %c%c%c%c at %#RTfoff - size %#x, directory at %#x. file type %d\n",
     
    16582148
    16592149            /*
    1660              * Create a module instance.
     2150             * Create a module instance, if not already done.
    16612151             */
    1662             PRTDBGMODCV pThis = (PRTDBGMODCV)RTMemAllocZ(sizeof(RTDBGMODCV));
    1663             if (pThis)
     2152            PRTDBGMODCV pThis;
     2153            rc = rtDbgModCvCreateInstance(pDbgMod, enmFileType, hFile, &pThis);
     2154            if (RT_SUCCESS(rc))
    16642155            {
    1665                 rc = RTDbgModCreate(&pThis->hCnt, pDbgMod->pszName, 0 /*cbSeg*/, 0 /*fFlags*/);
    1666                 if (RT_SUCCESS(rc))
    1667                 {
    1668                     pDbgMod->pvDbgPriv = pThis;
    1669                     pThis->u32CvMagic = pCvHdr->u32Magic;
    1670                     pThis->enmType    = enmFileType;
    1671                     pThis->offBase    = off;
    1672                     pThis->cbDbgInfo  = cb;
    1673                     pThis->offDir     = pCvHdr->off;
    1674                     pThis->hFile      = hFile;
    1675                     pThis->pMod       = pDbgMod;
    1676                     return VINF_CALLBACK_RETURN;
    1677                 }
    1678 
    1679                 RTMemFree(pThis);
     2156                pThis->u32CvMagic = pCvHdr->u32Magic;
     2157                pThis->offBase    = off;
     2158                pThis->cbDbgInfo  = cb;
     2159                pThis->offDir     = pCvHdr->off;
     2160                return VINF_SUCCESS;
    16802161            }
    1681             else
    1682                 rc = VERR_NO_MEMORY;
    16832162        }
    16842163    }
     
    17002179
    17012180    /* We only handle the codeview sections. */
    1702     if (pDbgInfo->enmType != RTLDRDBGINFOTYPE_CODEVIEW)
    1703         return VINF_SUCCESS;
    1704 
    1705     /* Read the specified header and check if we like it. */
    1706     RTCVHDR CvHdr;
    1707     int rc = pDbgMod->pImgVt->pfnReadAt(pDbgMod, pDbgInfo->iDbgInfo, pDbgInfo->offFile, &CvHdr, sizeof(CvHdr));
    1708     if (RT_SUCCESS(rc))
    1709         rc = rtDbgModCvProbeCommon(pDbgMod, &CvHdr, RTCVFILETYPE_IMAGE, NIL_RTFILE, pDbgInfo->offFile, pDbgInfo->cb,
    1710                                    pDbgMod->pImgVt->pfnGetArch(pDbgMod), pDbgMod->pszImgFile);
     2181    if (pDbgInfo->enmType == RTLDRDBGINFOTYPE_CODEVIEW)
     2182    {
     2183        /* Read the specified header and check if we like it. */
     2184        RTCVHDR CvHdr;
     2185        int rc = pDbgMod->pImgVt->pfnReadAt(pDbgMod, pDbgInfo->iDbgInfo, pDbgInfo->offFile, &CvHdr, sizeof(CvHdr));
     2186        if (RT_SUCCESS(rc))
     2187            rc = rtDbgModCvProbeCommon(pDbgMod, &CvHdr, RTCVFILETYPE_IMAGE, NIL_RTFILE, pDbgInfo->offFile, pDbgInfo->cb,
     2188                                       pDbgMod->pImgVt->pfnGetArch(pDbgMod), pDbgMod->pszImgFile);
     2189    }
     2190    else if (pDbgInfo->enmType == RTLDRDBGINFOTYPE_COFF)
     2191    {
     2192        /* Join paths with the DBG code. */
     2193        rtDbgModCvProbeCoff(pDbgMod, RTCVFILETYPE_IMAGE, NIL_RTFILE, pDbgInfo->offFile, pDbgInfo->cb, pDbgMod->pszImgFile);
     2194    }
     2195
    17112196    return VINF_SUCCESS;
    17122197}
     
    18152300                break;
    18162301            if (DbgDir.Type == IMAGE_DEBUG_TYPE_CODEVIEW)
    1817             {
    18182302                rc = rtDbgModCvProbeFile2(pDbgMod, RTCVFILETYPE_DBG, hFile,
    18192303                                          DbgDir.PointerToRawData, DbgDir.SizeOfData,
    18202304                                          enmArch, pszFilename);
    1821                 if (RT_SUCCESS(rc))
    1822                 {
    1823                     /*
    1824                      * Add section headers and such if necessary.
    1825                      */
    1826                     PRTDBGMODCV pThis = (PRTDBGMODCV)pDbgMod->pvDbgPriv;
    1827                     pThis->cbImage = DbgHdr.SizeOfImage;
    1828                     if (!pDbgMod->pImgVt)
    1829                     {
    1830                         rc = rtDbgModCvAddSegmentsFromDbg(pThis, &DbgHdr, pszFilename);
    1831                         if (RT_FAILURE(rc))
    1832                             rtDbgModCv_Close(pDbgMod);
    1833                     }
    1834                     return rc;
    1835                 }
     2305            else if (DbgDir.Type == IMAGE_DEBUG_TYPE_COFF)
     2306                rc = rtDbgModCvProbeCoff(pDbgMod, RTCVFILETYPE_DBG, hFile,
     2307                                         DbgDir.PointerToRawData, DbgDir.SizeOfData, pszFilename);
     2308        }
     2309
     2310        /*
     2311         * If we get down here with an instance, it prooves that we've found
     2312         * something, regardless of any errors.  Add the sections and such.
     2313         */
     2314        PRTDBGMODCV pThis = (PRTDBGMODCV)pDbgMod->pvDbgPriv;
     2315        if (pThis)
     2316        {
     2317            PRTDBGMODCV pThis = (PRTDBGMODCV)pDbgMod->pvDbgPriv;
     2318            pThis->cbImage = DbgHdr.SizeOfImage;
     2319            if (pDbgMod->pImgVt)
     2320                rc = VINF_SUCCESS;
     2321            else
     2322            {
     2323                rc = rtDbgModCvAddSegmentsFromDbg(pThis, &DbgHdr, pszFilename);
     2324                if (RT_FAILURE(rc))
     2325                    rtDbgModCv_Close(pDbgMod);
    18362326            }
     2327            return rc;
    18372328        }
    18382329
     
    18902381    if (!pThis)
    18912382        return RT_SUCCESS_NP(rc) ? VERR_DBG_NO_MATCHING_INTERPRETER : rc;
     2383    Assert(pThis->offBase || pThis->offCoffDbgInfo);
    18922384
    18932385    /*
     
    18992391        pThis->fHaveLoadedSegments = true;
    19002392    }
    1901     if (RT_SUCCESS(rc))
    1902         rc = rtDbgModCvLoadInfo(pThis);
     2393    if (RT_SUCCESS(rc) && pThis->offBase)
     2394        rc = rtDbgModCvLoadCodeViewInfo(pThis);
     2395    if (RT_SUCCESS(rc) && pThis->offCoffDbgInfo)
     2396        rc = rtDbgModCvLoadCoffInfo(pThis);
    19032397    if (RT_SUCCESS(rc))
    19042398    {
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