Beispiel #1
0
/** @copydoc RTDBGMODVTDBG::pfnLineAdd */
static DECLCALLBACK(int) rtDbgModContainer_LineAdd(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
                                                   uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal)
{
    PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;

    /*
     * Validate the input address.
     */
    AssertMsgReturn(iSeg < pThis->cSegs,          ("iSeg=%#x cSegs=%#x\n", iSeg, pThis->cSegs),
                    VERR_DBG_INVALID_SEGMENT_INDEX);
    AssertMsgReturn(off < pThis->paSegs[iSeg].cb, ("off=%RTptr cbSeg=%RTptr\n", off, pThis->paSegs[iSeg].cb),
                    VERR_DBG_INVALID_SEGMENT_OFFSET);

    /*
     * Create a new entry.
     */
#ifdef RTDBGMODCNT_WITH_MEM_CACHE
    PRTDBGMODCTNLINE pLine = (PRTDBGMODCTNLINE)RTMemCacheAlloc(pThis->hLineNumAllocator);
#else
    PRTDBGMODCTNLINE pLine = (PRTDBGMODCTNLINE)RTMemAllocZ(sizeof(*pLine));
#endif
    if (!pLine)
        return VERR_NO_MEMORY;
    pLine->AddrCore.Key     = off;
    pLine->OrdinalCore.Key  = pThis->iNextLineOrdinal;
    pLine->uLineNo          = uLineNo;
    pLine->iSeg             = iSeg;
    pLine->pszFile          = RTStrCacheEnterN(g_hDbgModStrCache, pszFile, cchFile);
    int rc;
    if (pLine->pszFile)
    {
        if (RTAvlUIntPtrInsert(&pThis->paSegs[iSeg].LineAddrTree, &pLine->AddrCore))
        {
            if (RTAvlU32Insert(&pThis->LineOrdinalTree, &pLine->OrdinalCore))
            {
                if (piOrdinal)
                    *piOrdinal = pThis->iNextLineOrdinal;
                pThis->iNextLineOrdinal++;
                return VINF_SUCCESS;
            }

            rc = VERR_INTERNAL_ERROR_5;
            RTAvlUIntPtrRemove(&pThis->paSegs[iSeg].LineAddrTree, pLine->AddrCore.Key);
        }

        /* bail out */
        rc = VERR_DBG_ADDRESS_CONFLICT;
        RTStrCacheRelease(g_hDbgModStrCache, pLine->pszFile);
    }
    else
        rc = VERR_NO_MEMORY;
#ifdef RTDBGMODCNT_WITH_MEM_CACHE
    RTMemCacheFree(pThis->hLineNumAllocator, pLine);
#else
    RTMemFree(pLine);
#endif
    return rc;
}
RTDECL(const char *) RTStrCacheEnter(RTSTRCACHE hStrCache, const char *psz)
{
    return RTStrCacheEnterN(hStrCache, psz, strlen(psz));
}
Beispiel #3
0
/** @copydoc RTDBGMODVTDBG::pfnSegmentAdd */
static DECLCALLBACK(int) rtDbgModContainer_SegmentAdd(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
                                                      uint32_t fFlags, PRTDBGSEGIDX piSeg)
{
    PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;

    /*
     * Input validation (the bits the caller cannot do).
     */
    /* Overlapping segments are not yet supported. Will use flags to deal with it if it becomes necessary. */
    RTUINTPTR   uRvaLast    = uRva + RT_MAX(cb, 1) - 1;
    RTUINTPTR   uRvaLastMax = uRvaLast;
    RTDBGSEGIDX iSeg        = pThis->cSegs;
    while (iSeg-- > 0)
    {
        RTUINTPTR uCurRva     = pThis->paSegs[iSeg].off;
        RTUINTPTR uCurRvaLast = uCurRva + RT_MAX(pThis->paSegs[iSeg].cb, 1) - 1;
        if (   uRva      <= uCurRvaLast
            && uRvaLast  >= uCurRva
            && (   /* HACK ALERT! Allow empty segments to share space (bios/watcom, elf). */
                   (cb != 0 && pThis->paSegs[iSeg].cb != 0)
                || (   cb == 0
                    && uRva != uCurRva
                    && uRva != uCurRvaLast)
                || (    pThis->paSegs[iSeg].cb == 0
                    && uCurRva != uRva
                    && uCurRva != uRvaLast)
               )
           )
            AssertMsgFailedReturn(("uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\";\n"
                                   "uRva=%RTptr uRvaLast=%RTptr (cb=%RTptr) \"%s\" iSeg=%#x\n",
                                   uRva, uRvaLast, cb, pszName,
                                   uCurRva, uCurRvaLast, pThis->paSegs[iSeg].cb, pThis->paSegs[iSeg].pszName, iSeg),
                                  VERR_DBG_SEGMENT_INDEX_CONFLICT);
        if (uRvaLastMax < uCurRvaLast)
            uRvaLastMax = uCurRvaLast;
    }
    /* Strict ordered segment addition at the moment. */
    iSeg = pThis->cSegs;
    AssertMsgReturn(!piSeg || *piSeg == NIL_RTDBGSEGIDX || *piSeg == iSeg,
                    ("iSeg=%#x *piSeg=%#x\n", iSeg, *piSeg),
                    VERR_DBG_INVALID_SEGMENT_INDEX);

    /*
     * Add an entry to the segment table, extending it if necessary.
     */
    if (!(iSeg % 8))
    {
        void *pvSegs = RTMemRealloc(pThis->paSegs, sizeof(RTDBGMODCTNSEGMENT) * (iSeg + 8));
        if (!pvSegs)
            return VERR_NO_MEMORY;
        pThis->paSegs = (PRTDBGMODCTNSEGMENT)pvSegs;
    }

    pThis->paSegs[iSeg].SymAddrTree     = NULL;
    pThis->paSegs[iSeg].LineAddrTree    = NULL;
    pThis->paSegs[iSeg].off             = uRva;
    pThis->paSegs[iSeg].cb              = cb;
    pThis->paSegs[iSeg].fFlags          = fFlags;
    pThis->paSegs[iSeg].pszName         = RTStrCacheEnterN(g_hDbgModStrCache, pszName, cchName);
    if (pThis->paSegs[iSeg].pszName)
    {
        if (piSeg)
            *piSeg = iSeg;
        pThis->cSegs++;
        pThis->cb = uRvaLastMax + 1;
        if (!pThis->cb)
            pThis->cb = RTUINTPTR_MAX;
        return VINF_SUCCESS;
    }
    return VERR_NO_MEMORY;
}
Beispiel #4
0
/** @copydoc RTDBGMODVTDBG::pfnSymbolAdd */
static DECLCALLBACK(int) rtDbgModContainer_SymbolAdd(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
                                                     RTDBGSEGIDX iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
                                                     uint32_t *piOrdinal)
{
    PRTDBGMODCTN pThis = (PRTDBGMODCTN)pMod->pvDbgPriv;

    /*
     * Address validation. The other arguments have already been validated.
     */
    AssertMsgReturn(    iSeg == RTDBGSEGIDX_ABS
                    ||  iSeg < pThis->cSegs,
                    ("iSeg=%#x cSegs=%#x\n", iSeg, pThis->cSegs),
                    VERR_DBG_INVALID_SEGMENT_INDEX);
    AssertMsgReturn(    iSeg >= RTDBGSEGIDX_SPECIAL_FIRST
                    ||  off <= pThis->paSegs[iSeg].cb,
                    ("off=%RTptr cb=%RTptr cbSeg=%RTptr\n", off, cb, pThis->paSegs[iSeg].cb),
                    VERR_DBG_INVALID_SEGMENT_OFFSET);

    /* Be a little relaxed wrt to the symbol size. */
    int rc = VINF_SUCCESS;
    if (iSeg != RTDBGSEGIDX_ABS && off + cb > pThis->paSegs[iSeg].cb)
    {
        cb = pThis->paSegs[iSeg].cb - off;
        rc = VINF_DBG_ADJUSTED_SYM_SIZE;
    }

    /*
     * Create a new entry.
     */
    PRTDBGMODCTNSYMBOL pSymbol = (PRTDBGMODCTNSYMBOL)RTMemAllocZ(sizeof(*pSymbol));
    if (!pSymbol)
        return VERR_NO_MEMORY;

    pSymbol->AddrCore.Key       = off;
    pSymbol->AddrCore.KeyLast   = off + (cb ? cb - 1 : 0);
    pSymbol->OrdinalCore.Key    = pThis->iNextSymbolOrdinal;
    pSymbol->iSeg               = iSeg;
    pSymbol->cb                 = cb;
    pSymbol->fFlags             = fFlags;
    pSymbol->NameCore.pszString = RTStrCacheEnterN(g_hDbgModStrCache, pszSymbol, cchSymbol);
    if (pSymbol->NameCore.pszString)
    {
        if (RTStrSpaceInsert(&pThis->Names, &pSymbol->NameCore))
        {
            PAVLRUINTPTRTREE pAddrTree = iSeg == RTDBGSEGIDX_ABS
                                       ? &pThis->AbsAddrTree
                                       : &pThis->paSegs[iSeg].SymAddrTree;
            if (RTAvlrUIntPtrInsert(pAddrTree, &pSymbol->AddrCore))
            {
                if (RTAvlU32Insert(&pThis->SymbolOrdinalTree, &pSymbol->OrdinalCore))
                {
                    if (piOrdinal)
                        *piOrdinal = pThis->iNextSymbolOrdinal;
                    pThis->iNextSymbolOrdinal++;
                    return rc;
                }

                /* bail out */
                rc = VERR_INTERNAL_ERROR_5;
                RTAvlrUIntPtrRemove(pAddrTree, pSymbol->AddrCore.Key);
            }
            else
                rc = VERR_DBG_ADDRESS_CONFLICT;
            RTStrSpaceRemove(&pThis->Names, pSymbol->NameCore.pszString);
        }
        else
            rc = VERR_DBG_DUPLICATE_SYMBOL;
        RTStrCacheRelease(g_hDbgModStrCache, pSymbol->NameCore.pszString);
    }
    else
        rc = VERR_NO_MEMORY;
    RTMemFree(pSymbol);
    return rc;
}
Beispiel #5
0
/**
 * Basic API checks.
 * We'll return if any of these fails.
 */
