Ejemplo n.º 1
0
// DacFreeVirtual - Free memory from the target process
// Note: this is only available to clients supporting the legacy
// ICLRDataTarget2 interface.  This is not currently used.
HRESULT
DacFreeVirtual(TADDR mem, ULONG32 size, ULONG32 typeFlags,
               bool throwEx)
{
    if (!g_dacImpl)
    {
        DacError(E_UNEXPECTED);
        UNREACHABLE();
    }

    ICLRDataTarget2 * pTarget2 = g_dacImpl->GetLegacyTarget2();
    if (pTarget2 == NULL)
    {
        DacError(E_NOTIMPL);
        UNREACHABLE();
    }

    HRESULT status = pTarget2->FreeVirtual(
        TO_CDADDR(mem), size, typeFlags);

    if (status != S_OK && throwEx)
    {
        DacError(status);
        UNREACHABLE();
    }

    return status;
}
Ejemplo n.º 2
0
HRESULT DecodeILFromAddress(IMetaDataImport *pImport, TADDR ilAddr)
{
    HRESULT Status = S_OK;

    ULONG Size = GetILSize(ilAddr);
    if (Size == 0)
    {
        ExtOut("error decoding IL\n");
        return Status;
    }

    ExtOut("ilAddr = %p\n", (ULONG64) ilAddr);

    // Read the memory into a local buffer
    ArrayHolder<BYTE> pArray = new BYTE[Size];
    Status = g_ExtData->ReadVirtual(TO_CDADDR(ilAddr), pArray, Size, NULL);
    if (Status != S_OK)
    {
        ExtOut("Failed to read memory\n");
        return Status;
    }

    DecodeIL(pImport, pArray, Size);

    return Status;
}
Ejemplo n.º 3
0
// DacAllocVirtual - Allocate memory from the target process
// Note: this is only available to clients supporting the legacy
// ICLRDataTarget2 interface.  It's currently used by SOS for notification tables.
HRESULT
DacAllocVirtual(TADDR addr, ULONG32 size,
                ULONG32 typeFlags, ULONG32 protectFlags,
                bool throwEx, TADDR* mem)
{
    if (!g_dacImpl)
    {
        DacError(E_UNEXPECTED);
        UNREACHABLE();
    }

    ICLRDataTarget2 * pTarget2 = g_dacImpl->GetLegacyTarget2();
    if (pTarget2 == NULL)
    {
        DacError(E_NOTIMPL);
        UNREACHABLE();
    }

    CLRDATA_ADDRESS cdaMem;
    HRESULT status = pTarget2->AllocVirtual(
        TO_CDADDR(addr), size, typeFlags, protectFlags, &cdaMem);
    if (status != S_OK)
    {
        if (throwEx)
        {
            DacError(status);
            UNREACHABLE();
        }

        return status;
    }

    *mem = CLRDATA_ADDRESS_TO_TADDR(cdaMem);
    return S_OK;
}
Ejemplo n.º 4
0
// impl of interface method ICorDebugDataTarget::ReadVirtual
HRESULT STDMETHODCALLTYPE
DataTargetAdapter::ReadVirtual( 
    CORDB_ADDRESS address,
    PBYTE pBuffer,
    ULONG32 cbRequestSize,
    ULONG32 * pcbRead)
{
    SUPPORTS_DAC_HOST_ONLY;
    CLRDATA_ADDRESS cdAddr = TO_CDADDR(address);
    return m_pLegacyTarget->ReadVirtual(cdAddr, pBuffer, cbRequestSize, pcbRead);
}
Ejemplo n.º 5
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;
    }
Ejemplo n.º 6
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);
 }
Ejemplo n.º 7
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;
    }
