Пример #1
0
// Can't refer to the types in sospriv.h because it drags in windows.h
void StressLog::EnumerateStressMsgs(/*STRESSMSGCALLBACK*/void* smcbWrapper, /*ENDTHREADLOGCALLBACK*/void* etcbWrapper, void *token)
{
    STRESSMSGCALLBACK smcb = (STRESSMSGCALLBACK)smcbWrapper;
    ENDTHREADLOGCALLBACK etcb = (ENDTHREADLOGCALLBACK) etcbWrapper;
    void *argsCopy[StressMsg::maxArgCnt];

    for (;;) 
    {
        ThreadStressLog* latestLog = this->FindLatestThreadLog();

        if (latestLog == 0)
        {
            break;
        }
        StressMsg* latestMsg = latestLog->readPtr;
        if (latestMsg->formatOffset != 0 && !latestLog->CompletedDump()) 
        {
            char format[256];
            TADDR taFmt = (latestMsg->formatOffset) + (TADDR)(this->moduleOffset);
            HRESULT hr = DacReadAll(taFmt, format, _countof(format), false);
            if (hr != S_OK) 
                strcpy_s(format, _countof(format), "Could not read address of format string");

            double deltaTime = ((double) (latestMsg->timeStamp - this->startTimeStamp)) / this->tickFrequency;

            // Pass a copy of the args to the callback to avoid foreign code overwriting the stress log 
            // entries (this was the case for %s arguments)
            memcpy_s(argsCopy, sizeof(argsCopy), latestMsg->args, (latestMsg->numberOfArgs)*sizeof(void*));
            if (!smcb(latestLog->threadId, deltaTime, latestMsg->facility, format, argsCopy, token))
                break;
        }

        latestLog->readPtr = latestLog->AdvanceRead();
        if (latestLog->CompletedDump())
        {
            latestLog->readPtr = NULL;
            if (!etcb(latestLog->threadId, token))
                break;
        }
    }
}
Пример #2
0
PVOID
DacInstantiateClassByVTable(TADDR addr, ULONG32 minSize, bool throwEx)
{
#ifdef _PREFIX_

    // Dac accesses are not interesting for PREfix and cause alot of PREfix noise
    // so we just return the unmodified pointer for our PREFIX builds
    return (PVOID)addr;

#else // !_PREFIX_

    if (!g_dacImpl)
    {
        DacError(E_UNEXPECTED);
        UNREACHABLE();
    }

    // Preserve special pointer values.
    if (!addr || addr == (TADDR)-1)
    {
        return (PVOID)addr;
    }
    
    // Do not attempt to allocate more than 64megs for one object instance.  While we should
    // never even come close to this size, in cases of heap corruption or bogus data passed
    // into the dac, we can allocate huge amounts of data if we are unlucky.  This santiy
    // checks the size to ensure we don't allocate gigs of data.
    if (minSize > 0x4000000)
    {
        if (throwEx)
        {
            DacError(E_OUTOFMEMORY);
        }
        return NULL;
    }

    //
    // Check the cache for an existing VPTR instance.
    // If there is an instance we assume that it's
    // the right object.
    //

    DAC_INSTANCE* inst = g_dacImpl->m_instances.Find(addr);
    DAC_INSTANCE* oldInst = NULL;
    if (inst)
    {
        // If the existing instance is a VPTR we can
        // reuse it, otherwise we need to promote.
        if (inst->usage == DAC_VPTR)
        {
            // Sanity check that the object we're returning is big enough to fill the PTR type it's being
            // accessed with.  For more information, see the similar check below for the case when the 
            // object isn't already cached
            _ASSERTE_MSG(inst->size >= minSize, "DAC coding error: Attempt to instantiate a VPTR from an object that is too small");

            return inst + 1;
        }
        else
        {
            // Existing instance is not a match and must
            // be superseded.
            // Promote the new instance into the hash
            // in place of the old, but keep the
            // old instance around in case code still
            // has a pointer to it. But ensure that we can
            // create the larger instance and add it to the
            // hash table before removing the old one.
            oldInst = inst;
        }
    }

    HRESULT status;
    TADDR vtAddr;
    ULONG32 size;
    PVOID hostVtPtr;

    // Read the vtable pointer to get the actual
    // implementation class identity.
    if ((status = DacReadAll(addr, &vtAddr, sizeof(vtAddr), throwEx)) != S_OK)
    {
        return NULL;
    }

    //
    // Instantiate the right class, using the vtable as
    // class identity.
    //

#define VPTR_CLASS(name)                       \
    if (vtAddr == g_dacImpl->m_globalBase +    \
        g_dacGlobals.name##__vtAddr)           \
    {                                          \
        size = sizeof(name);                   \
        hostVtPtr = g_dacHostVtPtrs.name;      \
    }                                          \
    else
#define VPTR_MULTI_CLASS(name, keyBase)        \
    if (vtAddr == g_dacImpl->m_globalBase +    \
        g_dacGlobals.name##__##keyBase##__mvtAddr) \
    {                                          \
        size = sizeof(name);                   \
        hostVtPtr = g_dacHostVtPtrs.name##__##keyBase; \
    }                                          \
    else
#include <vptr_list.h>
#undef VPTR_CLASS
#undef VPTR_MULTI_CLASS

    {
        // Can't identify the vtable pointer.
        if (throwEx)
        {
            _ASSERTE_MSG(false,"DAC coding error: Unrecognized vtable pointer in VPTR marshalling code");
            DacError(E_INVALIDARG);
        }
        return NULL;
    }

    // Sanity check that the object we're returning is big enough to fill the PTR type it's being
    // accessed with.
    // If this is not true, it means the type being marshalled isn't a sub-type (or the same type)
    // as the PTR type it's being used as.  For example, trying to marshal an instance of a SystemDomain 
    // object into a PTR_AppDomain will cause this ASSERT to fire (because both SystemDomain and AppDomain
    // derived from BaseDomain, and SystemDomain is smaller than AppDomain).
    _ASSERTE_MSG(size >= minSize, "DAC coding error: Attempt to instantiate a VPTR from an object that is too small");

    inst = g_dacImpl->m_instances.Alloc(addr, size, DAC_VPTR);
    if (!inst)
    {
        DacError(E_OUTOFMEMORY);
        UNREACHABLE();
    }

    // Copy the object contents into the host instance.  Note that this assumes the host and target
    // have the same exact layout.  Specifically, it assumes the host and target vtable pointers are
    // the same size.
    if ((status = DacReadAll(addr, inst + 1, size, false)) != S_OK)
    {
        g_dacImpl->m_instances.ReturnAlloc(inst);
        if (throwEx)
        {
            DacError(status);
        }
        return NULL;
    }

    // We now have a proper target object with a target
    // vtable.  We need to patch the vtable to the appropriate
    // host vtable so that the virtual functions can be
    // called in the host process.
    *(PVOID*)(inst + 1) = hostVtPtr;

    if (!g_dacImpl->m_instances.Add(inst))
    {
        g_dacImpl->m_instances.ReturnAlloc(inst);
        DacError(E_OUTOFMEMORY);
        UNREACHABLE();        
    }

    if (oldInst)
    {
        g_dacImpl->m_instances.Supersede(oldInst);
    }
    return inst + 1;

#endif // !_PREFIX_
}
Пример #3
0
PVOID
DacInstantiateTypeByAddressHelper(TADDR addr, ULONG32 size, bool throwEx, bool fReport)
{
#ifdef _PREFIX_

    // Dac accesses are not interesting for PREfix and cause alot of PREfix noise
    // so we just return the unmodified pointer for our PREFIX builds
    return (PVOID)addr;

#else // !_PREFIX_

    if (!g_dacImpl)
    {
        DacError(E_UNEXPECTED);
        UNREACHABLE();
    }

    // Preserve special pointer values.
    if (!addr || addr == (TADDR)-1)
    {
        return (PVOID)addr;
    }

    // DacInstanceManager::Alloc will assert (with a non-obvious message) on 0-size instances. 
    // Fail sooner and more obviously here.
    _ASSERTE_MSG( size > 0, "DAC coding error: instance size cannot be 0" );
    
    // Do not attempt to allocate more than 64megs for one object instance.  While we should
    // never even come close to this size, in cases of heap corruption or bogus data passed
    // into the dac, we can allocate huge amounts of data if we are unlucky.  This santiy
    // checks the size to ensure we don't allocate gigs of data.
    if (size > 0x4000000)
    {
        if (throwEx)
        {
            DacError(E_OUTOFMEMORY);
        }
        return NULL;
    }

    //
    // Check the cache for an existing DPTR instance.
    // It's possible that a previous access may have been
    // smaller than the current access, so we have to
    // allow an existing instance to be superseded.
    //

    DAC_INSTANCE* inst = g_dacImpl->m_instances.Find(addr);
    DAC_INSTANCE* oldInst = NULL;
    if (inst)
    {
        // If the existing instance is large enough we
        // can reuse it, otherwise we need to promote.
        // We cannot promote a VPTR as the VPTR data
        // has been updated with a host vtable and we
        // don't want to lose that.  This shouldn't
        // happen anyway.
        if (inst->size >= size)
        {
            return inst + 1;
        }
        else
        {
            // Existing instance is too small and must
            // be superseded.
            if (inst->usage == DAC_VPTR)
            {
                // The same address has already been marshalled as a VPTR, now we're trying to marshal as a 
                // DPTR.  This is not allowed.
                _ASSERTE_MSG(false, "DAC coding error: DPTR/VPTR usage conflict");
                DacError(E_INVALIDARG);
                UNREACHABLE();
            }

            // Promote the larger instance into the hash
            // in place of the smaller, but keep the
            // smaller instance around in case code still
            // has a pointer to it. But ensure that we can
            // create the larger instance and add it to the
            // hash table before removing the old one.
            oldInst = inst;
        }
    }

    inst = g_dacImpl->m_instances.Alloc(addr, size, DAC_DPTR);
    if (!inst)
    {
        DacError(E_OUTOFMEMORY);
        UNREACHABLE();
    }

    if (fReport == false)
    {
        // mark the bit if necessary
        inst->noReport = 1;
    }
    else
    {
        // clear the bit
        inst->noReport = 0;
    }
    HRESULT status = DacReadAll(addr, inst + 1, size, false);
    if (status != S_OK)
    {
        g_dacImpl->m_instances.ReturnAlloc(inst);
        if (throwEx)
        {
            DacError(status);
        }
        return NULL;
    }

    if (!g_dacImpl->m_instances.Add(inst))
    {
        g_dacImpl->m_instances.ReturnAlloc(inst);
        DacError(E_OUTOFMEMORY);
        UNREACHABLE();        
    }

    if (oldInst)
    {
        g_dacImpl->m_instances.Supersede(oldInst);
    }

    return inst + 1;

#endif // !_PREFIX_
}
Пример #4
0
static BOOL DacReadAllAdapter(PVOID address, PVOID buffer, SIZE_T size)
{
    HRESULT hr = DacReadAll((TADDR)address, (PVOID)buffer, size, false);
    return SUCCEEDED(hr);
}