Changeset 64359 in vbox for trunk/src/VBox/Debugger
- Timestamp:
- Oct 21, 2016 2:14:24 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 111462
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGPlugInLinux.cpp
r63567 r64359 96 96 /** Set if 64-bit, clear if 32-bit. */ 97 97 bool f64Bit; 98 /** Set if the kallsyms table uses relative addressing, clear 99 * if absolute addresses are used. */ 100 bool fRelKrnlAddr; 101 /** The relative base when kernel symbols use offsets rather than 102 * absolute addresses. */ 103 RTGCUINTPTR uKernelRelativeBase; 98 104 99 105 /** The address of the linux banner. … … 212 218 213 219 static const uint8_t g_abLinuxVersion[] = "Linux version "; 220 221 /** 222 * Converts a given offset into an absolute address if relative kernel offsets are used for 223 * kallsyms. 224 * 225 * @returns The absolute kernel address. 226 * @param pThis The Linux digger data. 227 * @param uOffset The offset to convert. 228 */ 229 DECLINLINE(RTGCUINTPTR) dbgDiggerLinuxConvOffsetToAddr(PDBGDIGGERLINUX pThis, int32_t uOffset) 230 { 231 RTGCUINTPTR uAddr; 232 233 /* 234 * How the absolute address is calculated from the offset depends on the 235 * CONFIG_KALLSYMS_ABSOLUTE_PERCPU config which is only set for 64bit 236 * SMP kernels (we assume that all 64bit kernels always have SMP enabled too). 237 */ 238 if (pThis->f64Bit) 239 { 240 if (uOffset >= 0) 241 uAddr = uOffset; 242 else 243 uAddr = pThis->uKernelRelativeBase - 1 - uOffset; 244 } 245 else 246 uAddr = pThis->uKernelRelativeBase + (uint32_t)uOffset; 247 248 return uAddr; 249 } 214 250 215 251 /** … … 1138 1174 pThis->AddrKernelNames = *pAddrKernelNames; 1139 1175 pThis->AddrKernelAddresses = *pAddrKernelNames; 1140 DBGFR3AddrSub(&pThis->AddrKernelAddresses, (cKernelSymbols + 1) * cbAddress); 1176 uint32_t cbSymbolsSkip = (pThis->fRelKrnlAddr ? 2 : 1) * cbAddress; /* Relative addressing introduces kallsyms_relative_base. */ 1177 uint32_t cbOffsets = pThis->fRelKrnlAddr ? sizeof(int32_t) : cbAddress; /* Offsets are always 32bits wide for relative addressing. */ 1178 uint32_t cbAlign = 0; 1179 1180 /* 1181 * If the number of symbols is odd there is padding to align the following guest pointer 1182 * sized data properly on 64bit systems with relative addressing. 1183 */ 1184 if ( pThis->fRelKrnlAddr 1185 && pThis->f64Bit 1186 && (pThis->cKernelSymbols & 1)) 1187 cbAlign = sizeof(int32_t); 1188 DBGFR3AddrSub(&pThis->AddrKernelAddresses, cKernelSymbols * cbOffsets + cbSymbolsSkip + cbAlign); 1141 1189 1142 1190 Log(("dbgDiggerLinuxFoundStartOfNames: AddrKernelAddresses=%RGv\n" … … 1187 1235 1188 1236 /* 1189 * We assume that the three symbols are aligned on guest pointer boundrary. 1237 * Since Linux 4.6 there are two different methods to store the kallsyms addresses 1238 * in the image. 1190 1239 * 1191 * The boundrary between the two tables should be noticable as the number 1192 * is unlikely to be more than 16 millions, there will be at least one zero 1193 * byte where it is, 64-bit will have 5 zero bytes. Zero bytes aren't all 1194 * that common in the kallsyms_names table. 1240 * The first and longer existing method is to store the absolute addresses in an 1241 * array starting at kallsyms_addresses followed by a field which stores the number 1242 * of kernel symbols called kallsyms_num_syms. 1243 * The newer method is to use offsets stored in kallsyms_offsets and have a base pointer 1244 * to relate the offsets to called kallsyms_relative_base. One entry in kallsyms_offsets is 1245 * always 32bit wide regardless of the guest pointer size (this halves the table on 64bit 1246 * systems) but means more work for us for the 64bit case. 1195 1247 * 1196 * Also the kallsyms_names table starts with a length byte, which means 1197 * we're likely to see a byte in the range 1..31. 1248 * When absolute addresses are used the following assumptions hold: 1198 1249 * 1199 * The kallsyms_addresses are mostly sorted (except for the start where the 1200 * absolute symbols are), so we'll spot a bunch of kernel addresses 1201 * immediately preceeding the kallsyms_num_syms field. 1250 * We assume that the three symbols are aligned on guest pointer boundary. 1202 1251 * 1203 * Lazy bird: If kallsyms_num_syms is on a buffer boundrary, we skip 1204 * the check for kernel addresses preceeding it. 1252 * The boundary between the two tables should be noticable as the number 1253 * is unlikely to be more than 16 millions, there will be at least one zero 1254 * byte where it is, 64-bit will have 5 zero bytes. Zero bytes aren't all 1255 * that common in the kallsyms_names table. 1256 * 1257 * Also the kallsyms_names table starts with a length byte, which means 1258 * we're likely to see a byte in the range 1..31. 1259 * 1260 * The kallsyms_addresses are mostly sorted (except for the start where the 1261 * absolute symbols are), so we'll spot a bunch of kernel addresses 1262 * immediately preceeding the kallsyms_num_syms field. 1263 * 1264 * Lazy bird: If kallsyms_num_syms is on a buffer boundrary, we skip 1265 * the check for kernel addresses preceeding it. 1266 * 1267 * For relative offsets most of the assumptions from above are true too 1268 * except that we have to distinguish between the relative base address and the offsets. 1269 * Every observed kernel has a valid kernel address fo the relative base and kallsyms_relative_base 1270 * always comes before kallsyms_num_syms and is aligned on a guest pointer boundary. 1271 * Offsets are stored before kallsyms_relative_base and don't contain valid kernel addresses. 1272 * 1273 * To distinguish between absolute and relative offsetting we check the data before a candidate 1274 * for kallsyms_num_syms. If all entries before the kallsyms_num_syms candidate are valid kernel 1275 * addresses absolute addresses are assumed. If this is not the case but the first entry before 1276 * kallsyms_num_syms is a valid kernel address we check whether the data before and the possible 1277 * relative base form a valid kernel address and assume relative offsets. 1205 1278 */ 1206 1279 if (pThis->f64Bit) … … 1215 1288 && pb[0] >= LNX_MIN_KALLSYMS_ENC_LENGTH) 1216 1289 { 1290 /* 1291 * Check whether we have a valid kernel address and try to distinguish 1292 * whether the kernel uses relative offsetting or absolute addresses. 1293 */ 1294 if ( (i >= 1 && LNX64_VALID_ADDRESS(uBuf.au64[i - 1])) 1295 && (i >= 2 && !LNX64_VALID_ADDRESS(uBuf.au64[i - 2])) 1296 && (i >= 3 && !LNX64_VALID_ADDRESS(uBuf.au64[i - 3]))) 1297 { 1298 RTGCUINTPTR uKrnlRelBase = uBuf.au64[i - 1]; 1299 DBGFADDRESS RelAddr = CurAddr; 1300 int32_t aiRelOff[3]; 1301 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrAdd(&RelAddr, (i - 1) * sizeof(uint64_t) - sizeof(aiRelOff)), 1302 &aiRelOff[0], sizeof(aiRelOff)); 1303 if ( RT_SUCCESS(rc) 1304 && LNX64_VALID_ADDRESS(uKrnlRelBase + aiRelOff[0]) 1305 && LNX64_VALID_ADDRESS(uKrnlRelBase + aiRelOff[1]) 1306 && LNX64_VALID_ADDRESS(uKrnlRelBase + aiRelOff[2])) 1307 { 1308 Log(("dbgDiggerLinuxFindStartOfNamesAndSymbolCount: relative base %RGv (at %RGv)\n", 1309 uKrnlRelBase, CurAddr.FlatPtr + (i - 1) * sizeof(uint64_t))); 1310 pThis->fRelKrnlAddr = true; 1311 pThis->uKernelRelativeBase = uKrnlRelBase; 1312 return dbgDiggerLinuxFoundStartOfNames(pThis, 1313 DBGFR3AddrAdd(&CurAddr, (i + 1) * sizeof(uint64_t)), 1314 (uint32_t)uBuf.au64[i], sizeof(uint64_t)); 1315 } 1316 } 1317 1217 1318 if ( (i <= 0 || LNX64_VALID_ADDRESS(uBuf.au64[i - 1])) 1218 1319 && (i <= 1 || LNX64_VALID_ADDRESS(uBuf.au64[i - 2])) … … 1235 1336 && pb[0] >= LNX_MIN_KALLSYMS_ENC_LENGTH) 1236 1337 { 1338 /* Check for relative base addressing. */ 1339 if (i >= 1 && LNX32_VALID_ADDRESS(uBuf.au32[i - 1])) 1340 { 1341 RTGCUINTPTR uKrnlRelBase = uBuf.au32[i - 1]; 1342 if ( (i <= 1 || LNX32_VALID_ADDRESS(uKrnlRelBase + uBuf.au32[i - 2])) 1343 && (i <= 2 || LNX32_VALID_ADDRESS(uKrnlRelBase + uBuf.au32[i - 3]))) 1344 { 1345 Log(("dbgDiggerLinuxFindStartOfNamesAndSymbolCount: relative base %RGv (at %RGv)\n", 1346 uKrnlRelBase, CurAddr.FlatPtr + (i - 1) * sizeof(uint32_t))); 1347 pThis->fRelKrnlAddr = true; 1348 pThis->uKernelRelativeBase = uKrnlRelBase; 1349 return dbgDiggerLinuxFoundStartOfNames(pThis, 1350 DBGFR3AddrAdd(&CurAddr, (i + 1) * sizeof(uint32_t)), 1351 uBuf.au32[i], sizeof(uint32_t)); 1352 } 1353 } 1354 1237 1355 if ( (i <= 0 || LNX32_VALID_ADDRESS(uBuf.au32[i - 1])) 1238 1356 && (i <= 1 || LNX32_VALID_ADDRESS(uBuf.au32[i - 2])) … … 1468 1586 1469 1587 /** 1470 * Loads the kernel symbols from the kallsyms tables. 1588 * Loads the kernel symbols from the given kallsyms offset table decoding the symbol names 1589 * (worker common for dbgDiggerLinuxLoadKernelSymbolsAbsolute() and dbgDiggerLinuxLoadKernelSymbolsRelative()). 1471 1590 * 1472 1591 * @returns VBox status code. 1473 1592 * @param pUVM The user mode VM handle. 1474 1593 * @param pThis The Linux digger data. 1475 */ 1476 static int dbgDiggerLinuxLoadKernelSymbols(PUVM pUVM, PDBGDIGGERLINUX pThis) 1477 { 1478 /* 1479 * Allocate memory for temporary table copies, reading the tables as we go. 1480 */ 1481 uint32_t const cbGuestAddr = pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t); 1482 void *pvAddresses = RTMemAllocZ(pThis->cKernelSymbols * cbGuestAddr); 1483 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelAddresses, pvAddresses, pThis->cKernelSymbols * cbGuestAddr); 1594 * @param uKernelStart Flat kernel start address. 1595 * @param cbKernel Size of the kernel in bytes. 1596 * @param pauSymOff Pointer to the array of symbol offsets in the kallsyms table 1597 * relative to the start of the kernel. 1598 */ 1599 static int dbgDiggerLinuxLoadKernelSymbolsWorker(PUVM pUVM, PDBGDIGGERLINUX pThis, RTGCUINTPTR uKernelStart, 1600 RTGCUINTPTR cbKernel, RTGCUINTPTR *pauSymOff) 1601 { 1602 uint8_t *pbNames = (uint8_t *)RTMemAllocZ(pThis->cbKernelNames); 1603 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelNames, pbNames, pThis->cbKernelNames); 1484 1604 if (RT_SUCCESS(rc)) 1485 1605 { 1486 uint8_t *pbNames = (uint8_t *)RTMemAllocZ(pThis->cbKernelNames);1487 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernel Names, pbNames, pThis->cbKernelNames);1606 char *pszzTokens = (char *)RTMemAllocZ(pThis->cbKernelTokenTable); 1607 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenTable, pszzTokens, pThis->cbKernelTokenTable); 1488 1608 if (RT_SUCCESS(rc)) 1489 1609 { 1490 char *pszzTokens = (char *)RTMemAllocZ(pThis->cbKernelTokenTable);1491 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelToken Table, pszzTokens, pThis->cbKernelTokenTable);1610 uint16_t *paoffTokens = (uint16_t *)RTMemAllocZ(256 * sizeof(uint16_t)); 1611 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenIndex, paoffTokens, 256 * sizeof(uint16_t)); 1492 1612 if (RT_SUCCESS(rc)) 1493 1613 { 1494 uint16_t *paoffTokens = (uint16_t *)RTMemAllocZ(256 * sizeof(uint16_t)); 1495 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenIndex, paoffTokens, 256 * sizeof(uint16_t)); 1614 /* 1615 * Create a module for the kernel. 1616 */ 1617 RTDBGMOD hMod; 1618 rc = RTDbgModCreate(&hMod, "vmlinux", cbKernel, 0 /*fFlags*/); 1496 1619 if (RT_SUCCESS(rc)) 1497 1620 { 1621 rc = RTDbgModSetTag(hMod, DIG_LNX_MOD_TAG); AssertRC(rc); 1622 rc = VINF_SUCCESS; 1623 1498 1624 /* 1499 * Figure out the kernel start and end.1625 * Enumerate the symbols. 1500 1626 */ 1501 RTGCUINTPTR uKernelStart = pThis->AddrKernelAddresses.FlatPtr; 1502 RTGCUINTPTR uKernelEnd = pThis->AddrKernelTokenIndex.FlatPtr + 256 * sizeof(uint16_t); 1503 uint32_t i; 1504 if (cbGuestAddr == sizeof(uint64_t)) 1627 uint32_t offName = 0; 1628 uint32_t cLeft = pThis->cKernelSymbols; 1629 while (cLeft-- > 0 && RT_SUCCESS(rc)) 1505 1630 { 1506 uint64_t *pauAddrs = (uint64_t *)pvAddresses; 1507 for (i = 0; i < pThis->cKernelSymbols; i++) 1508 if ( pauAddrs[i] < uKernelStart 1509 && LNX64_VALID_ADDRESS(pauAddrs[i]) 1510 && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE) 1511 uKernelStart = pauAddrs[i]; 1512 1513 for (i = pThis->cKernelSymbols - 1; i > 0; i--) 1514 if ( pauAddrs[i] > uKernelEnd 1515 && LNX64_VALID_ADDRESS(pauAddrs[i]) 1516 && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE) 1517 uKernelEnd = pauAddrs[i]; 1518 } 1519 else 1520 { 1521 uint32_t *pauAddrs = (uint32_t *)pvAddresses; 1522 for (i = 0; i < pThis->cKernelSymbols; i++) 1523 if ( pauAddrs[i] < uKernelStart 1524 && LNX32_VALID_ADDRESS(pauAddrs[i]) 1525 && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE) 1526 uKernelStart = pauAddrs[i]; 1527 1528 for (i = pThis->cKernelSymbols - 1; i > 0; i--) 1529 if ( pauAddrs[i] > uKernelEnd 1530 && LNX32_VALID_ADDRESS(pauAddrs[i]) 1531 && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE) 1532 uKernelEnd = pauAddrs[i]; 1533 } 1534 1535 RTGCUINTPTR cbKernel = uKernelEnd - uKernelStart; 1536 pThis->cbKernel = (uint32_t)cbKernel; 1537 DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelBase, uKernelStart); 1538 Log(("dbgDiggerLinuxLoadKernelSymbols: uKernelStart=%RGv cbKernel=%#x\n", uKernelStart, cbKernel)); 1539 1540 /* 1541 * Create a module for the kernel. 1542 */ 1543 RTDBGMOD hMod; 1544 rc = RTDbgModCreate(&hMod, "vmlinux", cbKernel, 0 /*fFlags*/); 1545 if (RT_SUCCESS(rc)) 1546 { 1547 rc = RTDbgModSetTag(hMod, DIG_LNX_MOD_TAG); AssertRC(rc); 1548 rc = VINF_SUCCESS; 1549 1550 /* 1551 * Enumerate the symbols. 1552 */ 1553 uint8_t const *pbCurAddr = (uint8_t const *)pvAddresses; 1554 uint32_t offName = 0; 1555 uint32_t cLeft = pThis->cKernelSymbols; 1556 while (cLeft-- > 0 && RT_SUCCESS(rc)) 1631 /* Decode the symbol name first. */ 1632 if (RT_LIKELY(offName < pThis->cbKernelNames)) 1557 1633 { 1558 /* Decode the symbol name first. */1559 if (RT_LIKELY(offName <pThis->cbKernelNames))1634 uint8_t cbName = pbNames[offName++]; 1635 if (RT_LIKELY(offName + cbName <= pThis->cbKernelNames)) 1560 1636 { 1561 uint8_t cbName = pbNames[offName++]; 1562 if (RT_LIKELY(offName + cbName <= pThis->cbKernelNames)) 1637 char szSymbol[4096]; 1638 uint32_t offSymbol = 0; 1639 while (cbName-- > 0) 1563 1640 { 1564 char szSymbol[4096];1565 uint 32_t offSymbol = 0;1566 while (cbName-- > 0)1641 uint8_t bEnc = pbNames[offName++]; 1642 uint16_t offToken = paoffTokens[bEnc]; 1643 if (RT_LIKELY(offToken < pThis->cbKernelTokenTable)) 1567 1644 { 1568 uint8_t bEnc = pbNames[offName++]; 1569 uint16_t offToken = paoffTokens[bEnc]; 1570 if (RT_LIKELY(offToken < pThis->cbKernelTokenTable)) 1645 const char *pszToken = &pszzTokens[offToken]; 1646 char ch; 1647 while ((ch = *pszToken++) != '\0') 1648 if (offSymbol < sizeof(szSymbol) - 1) 1649 szSymbol[offSymbol++] = ch; 1650 } 1651 else 1652 { 1653 rc = VERR_INVALID_UTF8_ENCODING; 1654 break; 1655 } 1656 } 1657 szSymbol[offSymbol < sizeof(szSymbol) ? offSymbol : sizeof(szSymbol) - 1] = '\0'; 1658 1659 /* The offset. */ 1660 RTGCUINTPTR uSymOff = *pauSymOff; 1661 pauSymOff++; 1662 1663 /* Add it without the type char. */ 1664 if (uSymOff <= cbKernel) 1665 { 1666 rc = RTDbgModSymbolAdd(hMod, &szSymbol[1], RTDBGSEGIDX_RVA, uSymOff, 1667 0 /*cb*/, 0 /*fFlags*/, NULL); 1668 if (RT_FAILURE(rc)) 1669 { 1670 if ( rc == VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE 1671 || rc == VERR_DBG_INVALID_RVA 1672 || rc == VERR_DBG_ADDRESS_CONFLICT 1673 || rc == VERR_DBG_DUPLICATE_SYMBOL) 1571 1674 { 1572 const char *pszToken = &pszzTokens[offToken]; 1573 char ch; 1574 while ((ch = *pszToken++) != '\0') 1575 if (offSymbol < sizeof(szSymbol) - 1) 1576 szSymbol[offSymbol++] = ch; 1675 Log2(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc (ignored)\n", szSymbol, rc)); 1676 rc = VINF_SUCCESS; 1577 1677 } 1578 1678 else 1579 { 1580 rc = VERR_INVALID_UTF8_ENCODING; 1581 break; 1582 } 1679 Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n", szSymbol, rc)); 1583 1680 } 1584 szSymbol[offSymbol < sizeof(szSymbol) ? offSymbol : sizeof(szSymbol) - 1] = '\0';1585 1586 /* The address. */1587 RTGCUINTPTR uSymAddr = cbGuestAddr == sizeof(uint64_t)1588 ? *(uint64_t *)pbCurAddr : *(uint32_t *)pbCurAddr;1589 pbCurAddr += cbGuestAddr;1590 1591 /* Add it without the type char. */1592 if (uSymAddr - uKernelStart <= cbKernel)1593 {1594 rc = RTDbgModSymbolAdd(hMod, &szSymbol[1], RTDBGSEGIDX_RVA, uSymAddr - uKernelStart,1595 0 /*cb*/, 0 /*fFlags*/, NULL);1596 if (RT_FAILURE(rc))1597 {1598 if ( rc == VERR_DBG_SYMBOL_NAME_OUT_OF_RANGE1599 || rc == VERR_DBG_INVALID_RVA1600 || rc == VERR_DBG_ADDRESS_CONFLICT1601 || rc == VERR_DBG_DUPLICATE_SYMBOL)1602 {1603 Log2(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc (ignored)\n", szSymbol, rc));1604 rc = VINF_SUCCESS;1605 }1606 else1607 Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n", szSymbol, rc));1608 }1609 }1610 }1611 else1612 {1613 rc = VERR_END_OF_STRING;1614 Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbName=%#x cbKernelNames=%#x\n",1615 offName, cLeft, cbName, pThis->cbKernelNames));1616 1681 } 1617 1682 } … … 1619 1684 { 1620 1685 rc = VERR_END_OF_STRING; 1621 Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cb KernelNames=%#x\n",1622 offName, cLeft, pThis->cbKernelNames));1686 Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbName=%#x cbKernelNames=%#x\n", 1687 offName, cLeft, cbName, pThis->cbKernelNames)); 1623 1688 } 1624 1689 } 1625 1626 /* 1627 * Link the module into the address space. 1628 */ 1629 if (RT_SUCCESS(rc)) 1690 else 1630 1691 { 1631 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); 1632 if (hAs != NIL_RTDBGAS) 1633 rc = RTDbgAsModuleLink(hAs, hMod, uKernelStart, RTDBGASLINK_FLAGS_REPLACE); 1634 else 1635 rc = VERR_INTERNAL_ERROR; 1636 RTDbgAsRelease(hAs); 1692 rc = VERR_END_OF_STRING; 1693 Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbKernelNames=%#x\n", 1694 offName, cLeft, pThis->cbKernelNames)); 1637 1695 } 1696 } 1697 1698 /* 1699 * Link the module into the address space. 1700 */ 1701 if (RT_SUCCESS(rc)) 1702 { 1703 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); 1704 if (hAs != NIL_RTDBGAS) 1705 rc = RTDbgAsModuleLink(hAs, hMod, uKernelStart, RTDBGASLINK_FLAGS_REPLACE); 1638 1706 else 1639 Log(("dbgDiggerLinuxLoadKernelSymbols: Failed: %Rrc\n", rc));1640 RTDbg ModRelease(hMod);1707 rc = VERR_INTERNAL_ERROR; 1708 RTDbgAsRelease(hAs); 1641 1709 } 1642 1710 else 1643 Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModCreate failed: %Rrc\n", rc)); 1711 Log(("dbgDiggerLinuxLoadKernelSymbols: Failed: %Rrc\n", rc)); 1712 RTDbgModRelease(hMod); 1644 1713 } 1645 1714 else 1646 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token index at %RGv failed: %Rrc\n", 1647 pThis->AddrKernelTokenIndex.FlatPtr, rc)); 1648 RTMemFree(paoffTokens); 1715 Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModCreate failed: %Rrc\n", rc)); 1649 1716 } 1650 1717 else 1651 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token tableat %RGv failed: %Rrc\n",1652 pThis->AddrKernelToken Table.FlatPtr, rc));1653 RTMemFree(p szzTokens);1718 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token index at %RGv failed: %Rrc\n", 1719 pThis->AddrKernelTokenIndex.FlatPtr, rc)); 1720 RTMemFree(paoffTokens); 1654 1721 } 1655 1722 else 1656 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading encoded namesat %RGv failed: %Rrc\n",1657 pThis->AddrKernel Names.FlatPtr, rc));1658 RTMemFree(p bNames);1723 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token table at %RGv failed: %Rrc\n", 1724 pThis->AddrKernelTokenTable.FlatPtr, rc)); 1725 RTMemFree(pszzTokens); 1659 1726 } 1660 1727 else 1661 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading symbol addresses at %RGv failed: %Rrc\n", 1728 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading encoded names at %RGv failed: %Rrc\n", 1729 pThis->AddrKernelNames.FlatPtr, rc)); 1730 RTMemFree(pbNames); 1731 1732 return rc; 1733 } 1734 1735 /** 1736 * Loads the kernel symbols from the kallsyms table if it contains absolute addresses 1737 * 1738 * @returns VBox status code. 1739 * @param pUVM The user mode VM handle. 1740 * @param pThis The Linux digger data. 1741 */ 1742 static int dbgDiggerLinuxLoadKernelSymbolsAbsolute(PUVM pUVM, PDBGDIGGERLINUX pThis) 1743 { 1744 /* 1745 * Allocate memory for temporary table copies, reading the tables as we go. 1746 */ 1747 uint32_t const cbGuestAddr = pThis->f64Bit ? sizeof(uint64_t) : sizeof(uint32_t); 1748 void *pvAddresses = RTMemAllocZ(pThis->cKernelSymbols * cbGuestAddr); 1749 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelAddresses, pvAddresses, pThis->cKernelSymbols * cbGuestAddr); 1750 if (RT_SUCCESS(rc)) 1751 { 1752 /* 1753 * Figure out the kernel start and end and convert the absolute addresses to relative offsets. 1754 */ 1755 RTGCUINTPTR uKernelStart = pThis->AddrKernelAddresses.FlatPtr; 1756 RTGCUINTPTR uKernelEnd = pThis->AddrKernelTokenIndex.FlatPtr + 256 * sizeof(uint16_t); 1757 RTGCUINTPTR *pauSymOff = (RTGCUINTPTR *)RTMemTmpAllocZ(pThis->cKernelSymbols * sizeof(RTGCUINTPTR)); 1758 uint32_t i; 1759 if (cbGuestAddr == sizeof(uint64_t)) 1760 { 1761 uint64_t *pauAddrs = (uint64_t *)pvAddresses; 1762 for (i = 0; i < pThis->cKernelSymbols; i++) 1763 if ( pauAddrs[i] < uKernelStart 1764 && LNX64_VALID_ADDRESS(pauAddrs[i]) 1765 && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE) 1766 uKernelStart = pauAddrs[i]; 1767 1768 for (i = pThis->cKernelSymbols - 1; i > 0; i--) 1769 if ( pauAddrs[i] > uKernelEnd 1770 && LNX64_VALID_ADDRESS(pauAddrs[i]) 1771 && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE) 1772 uKernelEnd = pauAddrs[i]; 1773 1774 for (i = 0; i < pThis->cKernelSymbols; i++) 1775 pauSymOff[i] = pauAddrs[i] - uKernelStart; 1776 } 1777 else 1778 { 1779 uint32_t *pauAddrs = (uint32_t *)pvAddresses; 1780 for (i = 0; i < pThis->cKernelSymbols; i++) 1781 if ( pauAddrs[i] < uKernelStart 1782 && LNX32_VALID_ADDRESS(pauAddrs[i]) 1783 && uKernelStart - pauAddrs[i] < LNX_MAX_KERNEL_SIZE) 1784 uKernelStart = pauAddrs[i]; 1785 1786 for (i = pThis->cKernelSymbols - 1; i > 0; i--) 1787 if ( pauAddrs[i] > uKernelEnd 1788 && LNX32_VALID_ADDRESS(pauAddrs[i]) 1789 && pauAddrs[i] - uKernelEnd < LNX_MAX_KERNEL_SIZE) 1790 uKernelEnd = pauAddrs[i]; 1791 1792 for (i = 0; i < pThis->cKernelSymbols; i++) 1793 pauSymOff[i] = pauAddrs[i] - uKernelStart; 1794 } 1795 1796 RTGCUINTPTR cbKernel = uKernelEnd - uKernelStart; 1797 pThis->cbKernel = (uint32_t)cbKernel; 1798 DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelBase, uKernelStart); 1799 Log(("dbgDiggerLinuxLoadKernelSymbolsAbsolute: uKernelStart=%RGv cbKernel=%#x\n", uKernelStart, cbKernel)); 1800 1801 rc = dbgDiggerLinuxLoadKernelSymbolsWorker(pUVM, pThis, uKernelStart, cbKernel, pauSymOff); 1802 if (RT_FAILURE(rc)) 1803 Log(("dbgDiggerLinuxLoadKernelSymbolsAbsolute: Loading symbols from given offset table failed: %Rrc\n", rc)); 1804 RTMemTmpFree(pauSymOff); 1805 } 1806 else 1807 Log(("dbgDiggerLinuxLoadKernelSymbolsAbsolute: Reading symbol addresses at %RGv failed: %Rrc\n", 1662 1808 pThis->AddrKernelAddresses.FlatPtr, rc)); 1663 1809 RTMemFree(pvAddresses); 1810 1664 1811 return rc; 1665 1812 } 1666 1813 1814 1815 /** 1816 * Loads the kernel symbols from the kallsyms table if it contains absolute addresses 1817 * 1818 * @returns VBox status code. 1819 * @param pUVM The user mode VM handle. 1820 * @param pThis The Linux digger data. 1821 */ 1822 static int dbgDiggerLinuxLoadKernelSymbolsRelative(PUVM pUVM, PDBGDIGGERLINUX pThis) 1823 { 1824 /* 1825 * Allocate memory for temporary table copies, reading the tables as we go. 1826 */ 1827 int32_t *pai32Offsets = (int32_t *)RTMemAllocZ(pThis->cKernelSymbols * sizeof(int32_t)); 1828 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelAddresses, pai32Offsets, pThis->cKernelSymbols * sizeof(int32_t)); 1829 if (RT_SUCCESS(rc)) 1830 { 1831 /* 1832 * Figure out the kernel start and end and convert the absolute addresses to relative offsets. 1833 */ 1834 RTGCUINTPTR uKernelStart = pThis->AddrKernelAddresses.FlatPtr; 1835 RTGCUINTPTR uKernelEnd = pThis->AddrKernelTokenIndex.FlatPtr + 256 * sizeof(uint16_t); 1836 RTGCUINTPTR *pauSymOff = (RTGCUINTPTR *)RTMemTmpAllocZ(pThis->cKernelSymbols * sizeof(RTGCUINTPTR)); 1837 uint32_t i; 1838 1839 for (i = 0; i < pThis->cKernelSymbols; i++) 1840 { 1841 RTGCUINTPTR uSymAddr = dbgDiggerLinuxConvOffsetToAddr(pThis, pai32Offsets[i]); 1842 1843 if ( uSymAddr < uKernelStart 1844 && (pThis->f64Bit ? LNX64_VALID_ADDRESS(uSymAddr) : LNX32_VALID_ADDRESS(uSymAddr)) 1845 && uKernelStart - uSymAddr < LNX_MAX_KERNEL_SIZE) 1846 uKernelStart = uSymAddr; 1847 } 1848 1849 for (i = pThis->cKernelSymbols - 1; i > 0; i--) 1850 { 1851 RTGCUINTPTR uSymAddr = dbgDiggerLinuxConvOffsetToAddr(pThis, pai32Offsets[i]); 1852 1853 if ( uSymAddr > uKernelEnd 1854 && (pThis->f64Bit ? LNX64_VALID_ADDRESS(uSymAddr) : LNX32_VALID_ADDRESS(uSymAddr)) 1855 && uSymAddr - uKernelEnd < LNX_MAX_KERNEL_SIZE) 1856 uKernelEnd = uSymAddr; 1857 1858 /* Store the offset from the derived kernel start address. */ 1859 pauSymOff[i] = uSymAddr - uKernelStart; 1860 } 1861 1862 RTGCUINTPTR cbKernel = uKernelEnd - uKernelStart; 1863 pThis->cbKernel = (uint32_t)cbKernel; 1864 DBGFR3AddrFromFlat(pUVM, &pThis->AddrKernelBase, uKernelStart); 1865 Log(("dbgDiggerLinuxLoadKernelSymbolsRelative: uKernelStart=%RGv cbKernel=%#x\n", uKernelStart, cbKernel)); 1866 1867 rc = dbgDiggerLinuxLoadKernelSymbolsWorker(pUVM, pThis, uKernelStart, cbKernel, pauSymOff); 1868 if (RT_FAILURE(rc)) 1869 Log(("dbgDiggerLinuxLoadKernelSymbolsRelative: Loading symbols from given offset table failed: %Rrc\n", rc)); 1870 RTMemTmpFree(pauSymOff); 1871 } 1872 else 1873 Log(("dbgDiggerLinuxLoadKernelSymbolsRelative: Reading symbol addresses at %RGv failed: %Rrc\n", 1874 pThis->AddrKernelAddresses.FlatPtr, rc)); 1875 RTMemFree(pai32Offsets); 1876 1877 return rc; 1878 } 1879 1880 1881 /** 1882 * Loads the kernel symbols. 1883 * 1884 * @returns VBox status code. 1885 * @param pUVM The user mode VM handle. 1886 * @param pThis The Linux digger data. 1887 */ 1888 static int dbgDiggerLinuxLoadKernelSymbols(PUVM pUVM, PDBGDIGGERLINUX pThis) 1889 { 1890 if (pThis->fRelKrnlAddr) 1891 return dbgDiggerLinuxLoadKernelSymbolsRelative(pUVM, pThis); 1892 else 1893 return dbgDiggerLinuxLoadKernelSymbolsAbsolute(pUVM, pThis); 1894 } 1667 1895 1668 1896 /** … … 2197 2425 */ 2198 2426 pThis->f64Bit = pThis->AddrLinuxBanner.FlatPtr > UINT32_MAX; 2427 pThis->fRelKrnlAddr = false; 2199 2428 2200 2429 pThis->hCfgDb = NULL;
Note:
See TracChangeset
for help on using the changeset viewer.