VirtualBox

Ignore:
Timestamp:
Aug 31, 2011 2:38:20 PM (13 years ago)
Author:
vboxsync
Message:

iprt/dwarf: Attacking .debug_info...

File:
1 edited

Legend:

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

    r38581 r38584  
    9898} krtDbgModDwarfSect;
    9999
     100/**
     101 * Abbreviation cache entry.
     102 */
     103typedef struct RTDBGMODDWARFABBREV
     104{
     105    /** Whether this entry is filled in or not. */
     106    bool                fFilled;
     107    /** Whether there are children or not. */
     108    bool                fChildren;
     109    /** The tag.  */
     110    uint16_t            uTag;
     111    /** Offset into the abbrev section of the specification pairs. */
     112    uint32_t            offSpec;
     113} RTDBGMODDWARFABBREV;
     114/** Pointer to an abbreviation cache entry. */
     115typedef RTDBGMODDWARFABBREV *PRTDBGMODDWARFABBREV;
     116/** Pointer to a const abbreviation cache entry. */
     117typedef RTDBGMODDWARFABBREV const *PCRTDBGMODDWARFABBREV;
     118
    100119
    101120/**
     
    105124{
    106125    /** The debug container containing doing the real work. */
    107     RTDBGMOD            hCnt;
     126    RTDBGMOD                hCnt;
    108127    /** Pointer to back to the debug info module (no reference ofc). */
    109     PRTDBGMODINT        pMod;
     128    PRTDBGMODINT            pMod;
    110129
    111130    /** DWARF debug info sections. */
     
    113132    {
    114133        /** The file offset of the part. */
    115         RTFOFF          offFile;
     134        RTFOFF              offFile;
    116135        /** The size of the part. */
    117         size_t          cb;
     136        size_t              cb;
    118137        /** The memory mapping of the part. */
    119         void const     *pv;
     138        void const         *pv;
    120139        /** Set if present. */
    121         bool            fPresent;
     140        bool                fPresent;
    122141    } aSections[krtDbgModDwarfSect_End];
     142
     143    /** The offset into the abbreviation section of the current cache. */
     144    uint32_t                offCachedAbbrev;
     145    /** The number of cached abbreviations we've allocated space for. */
     146    uint32_t                cCachedAbbrevsAlloced;
     147    /** Used for range checking cache lookups. */
     148    uint32_t                cCachedAbbrevs;
     149    /** Array of cached abbreviations, indexed by code. */
     150    PRTDBGMODDWARFABBREV    paCachedAbbrevs;
     151    /** Used by rtDwarfAbbrev_Lookup when the result is uncachable. */
     152    RTDBGMODDWARFABBREV     LookupAbbrev;
    123153} RTDBGMODDWARF;
    124154/** Pointer to instance data of the DWARF reader. */
     
    151181     * Used for repositioning the cursor relative to the start of a section. */
    152182    uint8_t const          *pbStart;
     183    /** The section. */
     184    krtDbgModDwarfSect      enmSect;
    153185} RTDWARFCURSOR;
    154186/** Pointer to a DWARF section reader. */
     
    799831
    800832/**
     833 * Calculates the section offset corresponding to the current cursor position.
     834 *
     835 * @returns 32-bit section offset. If out of range, RTDWARFCURSOR::rc will be
     836 *          set and UINT32_MAX returned.
     837 * @param   pCursor             The cursor.
     838 */
     839static uint32_t rtDwarfCursor_CalcSectOffsetU32(PRTDWARFCURSOR pCursor)
     840{
     841    size_t off = (uint8_t const *)pCursor->pDwarfMod->aSections[pCursor->enmSect].pv - pCursor->pb;
     842    uint32_t offRet = (uint32_t)off;
     843    if (offRet != off)
     844    {
     845        pCursor->rc = VERR_OUT_OF_RANGE;
     846        offRet = UINT32_MAX;
     847    }
     848    return offRet;
     849}
     850
     851
     852/**
    801853 * Calculates an absolute cursor position from one relative to the current
    802854 * cursor position.
     
    903955        return rc;
    904956
     957    pCursor->enmSect          = enmSect;
    905958    pCursor->pbStart          = (uint8_t const *)pThis->aSections[enmSect].pv;
    906959    pCursor->pb               = pCursor->pbStart;
     
    916969
    917970    return VINF_SUCCESS;
     971}
     972
     973
     974/**
     975 * Initialize a section reader cursor with an offset.
     976 *
     977 * @returns IPRT status code.
     978 * @param   pCursor             The cursor.
     979 * @param   pThis               The dwarf module.
     980 * @param   enmSect             The name of the section to read.
     981 * @param   offSect             The offset into the section.
     982 */
     983static int rtDwarfCursor_InitWithOffset(PRTDWARFCURSOR pCursor, PRTDBGMODDWARF pThis,
     984                                        krtDbgModDwarfSect enmSect, uint32_t offSect)
     985{
     986    if (offSect > pThis->aSections[enmSect].cb)
     987        return VERR_DWARF_BAD_POS;
     988
     989    int rc = rtDwarfCursor_Init(pCursor, pThis, enmSect);
     990    if (RT_SUCCESS(rc))
     991    {
     992        pCursor->pbStart    += offSect;
     993        pCursor->pb         += offSect;
     994        pCursor->cbLeft     -= offSect;
     995        pCursor->cbUnitLeft -= offSect;
     996    }
     997
     998    return rc;
    918999}
    9191000
     
    14301511
    14311512
     1513/*
     1514 *
     1515 * DWARF Abbreviations.
     1516 * DWARF Abbreviations.
     1517 * DWARF Abbreviations.
     1518 *
     1519 */
     1520
     1521/**
     1522 * Deals with a cache miss in rtDwarfAbbrev_Lookup.
     1523 *
     1524 * @returns Pointer to abbreviation cache entry (read only).  May be rendered
     1525 *          invalid by subsequent calls to this function.
     1526 * @param   pThis               The DWARF instance.
     1527 * @param   uCode               The abbreviation code to lookup.
     1528 */
     1529static PCRTDBGMODDWARFABBREV rtDwarfAbbrev_LookupMiss(PRTDBGMODDWARF pThis, uint32_t uCode)
     1530{
     1531    /*
     1532     * There is no entry with code zero.
     1533     */
     1534    if (!uCode)
     1535        return NULL;
     1536
     1537    /*
     1538     * Resize the cache array if the code is considered cachable.
     1539     */
     1540    bool fFillCache = true;
     1541    if (pThis->cCachedAbbrevsAlloced < uCode)
     1542    {
     1543        if (uCode > _64K)
     1544            fFillCache = false;
     1545        else
     1546        {
     1547            uint32_t cNew = RT_ALIGN(uCode, 64);
     1548            void *pv = RTMemRealloc(pThis->paCachedAbbrevs, sizeof(pThis->paCachedAbbrevs[0]) * cNew);
     1549            if (!pv)
     1550                fFillCache = false;
     1551            else
     1552            {
     1553                pThis->cCachedAbbrevsAlloced = cNew;
     1554                pThis->paCachedAbbrevs       = (PRTDBGMODDWARFABBREV)pv;
     1555            }
     1556        }
     1557    }
     1558
     1559    /*
     1560     * Walk the abbreviations till we find the desired code.
     1561     */
     1562    RTDWARFCURSOR Cursor;
     1563    int rc = rtDwarfCursor_InitWithOffset(&Cursor, pThis, krtDbgModDwarfSect_abbrev, pThis->offCachedAbbrev);
     1564    if (RT_FAILURE(rc))
     1565        return NULL;
     1566
     1567    PRTDBGMODDWARFABBREV pRet = NULL;
     1568    if (fFillCache)
     1569    {
     1570        /*
     1571         * Search for the entry and fill the cache while doing so.
     1572         */
     1573        for (;;)
     1574        {
     1575            /* Read the 'header'. */
     1576            uint32_t const uCurCode  = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1577            uint32_t const uCurTag   = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1578            uint8_t  const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
     1579            if (RT_FAILURE(Cursor.rc))
     1580                break;
     1581            if (   uCurTag > 0xffff
     1582                || uChildren > 1)
     1583            {
     1584                Cursor.rc = VERR_DWARF_BAD_ABBREV;
     1585                break;
     1586            }
     1587
     1588            /* Cache it? */
     1589            if (uCurCode >= pThis->cCachedAbbrevsAlloced)
     1590            {
     1591                PRTDBGMODDWARFABBREV pEntry = &pThis->paCachedAbbrevs[uCurCode - 1];
     1592                while (pThis->cCachedAbbrevs < uCurCode)
     1593                {
     1594                    pThis->paCachedAbbrevs[pThis->cCachedAbbrevs].fFilled = false;
     1595                    pThis->cCachedAbbrevs++;
     1596                }
     1597
     1598                pEntry->fFilled   = true;
     1599                pEntry->fChildren = RT_BOOL(uChildren);
     1600                pEntry->uTag      = uCurTag;
     1601                pEntry->offSpec   = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
     1602
     1603                if (uCurCode == uCode)
     1604                {
     1605                    pRet = pEntry;
     1606                    if (uCurCode == pThis->cCachedAbbrevsAlloced)
     1607                        break;
     1608                }
     1609            }
     1610
     1611            /* Skip the specification. */
     1612            uint32_t uAttr, uForm;
     1613            do
     1614            {
     1615                uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1616                uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1617            } while (uAttr != 0 && uForm != 0);
     1618            if (RT_FAILURE(Cursor.rc))
     1619                break;
     1620
     1621            /* Done? (Maximize cache filling.) */
     1622            if (   pRet != NULL
     1623                && uCurCode >= pThis->cCachedAbbrevsAlloced)
     1624                break;
     1625        }
     1626    }
     1627    else
     1628    {
     1629        /*
     1630         * Search for the entry with the desired code, no cache filling.
     1631         */
     1632        for (;;)
     1633        {
     1634            /* Read the 'header'. */
     1635            uint32_t const uCurCode  = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1636            uint32_t const uCurTag   = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1637            uint8_t  const uChildren = rtDwarfCursor_GetU8(&Cursor, 0);
     1638            if (RT_FAILURE(Cursor.rc))
     1639                break;
     1640            if (   uCurTag > 0xffff
     1641                || uChildren > 1)
     1642            {
     1643                Cursor.rc = VERR_DWARF_BAD_ABBREV;
     1644                break;
     1645            }
     1646
     1647            /* Do we have a match? */
     1648            if (uCurCode == uCode)
     1649            {
     1650                pRet = &pThis->LookupAbbrev;
     1651                pRet->fFilled   = true;
     1652                pRet->fChildren = RT_BOOL(uChildren);
     1653                pRet->uTag      = uCurTag;
     1654                pRet->offSpec   = rtDwarfCursor_CalcSectOffsetU32(&Cursor);
     1655                break;
     1656            }
     1657
     1658            /* Skip the specification. */
     1659            uint32_t uAttr, uForm;
     1660            do
     1661            {
     1662                uAttr = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1663                uForm = rtDwarfCursor_GetULeb128AsU32(&Cursor, 0);
     1664            } while (uAttr != 0 && uForm != 0);
     1665            if (RT_FAILURE(Cursor.rc))
     1666                break;
     1667        }
     1668    }
     1669
     1670    rtDwarfCursor_Delete(&Cursor);
     1671    return pRet;
     1672}
     1673
     1674
     1675/**
     1676 * Looks up an abbreviation.
     1677 *
     1678 * @returns Pointer to abbreviation cache entry (read only).  May be rendered
     1679 *          invalid by subsequent calls to this function.
     1680 * @param   pThis               The DWARF instance.
     1681 * @param   uCode               The abbreviation code to lookup.
     1682 */
     1683static PCRTDBGMODDWARFABBREV rtDwarfAbbrev_Lookup(PRTDBGMODDWARF pThis, uint32_t uCode)
     1684{
     1685    if (   uCode - 1 >= pThis->cCachedAbbrevs
     1686        || !pThis->paCachedAbbrevs[uCode - 1].fFilled)
     1687        return rtDwarfAbbrev_LookupMiss(pThis, uCode);
     1688    return &pThis->paCachedAbbrevs[uCode - 1];
     1689}
     1690
     1691
     1692/**
     1693 * Sets the abbreviation offset of the current unit.
     1694 *
     1695 * This will flush the cached abbreviation entries if the offset differs from
     1696 * the previous unit.
     1697 *
     1698 * @param   pThis               The DWARF instance.
     1699 * @param   offAbbrev           The offset into the abbreviation section.
     1700 */
     1701static void rtDwarfAbbrev_SetUnitOffset(PRTDBGMODDWARF pThis, uint32_t offAbbrev)
     1702{
     1703    if (pThis->offCachedAbbrev != offAbbrev)
     1704    {
     1705        pThis->offCachedAbbrev = offAbbrev;
     1706        pThis->cCachedAbbrevs  = 0;
     1707    }
     1708}
     1709
     1710
     1711/*
     1712 *
     1713 * DWARF debug_info parser
     1714 * DWARF debug_info parser
     1715 * DWARF debug_info parser
     1716 *
     1717 */
     1718
     1719
     1720static int rtDwarfInfo_LoadUnit(PRTDBGMODDWARF pThis, PRTDWARFCURSOR pCursor)
     1721{
     1722    /*
     1723     * Read the compilation unit header.
     1724     */
     1725    rtDwarfCursor_GetInitalLength(pCursor);
     1726    uint16_t const uVer = rtDwarfCursor_GetUHalf(pCursor, 0);
     1727    if (   uVer < 2
     1728        || uVer > 4)
     1729        return rtDwarfCursor_SkipUnit(pCursor);
     1730    uint64_t const offAbbrev    = rtDwarfCursor_GetUOff(pCursor, UINT64_MAX);
     1731    uint8_t  const cbNativeAddr = rtDwarfCursor_GetU8(pCursor, UINT8_MAX);
     1732    if (RT_FAILURE(pCursor->rc))
     1733        return pCursor->rc;
     1734
     1735    /*
     1736     * Set up the abbreviation cache and store the native address size in the cursor.
     1737     */
     1738    if (offAbbrev > UINT32_MAX)
     1739        return VERR_DWARF_BAD_INFO;
     1740    rtDwarfAbbrev_SetUnitOffset(pThis, offAbbrev);
     1741    pCursor->cbNativeAddr = cbNativeAddr;
     1742
     1743    /*
     1744     * Parse DIEs.
     1745     */
     1746    int rc = VINF_SUCCESS;
     1747    while (!rtDwarfCursor_IsAtEndOfUnit(pCursor))
     1748    {
     1749        /** @todo The fun starts again here.  */
     1750        rtDwarfCursor_SkipUnit(pCursor);
     1751
     1752        /*
     1753         * Check status codes before continuing.
     1754         */
     1755        if (RT_FAILURE(rc))
     1756            return rc;
     1757        if (RT_FAILURE(pCursor->rc))
     1758            return pCursor->rc;
     1759    }
     1760
     1761    return rc;
     1762}
     1763
     1764
    14321765/**
    14331766 * Extracts the symbols.
     
    14381771 * @param   pThis               The DWARF instance.
    14391772 */
    1440 static int rtDbgModDwarfExtractSymbols(PRTDBGMODDWARF pThis)
    1441 {
    1442     int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_info);
     1773static int rtDwarfInfo_LoadAll(PRTDBGMODDWARF pThis)
     1774{
     1775    RTDWARFCURSOR Cursor;
     1776    int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info);
    14431777    if (RT_FAILURE(rc))
    1444         return rc;
    1445 
    1446     /** @todo  */
    1447 
    1448     rtDbgModDwarfUnloadSection(pThis, krtDbgModDwarfSect_info);
     1778        return NULL;
     1779
     1780    while (   !rtDwarfCursor_IsAtEnd(&Cursor)
     1781           && RT_SUCCESS(rc))
     1782        rc = rtDwarfInfo_LoadUnit(pThis, &Cursor);
     1783
     1784    rtDwarfCursor_Delete(&Cursor);
    14491785    return rc;
    14501786}
    14511787
    14521788
    1453 /**
    1454  * Loads the abbreviations used to parse the info section.
    1455  *
    1456  * @returns IPRT status code
    1457  * @param   pThis               The DWARF instance.
    1458  */
    1459 static int rtDbgModDwarfLoadAbbreviations(PRTDBGMODDWARF pThis)
    1460 {
    1461     int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_abbrev);
    1462     if (RT_FAILURE(rc))
    1463         return rc;
    1464 
    1465 #if 0 /** @todo  */
    1466     size_t          cbLeft = pThis->aSections[krtDbgModDwarfSect_abbrev].cb;
    1467     uint8_t const  *pb     = (uint8_t const *)pThis->aSections[krtDbgModDwarfSect_abbrev].pv;
    1468     while (cbLeft > 0)
    1469     {
    1470 
    1471     }
    1472 #endif
    1473 
    1474     rtDbgModDwarfUnloadSection(pThis, krtDbgModDwarfSect_abbrev);
    1475     return rc;
    1476 }
    14771789
    14781790
     
    16181930
    16191931    RTDbgModRelease(pThis->hCnt);
     1932    RTMemFree(pThis->paCachedAbbrevs);
    16201933    RTMemFree(pThis);
    16211934
     
    17252038                rc = rtDbgModHlpAddSegmentsFromImage(pMod);
    17262039                if (RT_SUCCESS(rc))
    1727                     rc = rtDbgModDwarfLoadAbbreviations(pThis);
    1728                 if (RT_SUCCESS(rc))
    1729                     rc = rtDbgModDwarfExtractSymbols(pThis);
     2040                    rc = rtDwarfInfo_LoadAll(pThis);
    17302041                if (RT_SUCCESS(rc))
    17312042                    rc = rtDwarfLine_ExplodeAll(pThis);
    17322043                if (RT_SUCCESS(rc))
    17332044                {
     2045                    /*
     2046                     * Free the cached abbreviations and unload all sections.
     2047                     */
     2048                    pThis->cCachedAbbrevs = pThis->cCachedAbbrevsAlloced = 0;
     2049                    RTMemFree(pThis->paCachedAbbrevs);
     2050
     2051                    for (unsigned iSect = 0; iSect < RT_ELEMENTS(pThis->aSections); iSect++)
     2052                        if (pThis->aSections[iSect].pv)
     2053                            pThis->pMod->pImgVt->pfnUnmapPart(pThis->pMod, pThis->aSections[iSect].cb,
     2054                                                              &pThis->aSections[iSect].pv);
     2055
     2056
    17342057                    return VINF_SUCCESS;
    17352058                }
     
    17432066            rc = VERR_DBG_NO_MATCHING_INTERPRETER;
    17442067    }
     2068    RTMemFree(pThis->paCachedAbbrevs);
    17452069    RTMemFree(pThis);
    17462070
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