Changeset 38584 in vbox for trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp
- Timestamp:
- Aug 31, 2011 2:38:20 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dbg/dbgmoddwarf.cpp
r38581 r38584 98 98 } krtDbgModDwarfSect; 99 99 100 /** 101 * Abbreviation cache entry. 102 */ 103 typedef 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. */ 115 typedef RTDBGMODDWARFABBREV *PRTDBGMODDWARFABBREV; 116 /** Pointer to a const abbreviation cache entry. */ 117 typedef RTDBGMODDWARFABBREV const *PCRTDBGMODDWARFABBREV; 118 100 119 101 120 /** … … 105 124 { 106 125 /** The debug container containing doing the real work. */ 107 RTDBGMOD hCnt;126 RTDBGMOD hCnt; 108 127 /** Pointer to back to the debug info module (no reference ofc). */ 109 PRTDBGMODINT pMod;128 PRTDBGMODINT pMod; 110 129 111 130 /** DWARF debug info sections. */ … … 113 132 { 114 133 /** The file offset of the part. */ 115 RTFOFF offFile;134 RTFOFF offFile; 116 135 /** The size of the part. */ 117 size_t cb;136 size_t cb; 118 137 /** The memory mapping of the part. */ 119 void const *pv;138 void const *pv; 120 139 /** Set if present. */ 121 bool fPresent;140 bool fPresent; 122 141 } 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; 123 153 } RTDBGMODDWARF; 124 154 /** Pointer to instance data of the DWARF reader. */ … … 151 181 * Used for repositioning the cursor relative to the start of a section. */ 152 182 uint8_t const *pbStart; 183 /** The section. */ 184 krtDbgModDwarfSect enmSect; 153 185 } RTDWARFCURSOR; 154 186 /** Pointer to a DWARF section reader. */ … … 799 831 800 832 /** 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 */ 839 static 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 /** 801 853 * Calculates an absolute cursor position from one relative to the current 802 854 * cursor position. … … 903 955 return rc; 904 956 957 pCursor->enmSect = enmSect; 905 958 pCursor->pbStart = (uint8_t const *)pThis->aSections[enmSect].pv; 906 959 pCursor->pb = pCursor->pbStart; … … 916 969 917 970 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 */ 983 static 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; 918 999 } 919 1000 … … 1430 1511 1431 1512 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 */ 1529 static 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 */ 1683 static 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 */ 1701 static 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 1720 static 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 1432 1765 /** 1433 1766 * Extracts the symbols. … … 1438 1771 * @param pThis The DWARF instance. 1439 1772 */ 1440 static int rtDbgModDwarfExtractSymbols(PRTDBGMODDWARF pThis) 1441 { 1442 int rc = rtDbgModDwarfLoadSection(pThis, krtDbgModDwarfSect_info); 1773 static int rtDwarfInfo_LoadAll(PRTDBGMODDWARF pThis) 1774 { 1775 RTDWARFCURSOR Cursor; 1776 int rc = rtDwarfCursor_Init(&Cursor, pThis, krtDbgModDwarfSect_info); 1443 1777 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); 1449 1785 return rc; 1450 1786 } 1451 1787 1452 1788 1453 /**1454 * Loads the abbreviations used to parse the info section.1455 *1456 * @returns IPRT status code1457 * @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 #endif1473 1474 rtDbgModDwarfUnloadSection(pThis, krtDbgModDwarfSect_abbrev);1475 return rc;1476 }1477 1789 1478 1790 … … 1618 1930 1619 1931 RTDbgModRelease(pThis->hCnt); 1932 RTMemFree(pThis->paCachedAbbrevs); 1620 1933 RTMemFree(pThis); 1621 1934 … … 1725 2038 rc = rtDbgModHlpAddSegmentsFromImage(pMod); 1726 2039 if (RT_SUCCESS(rc)) 1727 rc = rtDbgModDwarfLoadAbbreviations(pThis); 1728 if (RT_SUCCESS(rc)) 1729 rc = rtDbgModDwarfExtractSymbols(pThis); 2040 rc = rtDwarfInfo_LoadAll(pThis); 1730 2041 if (RT_SUCCESS(rc)) 1731 2042 rc = rtDwarfLine_ExplodeAll(pThis); 1732 2043 if (RT_SUCCESS(rc)) 1733 2044 { 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 1734 2057 return VINF_SUCCESS; 1735 2058 } … … 1743 2066 rc = VERR_DBG_NO_MATCHING_INTERPRETER; 1744 2067 } 2068 RTMemFree(pThis->paCachedAbbrevs); 1745 2069 RTMemFree(pThis); 1746 2070
Note:
See TracChangeset
for help on using the changeset viewer.