Example #1
0
    bool Object::VerifyMemberFields(TADDR pMT, TADDR obj, WORD &numInstanceFields)
    {
        DacpMethodTableData vMethTable;
        if (FAILED(vMethTable.Request(g_sos, pMT)))
            return false;

        // Recursively verify the parent (this updates numInstanceFields)
        if (vMethTable.ParentMethodTable)
        {
            if (!VerifyMemberFields(TO_TADDR(vMethTable.ParentMethodTable), obj, numInstanceFields))
                return false;
        }

        DacpMethodTableFieldData vMethodTableFields;

        // Verify all fields on the object.
        CLRDATA_ADDRESS dwAddr = vMethodTableFields.FirstField;
        DacpFieldDescData vFieldDesc;
        
        while (numInstanceFields < vMethodTableFields.wNumInstanceFields)
        {
            CheckInterrupt();
            
            if (FAILED(vFieldDesc.Request(g_sos, dwAddr)))
                return false;

            if (vFieldDesc.Type >= ELEMENT_TYPE_MAX)
                return false;

            dwAddr = vFieldDesc.NextField;
                
            if (!vFieldDesc.bIsStatic)
            {
                numInstanceFields++;            
                TADDR dwTmp = TO_TADDR(obj + vFieldDesc.dwOffset + sizeof(BaseObject));
                if (vFieldDesc.Type == ELEMENT_TYPE_CLASS)
                {
                    // Is it a valid object?  
                    if (FAILED(MOVE(dwTmp, dwTmp)))
                        return false;

                    if (dwTmp != NULL)
                    {
                        DacpObjectData objData;
                        if (FAILED(objData.Request(g_sos, TO_CDADDR(dwTmp))))
                            return false;
                    }
                }
            }        
        }
        
        return true;
    }
Example #2
0
 TADDR Object::GetComponentMT() const
 {
     if (mMT != NULL && mMT != sos::MethodTable::GetArrayMT())
         return NULL;
     
     DacpObjectData objData;
     if (FAILED(objData.Request(g_sos, TO_CDADDR(mAddress))))
         sos::Throw<DataRead>("Failed to request object data for %s.", DMLListNearObj(mAddress));
     
     if (mMT == NULL)
         mMT = TO_TADDR(objData.MethodTable) & ~3;
     
     return TO_TADDR(objData.ElementTypeHandle);
 }
Example #3
0
    bool Object::IsValid(TADDR address, bool verifyFields)
    {
        DacpObjectData objectData;
        if (FAILED(objectData.Request(g_sos, TO_CDADDR(address))))
            return false;

        if (verifyFields &&
            objectData.MethodTable != g_special_usefulGlobals.FreeMethodTable &&
            !MethodTable::IsZombie(TO_TADDR(objectData.MethodTable)))
        {
            return VerifyMemberFields(TO_TADDR(objectData.MethodTable), address);
        }
        
        return true;
    }
HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapDetails *detailsData)
{    
    if (!heapAddr)
    {
        // PREfix.
        return E_INVALIDARG;
    }

    SVR::gc_heap *pHeap = PTR_SVR_gc_heap(TO_TADDR(heapAddr));
    int i;

    detailsData->heapAddr = heapAddr;
    
    detailsData->lowest_address = PTR_CDADDR(g_lowest_address);
    detailsData->highest_address = PTR_CDADDR(g_highest_address);
    detailsData->card_table = PTR_CDADDR(g_card_table);
    
    detailsData->alloc_allocated = (CLRDATA_ADDRESS)(ULONG_PTR) pHeap->alloc_allocated;
    detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)(ULONG_PTR) pHeap->ephemeral_heap_segment;
    for (i=0;i<NUMBERGENERATIONS;i++)
    {
        detailsData->generation_table[i].start_segment = (CLRDATA_ADDRESS)(ULONG_PTR) pHeap->generation_table[i].start_segment;
        detailsData->generation_table[i].allocation_start = (CLRDATA_ADDRESS)(ULONG_PTR) pHeap->generation_table[i].allocation_start;        
        detailsData->generation_table[i].allocContextPtr = (CLRDATA_ADDRESS)(ULONG_PTR) pHeap->generation_table[i].allocation_context.alloc_ptr;
        detailsData->generation_table[i].allocContextLimit = (CLRDATA_ADDRESS)(ULONG_PTR) pHeap->generation_table[i].allocation_context.alloc_limit;
    }

    TADDR pFillPointerArray = TO_TADDR(pHeap->finalize_queue) + offsetof(SVR::CFinalize,m_FillPointers);
    for(i=0;i<(NUMBERGENERATIONS+SVR::CFinalize::ExtraSegCount);i++)
    {
        ULONG32 returned = sizeof(size_t);    
        size_t pValue;
        m_target->ReadVirtual(pFillPointerArray+(i*sizeof(size_t)), (PBYTE)&pValue, sizeof(size_t),&returned);    
        if (returned != sizeof(size_t))
        {
            return E_FAIL;
        }

        detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS) pValue;
    }

    return S_OK;
}
Example #5
0
HRESULT 
ClrDataAccess::ServerOomData(CLRDATA_ADDRESS addr, DacpOomData *oomData)
{
    DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(addr));

    oom_history pOOMInfo = pHeap->oom_info;
    oomData->reason = pOOMInfo.reason;
    oomData->alloc_size = pOOMInfo.alloc_size;
    oomData->available_pagefile_mb = pOOMInfo.available_pagefile_mb;
    oomData->gc_index = pOOMInfo.gc_index;
    oomData->fgm = pOOMInfo.fgm;
    oomData->size = pOOMInfo.size;
    oomData->loh_p = pOOMInfo.loh_p;

    return S_OK;
}
Example #6
0
HRESULT ClrDataAccess::ServerGCHeapAnalyzeData(CLRDATA_ADDRESS heapAddr, DacpGcHeapAnalyzeData *analyzeData)
{
    if (!heapAddr)
    {
        // PREfix.
        return E_INVALIDARG;
    }

    DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(heapAddr));

    analyzeData->heapAddr = heapAddr;
    analyzeData->internal_root_array = (CLRDATA_ADDRESS)pHeap->internal_root_array;
    analyzeData->internal_root_array_index = (size_t)pHeap->internal_root_array_index;
    analyzeData->heap_analyze_success = (BOOL)pHeap->heap_analyze_success;

    return S_OK;
}
Example #7
0
    void Object::CalculateSizeAndPointers() const
    {
        TADDR mt = GetMT();
        MethodTableInfo* info = g_special_mtCache.Lookup((DWORD_PTR)mt);
        if (!info->IsInitialized())	
        {
            // this is the first time we see this method table, so we need to get the information
            // from the target
            FillMTData();

            info->BaseSize = mMTData->BaseSize;
            info->ComponentSize = mMTData->ComponentSize;
            info->bContainsPointers = mMTData->bContainsPointers;

            // The following request doesn't work on older runtimes. For those, the
            // objects would just look like non-collectible, which is acceptable.
            DacpMethodTableCollectibleData mtcd;
            if (SUCCEEDED(mtcd.Request(g_sos, GetMT())))
            {
                info->bCollectible = mtcd.bCollectible;
                info->LoaderAllocatorObjectHandle = TO_TADDR(mtcd.LoaderAllocatorObjectHandle);
            }
        }
        
        if (mSize == (size_t)~0)
        {
            mSize = info->BaseSize;
            if (info->ComponentSize)
            {
                // this is an array, so the size has to include the size of the components. We read the number
                // of components from the target and multiply by the component size to get the size.
                mSize += info->ComponentSize * GetNumComponents(GetAddress());
            }

            // On x64 we do an optimization to save 4 bytes in almost every string we create.
        #ifdef _WIN64
            // Pad to min object size if necessary
            if (mSize < min_obj_size)
                mSize = min_obj_size;
        #endif // _WIN64
        }

        mPointers = info->bContainsPointers != FALSE;
    }
Example #8
0
HRESULT ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapDetails *detailsData)
{    
    if (!heapAddr)
    {
        // PREfix.
        return E_INVALIDARG;
    }

    DPTR(dac_gc_heap) pHeap = __DPtr<dac_gc_heap>(TO_TADDR(heapAddr));
    int i;

    //get global information first
    detailsData->heapAddr = heapAddr;
    
    detailsData->lowest_address = PTR_CDADDR(g_lowest_address);
    detailsData->highest_address = PTR_CDADDR(g_highest_address);
    detailsData->card_table = PTR_CDADDR(g_card_table);
    
    // now get information specific to this heap (server mode gives us several heaps; we're getting
    // information about only one of them. 
    detailsData->alloc_allocated = (CLRDATA_ADDRESS)pHeap->alloc_allocated;
    detailsData->ephemeral_heap_segment = (CLRDATA_ADDRESS)dac_cast<TADDR>(pHeap->ephemeral_heap_segment);

    // get bounds for the different generations
    for (i=0; i<NUMBERGENERATIONS; i++)
    {
        DPTR(dac_generation) generation = ServerGenerationTableIndex(pHeap, i);
        detailsData->generation_table[i].start_segment     = (CLRDATA_ADDRESS)dac_cast<TADDR>(generation->start_segment);
        detailsData->generation_table[i].allocation_start   = (CLRDATA_ADDRESS)(ULONG_PTR)generation->allocation_start;
        DPTR(gc_alloc_context) alloc_context = dac_cast<TADDR>(generation) + offsetof(dac_generation, allocation_context);
        detailsData->generation_table[i].allocContextPtr    = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_ptr;
        detailsData->generation_table[i].allocContextLimit = (CLRDATA_ADDRESS)(ULONG_PTR) alloc_context->alloc_limit;
    }

    DPTR(dac_finalize_queue) fq = pHeap->finalize_queue;
    DPTR(uint8_t*) pFillPointerArray= dac_cast<TADDR>(fq) + offsetof(dac_finalize_queue, m_FillPointers);
    for(i=0; i<(NUMBERGENERATIONS+dac_finalize_queue::ExtraSegCount); i++)
    {
        detailsData->finalization_fill_pointers[i] = (CLRDATA_ADDRESS) pFillPointerArray[i];
    }

    return S_OK;
}
Example #9
0
    bool Object::TryGetHeader(ULONG &outHeader) const
    {
        struct ObjectHeader
        {
    #ifdef _WIN64
            ULONG _alignpad;
    #endif
            ULONG SyncBlockValue;      // the Index and the Bits
        };

        ObjectHeader header;

        if (SUCCEEDED(rvCache->Read(TO_TADDR(GetAddress() - sizeof(ObjectHeader)), &header, sizeof(ObjectHeader), NULL)))
        {
            outHeader = header.SyncBlockValue;
            return true;
        }

        return false;
    }
