VirtualBox

Ignore:
Timestamp:
Oct 29, 2018 8:58:56 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
126241
Message:

IPRT/dbg: Fixed a DWARF abbreviation cache bug, was calculating the wrong offSpec values for all but the first compile unit. Implemented LX debug info enumeration, making the embedded ELF info loadable (required disabling a RVA alignment optimization). bugref:3897

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/ldr/ldrLX.cpp

    r74664 r75163  
    4545
    4646#include <iprt/formats/lx.h>
     47#include <iprt/formats/pecoff.h>
     48#include <iprt/formats/codeview.h>
     49#include <iprt/formats/elf32.h>
    4750#include "internal/ldr.h"
    4851
     
    220223        return RTErrInfoSetF(pErrInfo, VERR_LDRLX_BAD_LOADER_SECTION,
    221224                             "Object table spans beyond the executable: e32_objcnt=%u", Hdr.e32_objcnt);
     225    if (Hdr.e32_objcnt >= _32K)
     226        return RTErrInfoSetF(pErrInfo, VERR_LDRLX_BAD_LOADER_SECTION, "Too many segments: %#x\n", Hdr.e32_objcnt);
    222227    if (    Hdr.e32_objmap
    223228        &&  (Hdr.e32_objmap < off || Hdr.e32_objmap > offEnd))
     
    267272     */
    268273    size_t cbModLXAndSegments = RT_ALIGN_Z(RT_UOFFSETOF_DYN(KLDRMODLX, aSegments[Hdr.e32_objcnt + 1]), 8);
     274    cbModLXAndSegments += sizeof("segXXXXX") * (Hdr.e32_objcnt + 1);
     275
    269276    pModLX = (PKLDRMODLX)RTMemAlloc(cbModLXAndSegments + Hdr.e32_ldrsize + 2 /*for two extra zeros*/);
    270277    if (!pModLX)
     
    410417     * object alignment. The linker typically uses 64KB alignment,
    411418     * we can easily get away with page alignment in most cases.
    412      */
    413     fCanOptimizeMapping = !(Hdr.e32_mflags & (E32NOINTFIX | E32SYSDLL));
     419     *
     420     * However, this screws up DwARF debug info, let's not do this
     421     * when the purpose is reading debug info.
     422     */
     423    /** @todo Add flag for enabling this optimization. */
     424    fCanOptimizeMapping = !(Hdr.e32_mflags & (E32NOINTFIX | E32SYSDLL))
     425                       && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION));
    414426    NextRVA = 0;
    415427
     
    417429     * Setup the KLDRMOD segment array.
    418430     */
     431    char *pszSegNm = (char *)&pModLX->aSegments[pModLX->cSegments];
    419432    for (i = 0; i < pModLX->cSegments; i++)
    420433    {
     434        /* dummy segment name */
     435        pModLX->aSegments[i].pszName    = pszSegNm;
     436        size_t cchName = RTStrPrintf(pszSegNm, sizeof("segXXXXX"), "seg%u", i);
     437        pszSegNm += cchName + 1;
     438        pModLX->aSegments[i].cchName    = (uint32_t)cchName;
     439
    421440        /* unused */
    422         pModLX->aSegments[i].pszName    = NULL;
    423441        pModLX->aSegments[i].offFile    = -1;
    424442        pModLX->aSegments[i].cbFile     = -1;
     
    449467        else
    450468            pModLX->aSegments[i].cbMapped = pModLX->paObjs[i + 1].o32_base - pModLX->paObjs[i].o32_base;
     469        /** @todo Above probably doesn't work for os2krnl and other images
     470         *        non-sequential virtual address assignments. */
    451471        NextRVA += (uint32_t)pModLX->aSegments[i].cbMapped;
    452472
     
    12581278#endif
    12591279
     1280/** Helper for rtldrLX_EnumDbgInfo. */
     1281static int rtldrLx_EnumDbgInfoHelper(PKLDRMODLX pModLX, PFNRTLDRENUMDBG pfnCallback, void *pvUser,
     1282                                     uint8_t *pbBuf, uint32_t cbRead, uint32_t offDbgInfo, bool *pfReturn)
     1283{
     1284    RTLDRDBGINFO DbgInfo;
     1285    uint32_t     iDbgInfo = 0;
     1286    uint32_t     cbDbgInfo = pModLX->Hdr.e32_debuglen;
     1287
     1288    /*
     1289     * Recent watcom linkers emit PE style IMAGE_DEBUG_MISC for specifying
     1290     * external file with CV info.
     1291     */
     1292    if (cbRead >= sizeof(IMAGE_DEBUG_MISC))
     1293    {
     1294        PCIMAGE_DEBUG_MISC pMisc = (PCIMAGE_DEBUG_MISC)pbBuf;
     1295        if (   pMisc->DataType    == IMAGE_DEBUG_MISC_EXENAME
     1296            && pMisc->Length      <= cbRead
     1297            && pMisc->Length      >= RT_UOFFSETOF(IMAGE_DEBUG_MISC, Data[4])
     1298            && pMisc->Unicode     == 0
     1299            && pMisc->Reserved[0] == 0
     1300            && pMisc->Reserved[1] == 0
     1301            && pMisc->Reserved[2] == 0
     1302            && pMisc->Data[0]     >= 0x20
     1303            && pMisc->Data[0]     <  0x7f
     1304            && pMisc->Data[1]     >= 0x20
     1305            && pMisc->Data[1]     <  0x7f
     1306            && pMisc->Data[2]     >= 0x20
     1307            && pMisc->Data[2]     <  0x7f )
     1308        {
     1309            uint32_t cchMaxName = pMisc->Length - RT_UOFFSETOF(IMAGE_DEBUG_MISC, Data[0]);
     1310            for (uint32_t cchName = 3; cchName < cchMaxName; cchName++)
     1311            {
     1312                char const ch = pMisc->Data[cchName];
     1313                if (ch == 0)
     1314                {
     1315                    DbgInfo.enmType         = RTLDRDBGINFOTYPE_CODEVIEW;
     1316                    DbgInfo.iDbgInfo        = iDbgInfo;
     1317                    DbgInfo.offFile         = offDbgInfo;
     1318                    DbgInfo.LinkAddress     = NIL_RTLDRADDR;
     1319                    DbgInfo.cb              = pMisc->Length;
     1320                    DbgInfo.pszExtFile      = (char *)&pMisc->Data[0];
     1321                    DbgInfo.u.Cv.cbImage    = pModLX->Hdr.e32_mpages * pModLX->Hdr.e32_pagesize;
     1322                    DbgInfo.u.Cv.uTimestamp = 0;
     1323                    DbgInfo.u.Cv.uMajorVer  = 0;
     1324                    DbgInfo.u.Cv.uMinorVer  = 0;
     1325
     1326                    *pfReturn = true;
     1327                    int rc = pfnCallback(&pModLX->Core, &DbgInfo, pvUser);
     1328                    if (rc != VINF_SUCCESS)
     1329                        return rc;
     1330                }
     1331                else if (ch >= 0x30 && ch < 0x7f)
     1332                    continue;
     1333                break;
     1334            }
     1335
     1336            /* Skip it. */
     1337            pbBuf      += pMisc->Length;
     1338            cbRead     -= pMisc->Length;
     1339            offDbgInfo += pMisc->Length;
     1340            cbDbgInfo  -= pMisc->Length;
     1341            iDbgInfo++;
     1342        }
     1343    }
     1344
     1345    /*
     1346     * Look for codeview signature.
     1347     */
     1348    RTCVHDR const *pCvHdr = (RTCVHDR const *)pbBuf;
     1349    if (   cbRead > sizeof(*pCvHdr)
     1350        && pCvHdr->off >= sizeof(*pCvHdr)
     1351        && pCvHdr->off < cbDbgInfo)
     1352    {
     1353        switch (pCvHdr->u32Magic)
     1354        {
     1355            case RTCVHDR_MAGIC_NB11:
     1356            case RTCVHDR_MAGIC_NB09:
     1357            case RTCVHDR_MAGIC_NB08:
     1358            case RTCVHDR_MAGIC_NB07:
     1359            case RTCVHDR_MAGIC_NB06:
     1360            case RTCVHDR_MAGIC_NB05:
     1361            case RTCVHDR_MAGIC_NB04:
     1362            case RTCVHDR_MAGIC_NB02:
     1363            case RTCVHDR_MAGIC_NB01:
     1364            case RTCVHDR_MAGIC_NB00:
     1365                DbgInfo.enmType         = RTLDRDBGINFOTYPE_CODEVIEW;
     1366                DbgInfo.iDbgInfo        = iDbgInfo;
     1367                DbgInfo.offFile         = offDbgInfo;
     1368                DbgInfo.LinkAddress     = NIL_RTLDRADDR;
     1369                DbgInfo.cb              = cbDbgInfo;
     1370                DbgInfo.pszExtFile      = NULL;
     1371                DbgInfo.u.Cv.cbImage    = pModLX->Hdr.e32_mpages * pModLX->Hdr.e32_pagesize;
     1372                DbgInfo.u.Cv.uTimestamp = 0;
     1373                DbgInfo.u.Cv.uMajorVer  = 0;
     1374                DbgInfo.u.Cv.uMinorVer  = 0;
     1375
     1376                *pfReturn = true;
     1377                return pfnCallback(&pModLX->Core, &DbgInfo, pvUser);
     1378        }
     1379    }
     1380
     1381    /*
     1382     * Watcom wraps its DWARF output in an ELF image, so look for and ELF magic.
     1383     */
     1384    Elf32_Ehdr const *pElfHdr = (Elf32_Ehdr const *)pbBuf;
     1385    if (   cbRead >= sizeof(*pElfHdr)
     1386        && pElfHdr->e_ident[EI_MAG0]    == ELFMAG0
     1387        && pElfHdr->e_ident[EI_MAG1]    == ELFMAG1
     1388        && pElfHdr->e_ident[EI_MAG2]    == ELFMAG2
     1389        && pElfHdr->e_ident[EI_MAG3]    == ELFMAG3
     1390        && pElfHdr->e_ident[EI_CLASS]   == ELFCLASS32
     1391        && pElfHdr->e_ident[EI_DATA]    == ELFDATA2LSB
     1392        && pElfHdr->e_ident[EI_VERSION] == EV_CURRENT
     1393        && pElfHdr->e_shentsize         == sizeof(Elf32_Shdr)
     1394        && pElfHdr->e_shnum             >= 2
     1395        && pElfHdr->e_shnum             <  _32K + 10
     1396        && pElfHdr->e_shstrndx          <= pElfHdr->e_shnum
     1397        && pElfHdr->e_shstrndx          >  0
     1398       )
     1399    {
     1400        /** @todo try use pBuf for reading into and try to read more at once. */
     1401        uint32_t const offShdrs = pElfHdr->e_shoff + offDbgInfo;
     1402        uint32_t const cShdrs   = pElfHdr->e_shnum;
     1403        uint32_t const cbShdr   = pElfHdr->e_shentsize;
     1404        int            rc       = VINF_SUCCESS;
     1405
     1406        /* Read the section string table. */
     1407        Elf32_Shdr Shdr;
     1408        int rc2 = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &Shdr, sizeof(Shdr),
     1409                                                offShdrs + pElfHdr->e_shstrndx * cbShdr);
     1410        if (   RT_SUCCESS(rc2)
     1411            && Shdr.sh_offset > 0
     1412            && Shdr.sh_size > 0
     1413            && Shdr.sh_size < _256K
     1414            && Shdr.sh_type == SHT_STRTAB)
     1415        {
     1416            uint32_t const cbStrTab = Shdr.sh_size;
     1417            char * const   pszStrTab = (char *)RTMemTmpAlloc(cbStrTab + 2);
     1418            if (pszStrTab)
     1419            {
     1420                rc2 = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, pszStrTab, Shdr.sh_size, offDbgInfo + Shdr.sh_offset);
     1421                if (RT_SUCCESS(rc2))
     1422                {
     1423                    pszStrTab[cbStrTab] = '\0';
     1424
     1425                    /* Iterate the sections, one by one. */
     1426                    for (uint32_t i = 1; i < cShdrs; i++)
     1427                    {
     1428                        rc = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &Shdr, sizeof(Shdr), offShdrs + i * cbShdr);
     1429                        if (   RT_SUCCESS(rc)
     1430                            && Shdr.sh_name < cbStrTab
     1431                            && strncmp(&pszStrTab[Shdr.sh_name], RT_STR_TUPLE(".debug_")) == 0)
     1432                        {
     1433                            DbgInfo.enmType            = RTLDRDBGINFOTYPE_DWARF;
     1434                            DbgInfo.iDbgInfo           = iDbgInfo;
     1435                            DbgInfo.offFile            = offDbgInfo + Shdr.sh_offset;
     1436                            DbgInfo.LinkAddress        = NIL_RTLDRADDR;
     1437                            DbgInfo.cb                 = Shdr.sh_size;
     1438                            DbgInfo.pszExtFile         = NULL;
     1439                            DbgInfo.u.Dwarf.pszSection = &pszStrTab[Shdr.sh_name];
     1440
     1441                            *pfReturn = true;
     1442                            rc = pfnCallback(&pModLX->Core, &DbgInfo, pvUser);
     1443                            if (rc != VINF_SUCCESS)
     1444                                break;
     1445                            iDbgInfo++;
     1446                        }
     1447                    }
     1448                }
     1449                RTMemTmpFree(pszStrTab);
     1450            }
     1451        }
     1452        return rc;
     1453    }
     1454
     1455    /*
     1456     * Watcom debug info? Don't know how to detect it...
     1457     */
     1458
     1459    return VINF_SUCCESS;
     1460}
     1461
    12601462
    12611463/**
     
    12741476    if (kldrModLXHasDbgInfo(pMod, pvBits))
    12751477        return VINF_SUCCESS;
    1276 #if 0
     1478    PKLDRMODLX pModLX = RT_FROM_MEMBER(pMod, KLDRMODLX, Core);
     1479
    12771480    /*
    12781481     * Read the debug info and look for familiar magics and structures.
    12791482     */
    1280     /** @todo */
    1281 #endif
    1282 
    1283     return VINF_SUCCESS;
     1483    union
     1484    {
     1485        uint8_t             ab[1024];
     1486        IMAGE_DEBUG_MISC    Misc;
     1487        RTCVHDR             CvHdr;
     1488    } uBuf;
     1489
     1490    bool fReturn = false;
     1491
     1492    /* Try the offset without header displacement first. */
     1493    uint32_t cbToRead = RT_MIN(pModLX->Hdr.e32_debuglen, sizeof(uBuf));
     1494    int rc = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &uBuf, cbToRead, pModLX->Hdr.e32_debuginfo);
     1495    if (RT_SUCCESS(rc))
     1496        rc = rtldrLx_EnumDbgInfoHelper(pModLX, pfnCallback, pvUser, &uBuf.ab[0], cbToRead, pModLX->Hdr.e32_debuginfo, &fReturn);
     1497
     1498    /* If that didn't yield anything, try displaying it by the header offset. */
     1499    if (!fReturn && pModLX->offHdr > 0)
     1500    {
     1501        rc = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &uBuf, cbToRead, pModLX->Hdr.e32_debuginfo + pModLX->offHdr);
     1502        if (RT_SUCCESS(rc))
     1503            rc = rtldrLx_EnumDbgInfoHelper(pModLX, pfnCallback, pvUser, &uBuf.ab[0], cbToRead,
     1504                                           pModLX->Hdr.e32_debuginfo + pModLX->offHdr, &fReturn);
     1505    }
     1506    return rc;
    12841507}
    12851508
     
    12911514
    12921515    /*
    1293      * Don't curretnly bother with linkers which doesn't advertise it in the header.
     1516     * Don't currently bother with linkers which doesn't advertise it in the header.
    12941517     */
    12951518    if (    !pModLX->Hdr.e32_debuginfo
     
    27532976{
    27542977    PKLDRMODLX pThis = RT_FROM_MEMBER(pMod, KLDRMODLX, Core);
    2755     if (iDbgInfo == 0)
    2756         return pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvBuf, cb, off);
    2757     return VERR_OUT_OF_RANGE;
     2978    RT_NOREF(iDbgInfo);
     2979    return pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvBuf, cb, off);
    27582980}
    27592981
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