static void tst1(RTSTRCACHE hStrCache)
{
    const char *psz;

    /* Simple string entering and length. */
    RTTESTI_CHECK_RETV(psz = RTStrCacheEnter(hStrCache, "abcdefgh"));
    RTTESTI_CHECK_RETV(strcmp(psz, "abcdefgh") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("abcdefgh"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    RTTESTI_CHECK_RETV(psz = RTStrCacheEnter(hStrCache, "abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RETV(strcmp(psz, "abcdefghijklmnopqrstuvwxyz") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("abcdefghijklmnopqrstuvwxyz"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    /* Unterminated strings. */
    RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, "0123456789", 3));
    RTTESTI_CHECK_RETV(strcmp(psz, "012") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("012"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, "0123456789abcdefghijklmnopqrstuvwxyz", 16));
    RTTESTI_CHECK_RETV(strcmp(psz, "0123456789abcdef") == 0);
    RTTESTI_CHECK_RETV(RTStrCacheLength(psz) == strlen("0123456789abcdef"));
    RTTESTI_CHECK_RETV(RTStrCacheRelease(hStrCache, psz) == 0);

    /* String referencing. */
    char szTest[4096+16];
    memset(szTest, 'a', sizeof(szTest));
    char szTest2[4096+16];
    memset(szTest2, 'f', sizeof(szTest));
    for (int32_t i = 4096; i > 3; i /= 3)
    {
        void *pv2;
        RTTESTI_CHECK_RETV(psz = RTStrCacheEnterN(hStrCache, szTest, i));
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 2);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 3);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 4);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));
        RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 3);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 4);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 5);
        RTTESTI_CHECK(RTStrCacheRetain(psz) == 6);
        RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 5);
        RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == 4);
        RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz));

        for (uint32_t cRefs = 3;; cRefs--)
        {
            RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz) == cRefs);
            if (cRefs == 0)
                break;
            RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x cRefs=%d\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz, cRefs));
            for (uint32_t j = 0; j < 42; j++)
            {
                const char *psz2;
                RTTESTI_CHECK_RETV(psz2 = RTStrCacheEnterN(hStrCache, szTest2, i));
                RTTESTI_CHECK_RETV(psz2 != psz);
                RTTESTI_CHECK(RTStrCacheRelease(hStrCache, psz2) == 0);
                RTTESTI_CHECK_MSG_RETV((pv2 = ASMMemFirstMismatchingU8(psz, i, 'a')) == NULL && !psz[i], ("i=%#x psz=%p off=%#x cRefs=%d\n", i, psz, (uintptr_t)pv2 - (uintptr_t)psz, cRefs));
            }
        }
    }

    /* Lots of allocations. */
    memset(szTest, 'b', sizeof(szTest));
    memset(szTest2, 'e', sizeof(szTest));
    const char *pszTest1Rets[4096 + 16];
    const char *pszTest2Rets[4096 + 16];
    for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++)
    {
        RTTESTI_CHECK(pszTest1Rets[i] = RTStrCacheEnterN(hStrCache, szTest, i));
        RTTESTI_CHECK(strlen(pszTest1Rets[i]) == i);
        RTTESTI_CHECK(pszTest2Rets[i] = RTStrCacheEnterN(hStrCache, szTest2, i));
        RTTESTI_CHECK(strlen(pszTest2Rets[i]) == i);
    }

    if (RTStrCacheIsRealImpl())
    {
        for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++)
        {
            uint32_t cRefs;
            const char *psz1, *psz2;
            RTTESTI_CHECK((psz1 = RTStrCacheEnterN(hStrCache, szTest,  i)) == pszTest1Rets[i]);
            RTTESTI_CHECK((psz2 = RTStrCacheEnterN(hStrCache, szTest2, i)) == pszTest2Rets[i]);
            RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, psz1)) == 1, ("cRefs=%#x i=%#x\n", cRefs, i));
            RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, psz2)) == 1, ("cRefs=%#x i=%#x\n", cRefs, i));
        }
    }

    for (uint32_t i = 1; i < RT_ELEMENTS(pszTest1Rets); i++)
    {
        uint32_t cRefs;
        RTTESTI_CHECK(strlen(pszTest1Rets[i]) == i);
        RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, pszTest1Rets[i])) == 0, ("cRefs=%#x i=%#x\n", cRefs, i));
        RTTESTI_CHECK(strlen(pszTest2Rets[i]) == i);
        RTTESTI_CHECK_MSG((cRefs = RTStrCacheRelease(hStrCache, pszTest2Rets[i])) == 0, ("cRefs=%#x i=%#x\n", cRefs, i));
    }
}