Ejemplo n.º 8
0
ULONG GetILSize(DWORD_PTR ilAddr)
{
    ULONG uRet = 0;

    // workaround: read enough bytes at ilAddr to presumably get the entire header.
    // Could be error prone.

    static BYTE headerArray[1024];
    HRESULT Status = g_ExtData->ReadVirtual(TO_CDADDR(ilAddr), headerArray, sizeof(headerArray), NULL);    
    if (SUCCEEDED(Status))
    {            
        COR_ILMETHOD_DECODER header((COR_ILMETHOD *)headerArray);
        // uRet = header.GetHeaderSize();
        uRet = header.GetOnDiskSize((COR_ILMETHOD *)headerArray);
    }

    return uRet;
}
Ejemplo n.º 9
0
// impl of interface method ICorDebugMutableDataTarget::WriteVirtual
HRESULT STDMETHODCALLTYPE
DataTargetAdapter::WriteVirtual( 
    CORDB_ADDRESS address,
    const BYTE * pBuffer,
    ULONG32 cbRequestSize)
{
    SUPPORTS_DAC_HOST_ONLY;
    CLRDATA_ADDRESS cdAddr = TO_CDADDR(address);
    ULONG32 cbWritten = 0;
    HRESULT hr = S_OK;

    hr = m_pLegacyTarget->WriteVirtual(cdAddr, const_cast<BYTE *>(pBuffer), cbRequestSize, &cbWritten);

    if (SUCCEEDED(hr) && cbWritten != cbRequestSize)
    {
        // This shouldn't happen - existing data target implementations make writes atomic (eg. 
        // WriteProcessMemory), even though that isn't strictly required by the old interface.  
        // If this does happen, we technically leave the process in an inconsistent state, and we make no
        // attempt to recover from that here.
        _ASSERTE_MSG(false, "Legacy data target WriteVirtual partial write - target left in inconsistent state");
        return HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY);
    }
    return hr;
}
Ejemplo n.º 10
0
void UnassemblyUnmanaged(DWORD_PTR IP, BOOL bSuppressLines)
{
    char            filename[MAX_PATH_FNAME+1];
    char            line[256];
    int             lcount          = 10;

    ULONG linenum = 0;
    ULONG64 Displacement = 0;
    BOOL fLineAvailable = FALSE;
    ULONG64 vIP = 0;
    
    if (!bSuppressLines)
    {
        ReloadSymbolWithLineInfo();
        fLineAvailable = SUCCEEDED (g_ExtSymbols->GetLineByOffset (TO_CDADDR(IP), &linenum,
                                                                    filename,
                                                                    MAX_PATH_FNAME+1,
                                                                    NULL,
                                                                    &Displacement));
    }
    ULONG FileLines = 0;
    ArrayHolder<ULONG64> Buffer = NULL;

    if (fLineAvailable)
    {
        g_ExtSymbols->GetSourceFileLineOffsets (filename, NULL, 0, &FileLines);
        if (FileLines == 0xFFFFFFFF || FileLines == 0)
            fLineAvailable = FALSE;
    }

    if (fLineAvailable)
    {
        Buffer = new ULONG64[FileLines];
        if (Buffer == NULL)
            fLineAvailable = FALSE;
    }
    
    if (!fLineAvailable)
    {
        vIP = TO_CDADDR(IP);
        // There is no line info.  Just disasm the code.
        while (lcount-- > 0)
        {
            if (IsInterrupt())
                return;
            g_ExtControl->Disassemble (vIP, 0, line, 256, NULL, &vIP);
            ExtOut (line);
        }
        return;
    }

    g_ExtSymbols->GetSourceFileLineOffsets (filename, Buffer, FileLines, NULL);
    
    int beginLine = 0;
    int endLine = 0;
    int lastLine;
    linenum --;
    for (lastLine = linenum; lastLine >= 0; lastLine --) {
        if (IsInterrupt())
            return;
        if (Buffer[lastLine] != DEBUG_INVALID_OFFSET) {
            g_ExtSymbols->GetNameByOffset(Buffer[lastLine],NULL,0,NULL,&Displacement);
            if (Displacement == 0) {
                beginLine = lastLine;
                break;
            }
        }
    }
    if (lastLine < 0) {
        int n = lcount / 2;
        lastLine = linenum-1;
        beginLine = lastLine;
        while (lastLine >= 0) {
            if (IsInterrupt())
                return;
            if (Buffer[lastLine] != DEBUG_INVALID_OFFSET) {
                beginLine = lastLine;
                n --;
                if (n == 0) {
                    break;
                }
            }
            lastLine --;
        }
    }
    while (beginLine > 0 && Buffer[beginLine-1] == DEBUG_INVALID_OFFSET) {
        if (IsInterrupt())
            return;
        beginLine --;
    }
    int endOfFunc = 0;
    for (lastLine = linenum+1; (ULONG)lastLine < FileLines; lastLine ++) {
        if (IsInterrupt())
            return;
        if (Buffer[lastLine] != DEBUG_INVALID_OFFSET) {
            g_ExtSymbols->GetNameByOffset(Buffer[lastLine],NULL,0,NULL,&Displacement);
            if (Displacement == 0) {
                endLine = lastLine;
                break;
            }
            endOfFunc = lastLine;
        }
    }
    if ((ULONG)lastLine == FileLines) {
        int n = lcount / 2;
        lastLine = linenum+1;
        endLine = lastLine;
        while ((ULONG)lastLine < FileLines) {
            if (IsInterrupt())
                return;
            if (Buffer[lastLine] != DEBUG_INVALID_OFFSET) {
                endLine = lastLine;
                n --;
                if (n == 0) {
                    break;
                }
            }
            lastLine ++;
        }
    }

    PVOID MappedBase = NULL;
    ULONG MappedSize = 0;

    class ToUnmap
    {
        PVOID *m_Base;
    public:
        ToUnmap (PVOID *base)
        :m_Base(base)
        {}
        ~ToUnmap ()
        {
            if (*m_Base) {
                UnmapViewOfFile (*m_Base);
                *m_Base = NULL;
            }
        }
    };
    ToUnmap toUnmap(&MappedBase);

#define MAX_SOURCE_PATH 1024
    char Found[MAX_SOURCE_PATH];
    char *pFile;
    if (g_ExtSymbols->FindSourceFile(0, filename,
                       DEBUG_FIND_SOURCE_BEST_MATCH |
                       DEBUG_FIND_SOURCE_FULL_PATH,
                       NULL, Found, sizeof(Found), NULL) != S_OK)
    {
        pFile = filename;
    }
    else
    {
        MappedBase = GenOpenMapping ( Found, &MappedSize );
        pFile = Found;
    }
    
    lastLine = beginLine;
    char *pFileCh = (char*)MappedBase;
    if (MappedBase) {
        ExtOut ("%s\n", pFile);
        int n = beginLine;
        while (n > 0) {
            while (!(pFileCh[0] == '\r' && pFileCh[1] == 0xa)) {
                if (IsInterrupt())
                    return;
                pFileCh ++;
            }
            pFileCh += 2;
            n --;
        }
    }
    
    char filename1[MAX_PATH_FNAME+1];
    for (lastLine = beginLine; lastLine < endLine; lastLine ++) {
        if (IsInterrupt())
            return;
        if (MappedBase) {
            ExtOut ("%4d ", lastLine+1);
            pFileCh = PrintOneLine (pFileCh, (char*)MappedBase+MappedSize);
        }
        if (Buffer[lastLine] != DEBUG_INVALID_OFFSET) {
            if (MappedBase == 0) {
                ExtOut (">>> %s:%d\n", pFile, lastLine+1);
            }
            vIP = Buffer[lastLine];
            ULONG64 vNextLineIP;
            int i;
            for (i = lastLine + 1; (ULONG)i < FileLines && Buffer[i] == DEBUG_INVALID_OFFSET; i ++) {
                if (IsInterrupt())
                    return;
            }
            if ((ULONG)i == FileLines) {
                vNextLineIP = 0;
            }
            else
                vNextLineIP = Buffer[i];
            while (1) {
                if (IsInterrupt())
                    return;
                g_ExtControl->Disassemble (vIP, 0, line, 256, NULL, &vIP);
                ExtOut (line);
                if (vIP > vNextLineIP || vNextLineIP - vIP > 40) {
                    if (FAILED (g_ExtSymbols->GetLineByOffset (vIP, &linenum,
                                                               filename1,
                                                               MAX_PATH_FNAME+1,
                                                               NULL,
                                                               &Displacement))) {
                        if (lastLine != endOfFunc) {
                            break;
                        }
                        if (strstr (line, "ret") || strstr (line, "jmp")) {
                            break;
                        }
                    }

                    if (linenum != (ULONG)lastLine+1 || strcmp (filename, filename1)) {
                        break;
                    }
                }
                else if (vIP == vNextLineIP) {
                    break;
                }
            }
        }
    }
        
}