HRESULT GetServerHeapData(CLRDATA_ADDRESS addr, DacpHeapSegmentData *pSegment)
{
    if (!addr)
    {
        // PREfix.
        return E_INVALIDARG;
    }

    SVR::heap_segment *pHeapSegment =
        __DPtr<SVR::heap_segment>(TO_TADDR(addr));

    pSegment->segmentAddr = addr;
    pSegment->allocated = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->allocated;
    pSegment->committed = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->committed;
    pSegment->reserved = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->reserved;
    pSegment->used = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->used;
    pSegment->mem = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->mem;
    pSegment->next = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->next;
    pSegment->gc_heap = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->heap;

    return S_OK;
}
Example #11
0
    bool Object::GetThinLock(ThinLockInfo &out) const
    {
        ULONG header = GetHeader();
        if (header & (BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX | BIT_SBLK_SPIN_LOCK))
        {
            return false;
        }

        out.ThreadId = header & SBLK_MASK_LOCK_THREADID;
        out.Recursion = (header & SBLK_MASK_LOCK_RECLEVEL) >> SBLK_RECLEVEL_SHIFT;

        CLRDATA_ADDRESS threadPtr = NULL;
        if (g_sos->GetThreadFromThinlockID(out.ThreadId, &threadPtr) != S_OK)
        {
            out.ThreadPtr = NULL;
        }
        else
        {
            out.ThreadPtr = TO_TADDR(threadPtr);
        }
        
        return out.ThreadId != 0 && out.ThreadPtr != NULL;
    }
Example #12
0
HRESULT GetServerHeapData(CLRDATA_ADDRESS addr, DacpHeapSegmentData *pSegment)
{
    // get field values (target addresses) for the heap segment at addr
    if (!addr)
    {
        // PREfix.
        return E_INVALIDARG;
    }

    // marshal the segment from target to host
    dac_heap_segment *pHeapSegment = __DPtr<dac_heap_segment>(TO_TADDR(addr));

    // initialize fields by copying from the marshaled segment (note that these are all target addresses)
    pSegment->segmentAddr = addr;
    pSegment->allocated = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->allocated;
    pSegment->committed = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->committed;
    pSegment->reserved = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->reserved;
    pSegment->used = (CLRDATA_ADDRESS)(ULONG_PTR) pHeapSegment->used;
    pSegment->mem = (CLRDATA_ADDRESS)(ULONG_PTR) (pHeapSegment->mem);
    pSegment->next = (CLRDATA_ADDRESS)dac_cast<TADDR>(pHeapSegment->next);
    pSegment->gc_heap = (CLRDATA_ADDRESS)pHeapSegment->heap;

    return S_OK;
}
Example #13
0
HRESULT 
ClrDataAccess::ServerGCInterestingInfoData(CLRDATA_ADDRESS addr, DacpGCInterestingInfoData *interestingInfoData)
{
#ifdef GC_CONFIG_DRIVEN
    dac_gc_heap *pHeap = __DPtr<dac_gc_heap>(TO_TADDR(addr));

    size_t* dataPoints = (size_t*)&(pHeap->interesting_data_per_heap);
    for (int i = 0; i < NUM_GC_DATA_POINTS; i++)
        interestingInfoData->interestingDataPoints[i] = dataPoints[i];
    size_t* mechanisms = (size_t*)&(pHeap->compact_reasons_per_heap);
    for (int i = 0; i < MAX_COMPACT_REASONS_COUNT; i++)
        interestingInfoData->compactReasons[i] = mechanisms[i];
    mechanisms = (size_t*)&(pHeap->expand_mechanisms_per_heap);
    for (int i = 0; i < MAX_EXPAND_MECHANISMS_COUNT; i++)
        interestingInfoData->expandMechanisms[i] = mechanisms[i];
    mechanisms = (size_t*)&(pHeap->interesting_mechanism_bits_per_heap);
    for (int i = 0; i < MAX_GC_MECHANISM_BITS_COUNT; i++)
        interestingInfoData->bitMechanisms[i] = mechanisms[i];

    return S_OK;
#else
    return E_NOTIMPL;
#endif //GC_CONFIG_DRIVEN
}