Changeset 46274 in vbox for trunk/src/VBox/Runtime/common/dbg/dbgmodcodeview.cpp
- Timestamp:
- May 26, 2013 10:40:09 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dbg/dbgmodcodeview.cpp
r46271 r46274 1 1 /* $Id: dbgmoddeferred.cpp 85864 2013-05-19 16:58:01Z bird $ */ 2 2 /** @file 3 * IPRT - Debug Module Reader For Microsoft CodeView .3 * IPRT - Debug Module Reader For Microsoft CodeView and COFF. 4 4 * 5 5 * Based on the following documentation (plus guess work and googling): … … 481 481 /** The code view magic (used as format indicator). */ 482 482 uint32_t u32CvMagic; 483 /** The file type. */484 RTCVFILETYPE enmType;485 483 /** The offset of the CV debug info in the file. */ 486 484 uint32_t offBase; … … 491 489 /** @} */ 492 490 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; 493 503 /** The file handle (if external). */ 494 504 RTFILE hFile; … … 502 512 bool fHaveLoadedSegments; 503 513 504 /** @name Parsing state.514 /** @name Codeview Parsing state. 505 515 * @{ */ 506 516 /** Number of directory entries. */ … … 575 585 576 586 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 */ 577 597 static int rtDbgModCvReadAt(PRTDBGMODCV pThis, uint32_t off, void *pvBuf, size_t cb) 578 598 { … … 586 606 587 607 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 */ 588 618 static int rtDbgModCvReadAtAlloc(PRTDBGMODCV pThis, uint32_t off, void **ppvBuf, size_t cb) 589 619 { … … 1232 1262 1233 1263 1234 static int rtDbgModCvLoad Info(PRTDBGMODCV pThis)1264 static int rtDbgModCvLoadCodeViewInfo(PRTDBGMODCV pThis) 1235 1265 { 1236 1266 /* … … 1322 1352 return rc; 1323 1353 } 1354 1355 1356 /* 1357 * 1358 * COFF Debug Info Parsing. 1359 * COFF Debug Info Parsing. 1360 * COFF Debug Info Parsing. 1361 * 1362 */ 1363 1364 static 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 */ 1413 static 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 */ 1439 static 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 */ 1461 static 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 1638 static 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 1324 1677 1325 1678 … … 1623 1976 1624 1977 /** 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 */ 1986 static 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. 1626 2025 * 1627 2026 * @returns status code. … … 1632 2031 * @param cb The number of bytes of debug info. 1633 2032 * @param enmArch The desired image architecture. 2033 * @param pszFilename The path to the file (for logging). 2034 */ 2035 static 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. 1634 2124 * @param pszFilename The path to the file (for logging). 1635 2125 */ … … 1651 2141 /* We're assuming it's a base header, so the offset must be within 1652 2142 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)) 1654 2144 { 1655 2145 Log(("RTDbgModCv: Found %c%c%c%c at %#RTfoff - size %#x, directory at %#x. file type %d\n", … … 1658 2148 1659 2149 /* 1660 * Create a module instance .2150 * Create a module instance, if not already done. 1661 2151 */ 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)) 1664 2155 { 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; 1680 2161 } 1681 else1682 rc = VERR_NO_MEMORY;1683 2162 } 1684 2163 } … … 1700 2179 1701 2180 /* 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 1711 2196 return VINF_SUCCESS; 1712 2197 } … … 1815 2300 break; 1816 2301 if (DbgDir.Type == IMAGE_DEBUG_TYPE_CODEVIEW) 1817 {1818 2302 rc = rtDbgModCvProbeFile2(pDbgMod, RTCVFILETYPE_DBG, hFile, 1819 2303 DbgDir.PointerToRawData, DbgDir.SizeOfData, 1820 2304 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); 1836 2326 } 2327 return rc; 1837 2328 } 1838 2329 … … 1890 2381 if (!pThis) 1891 2382 return RT_SUCCESS_NP(rc) ? VERR_DBG_NO_MATCHING_INTERPRETER : rc; 2383 Assert(pThis->offBase || pThis->offCoffDbgInfo); 1892 2384 1893 2385 /* … … 1899 2391 pThis->fHaveLoadedSegments = true; 1900 2392 } 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); 1903 2397 if (RT_SUCCESS(rc)) 1904 2398 {
Note:
See TracChangeset
for help on using the changeset viewer.