VirtualBox

Ignore:
Timestamp:
Dec 31, 2015 12:24:57 AM (9 years ago)
Author:
vboxsync
Message:

IPRT: Implemented reading codeview (NB09,NB11) line numbers (sstSrcModule).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/dbg/dbgmodcodeview.cpp

    r58742 r59231  
    450450
    451451
     452/**
     453 * Adds a string to the g_hDbgModStrCache after sanitizing it.
     454 *
     455 * IPRT only deals with UTF-8 strings, so the string will be forced to UTF-8
     456 * encoding.  Also, codeview generally have length prefixed
     457 *
     458 * @returns String cached copy of the string.
     459 * @param   pch                 The string to copy to the cache.
     460 * @param   cch                 The length of the string.  RTSTR_MAX if zero
     461 *                              terminated.
     462 */
     463static const char *rtDbgModCvAddSanitizedStringToCache(const char *pch, size_t cch)
     464{
     465    /*
     466     * If the string is valid UTF-8 and or the right length, we're good.
     467     * This is usually the case.
     468     */
     469    const char *pszRet;
     470    int rc;
     471    if (cch != RTSTR_MAX)
     472        rc = RTStrValidateEncodingEx(pch, cch, RTSTR_VALIDATE_ENCODING_EXACT_LENGTH);
     473    else
     474        rc = RTStrValidateEncodingEx(pch, cch, 0);
     475    if (RT_SUCCESS(rc))
     476        pszRet = RTStrCacheEnterN(g_hDbgModStrCache, pch, cch);
     477    else
     478    {
     479        /*
     480         * Need to sanitize the string, so make a copy of it.
     481         */
     482        char *pszCopy = (char *)RTMemDupEx(pch, cch, 1);
     483        AssertPtrReturn(pszCopy, NULL);
     484
     485        /* Deal with anyembedded zero chars. */
     486        char *psz = RTStrEnd(pszCopy, cch);
     487        while (psz)
     488        {
     489            *psz = '_';
     490            psz = RTStrEnd(psz, cch - (psz - pszCopy));
     491        }
     492
     493        /* Force valid UTF-8 encoding. */
     494        size_t cchTmp = RTStrPurgeEncoding(pszCopy);
     495        NOREF(cchTmp); Assert(cchTmp == cch);
     496
     497        /* Enter it into the cache and free the temp copy. */
     498        pszRet = RTStrCacheEnterN(g_hDbgModStrCache, pszCopy, cch);
     499        RTMemFree(pszCopy);
     500    }
     501    return pszRet;
     502}
     503
     504
     505/**
     506 * Translates a codeview segment and offset into our segment layout.
     507 *
     508 * @returns
     509 * @param   pThis               .
     510 * @param   piSeg               .
     511 * @param   poff                .
     512 */
     513DECLINLINE(int) rtDbgModCvAdjustSegAndOffset(PRTDBGMODCV pThis, uint32_t *piSeg, uint64_t *poff)
     514{
     515    uint32_t iSeg = *piSeg;
     516    if (iSeg == 0)
     517        iSeg = RTDBGSEGIDX_ABS;
     518    else if (pThis->pSegMap)
     519    {
     520        if (pThis->fHaveDosFrames)
     521        {
     522            if (   iSeg > pThis->pSegMap->Hdr.cSegs
     523                || iSeg == 0)
     524                return VERR_CV_BAD_FORMAT;
     525            if (*poff <= pThis->pSegMap->aDescs[iSeg - 1].cb + pThis->pSegMap->aDescs[iSeg - 1].off)
     526                *poff -= pThis->pSegMap->aDescs[iSeg - 1].off;
     527            else
     528            {
     529                /* Workaround for VGABIOS where _DATA symbols like vgafont8 are
     530                   reported in the VGAROM segment. */
     531                uint64_t uAddrSym = *poff + ((uint32_t)pThis->pSegMap->aDescs[iSeg - 1].iFrame << 4);
     532                uint16_t j = pThis->pSegMap->Hdr.cSegs;
     533                while (j-- > 0)
     534                {
     535                    uint64_t uAddrFirst = (uint64_t)pThis->pSegMap->aDescs[j].off
     536                                        + ((uint32_t)pThis->pSegMap->aDescs[j].iFrame << 4);
     537                    if (uAddrSym - uAddrFirst < pThis->pSegMap->aDescs[j].cb)
     538                    {
     539                        Log(("CV addr fix: %04x:%08x -> %04x:%08x\n", iSeg, *poff, j + 1, uAddrSym - uAddrFirst));
     540                        *poff  = uAddrSym - uAddrFirst;
     541                        iSeg = j + 1;
     542                        break;
     543                    }
     544                }
     545                if (j == UINT16_MAX)
     546                    return VERR_CV_BAD_FORMAT;
     547            }
     548        }
     549        else
     550        {
     551            if (   iSeg > pThis->pSegMap->Hdr.cSegs
     552                || iSeg == 0
     553                || *poff > pThis->pSegMap->aDescs[iSeg - 1].cb)
     554                return VERR_CV_BAD_FORMAT;
     555            *poff += pThis->pSegMap->aDescs[iSeg - 1].off;
     556        }
     557        if (pThis->pSegMap->aDescs[iSeg - 1].fFlags & RTCVSEGMAPDESC_F_ABS)
     558            iSeg = RTDBGSEGIDX_ABS;
     559        else
     560            iSeg = pThis->pSegMap->aDescs[iSeg - 1].iGroup;
     561    }
     562    *piSeg = iSeg;
     563    return VINF_SUCCESS;
     564}
     565
    452566
    453567/**
     
    466580                               uint32_t cchName, uint32_t fFlags, uint32_t cbSym)
    467581{
    468     const char *pszName = RTStrCacheEnterN(g_hDbgModStrCache, pchName, cchName);
    469     if (!pszName)
    470         return VERR_NO_STR_MEMORY;
     582    const char *pszName = rtDbgModCvAddSanitizedStringToCache(pchName, cchName);
     583    int rc;
     584    if (pszName)
     585    {
    471586#if 1
    472     Log2(("CV Sym: %04x:%08x %.*s\n", iSeg, off, cchName, pchName));
    473     if (iSeg == 0)
    474         iSeg = RTDBGSEGIDX_ABS;
    475     else if (pThis->pSegMap)
    476     {
    477         if (pThis->fHaveDosFrames)
    478         {
    479             if (   iSeg > pThis->pSegMap->Hdr.cSegs
    480                 || iSeg == 0)
    481             {
    482                 Log(("Invalid segment index/offset %#06x:%08x for symbol %.*s\n", iSeg, off, cchName, pchName));
    483                 return VERR_CV_BAD_FORMAT;
    484             }
    485             if (off <= pThis->pSegMap->aDescs[iSeg - 1].cb + pThis->pSegMap->aDescs[iSeg - 1].off)
    486                 off -= pThis->pSegMap->aDescs[iSeg - 1].off;
    487             else
    488             {
    489                 /* Workaround for VGABIOS where _DATA symbols like vgafont8 are
    490                    reported in the VGAROM segment. */
    491                 uint64_t uAddrSym = off + ((uint32_t)pThis->pSegMap->aDescs[iSeg - 1].iFrame << 4);
    492                 uint16_t j = pThis->pSegMap->Hdr.cSegs;
    493                 while (j-- > 0)
     587        Log2(("CV Sym: %04x:%08x %.*s\n", iSeg, off, cchName, pchName));
     588        rc = rtDbgModCvAdjustSegAndOffset(pThis, &iSeg, &off);
     589        if (RT_SUCCESS(rc))
     590        {
     591            rc = RTDbgModSymbolAdd(pThis->hCnt, pszName, iSeg, off, cbSym, 0 /*fFlags*/, NULL);
     592
     593            /* Simple duplicate symbol mangling, just to get more details. */
     594            if (rc == VERR_DBG_DUPLICATE_SYMBOL && cchName < _2K)
     595            {
     596                char szTmpName[_2K + 96];
     597                memcpy(szTmpName, pszName, cchName);
     598                szTmpName[cchName] = '_';
     599                for (uint32_t i = 1; i < 32; i++)
    494600                {
    495                     uint64_t uAddrFirst = (uint64_t)pThis->pSegMap->aDescs[j].off
    496                                         + ((uint32_t)pThis->pSegMap->aDescs[j].iFrame << 4);
    497                     if (uAddrSym - uAddrFirst < pThis->pSegMap->aDescs[j].cb)
    498                     {
    499                         Log(("CV addr fix: %04x:%08x -> %04x:%08x\n", iSeg, off, j + 1, uAddrSym - uAddrFirst));
    500                         off  = uAddrSym - uAddrFirst;
    501                         iSeg = j + 1;
     601                    RTStrFormatU32(&szTmpName[cchName + 1], 80, i, 10, 0, 0, 0);
     602                    rc = RTDbgModSymbolAdd(pThis->hCnt, szTmpName, iSeg, off, cbSym, 0 /*fFlags*/, NULL);
     603                    if (rc != VERR_DBG_DUPLICATE_SYMBOL)
    502604                        break;
    503                     }
    504605                }
    505                 if (j == UINT16_MAX)
    506                 {
    507                     Log(("Invalid segment index/offset %#06x:%08x for symbol %.*s [2]\n", iSeg, off, cchName, pchName));
    508                     return VERR_CV_BAD_FORMAT;
    509                 }
    510             }
     606
     607            }
     608
     609            Log(("Symbol: %04x:%08x %.*s [%Rrc]\n", iSeg, off, cchName, pchName, rc));
     610            if (rc == VERR_DBG_ADDRESS_CONFLICT || rc == VERR_DBG_DUPLICATE_SYMBOL)
     611                rc = VINF_SUCCESS;
    511612        }
    512613        else
    513         {
    514             if (   iSeg > pThis->pSegMap->Hdr.cSegs
    515                 || iSeg == 0
    516                 || off > pThis->pSegMap->aDescs[iSeg - 1].cb)
    517             {
    518                 Log(("Invalid segment index/offset %#06x:%08x for symbol %.*s\n", iSeg, off, cchName, pchName));
    519                 return VERR_CV_BAD_FORMAT;
    520             }
    521             off += pThis->pSegMap->aDescs[iSeg - 1].off;
    522         }
    523         if (pThis->pSegMap->aDescs[iSeg - 1].fFlags & RTCVSEGMAPDESC_F_ABS)
    524             iSeg = RTDBGSEGIDX_ABS;
    525         else
    526             iSeg = pThis->pSegMap->aDescs[iSeg - 1].iGroup;
    527     }
    528 
    529     int rc = RTDbgModSymbolAdd(pThis->hCnt, pszName, iSeg, off, cbSym, 0 /*fFlags*/, NULL);
    530 
    531     /* Simple duplicate symbol mangling, just to get more details. */
    532     if (rc == VERR_DBG_DUPLICATE_SYMBOL && cchName < _2K)
    533     {
    534         char szTmpName[_2K + 96];
    535         memcpy(szTmpName, pszName, cchName);
    536         szTmpName[cchName] = '_';
    537         for (uint32_t i = 1; i < 32; i++)
    538         {
    539             RTStrFormatU32(&szTmpName[cchName + 1], 80, i, 10, 0, 0, 0);
    540             pszName = RTStrCacheEnterN(g_hDbgModStrCache, szTmpName, cchName + 1 + 1 + (i >= 10));
    541             rc = RTDbgModSymbolAdd(pThis->hCnt, pszName, iSeg, off, cbSym, 0 /*fFlags*/, NULL);
    542             if (rc != VERR_DBG_DUPLICATE_SYMBOL)
    543                 break;
    544         }
    545 
    546     }
    547 
    548     Log(("Symbol: %04x:%08x %.*s [%Rrc]\n", iSeg, off, cchName, pchName, rc));
    549     if (rc == VERR_DBG_ADDRESS_CONFLICT || rc == VERR_DBG_DUPLICATE_SYMBOL)
     614            Log(("Invalid segment index/offset %#06x:%08x for symbol %.*s\n", iSeg, off, cchName, pchName));
     615
     616#else
     617        Log(("Symbol: %04x:%08x %.*s\n", iSeg, off, cchName, pchName));
    550618        rc = VINF_SUCCESS;
    551     RTStrCacheRelease(g_hDbgModStrCache, pszName);
     619#endif
     620        RTStrCacheRelease(g_hDbgModStrCache, pszName);
     621    }
     622    else
     623        rc = VERR_NO_STR_MEMORY;
    552624    return rc;
    553 #else
    554     Log(("Symbol: %04x:%08x %.*s\n", iSeg, off, cchName, pchName));
    555     return VINF_SUCCESS;
    556 #endif
    557625}
    558626
     
    834902        return rtDbgModCvSsProcessV8SymTab(pThis, (uint8_t const *)pvSubSect + 4, cbSubSect - 4, 0);
    835903    return rtDbgModCvSsProcessV4PlusSymTab(pThis, (uint8_t const *)pvSubSect + 4, cbSubSect - 4, 0);
     904}
     905
     906
     907/** @callback_method_impl{FNDBGMODCVSUBSECTCALLBACK,
     908 * Parses kCvSst_SrcModule adding line numbers it finds to the container.}
     909 */
     910static DECLCALLBACK(int)
     911rtDbgModCvSs_SrcModule(PRTDBGMODCV pThis, void const *pvSubSect, size_t cbSubSect, PCRTCVDIRENT32 pDirEnt)
     912{
     913    Log(("rtDbgModCvSs_SrcModule: uCurStyle=%#x\n%.*Rhxd\n", pThis->uCurStyle, cbSubSect, pvSubSect));
     914
     915    /* Check the header. */
     916    PCRTCVSRCMODULE pHdr = (PCRTCVSRCMODULE)pvSubSect;
     917    AssertReturn(cbSubSect >= RT_OFFSETOF(RTCVSRCMODULE, aoffSrcFiles), VERR_CV_BAD_FORMAT);
     918    size_t cbHdr = sizeof(RTCVSRCMODULE)
     919                 + pHdr->cFiles * sizeof(uint32_t)
     920                 + pHdr->cSegs * sizeof(uint32_t) * 2
     921                 + pHdr->cSegs * sizeof(uint16_t);
     922    Log2(("RTDbgModCv: SrcModule: cFiles=%u cSegs=%u\n", pHdr->cFiles, pHdr->cFiles));
     923    RTDBGMODCV_CHECK_RET_BF(cbSubSect >= cbHdr, ("cbSubSect=%#x cbHdr=%zx\n", cbSubSect, cbHdr));
     924    if (LogIs2Enabled())
     925    {
     926        for (uint32_t i = 0; i < pHdr->cFiles; i++)
     927            Log2(("RTDbgModCv:   source file #%u: %#x\n", i, pHdr->aoffSrcFiles[i]));
     928        PCRTCVSRCRANGE  paSegRanges = (PCRTCVSRCRANGE)&pHdr->aoffSrcFiles[pHdr->cFiles];
     929        uint16_t const *paidxSegs   = (uint16_t const *)&paSegRanges[pHdr->cSegs];
     930        for (uint32_t i = 0; i < pHdr->cSegs; i++)
     931            Log2(("RTDbgModCv:   seg #%u: %#010x-%#010x\n", paidxSegs[i], paSegRanges[i].offStart, paSegRanges[i].offEnd));
     932    }
     933
     934    /*
     935     * Work over the source files.
     936     */
     937    for (uint32_t i = 0; i < pHdr->cFiles; i++)
     938    {
     939        uint32_t const  offSrcFile  = pHdr->aoffSrcFiles[i];
     940        RTDBGMODCV_CHECK_RET_BF(cbSubSect - RT_OFFSETOF(RTCVSRCFILE, aoffSrcLines) >= offSrcFile,
     941                                ("cbSubSect=%#x (- %#x) aoffSrcFiles[%u]=%#x\n",
     942                                 cbSubSect, RT_OFFSETOF(RTCVSRCFILE, aoffSrcLines), i, offSrcFile));
     943        PCRTCVSRCFILE   pSrcFile    = (PCRTCVSRCFILE)((uint8_t const *)pvSubSect + offSrcFile);
     944        size_t         cbSrcFileHdr = RT_OFFSETOF(RTCVSRCFILE, aoffSrcLines[pSrcFile->cSegs])
     945                                    + sizeof(RTCVSRCRANGE) * pSrcFile->cSegs
     946                                    + sizeof(uint8_t);
     947        RTDBGMODCV_CHECK_RET_BF(cbSubSect >= offSrcFile + cbSrcFileHdr && cbSubSect > cbSrcFileHdr,
     948                                ("cbSubSect=%#x aoffSrcFiles[%u]=%#x cbSrcFileHdr=%#x\n", cbSubSect, offSrcFile, i, cbSrcFileHdr));
     949        PCRTCVSRCRANGE  paSegRanges = (PCRTCVSRCRANGE)&pSrcFile->aoffSrcLines[pSrcFile->cSegs];
     950        uint8_t const  *pcchName    = (uint8_t const *)&paSegRanges[pSrcFile->cSegs]; /** @todo TIS NB09 docs say 16-bit length... */
     951        const char     *pchName     = (const char *)(pcchName + 1);
     952        RTDBGMODCV_CHECK_RET_BF(cbSubSect >= offSrcFile + cbSrcFileHdr + *pcchName,
     953                                ("cbSubSect=%#x offSrcFile=%#x cbSubSect=%#x *pcchName=%#x\n",
     954                                 cbSubSect, offSrcFile, cbSubSect, *pcchName));
     955        Log2(("RTDbgModCv:   source file #%u/%#x: cSegs=%#x '%.*s'\n", i, offSrcFile, pSrcFile->cSegs, *pcchName, pchName));
     956        const char *pszName = rtDbgModCvAddSanitizedStringToCache(pchName, *pcchName);
     957
     958        /*
     959         * Work the segments this source file contributes code to.
     960         */
     961        for (uint32_t iSeg = 0; iSeg < pSrcFile->cSegs; iSeg++)
     962        {
     963            uint32_t const  offSrcLine  = pSrcFile->aoffSrcLines[iSeg];
     964            RTDBGMODCV_CHECK_RET_BF(cbSubSect - RT_OFFSETOF(RTCVSRCLINE, aoffLines) >= offSrcLine,
     965                                    ("cbSubSect=%#x (- %#x) aoffSrcFiles[%u]=%#x\n",
     966                                     cbSubSect, RT_OFFSETOF(RTCVSRCLINE, aoffLines), iSeg, offSrcLine));
     967            PCRTCVSRCLINE   pSrcLine    = (PCRTCVSRCLINE)((uint8_t const *)pvSubSect + offSrcLine);
     968            size_t          cbSrcLine   = RT_OFFSETOF(RTCVSRCLINE, aoffLines[pSrcLine->cPairs])
     969                                        + pSrcLine->cPairs * sizeof(uint16_t);
     970            RTDBGMODCV_CHECK_RET_BF(cbSubSect >= offSrcLine + cbSrcLine,
     971                                    ("cbSubSect=%#x aoffSrcFiles[%u]=%#x cbSrcLine=%#x\n",
     972                                     cbSubSect, iSeg, offSrcLine, cbSrcLine));
     973            uint16_t const *paiLines    = (uint16_t const *)&pSrcLine->aoffLines[pSrcLine->cPairs];
     974            Log2(("RTDbgModCv:     seg #%u, %u pairs (off %#x)\n", pSrcLine->idxSeg, pSrcLine->cPairs, offSrcLine));
     975            for (uint32_t iPair = 0; iPair < pSrcLine->cPairs; iPair++)
     976            {
     977
     978                uint32_t idxSeg = pSrcLine->idxSeg;
     979                uint64_t off    = pSrcLine->aoffLines[iPair];
     980                int rc = rtDbgModCvAdjustSegAndOffset(pThis, &idxSeg, &off);
     981                if (RT_SUCCESS(rc))
     982                    rc = RTDbgModLineAdd(pThis->hCnt, pszName, paiLines[iPair], idxSeg, off, NULL);
     983                if (RT_SUCCESS(rc))
     984                    Log3(("RTDbgModCv:       %#x:%#010llx  %0u\n", idxSeg, off, paiLines[iPair]));
     985                /* Note! Wlink produces the sstSrcModule subsections from LINNUM records, however the
     986                         CVGenLines() function assumes there is only one segment contributing to the
     987                         line numbers.  So, when we do assembly that jumps between segments, it emits
     988                         the wrong addresses for some line numbers and we end up here, typically with
     989                         VERR_DBG_ADDRESS_CONFLICT. */
     990                else
     991                    Log(( "RTDbgModCv:       %#x:%#010llx  %0u - rc=%Rrc!! (org: idxSeg=%#x off=%#x)\n",
     992                          idxSeg, off, paiLines[iPair], rc, pSrcLine->idxSeg, pSrcLine->aoffLines[iPair]));
     993            }
     994        }
     995    }
     996
     997    return VINF_SUCCESS;
    836998}
    837999
     
    10991261                else
    11001262                    RTStrPrintf(szName, sizeof(szName), "Seg%02u", iSeg);
    1101                 Log(("CV: %#010x LB %#010x %s uRVA=%#010x iBest=%u cOverlaps=%u\n",
    1102                      uBestAddr, paDescs[iBest].cb, szName, uBestAddr - uImageBase, iBest, cOverlaps));
    1103                 rc = RTDbgModSegmentAdd(pThis->hCnt, uBestAddr - uImageBase, paDescs[iBest].cb, pszName, 0 /*fFlags*/, NULL);
     1263                RTDBGSEGIDX idxDbgSeg = NIL_RTDBGSEGIDX;
     1264                rc = RTDbgModSegmentAdd(pThis->hCnt, uBestAddr - uImageBase, paDescs[iBest].cb, pszName, 0 /*fFlags*/, &idxDbgSeg);
     1265                Log(("CV: %#010x LB %#010x %s uRVA=%#010x iBest=%u cOverlaps=%u [idxDbgSeg=%#x iSeg=%#x]\n",
     1266                     uBestAddr, paDescs[iBest].cb, szName, uBestAddr - uImageBase, iBest, cOverlaps, idxDbgSeg, idxDbgSeg));
    11041267
    11051268                /* Update translations. */
     
    15441707            case kCvSst_OldSrcLnSeg:
    15451708            case kCvSst_OldSrcLines3:
     1709                /** @todo implement more. */
     1710                break;
    15461711
    15471712            case kCvSst_Types:
    15481713            case kCvSst_Public:
    15491714            case kCvSst_SrcLnSeg:
     1715                /** @todo implement more. */
     1716                break;
    15501717            case kCvSst_SrcModule:
     1718                pfnCallback = rtDbgModCvSs_SrcModule;
     1719                break;
    15511720            case kCvSst_Libraries:
    15521721            case kCvSst_GlobalTypes:
Note: See TracChangeset for help on using the changeset viewer.

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