VirtualBox

Changeset 64359 in vbox for trunk/src/VBox/Debugger


Ignore:
Timestamp:
Oct 21, 2016 2:14:24 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
111462
Message:

Dbugger/Digger/Linux: Add support for relative offsets to the kernel symbol loading existing since Linux 4.6 and being used in recent distributions

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGPlugInLinux.cpp

    r63567 r64359  
    9696    /** Set if 64-bit, clear if 32-bit.  */
    9797    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;
    98104
    99105    /** The address of the linux banner.
     
    212218
    213219static 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 */
     229DECLINLINE(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}
    214250
    215251/**
     
    11381174    pThis->AddrKernelNames = *pAddrKernelNames;
    11391175    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);
    11411189
    11421190    Log(("dbgDiggerLinuxFoundStartOfNames: AddrKernelAddresses=%RGv\n"
     
    11871235
    11881236        /*
    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.
    11901239         *
    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.
    11951247         *
    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:
    11981249         *
    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.
    12021251         *
    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.
    12051278         */
    12061279        if (pThis->f64Bit)
     
    12151288                        && pb[0] >= LNX_MIN_KALLSYMS_ENC_LENGTH)
    12161289                    {
     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
    12171318                        if (   (i <= 0 || LNX64_VALID_ADDRESS(uBuf.au64[i - 1]))
    12181319                            && (i <= 1 || LNX64_VALID_ADDRESS(uBuf.au64[i - 2]))
     
    12351336                        && pb[0] >= LNX_MIN_KALLSYMS_ENC_LENGTH)
    12361337                    {
     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
    12371355                        if (   (i <= 0 || LNX32_VALID_ADDRESS(uBuf.au32[i - 1]))
    12381356                            && (i <= 1 || LNX32_VALID_ADDRESS(uBuf.au32[i - 2]))
     
    14681586
    14691587/**
    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()).
    14711590 *
    14721591 * @returns VBox status code.
    14731592 * @param   pUVM                The user mode VM handle.
    14741593 * @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 */
     1599static 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);
    14841604    if (RT_SUCCESS(rc))
    14851605    {
    1486         uint8_t *pbNames = (uint8_t *)RTMemAllocZ(pThis->cbKernelNames);
    1487         rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelNames, pbNames, pThis->cbKernelNames);
     1606        char *pszzTokens = (char *)RTMemAllocZ(pThis->cbKernelTokenTable);
     1607        rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenTable, pszzTokens, pThis->cbKernelTokenTable);
    14881608        if (RT_SUCCESS(rc))
    14891609        {
    1490             char *pszzTokens = (char *)RTMemAllocZ(pThis->cbKernelTokenTable);
    1491             rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->AddrKernelTokenTable, 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));
    14921612            if (RT_SUCCESS(rc))
    14931613            {
    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*/);
    14961619                if (RT_SUCCESS(rc))
    14971620                {
     1621                    rc = RTDbgModSetTag(hMod, DIG_LNX_MOD_TAG); AssertRC(rc);
     1622                    rc = VINF_SUCCESS;
     1623
    14981624                    /*
    1499                      * Figure out the kernel start and end.
     1625                     * Enumerate the symbols.
    15001626                     */
    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))
    15051630                    {
    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))
    15571633                        {
    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))
    15601636                            {
    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)
    15631640                                {
    1564                                     char     szSymbol[4096];
    1565                                     uint32_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))
    15671644                                    {
    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)
    15711674                                        {
    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;
    15771677                                        }
    15781678                                        else
    1579                                         {
    1580                                             rc = VERR_INVALID_UTF8_ENCODING;
    1581                                             break;
    1582                                         }
     1679                                            Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n", szSymbol, rc));
    15831680                                    }
    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_RANGE
    1599                                                 || rc == VERR_DBG_INVALID_RVA
    1600                                                 || rc == VERR_DBG_ADDRESS_CONFLICT
    1601                                                 || rc == VERR_DBG_DUPLICATE_SYMBOL)
    1602                                             {
    1603                                                 Log2(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc (ignored)\n", szSymbol, rc));
    1604                                                 rc = VINF_SUCCESS;
    1605                                             }
    1606                                             else
    1607                                                 Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModSymbolAdd(,%s,) failed %Rrc\n", szSymbol, rc));
    1608                                         }
    1609                                     }
    1610                                 }
    1611                                 else
    1612                                 {
    1613                                     rc = VERR_END_OF_STRING;
    1614                                     Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbName=%#x cbKernelNames=%#x\n",
    1615                                          offName, cLeft, cbName, pThis->cbKernelNames));
    16161681                                }
    16171682                            }
     
    16191684                            {
    16201685                                rc = VERR_END_OF_STRING;
    1621                                 Log(("dbgDiggerLinuxLoadKernelSymbols: offName=%#x cLeft=%#x cbKernelNames=%#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));
    16231688                            }
    16241689                        }
    1625 
    1626                         /*
    1627                          * Link the module into the address space.
    1628                          */
    1629                         if (RT_SUCCESS(rc))
     1690                        else
    16301691                        {
    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));
    16371695                        }
     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);
    16381706                        else
    1639                             Log(("dbgDiggerLinuxLoadKernelSymbols: Failed: %Rrc\n", rc));
    1640                         RTDbgModRelease(hMod);
     1707                            rc = VERR_INTERNAL_ERROR;
     1708                        RTDbgAsRelease(hAs);
    16411709                    }
    16421710                    else
    1643                         Log(("dbgDiggerLinuxLoadKernelSymbols: RTDbgModCreate failed: %Rrc\n", rc));
     1711                        Log(("dbgDiggerLinuxLoadKernelSymbols: Failed: %Rrc\n", rc));
     1712                    RTDbgModRelease(hMod);
    16441713                }
    16451714                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));
    16491716            }
    16501717            else
    1651                 Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token table at %RGv failed: %Rrc\n",
    1652                      pThis->AddrKernelTokenTable.FlatPtr, rc));
    1653             RTMemFree(pszzTokens);
     1718                Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token index at %RGv failed: %Rrc\n",
     1719                     pThis->AddrKernelTokenIndex.FlatPtr, rc));
     1720            RTMemFree(paoffTokens);
    16541721        }
    16551722        else
    1656             Log(("dbgDiggerLinuxLoadKernelSymbols: Reading encoded names at %RGv failed: %Rrc\n",
    1657                  pThis->AddrKernelNames.FlatPtr, rc));
    1658         RTMemFree(pbNames);
     1723            Log(("dbgDiggerLinuxLoadKernelSymbols: Reading token table at %RGv failed: %Rrc\n",
     1724                 pThis->AddrKernelTokenTable.FlatPtr, rc));
     1725        RTMemFree(pszzTokens);
    16591726    }
    16601727    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 */
     1742static 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",
    16621808             pThis->AddrKernelAddresses.FlatPtr, rc));
    16631809    RTMemFree(pvAddresses);
     1810
    16641811    return rc;
    16651812}
    16661813
     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 */
     1822static 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 */
     1888static int dbgDiggerLinuxLoadKernelSymbols(PUVM pUVM, PDBGDIGGERLINUX pThis)
     1889{
     1890    if (pThis->fRelKrnlAddr)
     1891        return dbgDiggerLinuxLoadKernelSymbolsRelative(pUVM, pThis);
     1892    else
     1893        return dbgDiggerLinuxLoadKernelSymbolsAbsolute(pUVM, pThis);
     1894}
    16671895
    16681896/**
     
    21972425     */
    21982426    pThis->f64Bit = pThis->AddrLinuxBanner.FlatPtr > UINT32_MAX;
     2427    pThis->fRelKrnlAddr = false;
    21992428
    22002429    pThis->hCfgDb = NULL;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette