diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 17731f39622ebe..15b887d74da4f7 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -5099,55 +5099,6 @@ ClrDataAccess::Initialize(void) HRESULT hr; CLRDATA_ADDRESS base = { 0 }; - // - // We do not currently support cross-platform - // debugging. Verify that cross-platform is not - // being attempted. - // - - // Determine our platform based on the pre-processor macros set when we were built - -#ifdef TARGET_UNIX - #if defined(TARGET_X86) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_X86; - #elif defined(TARGET_AMD64) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_AMD64; - #elif defined(TARGET_ARM) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_ARM; - #elif defined(TARGET_ARM64) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_ARM64; - #elif defined(TARGET_LOONGARCH64) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_LOONGARCH64; - #elif defined(TARGET_RISCV64) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_POSIX_RISCV64; - #else - #error Unknown Processor. - #endif -#else - #if defined(TARGET_X86) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_WINDOWS_X86; - #elif defined(TARGET_AMD64) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_WINDOWS_AMD64; - #elif defined(TARGET_ARM) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_WINDOWS_ARM; - #elif defined(TARGET_ARM64) - CorDebugPlatform hostPlatform = CORDB_PLATFORM_WINDOWS_ARM64; - #else - #error Unknown Processor. - #endif -#endif - - CorDebugPlatform targetPlatform; - IfFailRet(m_pTarget->GetPlatform(&targetPlatform)); - - if (targetPlatform != hostPlatform) - { - // DAC fatal error: Platform mismatch - the platform reported by the data target - // is not what this version of mscordacwks.dll was built for. - return CORDBG_E_INCOMPATIBLE_PLATFORMS; - } - - // // Get the current DLL base for mscorwks globals. // In case of multiple-CLRs, there may be multiple dlls named "mscorwks". // code:OpenVirtualProcess can take the base address (clrInstanceId) to select exactly diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 1de344cd271f3c..e2ef3f07fceb67 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -7793,6 +7793,48 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetGenericArgTokenIndex(VMPTR_Met return S_OK; } +HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetTargetInfo(OUT TargetInfo * pTargetInfo) +{ + DD_ENTER_MAY_THROW; + + if (pTargetInfo == NULL) + return E_INVALIDARG; + +#if defined(TARGET_X86) + pTargetInfo->arch = kArchX86; +#elif defined(TARGET_AMD64) + pTargetInfo->arch = kArchAMD64; +#elif defined(TARGET_ARM) + pTargetInfo->arch = kArchArm; +#elif defined(TARGET_ARM64) + pTargetInfo->arch = kArchArm64; +#elif defined(TARGET_LOONGARCH64) + pTargetInfo->arch = kArchLoongArch64; +#elif defined(TARGET_RISCV64) + pTargetInfo->arch = kArchRiscV64; +#elif defined(TARGET_WASM) + pTargetInfo->arch = kArchWasm; +#else + pTargetInfo->arch = kArchUnknown; +#endif + +#if defined(TARGET_UNIX) + pTargetInfo->os = kOSUnix; +#elif defined(TARGET_WINDOWS) + pTargetInfo->os = kOSWindows; +#else + pTargetInfo->os = kOSUnknown; +#endif + +#if defined(TARGET_64BIT) + pTargetInfo->pointerSize = 8; +#else + pTargetInfo->pointerSize = 4; +#endif + + return S_OK; +} + DacRefWalker::DacRefWalker(ClrDataAccess *dac, BOOL walkStacks, UINT32 handleMask, BOOL resolvePointers) : mDac(dac), mWalkStacks(walkStacks), mHandleMask(handleMask), mStackWalker(NULL), mResolvePointers(resolvePointers), mHandleWalker(NULL) diff --git a/src/coreclr/debug/daccess/dacdbiimpl.h b/src/coreclr/debug/daccess/dacdbiimpl.h index e9416d137f8a2d..842027460fb7ff 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/debug/daccess/dacdbiimpl.h @@ -154,6 +154,7 @@ class DacDbiInterfaceImpl : HRESULT STDMETHODCALLTYPE EnumerateAsyncLocals(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeAddr, UINT32 state, FP_ASYNC_LOCAL_CALLBACK fpCallback, CALLBACK_DATA pUserData); HRESULT STDMETHODCALLTYPE GetGenericArgTokenIndex(VMPTR_MethodDesc vmMethod, OUT UINT32* pIndex); + HRESULT STDMETHODCALLTYPE GetTargetInfo(OUT TargetInfo * pTargetInfo); HRESULT STDMETHODCALLTYPE GetReadWriteMetadataSize(VMPTR_Module vmModule, OUT ULONG32 * pSize); HRESULT STDMETHODCALLTYPE FillReadWriteMetadata(VMPTR_Module vmModule, BYTE * pBuffer, ULONG32 cbBuffer); diff --git a/src/coreclr/debug/di/cordb.cpp b/src/coreclr/debug/di/cordb.cpp index 18a11297b28193..15e474464e1b62 100644 --- a/src/coreclr/debug/di/cordb.cpp +++ b/src/coreclr/debug/di/cordb.cpp @@ -18,7 +18,7 @@ #include "dbgtransportmanager.h" #endif // FEATURE_DBGIPC_TRANSPORT_DI -#if defined(TARGET_UNIX) || defined(__ANDROID__) +#if defined(HOST_UNIX) || defined(__ANDROID__) // Local (in-process) debugging is not supported for UNIX and Android. #define SUPPORT_LOCAL_DEBUGGING 0 #else diff --git a/src/coreclr/debug/di/divalue.cpp b/src/coreclr/debug/di/divalue.cpp index 4a0abfa6bacd43..c35a458023269f 100644 --- a/src/coreclr/debug/di/divalue.cpp +++ b/src/coreclr/debug/di/divalue.cpp @@ -278,10 +278,9 @@ ICorDebugValue* CordbValue::CreateHeapValue(CordbAppDomain* pAppDomain, VMPTR_Ob CordbReferenceValue* CordbValue::CreateHeapReferenceValue(CordbAppDomain* pAppDomain, VMPTR_Object vmObj) { - VOID* pRemoteAddr = CORDB_ADDRESS_TO_PTR((CORDB_ADDRESS)VmPtrToCookie(vmObj)); - // This creates a local reference that has a remote address in it. Ie &pRemoteAddr is an address - // in the host address space and pRemoteAddr is an address in the target. - MemoryRange localReferenceDescription(&pRemoteAddr, sizeof(pRemoteAddr)); + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(pAppDomain->GetProcess()->GetTargetInfo(&targetInfo)); + MemoryRange localReferenceDescription(&vmObj, targetInfo.pointerSize); RSSmartPtr pRefValue; IfFailThrow(CordbReferenceValue::Build(pAppDomain, NULL, @@ -358,10 +357,12 @@ ULONG32 CordbValue::GetSizeForType(CordbType * pType, BoxedValue boxing) } if (!isUnboxedVCObject) { + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(pType->GetProcess()->GetTargetInfo(&targetInfo)); // if it's not an unboxed value type (we're in the case // for compound types), then it's a reference // and we just want to return the size of a pointer - size = sizeof(void *); + size = targetInfo.pointerSize; } else { @@ -439,7 +440,14 @@ HRESULT CordbValue::InternalCreateHandle(CorDebugHandleType handleType, // Create the ICorDebugHandleValue object - RSInitHolder pHandle(new (nothrow) CordbHandleValue(m_appdomain, m_type, handleType) ); + HRESULT hr = S_OK; + RSInitHolder pHandle; + EX_TRY + { + pHandle.Assign(new (nothrow) CordbHandleValue(m_appdomain, m_type, handleType)); + } + EX_CATCH_HRESULT(hr); + IfFailRet(hr); if (pHandle == NULL) { @@ -460,7 +468,7 @@ HRESULT CordbValue::InternalCreateHandle(CorDebugHandleType handleType, event.CreateHandle.handleType = handleType; // Note: two-way event here... - HRESULT hr = process->SendIPCEvent(&event, sizeof(DebuggerIPCEvent)); + hr = process->SendIPCEvent(&event, sizeof(DebuggerIPCEvent)); hr = WORST_HR(hr, event.hr); if (SUCCEEDED(hr)) @@ -741,8 +749,10 @@ CordbReferenceValue::CordbReferenceValue(CordbAppDomain * pAppdomai { memset(&m_info, 0, sizeof(m_info)); - LOG((LF_CORDB,LL_EVERYTHING,"CRV::CRV: this:0x%p\n",this)); - m_size = sizeof(void *); + LOG((LF_CORDB,LL_EVERYTHING,"CRV::CRV: this:0x%x\n",this)); + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(pAppdomain->GetProcess()->GetTargetInfo(&targetInfo)); + m_size = targetInfo.pointerSize; // now instantiate the value home NewHolder pHome(NULL); @@ -778,7 +788,9 @@ CordbReferenceValue::CordbReferenceValue(CordbType * pType) memset(&m_info, 0, sizeof(m_info)); // The only purpose of a literal value is to hold a RS literal value. - m_size = sizeof(void*); + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + m_size = targetInfo.pointerSize; // there is no value home for a literal m_valueHome.m_pHome = NULL; @@ -794,11 +806,10 @@ bool CordbReferenceValue::CopyLiteralData(BYTE *pBuffer) { _ASSERTE(pBuffer != NULL); - // If this is a RS fabrication, then its a null reference. + // If this is a RS fabrication, then it's a null reference. if (m_isLiteral) { - void *n = NULL; - memcpy(pBuffer, &n, sizeof(n)); + memset(pBuffer, 0, m_size); return true; } else @@ -975,11 +986,20 @@ HRESULT CordbReferenceValue::SetValue(CORDB_ADDRESS address) _ASSERTE((m_type != NULL) || (!m_valueHome.ObjHandleIsNull() && (m_info.objRef == (CORDB_ADDRESS)NULL))); - EX_TRY - { - m_valueHome.m_pHome->SetValue(MemoryRange(&address, sizeof(void *)), m_type); // throws - } - EX_CATCH_HRESULT(hr); + IDacDbiInterface::TargetInfo targetInfo = {}; + + EX_TRY + { + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + // If the target is 32-bit, we can't set a reference to a value that doesn't fit in 32 bits. + if ((targetInfo.pointerSize == sizeof(ULONG32)) && (address > UINT32_MAX)) + { + ThrowHR(E_INVALIDARG); + } + + m_valueHome.m_pHome->SetValue(MemoryRange(&address, targetInfo.pointerSize), m_type); // throws + } + EX_CATCH_HRESULT(hr); if (SUCCEEDED(hr)) { @@ -991,8 +1011,7 @@ HRESULT CordbReferenceValue::SetValue(CORDB_ADDRESS address) if (m_info.objTypeData.elementType == ELEMENT_TYPE_STRING) { // update information about the string - void * pObjRef = CORDB_ADDRESS_TO_PTR(m_info.objRef); - InitRef(MemoryRange(&pObjRef, sizeof (void *))); + InitRef(MemoryRange(&m_info.objRef, targetInfo.pointerSize)); } // All other data in m_info is no longer valid, and we may have invalidated other @@ -1200,7 +1219,7 @@ HRESULT CordbReferenceValue::DereferenceCommon( LOG((LF_CORDB, LL_INFO1000, "DereferenceInternal: type typedbyref\n")); - TargetBuffer remoteValue(pInfo->objRef, sizeof(void *)); + TargetBuffer remoteValue(pInfo->objRef, GetSizeForType(pRealTypeOfTypedByref, kUnboxed)); // Create the value for what this reference points // to. EX_TRY @@ -1314,7 +1333,9 @@ HRESULT CordbReferenceValue::BuildFromGCHandle( { CORDB_ADDRESS _handleAddr; IfFailThrow(pProc->GetDAC()->GetHandleAddressFromVmHandle(gcHandle, &_handleAddr)); - remoteValue.Init(_handleAddr, sizeof(void *)); + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(pProc->GetTargetInfo(&targetInfo)); + remoteValue.Init(_handleAddr, targetInfo.pointerSize); } EX_CATCH_HRESULT(hr); IfFailRet(hr); @@ -1417,8 +1438,11 @@ void CordbReferenceValue::SanityCheckPointer (CorElementType type) void CordbReferenceValue::GetPointerData(CorElementType type, MemoryRange localValue) { HRESULT hr = S_OK; + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); // Fill in the type since we will not be getting it from the DAC m_info.objTypeData.elementType = type; + m_info.objRef = 0; // First get the objRef if (localValue.StartAddress() != NULL) @@ -1453,10 +1477,8 @@ void CordbReferenceValue::GetPointerData(CorElementType type, MemoryRange localV // | object addr |--------- // --------------- | - _ASSERTE(localValue.Size() == sizeof(void *)); - void * pObjRef = NULL; - localCopy(&pObjRef, localValue); - m_info.objRef = PTR_TO_CORDB_ADDRESS(pObjRef); + _ASSERTE(localValue.Size() == targetInfo.pointerSize); + localCopy(&m_info.objRef, localValue); } else { @@ -1465,12 +1487,13 @@ void CordbReferenceValue::GetPointerData(CorElementType type, MemoryRange localV // do some preinitialization in case we get an exception EX_TRY { - m_valueHome.m_pHome->GetValue(MemoryRange(&(m_info.objRef), sizeof(void*))); // throws + m_info.objRef = 0; // Zero-extend addresses read from 32-bit targets. + m_valueHome.m_pHome->GetValue(MemoryRange(&m_info.objRef, targetInfo.pointerSize)); // throws } EX_CATCH_HRESULT(hr); if (FAILED(hr)) { - m_info.objRef = (CORDB_ADDRESS)NULL; + m_info.objRef = 0; m_info.objRefBad = TRUE; ThrowHR(hr); } @@ -1513,18 +1536,17 @@ void PreInitObjectData(DacDbiObjectData * pObjectData, CORDB_ADDRESS objAddress, // Note: Throws /* static */ void CordbReferenceValue::GetObjectData(CordbProcess * pProcess, - void * objectAddress, + CORDB_ADDRESS objectAddress, CorElementType type, VMPTR_AppDomain vmAppdomain, DacDbiObjectData * pInfo) { IDacDbiInterface *pInterface = pProcess->GetDAC(); - CORDB_ADDRESS objTargetAddr = PTR_TO_CORDB_ADDRESS(objectAddress); // make sure we don't end up with old garbage values in case the reference is bad - PreInitObjectData(pInfo, objTargetAddr, type); + PreInitObjectData(pInfo, objectAddress, type); BOOL isValidRef = FALSE; - IfFailThrow(pInterface->GetBasicObjectInfo(objTargetAddr, &isValidRef, &pInfo->objSize, &pInfo->objOffsetToVars, &pInfo->objTypeData)); + IfFailThrow(pInterface->GetBasicObjectInfo(objectAddress, &isValidRef, &pInfo->objSize, &pInfo->objOffsetToVars, &pInfo->objTypeData)); pInfo->objRefBad = !isValidRef; if (!pInfo->objRefBad) @@ -1532,13 +1554,13 @@ void CordbReferenceValue::GetObjectData(CordbProcess * pProcess, // for certain referent types, we need a bit more information: if (pInfo->objTypeData.elementType == ELEMENT_TYPE_STRING) { - IfFailThrow(pInterface->GetStringData(objTargetAddr, &pInfo->stringInfo.length, &pInfo->stringInfo.offsetToStringBase)); + IfFailThrow(pInterface->GetStringData(objectAddress, &pInfo->stringInfo.length, &pInfo->stringInfo.offsetToStringBase)); } else if ((pInfo->objTypeData.elementType == ELEMENT_TYPE_ARRAY) || (pInfo->objTypeData.elementType == ELEMENT_TYPE_SZARRAY)) { BOOL isValidArray = FALSE; - IfFailThrow(pInterface->GetArrayData(objTargetAddr, &isValidArray, &pInfo->arrayInfo)); + IfFailThrow(pInterface->GetArrayData(objectAddress, &isValidArray, &pInfo->arrayInfo)); pInfo->objRefBad = !isValidArray; } } @@ -1577,19 +1599,21 @@ void CordbReferenceValue::GetTypedByRefData(CordbProcess * pProcess, // Arguments: none // Return Value: the address of the object referenced (i.e., the value of the object ref) // Note: Throws -void * CordbReferenceValue::GetObjectAddress(MemoryRange localValue) +CORDB_ADDRESS CordbReferenceValue::GetObjectAddress(MemoryRange localValue) { - void * objectAddress; + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + CORDB_ADDRESS objectAddress = 0; if (localValue.StartAddress() != NULL) { // the object ref comes from a local cached copy - _ASSERTE(localValue.Size() == sizeof(void *)); + _ASSERTE(localValue.Size() == targetInfo.pointerSize); memcpy(&objectAddress, localValue.StartAddress(), localValue.Size()); } else { _ASSERTE(m_valueHome.m_pHome != NULL); - m_valueHome.m_pHome->GetValue(MemoryRange(&objectAddress, sizeof(void *))); // throws + m_valueHome.m_pHome->GetValue(MemoryRange(&objectAddress, targetInfo.pointerSize)); // throws } return objectAddress; } // CordbReferenceValue::GetObjectAddress @@ -4164,7 +4188,9 @@ CordbHandleValue::CordbHandleValue( m_fCanBeValid = TRUE; m_handleType = handleType; - m_size = sizeof(void*); + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + m_size = targetInfo.pointerSize; } // CordbHandleValue::CordbHandleValue //----------------------------------------------------------------------------- @@ -4315,15 +4341,17 @@ HRESULT CordbHandleValue::RefreshHandleValue() _ASSERTE (type != ELEMENT_TYPE_MVAR); CordbProcess * pProcess = GetProcess(); - void * objectAddress = NULL; + CORDB_ADDRESS objectAddress = 0; CORDB_ADDRESS objectHandle = 0; EX_TRY { + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(pProcess->GetTargetInfo(&targetInfo)); IfFailThrow(pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmHandle, &objectHandle)); if (type != ELEMENT_TYPE_TYPEDBYREF) { - pProcess->SafeReadBuffer(TargetBuffer(objectHandle, sizeof(void *)), (BYTE *)&objectAddress); + pProcess->SafeReadBuffer(TargetBuffer(objectHandle, targetInfo.pointerSize), (BYTE *)&objectAddress); } } EX_CATCH_HRESULT(hr); diff --git a/src/coreclr/debug/di/module.cpp b/src/coreclr/debug/di/module.cpp index 9846d82fcb9720..8303364c3c3233 100644 --- a/src/coreclr/debug/di/module.cpp +++ b/src/coreclr/debug/di/module.cpp @@ -880,7 +880,7 @@ HRESULT CordbModule::InitPublicMetaDataFromFile(const WCHAR * pszFullPathName, } return hr; -#endif // TARGET_UNIX +#endif // HOST_UNIX } //--------------------------------------------------------------------------------------- @@ -2410,7 +2410,7 @@ HRESULT CordbModule::CreateReaderForInMemorySymbols(REFIID riid, void** ppObj) ReleaseHolder pBinder; if (symFormat == IDacDbiInterface::kSymbolFormatPDB) { -#ifndef TARGET_UNIX +#ifndef HOST_UNIX // PDB format - use diasymreader.dll with COM activation InlineSString ssBuf; IfFailThrow(GetClrModuleDirectory(ssBuf)); diff --git a/src/coreclr/debug/di/platformspecific.cpp b/src/coreclr/debug/di/platformspecific.cpp index cd690dccc2fd25..e26cacb7b149df 100644 --- a/src/coreclr/debug/di/platformspecific.cpp +++ b/src/coreclr/debug/di/platformspecific.cpp @@ -21,22 +21,22 @@ #include "localeventchannel.cpp" #endif -#if TARGET_X86 +#if HOST_X86 #include "i386/cordbregisterset.cpp" #include "i386/primitives.cpp" -#elif TARGET_AMD64 +#elif HOST_AMD64 #include "amd64/cordbregisterset.cpp" #include "amd64/primitives.cpp" -#elif TARGET_ARM +#elif HOST_ARM #include "arm/cordbregisterset.cpp" #include "arm/primitives.cpp" -#elif TARGET_ARM64 +#elif HOST_ARM64 #include "arm64/cordbregisterset.cpp" #include "arm64/primitives.cpp" -#elif TARGET_LOONGARCH64 +#elif HOST_LOONGARCH64 #include "loongarch64/cordbregisterset.cpp" #include "loongarch64/primitives.cpp" -#elif TARGET_RISCV64 +#elif HOST_RISCV64 #include "riscv64/cordbregisterset.cpp" #include "riscv64/primitives.cpp" #else diff --git a/src/coreclr/debug/di/process.cpp b/src/coreclr/debug/di/process.cpp index 21ddf8b5f37383..8a985b63bda425 100644 --- a/src/coreclr/debug/di/process.cpp +++ b/src/coreclr/debug/di/process.cpp @@ -196,11 +196,11 @@ STDAPI DLLEXPORT OpenVirtualProcessImpl2( return hrInit; } #endif -#ifdef TARGET_WINDOWS +#ifdef HOST_WINDOWS HMODULE hDac = WszLoadLibrary(pDacModulePath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); #else HMODULE hDac = WszLoadLibrary(pDacModulePath); -#endif // !TARGET_WINDOWS +#endif // !HOST_WINDOWS if (hDac == NULL) { return HRESULT_FROM_WIN32(GetLastError()); @@ -681,6 +681,33 @@ IDacDbiInterface * CordbProcess::GetDAC() return m_pDacPrimitives; } +HRESULT CordbProcess::GetTargetInfo(IDacDbiInterface::TargetInfo * pTargetInfo) +{ + CONTRACTL + { + THROWS; + } + CONTRACTL_END; + + if (pTargetInfo == NULL) + return E_INVALIDARG; + + HRESULT hr = S_OK; + EX_TRY + { + if (!m_fHasCachedTargetInfo) + { + IfFailThrow(GetDAC()->GetTargetInfo(&m_cachedTargetInfo)); + m_fHasCachedTargetInfo = true; + } + + *pTargetInfo = m_cachedTargetInfo; + } + EX_CATCH_HRESULT(hr); + + return hr; +} + //--------------------------------------------------------------------------------------- // Get the Data-Target // @@ -886,6 +913,7 @@ CordbProcess::CordbProcess(ULONG64 clrInstanceId, m_hDacModule(hDacModule), m_pDacPrimitives(NULL), m_pLegacyDac(NULL), + m_fHasCachedTargetInfo(false), m_pEventChannel(NULL), m_fAssertOnTargetInconsistency(false), m_runtimeOffsetsInitialized(false), @@ -6641,7 +6669,7 @@ HRESULT CordbProcess::FindPatchByAddress(CORDB_ADDRESS address, bool *pfPatchFou if (*pfPatchFound == false) { // Read one instruction from the faulting address... -#if defined(TARGET_ARM) || defined(TARGET_ARM64) +#if defined(HOST_ARM) || defined(HOST_ARM64) PRD_TYPE TrapCheck = 0; #else BYTE TrapCheck = 0; @@ -6686,7 +6714,7 @@ HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size, DWORD fCheckInt3 = configCheckInt3.val(CLRConfig::INTERNAL_DbgCheckInt3); if (fCheckInt3) { -#if defined(TARGET_X86) || defined(TARGET_AMD64) +#if defined(HOST_X86) || defined(HOST_AMD64) if (size == 1 && buffer[0] == 0xCC) { CONSISTENCY_CHECK_MSGF(false, @@ -6695,7 +6723,7 @@ HRESULT CordbProcess::WriteMemory(CORDB_ADDRESS address, DWORD size, "(This assert is only enabled under the CLR knob DbgCheckInt3.)\n", CORDB_ADDRESS_TO_PTR(address))); } -#endif // TARGET_X86 || TARGET_AMD64 +#endif // HOST_X86 || HOST_AMD64 // check if we're replaced an opcode. if (size == 1) @@ -7133,7 +7161,7 @@ HRESULT CordbProcess::GetRuntimeOffsets() { -#if TARGET_UNIX +#if HOST_UNIX m_hHelperThread = NULL; //RS is supposed to be able to live without a helper thread handle. #else m_hHelperThread = OpenThread(SYNCHRONIZE, FALSE, dwHelperTid); @@ -8391,9 +8419,9 @@ bool CordbProcess::IsBreakOpcodeAtAddress(const void * address) { // There should have been an int3 there already. Since we already put it in there, // we should be able to safely read it out. -#if defined(TARGET_ARM) || defined(TARGET_ARM64) +#if defined(HOST_ARM) || defined(HOST_ARM64) PRD_TYPE opcodeTest = 0; -#elif defined(TARGET_AMD64) || defined(TARGET_X86) +#elif defined(HOST_AMD64) || defined(HOST_X86) BYTE opcodeTest = 0; #else PORTABILITY_ASSERT("NYI: Architecture specific opcode type to read"); @@ -8456,10 +8484,10 @@ CordbProcess::SetUnmanagedBreakpointInternal(CORDB_ADDRESS address, ULONG32 bufs HRESULT hr = S_OK; NativePatch * p = NULL; -#if defined(TARGET_X86) || defined(TARGET_AMD64) +#if defined(HOST_X86) || defined(HOST_AMD64) const BYTE patch = CORDbg_BREAK_INSTRUCTION; BYTE opcode; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) const PRD_TYPE patch = CORDbg_BREAK_INSTRUCTION; PRD_TYPE opcode; #else @@ -8498,10 +8526,10 @@ CordbProcess::SetUnmanagedBreakpointInternal(CORDB_ADDRESS address, ULONG32 bufs goto ErrExit; // It's all successful, so now update our out-params & internal bookkeaping. -#if defined(TARGET_X86) || defined(TARGET_AMD64) +#if defined(HOST_X86) || defined(HOST_AMD64) opcode = (BYTE)p->opcode; buffer[0] = opcode; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) opcode = p->opcode; memcpy_s(buffer, bufsize, &opcode, sizeof(opcode)); #else @@ -10429,7 +10457,7 @@ bool CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId) { LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded\n")); -#if defined(TARGET_WINDOWS) && defined(TARGET_AMD64) +#if defined(HOST_WINDOWS) && defined(HOST_AMD64) // Before we can read the left side context information, we must: // 1. obtain the thread handle // 2. suspened the thread @@ -12540,9 +12568,9 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven tempDebugContext.ContextFlags = DT_CONTEXT_FULL; DbiGetThreadContext(pUnmanagedThread->m_handle, &tempDebugContext); CordbUnmanagedThread::LogContext(&tempDebugContext); -#if defined(TARGET_X86) || defined(TARGET_AMD64) +#if defined(HOST_X86) || defined(HOST_AMD64) const ULONG_PTR breakpointOpcodeSize = 1; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) const ULONG_PTR breakpointOpcodeSize = 4; #else const ULONG_PTR breakpointOpcodeSize = 1; @@ -12763,7 +12791,7 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven // Because hijacks don't return normally they might have pushed handlers without poping them // back off. To take care of that we explicitly restore the old SEH chain. - #ifdef TARGET_X86 + #ifdef HOST_X86 hr = pUnmanagedThread->RestoreLeafSeh(); _ASSERTE(SUCCEEDED(hr)); #endif @@ -13170,7 +13198,7 @@ void EnableDebugTrace(CordbUnmanagedThread *ut) return; // Give us a nop so that we can setip in the optimized case. -#ifdef TARGET_X86 +#ifdef HOST_X86 __asm { nop } diff --git a/src/coreclr/debug/di/rsmain.cpp b/src/coreclr/debug/di/rsmain.cpp index e2f25163737021..8c2ead38ef5788 100644 --- a/src/coreclr/debug/di/rsmain.cpp +++ b/src/coreclr/debug/di/rsmain.cpp @@ -508,7 +508,7 @@ void CordbCommonBase::InitializeCommon() // setting this since V1.0 and removing it may be a breaking change. void CordbCommonBase::AddDebugPrivilege() { -#ifndef TARGET_UNIX +#ifndef HOST_UNIX HANDLE hToken; TOKEN_PRIVILEGES Privileges; BOOL fSucc; diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index f8011e14d564a8..7858819ab430d9 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -2861,6 +2861,8 @@ class IProcessShimHooks virtual bool IsThreadSuspendedOrHijacked(ICorDebugThread * pThread) = 0; + virtual HRESULT GetTargetInfo(IDacDbiInterface::TargetInfo * pTargetInfo) = 0; + #ifdef FEATURE_INTEROP_DEBUGGING virtual bool IsUnmanagedThreadHijacked(ICorDebugThread * pICorDebugThread) = 0; #endif @@ -3599,6 +3601,8 @@ class CordbProcess : // Get the DAC interface. IDacDbiInterface * GetDAC(); + HRESULT GetTargetInfo(IDacDbiInterface::TargetInfo * pTargetInfo); + // Get the data-target, which provides access to the debuggee. ICorDebugDataTarget * GetDataTarget(); @@ -3967,7 +3971,7 @@ class CordbProcess : PRD_TYPE *m_rgUncommittedOpcode; // CORDB_ADDRESS's are UINT_PTR's (64 bit under HOST_64BIT, 32 bit otherwise) -#if defined(TARGET_64BIT) +#if defined(HOST_64BIT) #define MAX_ADDRESS (UINT64_MAX) #else #define MAX_ADDRESS (UINT32_MAX) @@ -4094,6 +4098,9 @@ class CordbProcess : // Keeps the native fallback DAC alive until the managed cDAC has been released. IUnknown * m_pLegacyDac; + IDacDbiInterface::TargetInfo m_cachedTargetInfo; + bool m_fHasCachedTargetInfo; + IEventChannel * m_pEventChannel; // If true, then we'll ASSERT if we detect the target is corrupt or inconsistent @@ -4778,11 +4785,9 @@ class CordbType : public CordbBase, public ICorDebugType, public ICorDebugType2 // Is this type a GC-root. bool IsGCRoot(); -#ifdef FEATURE_64BIT_ALIGNMENT // checks if the type requires 8-byte alignment. // this is not exposed via ICorDebug at present. HRESULT RequiresAlign8(BOOL* isRequired); -#endif //----------------------------------------------------------- // Data members @@ -9028,7 +9033,7 @@ class CordbReferenceValue : public CordbValue, public ICorDebugReferenceValue, p // an array or string static void GetObjectData(CordbProcess * pProcess, - void * objectAddress, + CORDB_ADDRESS objectAddress, CorElementType type, VMPTR_AppDomain vmAppdomain, DacDbiObjectData * pInfo); @@ -9042,7 +9047,7 @@ class CordbReferenceValue : public CordbValue, public ICorDebugReferenceValue, p DacDbiObjectData * pInfo); // get the address of the object referenced - void * GetObjectAddress(MemoryRange localValue); + CORDB_ADDRESS GetObjectAddress(MemoryRange localValue); // update type information after initializing -- when we initialize, we may get more exact type // information than we previously had @@ -10502,7 +10507,7 @@ class CordbUnmanagedThread : public CordbBase return (DWORD) this->m_id; } -#ifdef TARGET_X86 +#ifdef HOST_X86 // Stores the thread's current leaf SEH handler HRESULT SaveCurrentLeafSeh(); // Restores the thread's leaf SEH handler from the previously saved value @@ -10550,7 +10555,7 @@ class CordbUnmanagedThread : public CordbBase ULONG_PTR m_raiseExceptionExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; -#ifdef TARGET_X86 +#ifdef HOST_X86 // the SEH handler which was the leaf when SaveCurrentSeh was called (prior to hijack) REMOTE_PTR m_pSavedLeafSeh; #endif @@ -11392,17 +11397,13 @@ inline void ValidateOrThrow(const void * p) // aligns argBase on platforms that require it else it's a no-op inline void AlignAddressForType(CordbType* pArgType, CORDB_ADDRESS& argBase) { -#ifdef TARGET_ARM -// TODO: review the following #ifdef FEATURE_64BIT_ALIGNMENT BOOL align = FALSE; HRESULT hr = pArgType->RequiresAlign8(&align); - _ASSERTE(SUCCEEDED(hr)); if (align) argBase = ALIGN_ADDRESS(argBase, 8); -#endif // FEATURE_64BIT_ALIGNMENT -#endif // TARGET_ARM +#endif } //----------------------------------------------------------------------------- diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index 345b59adaa86ea..52a8ec2290d418 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -1393,13 +1393,10 @@ HRESULT CordbThread::FindFrame(ICorDebugFrame ** ppFrame, FramePointer fp) ICorDebugFrame * pIFrame = pSSW->GetFrame(i); CordbFrame * pCFrame = CordbFrame::GetCordbFrameFromInterface(pIFrame); -#if !defined(TARGET_X86) - // Compare the FramePointer to determine if the frame matches - if (pCFrame->GetFramePointer() == fp) -#else - // On x86 we need to do a more elaborate check. The reason is that on x86, the FramePointer is always the same as the value of EBP, so we can just check if the input FramePointer is contained in the frame. However, on other platforms, the FramePointer may not be the same as the value of RSP, so we need to check if the input FramePointer is the same as the one of the frame. - if (pCFrame->IsContainedInFrame(fp)) -#endif + IDacDbiInterface::TargetInfo targetInfo; + GetProcess()->GetTargetInfo(&targetInfo); + bool frameMatches = targetInfo.arch == IDacDbiInterface::kArchX86 ? pCFrame->IsContainedInFrame(fp) : pCFrame->GetFramePointer() == fp; + if (frameMatches) { *ppFrame = pIFrame; (*ppFrame)->AddRef(); @@ -2734,7 +2731,7 @@ CordbUnmanagedThread::CordbUnmanagedThread(CordbProcess *pProcess, DWORD dwThrea m_pTLSExtendedArray(NULL), m_state(CUTS_None), m_originalHandler(NULL), -#ifdef TARGET_X86 +#ifdef HOST_X86 m_pSavedLeafSeh(NULL), #endif m_continueCountCached(0) @@ -2873,7 +2870,7 @@ VOID CordbUnmanagedThread::VerifyFSChain() return; }*/ -#ifdef TARGET_X86 +#ifdef HOST_X86 HRESULT CordbUnmanagedThread::SaveCurrentLeafSeh() { _ASSERTE(m_pSavedLeafSeh == NULL); @@ -3599,26 +3596,26 @@ VOID CordbUnmanagedThread::EndStepping() // Writes some details of the given context into the debugger log VOID CordbUnmanagedThread::LogContext(DT_CONTEXT* pContext) { -#if defined(TARGET_X86) +#if defined(HOST_X86) LOG((LF_CORDB, LL_INFO10000, "CUT::LC: Eip=0x%08x, Esp=0x%08x, Eflags=0x%08x\n", pContext->Eip, pContext->Esp, pContext->EFlags)); -#elif defined(TARGET_AMD64) +#elif defined(HOST_AMD64) LOG((LF_CORDB, LL_INFO10000, "CUT::LC: Rip=" FMT_ADDR ", Rsp=" FMT_ADDR ", Eflags=0x%08x\n", DBG_ADDR(pContext->Rip), DBG_ADDR(pContext->Rsp), pContext->EFlags)); // EFlags is still 32bits on AMD64 -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) LOG((LF_CORDB, LL_INFO10000, "CUT::LC: Pc=" FMT_ADDR ", Sp=" FMT_ADDR ", Lr=" FMT_ADDR ", Cpsr=" FMT_ADDR "\n", DBG_ADDR(pContext->Pc), DBG_ADDR(pContext->Sp), DBG_ADDR(pContext->Lr), DBG_ADDR(pContext->Cpsr))); -#else // TARGET_X86 +#else PORTABILITY_ASSERT("LogContext needs a PC and stack pointer."); -#endif // TARGET_X86 +#endif } // Hijacks this thread using the FirstChanceSuspend hijack @@ -3758,7 +3755,7 @@ HRESULT CordbUnmanagedThread::SetupFirstChanceHijack(EHijackReason::EHijackReaso { // We save off the SEH handler on X86 to make sure we restore it properly after the hijack is complete // The hijacks don't return normally and the SEH chain might have handlers added that don't get removed by default -#ifdef TARGET_X86 +#ifdef HOST_X86 hr = SaveCurrentLeafSeh(); if(FAILED(hr)) ThrowHR(hr); @@ -3814,55 +3811,57 @@ HRESULT CordbUnmanagedThread::SetupGenericHijack(DWORD eventCode, const EXCEPTIO return HRESULT_FROM_WIN32(GetLastError()); } -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) - - // On X86 Debugger::GenericHijackFunc() ensures the stack is walkable - // by simply using the EBP chain, therefore we can execute the hijack - // by setting the thread's context EIP to point to this function. - // On X64, however, we first attempt to set up a "proper" hijack, with - // a function that allows the OS to unwind the stack (ExceptionHijack). - // If this fails we'll use the same method as on X86, even though the - // stack will become un-walkable + IDacDbiInterface::TargetInfo targetInfo; + GetProcess()->GetTargetInfo(&targetInfo); + if (targetInfo.arch != IDacDbiInterface::kArchX86) + { + // On X86 Debugger::GenericHijackFunc() ensures the stack is walkable + // by simply using the EBP chain, therefore we can execute the hijack + // by setting the thread's context EIP to point to this function. + // On X64, however, we first attempt to set up a "proper" hijack, with + // a function that allows the OS to unwind the stack (ExceptionHijack). + // If this fails we'll use the same method as on X86, even though the + // stack will become un-walkable - ULONG32 dwThreadId = GetOSTid(); - CordbThread * pThread = GetProcess()->TryLookupOrCreateThreadByVolatileOSId(dwThreadId); + ULONG32 dwThreadId = GetOSTid(); + CordbThread * pThread = GetProcess()->TryLookupOrCreateThreadByVolatileOSId(dwThreadId); - // For threads in the thread store we set up the full size - // hijack, otherwise we fallback to hijacking by SetIP. - if (pThread != NULL) - { - HRESULT hr = S_OK; - EX_TRY + // For threads in the thread store we set up the full size + // hijack, otherwise we fallback to hijacking by SetIP. + if (pThread != NULL) { - // Note that the data-target is not atomic, and we have no rollback mechanism. - // We have to do several writes. If the data-target fails the writes half-way through the - // target will be inconsistent. - IfFailThrow(GetProcess()->GetDAC()->Hijack( - pThread->m_vmThreadToken, - dwThreadId, - pRecord, - (T_CONTEXT*) GetHijackCtx(), - sizeof(T_CONTEXT), - EHijackReason::kGenericHijack, - NULL, - NULL)); - } - EX_CATCH_HRESULT(hr); - if (SUCCEEDED(hr)) - { - // Remember that we've hijacked the thread. - SetState(CUTS_GenericHijacked); + HRESULT hr = S_OK; + EX_TRY + { + // Note that the data-target is not atomic, and we have no rollback mechanism. + // We have to do several writes. If the data-target fails the writes half-way through the + // target will be inconsistent. + IfFailThrow(GetProcess()->GetDAC()->Hijack( + pThread->m_vmThreadToken, + dwThreadId, + pRecord, + (T_CONTEXT*) GetHijackCtx(), + sizeof(T_CONTEXT), + EHijackReason::kGenericHijack, + NULL, + NULL)); + } + EX_CATCH_HRESULT(hr); + if (SUCCEEDED(hr)) + { + // Remember that we've hijacked the thread. + SetState(CUTS_GenericHijacked); - return S_OK; - } + return S_OK; + } - STRESS_LOG1(LF_CORDB, LL_INFO1000, "CUT::SGH: Error setting up hijack context hr=0x%x\n", hr); - // fallthrough (above hijack might have failed due to stack overflow, for example) + STRESS_LOG1(LF_CORDB, LL_INFO1000, "CUT::SGH: Error setting up hijack context hr=0x%x\n", hr); + // fallthrough (above hijack might have failed due to stack overflow, for example) - } - // else (non-threadstore threads) fallthrough + } + // else (non-threadstore threads) fallthrough -#endif // TARGET_AMD64 || defined(TARGET_ARM64) + } // Remember that we've hijacked the thread. SetState(CUTS_GenericHijacked); @@ -4027,7 +4026,7 @@ void CordbUnmanagedThread::SetupForSkipBreakpoint(NativePatch * pNativePatch) fTrapOnSkip = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_DbgTrapOnSkip); } #endif -#if defined(TARGET_X86) +#if defined(HOST_X86) STRESS_LOG2(LF_CORDB, LL_INFO100, "CUT::SetupSkip. addr=%p. Opcode=%x\n", pNativePatch->pAddress, (DWORD) pNativePatch->opcode); #endif @@ -4080,11 +4079,11 @@ void CordbUnmanagedThread::FixupForSkipBreakpoint() inline TADDR GetSP(DT_CONTEXT* context) { -#if defined(TARGET_X86) +#if defined(HOST_X86) return (TADDR)context->Esp; -#elif defined(TARGET_AMD64) +#elif defined(HOST_AMD64) return (TADDR)context->Rsp; -#elif defined(TARGET_ARM) || defined(TARGET_ARM64) +#elif defined(HOST_ARM) || defined(HOST_ARM64) return (TADDR)context->Sp; #else _ASSERTE(!"nyi for platform"); @@ -4227,17 +4226,17 @@ void CordbUnmanagedThread::SaveRaiseExceptionEntryContext() // calculate the exception that we would expect to come from this invocation of RaiseException REMOTE_PTR pExceptionInformation = NULL; -#if defined(TARGET_AMD64) +#if defined(HOST_AMD64) m_raiseExceptionExceptionCode = (DWORD)m_raiseExceptionEntryContext.Rcx; m_raiseExceptionExceptionFlags = (DWORD)m_raiseExceptionEntryContext.Rdx; m_raiseExceptionNumberParameters = (DWORD)m_raiseExceptionEntryContext.R8; pExceptionInformation = (REMOTE_PTR)m_raiseExceptionEntryContext.R9; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) m_raiseExceptionExceptionCode = (DWORD)m_raiseExceptionEntryContext.X0; m_raiseExceptionExceptionFlags = (DWORD)m_raiseExceptionEntryContext.X1; m_raiseExceptionNumberParameters = (DWORD)m_raiseExceptionEntryContext.X2; pExceptionInformation = (REMOTE_PTR)m_raiseExceptionEntryContext.X3; -#elif defined(TARGET_X86) +#elif defined(HOST_X86) hr = m_pProcess->SafeReadStruct(PTR_TO_CORDB_ADDRESS((BYTE*)m_raiseExceptionEntryContext.Esp+4), &m_raiseExceptionExceptionCode); if(FAILED(hr)) { @@ -4357,9 +4356,9 @@ BOOL CordbUnmanagedThread::IsExceptionFromLastRaiseException(const EXCEPTION_REC // This flavor is assuming our caller already knows the opcode. HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress) { -#if defined(TARGET_X86) || defined(TARGET_AMD64) +#if defined(HOST_X86) || defined(HOST_AMD64) const BYTE patch = CORDbg_BREAK_INSTRUCTION; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) const PRD_TYPE patch = CORDbg_BREAK_INSTRUCTION; #else const BYTE patch = 0; @@ -4374,10 +4373,10 @@ HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress) // Get the opcode that we're replacing. HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress, PRD_TYPE * pOpcode) { -#if defined(TARGET_X86) || defined(TARGET_AMD64) +#if defined(HOST_X86) || defined(HOST_AMD64) // Read out opcode. 1 byte on x86 BYTE opcode; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) // Read out opcode. 4 bytes on arm64 PRD_TYPE opcode; #else @@ -4401,10 +4400,10 @@ HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress, P //----------------------------------------------------------------------------- HRESULT RemoveRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress, PRD_TYPE opcode) { -#if defined(TARGET_X86) || defined(TARGET_AMD64) +#if defined(HOST_X86) || defined(HOST_AMD64) // Replace the BP w/ the opcode. BYTE opcode2 = (BYTE) opcode; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) // 4 bytes on arm64 PRD_TYPE opcode2 = opcode; #else @@ -4712,7 +4711,7 @@ HRESULT CordbFrame::CreateStepper(ICorDebugStepper **ppStepper) //--------------------------------------------------------------------------------------- // -// Given a frame pointer, determine if it is in the stack range owned by the frame. +// X86-specific helper: Given a frame pointer, determine if it is in the stack range owned by the frame. // // Arguments: // fp - frame pointer to check @@ -4733,7 +4732,6 @@ bool CordbFrame::IsContainedInFrame(FramePointer fp) CORDB_ADDRESS sp = PTR_TO_CORDB_ADDRESS(fp.GetSPValue()); -#if defined(TARGET_X86) // On x86, the runtime sends CallerSP - sizeof(TADDR) as the frame pointer // for exception notifications (see GetSpForDiagnosticReporting). Since this // does not account for the stack parameter size, we adjust for it here. @@ -4752,7 +4750,6 @@ bool CordbFrame::IsContainedInFrame(FramePointer fp) } } } -#endif // TARGET_X86 if ((stackStart <= sp) && (sp <= stackEnd)) { @@ -5937,13 +5934,18 @@ HRESULT CordbNativeFrame::GetStackParameterSize(ULONG32 * pSize) ThrowHR(E_INVALIDARG); } -#if defined(TARGET_X86) IDacDbiInterface * pDAC = GetProcess()->GetDAC(); - IfFailThrow(pDAC->GetStackParameterSize(PTR_TO_CORDB_ADDRESS(CORDbgGetIP(&m_context)), pSize)); -#else // !TARGET_X86 - hr = S_FALSE; - *pSize = 0; -#endif // TARGET_X86 + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + if (targetInfo.arch == IDacDbiInterface::kArchX86) + { + IfFailThrow(pDAC->GetStackParameterSize(PTR_TO_CORDB_ADDRESS(CORDbgGetIP(&m_context)), pSize)); + } + else + { + hr = S_FALSE; + *pSize = 0; + } } EX_CATCH_HRESULT(hr); @@ -6708,18 +6710,32 @@ HRESULT CordbNativeFrame::GetLocalRegisterValue(CorDebugRegister reg, VALIDATE_POINTER_TO_OBJECT(ppValue, ICorDebugValue **); ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); -#if defined(TARGET_X86) || defined(TARGET_64BIT) -#if defined(TARGET_X86) - if ((reg >= REGISTER_X86_FPSTACK_0) && (reg <= REGISTER_X86_FPSTACK_7)) -#elif defined(TARGET_AMD64) - if ((reg >= REGISTER_AMD64_XMM0) && (reg <= REGISTER_AMD64_XMM15)) -#elif defined(TARGET_ARM64) - if ((reg >= REGISTER_ARM64_V0) && (reg <= REGISTER_ARM64_V31)) -#endif + bool isFloatingPoint = false; + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + switch (targetInfo.arch) { - return GetLocalFloatingPointValue(reg, pType, ppValue); + case IDacDbiInterface::kArchX86: + isFloatingPoint = (reg >= REGISTER_X86_FPSTACK_0) && (reg <= REGISTER_X86_FPSTACK_7); + break; + case IDacDbiInterface::kArchAMD64: + isFloatingPoint = (reg >= REGISTER_AMD64_XMM0) && (reg <= REGISTER_AMD64_XMM15); + break; + case IDacDbiInterface::kArchArm64: + isFloatingPoint = (reg >= REGISTER_ARM64_V0) && (reg <= REGISTER_ARM64_V31); + break; + case IDacDbiInterface::kArchRiscV64: + isFloatingPoint = (reg >= REGISTER_RISCV64_F0) && (reg <= REGISTER_RISCV64_F31); + break; + case IDacDbiInterface::kArchLoongArch64: + isFloatingPoint = (reg >= REGISTER_LOONGARCH64_F0) && (reg <= REGISTER_LOONGARCH64_F31); + break; + default: + break; } -#endif + + if (isFloatingPoint) + return GetLocalFloatingPointValue(reg, pType, ppValue); // The address of the given register is the address of the value // in this process. We have no remote address here. @@ -6733,12 +6749,15 @@ HRESULT CordbNativeFrame::GetLocalRegisterValue(CorDebugRegister reg, EnregisteredValueHomeHolder pRemoteReg(new RegValueHome(this, reg)); EnregisteredValueHomeHolder * pRegHolder = pRemoteReg.GetAddr(); + ULONG32 valueSize = CordbValue::GetSizeForType(pType, kUnboxed); + _ASSERTE(valueSize <= REG_SIZE); + ICorDebugValue *pValue; CordbValue::CreateValueByType(GetCurrentAppDomain(), pType, false, EMPTY_BUFFER, - MemoryRange(pLocalValue, REG_SIZE), + MemoryRange(pLocalValue, valueSize), pRegHolder, &pValue); // throws @@ -6958,33 +6977,6 @@ HRESULT CordbNativeFrame::GetLocalFloatingPointValue(DWORD index, (et != ELEMENT_TYPE_R8)) return E_INVALIDARG; -#if defined(TARGET_AMD64) - if (!((index >= REGISTER_AMD64_XMM0) && - (index <= REGISTER_AMD64_XMM15))) - return E_INVALIDARG; - index -= REGISTER_AMD64_XMM0; -#elif defined(TARGET_ARM64) - if (!((index >= REGISTER_ARM64_V0) && - (index <= REGISTER_ARM64_V31))) - return E_INVALIDARG; - index -= REGISTER_ARM64_V0; -#elif defined(TARGET_ARM) - if (!((index >= REGISTER_ARM_D0) && - (index <= REGISTER_ARM_D31))) - return E_INVALIDARG; - index -= REGISTER_ARM_D0; -#elif defined(TARGET_RISCV64) - if (!((index >= REGISTER_RISCV64_F0) && - (index <= REGISTER_RISCV64_F31))) - return E_INVALIDARG; - index -= REGISTER_RISCV64_F0; -#else - if (!((index >= REGISTER_X86_FPSTACK_0) && - (index <= REGISTER_X86_FPSTACK_7))) - return E_INVALIDARG; - index -= REGISTER_X86_FPSTACK_0; -#endif - ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); @@ -7003,22 +6995,26 @@ HRESULT CordbNativeFrame::GetLocalFloatingPointValue(DWORD index, EX_CATCH_HRESULT(hr); if (SUCCEEDED(hr)) { -#if !defined(TARGET_64BIT) - // This is needed on x86 because we are dealing with a stack. - index = pThread->m_floatStackTop - index; -#endif + IDacDbiInterface::TargetInfo targetInfo; + GetProcess()->GetTargetInfo(&targetInfo); + if (targetInfo.arch == IDacDbiInterface::kArchX86) + { + // This is needed on x86 because we are dealing with a stack. + index = pThread->m_floatStackTop - index; + } if (index >= (sizeof(pThread->m_floatValues) / sizeof(pThread->m_floatValues[0]))) return E_INVALIDARG; -#ifdef TARGET_X86 - // A workaround (sort of) to get around the difference in format between - // a float value and a double value. We can't simply cast a double pointer to - // a float pointer. Instead, we have to cast the double itself to a float. - if (pType->m_elementType == ELEMENT_TYPE_R4) - *(float *)&(pThread->m_floatValues[index]) = (float)pThread->m_floatValues[index]; -#endif + if (targetInfo.arch == IDacDbiInterface::kArchX86) + { + // A workaround (sort of) to get around the difference in format between + // a float value and a double value. We can't simply cast a double pointer to + // a float pointer. Instead, we have to cast the double itself to a float. + if (pType->m_elementType == ELEMENT_TYPE_R4) + *(float *)&(pThread->m_floatValues[index]) = (float)pThread->m_floatValues[index]; + } ICorDebugValue* pValue; @@ -7469,12 +7465,17 @@ HRESULT CordbJITILFrame::Init() IfFailThrow(GetArgumentType(0, &pArgType)); ULONG32 argSize = 0; IfFailThrow(pArgType->GetUnboxedObjectSize(&argSize)); -#if defined(TARGET_X86) // (STACK_GROWS_DOWN_ON_ARGS_WALK) - m_FirstArgAddr = argBase - argSize; -#else // !TARGET_X86 (STACK_GROWS_UP_ON_ARGS_WALK) - AlignAddressForType(pArgType, argBase); - m_FirstArgAddr = argBase; -#endif // !TARGET_X86 (STACK_GROWS_UP_ON_ARGS_WALK) + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + if (targetInfo.arch == IDacDbiInterface::kArchX86) + { + m_FirstArgAddr = argBase - argSize; + } + else + { + AlignAddressForType(pArgType, argBase); + m_FirstArgAddr = argBase; + } } // The stackwalking code can't always successfully retrieve the generics type token. @@ -8102,21 +8103,8 @@ HRESULT CordbJITILFrame::FabricateNativeInfo(DWORD dwIndex, } else { - // We'll initialize everything at once - ULONG cbArchitectureMin; - - // m_FirstArgAddr will already be aligned on platforms that require alignment CORDB_ADDRESS rpCur = m_FirstArgAddr; -#if defined(TARGET_X86) || defined(TARGET_ARM) - cbArchitectureMin = 4; -#elif defined(TARGET_64BIT) - cbArchitectureMin = 8; -#else - cbArchitectureMin = 8; //REVISIT_TODO not sure if this is correct - PORTABILITY_ASSERT("What is the architecture-dependent minimum word size?"); -#endif // TARGET_X86 - // make a copy of the cached SigParser SigParser sigParser = m_sigParserCached; @@ -8134,13 +8122,16 @@ HRESULT CordbJITILFrame::FabricateNativeInfo(DWORD dwIndex, IfFailThrow(pArgType->GetUnboxedObjectSize(&cbType)); -#if defined(TARGET_X86) // STACK_GROWS_DOWN_ON_ARGS_WALK - // The rpCur pointer starts off in the right spot for the - // first argument, but thereafter we have to decrement it - // before getting the variable's location from it. So increment - // it here to be consistent later. - rpCur += max((ULONG)cbType, cbArchitectureMin); -#endif + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + if (targetInfo.arch == IDacDbiInterface::kArchX86) + { + // The rpCur pointer starts off in the right spot for the + // first argument, but thereafter we have to decrement it + // before getting the variable's location from it. So increment + // it here to be consistent later. + rpCur += max((ULONG)cbType, (ULONG)targetInfo.pointerSize); + } // Grab the IL code's function's method signature so we can see if it's static. BOOL fMethodIsStatic; @@ -8171,20 +8162,23 @@ HRESULT CordbJITILFrame::FabricateNativeInfo(DWORD dwIndex, IfFailThrow(pArgType->GetUnboxedObjectSize(&cbType)); -#if defined(TARGET_X86) // STACK_GROWS_DOWN_ON_ARGS_WALK - rpCur -= max((ULONG)cbType, cbArchitectureMin); - m_rgNVI[i].loc.vlFixedVarArg.vlfvOffset = - (unsigned)(m_FirstArgAddr - rpCur); - - // Since the JIT adds in the size of this field, we do too to - // be consistent. - m_rgNVI[i].loc.vlFixedVarArg.vlfvOffset += sizeof(((CORINFO_VarArgInfo*)0)->argBytes); -#else // STACK_GROWS_UP_ON_ARGS_WALK - m_rgNVI[i].loc.vlFixedVarArg.vlfvOffset = - (unsigned)(rpCur - m_FirstArgAddr); - rpCur += max((ULONG)cbType, cbArchitectureMin); - AlignAddressForType(pArgType, rpCur); -#endif + if (targetInfo.arch == IDacDbiInterface::kArchX86) + { + rpCur -= max((ULONG)cbType, (ULONG)targetInfo.pointerSize); + m_rgNVI[i].loc.vlFixedVarArg.vlfvOffset = + (unsigned)(m_FirstArgAddr - rpCur); + + // Since the JIT adds in the size of this field, we do too to + // be consistent. + m_rgNVI[i].loc.vlFixedVarArg.vlfvOffset += sizeof(((CORINFO_VarArgInfo*)0)->argBytes); + } + else + { + m_rgNVI[i].loc.vlFixedVarArg.vlfvOffset = + (unsigned)(rpCur - m_FirstArgAddr); + rpCur += max((ULONG)cbType, (ULONG)targetInfo.pointerSize); + AlignAddressForType(pArgType, rpCur); + } IfFailThrow(sigParser.SkipExactlyOne()); } // for ( ; i M m_allArgsCount; i++) @@ -8355,27 +8349,34 @@ HRESULT CordbJITILFrame::GetNativeVariable(CordbType *type, } break; -#if defined(TARGET_64BIT) || defined(TARGET_ARM) case ICorDebugInfo::VLT_REG_FP: -#if defined(TARGET_ARM) // @ARMTODO - hr = E_NOTIMPL; -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) - // AMD64/ARM64 enumerate the FP registers in the debug RegNum enum - // (XMM0-15 / V0-31), so g_JITToCorDbgReg maps vlrReg directly to the - // corresponding CorDebugRegister. - hr = m_nativeFrame->GetLocalFloatingPointValue(ConvertRegNumToCorDebugRegister(pNativeVarInfo->loc.vlReg.vlrReg), - type, ppValue); -#elif defined(TARGET_LOONGARCH64) - hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_LOONGARCH64_F0, - type, ppValue); -#elif defined(TARGET_RISCV64) - hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_RISCV64_F0, + { + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + switch (targetInfo.arch) + { + case IDacDbiInterface::kArchArm64: + case IDacDbiInterface::kArchAMD64: + // AMD64/ARM64 enumerate the FP registers in the debug RegNum enum + // (XMM0-15 / V0-31), so g_JITToCorDbgReg maps vlrReg directly to the + // corresponding CorDebugRegister. + hr = m_nativeFrame->GetLocalFloatingPointValue(ConvertRegNumToCorDebugRegister(pNativeVarInfo->loc.vlReg.vlrReg), + type, ppValue); + break; + case IDacDbiInterface::kArchLoongArch64: + hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_LOONGARCH64_F0, + type, ppValue); + break; + case IDacDbiInterface::kArchRiscV64: + hr = m_nativeFrame->GetLocalFloatingPointValue(pNativeVarInfo->loc.vlReg.vlrReg + REGISTER_RISCV64_F0, type, ppValue); -#else -#error Platform not implemented -#endif // TARGET_ARM @ARMTODO + break; + default: + break; + } + } + break; -#endif // TARGET_64BIT || TARGET_ARM case ICorDebugInfo::VLT_STK_BYREF: { @@ -8487,13 +8488,18 @@ HRESULT CordbJITILFrame::GetNativeVariable(CordbType *type, CORDB_ADDRESS pRemoteValue; -#if defined(TARGET_X86) // STACK_GROWS_DOWN_ON_ARGS_WALK - pRemoteValue = m_FirstArgAddr - pNativeVarInfo->loc.vlFixedVarArg.vlfvOffset; - // Remember to subtract out this amount - pRemoteValue += sizeof(((CORINFO_VarArgInfo*)0)->argBytes); -#else // STACK_GROWS_UP_ON_ARGS_WALK - pRemoteValue = m_FirstArgAddr + pNativeVarInfo->loc.vlFixedVarArg.vlfvOffset; -#endif + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(GetProcess()->GetTargetInfo(&targetInfo)); + if (targetInfo.arch == IDacDbiInterface::kArchX86) + { + pRemoteValue = m_FirstArgAddr - pNativeVarInfo->loc.vlFixedVarArg.vlfvOffset; + // Remember to subtract out this amount + pRemoteValue += sizeof(((CORINFO_VarArgInfo*)0)->argBytes); + } + else + { + pRemoteValue = m_FirstArgAddr + pNativeVarInfo->loc.vlFixedVarArg.vlfvOffset; + } hr = m_nativeFrame->GetLocalMemoryValue(pRemoteValue, type, diff --git a/src/coreclr/debug/di/rstype.cpp b/src/coreclr/debug/di/rstype.cpp index 86bc53ec3985f7..bae56b32603335 100644 --- a/src/coreclr/debug/di/rstype.cpp +++ b/src/coreclr/debug/di/rstype.cpp @@ -2726,7 +2726,6 @@ void CordbType::GatherTypeDataForInstantiation(unsigned int genericArgsCount, IC } } -#ifdef FEATURE_64BIT_ALIGNMENT // checks if the type requires 8-byte alignment. the algorithm used here // was adapted from AdjustArgPtrForAlignment() in bcltype/VarArgsNative.cpp HRESULT CordbType::RequiresAlign8(BOOL* isRequired) @@ -2770,7 +2769,6 @@ HRESULT CordbType::RequiresAlign8(BOOL* isRequired) return hr; } -#endif /* ------------------------------------------------------------------------- * * TypeParameter Enumerator class diff --git a/src/coreclr/debug/di/shimdatatarget.h b/src/coreclr/debug/di/shimdatatarget.h index 1786671c8d354c..0ab0d5bf5f82b3 100644 --- a/src/coreclr/debug/di/shimdatatarget.h +++ b/src/coreclr/debug/di/shimdatatarget.h @@ -14,6 +14,8 @@ // Function to invoke for typedef HRESULT (*FPContinueStatusChanged)(void * pUserData, DWORD dwThreadId, CORDB_CONTINUE_STATUS dwContinueStatus); +class ShimProcess; + //--------------------------------------------------------------------------------------- // Data target for a live process. This is used by Shim. // @@ -26,6 +28,9 @@ class ShimDataTarget : public ICorDebugMutableDataTarget, ICorDebugDataTarget4 // Allow hooking an implementation for ContinueStatusChanged. void HookContinueStatusChanged(FPContinueStatusChanged fpContinueStatusChanged, void * pUserData); + void SetShimProcess(ShimProcess * pShim) { m_pShim = pShim; } + ShimProcess * GetShimProcess() { return m_pShim; } + // Release any resources. Also called by destructor. virtual void Dispose() = 0; @@ -101,6 +106,8 @@ class ShimDataTarget : public ICorDebugMutableDataTarget, ICorDebugDataTarget4 FPContinueStatusChanged m_fpContinueStatusChanged; void * m_pContinueStatusChangedUserData; + ShimProcess * m_pShim = NULL; + // Reference count. LONG m_ref; }; diff --git a/src/coreclr/debug/di/shimlocaldatatarget.cpp b/src/coreclr/debug/di/shimlocaldatatarget.cpp index 8bad40ee735e29..88a7b0f65f2f67 100644 --- a/src/coreclr/debug/di/shimlocaldatatarget.cpp +++ b/src/coreclr/debug/di/shimlocaldatatarget.cpp @@ -81,7 +81,7 @@ class ShimLocalDataTarget : public ShimDataTarget // Note: throws BOOL CompatibleHostAndTargetPlatforms(HANDLE hTargetProcess) { -#if defined(TARGET_UNIX) +#if defined(HOST_UNIX) return TRUE; #else // get the platform for the host process @@ -278,17 +278,17 @@ HRESULT STDMETHODCALLTYPE ShimLocalDataTarget::GetPlatform( CorDebugPlatform *pPlatform) { -#ifdef TARGET_UNIX +#ifdef HOST_UNIX #error ShimLocalDataTarget is not implemented on PAL systems yet #endif // Assume that we're running on Windows for now. -#if defined(TARGET_X86) +#if defined(HOST_X86) *pPlatform = CORDB_PLATFORM_WINDOWS_X86; -#elif defined(TARGET_AMD64) +#elif defined(HOST_AMD64) *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64; -#elif defined(TARGET_ARM) +#elif defined(HOST_ARM) *pPlatform = CORDB_PLATFORM_WINDOWS_ARM; -#elif defined(TARGET_ARM64) +#elif defined(HOST_ARM64) *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64; #else #error Unknown Processor. @@ -462,9 +462,6 @@ ShimLocalDataTarget::ContinueStatusChanged( HRESULT STDMETHODCALLTYPE ShimLocalDataTarget::VirtualUnwind(DWORD threadId, ULONG32 contextSize, PBYTE context) { -#ifndef TARGET_UNIX - _ASSERTE(!"ShimLocalDataTarget::VirtualUnwind NOT IMPLEMENTED"); -#endif return E_NOTIMPL; } diff --git a/src/coreclr/debug/di/shimpriv.h b/src/coreclr/debug/di/shimpriv.h index fbc1bb0a5b6f1f..4c575e480a9a8f 100644 --- a/src/coreclr/debug/di/shimpriv.h +++ b/src/coreclr/debug/di/shimpriv.h @@ -20,6 +20,7 @@ // Forward declarations class CordbWin32EventThread; class Cordb; +struct IDacDbiInterface; class ShimStackWalk; class ShimChain; diff --git a/src/coreclr/debug/di/shimprocess.cpp b/src/coreclr/debug/di/shimprocess.cpp index 363cd07f926ff1..3992cc5a5b5825 100644 --- a/src/coreclr/debug/di/shimprocess.cpp +++ b/src/coreclr/debug/di/shimprocess.cpp @@ -159,6 +159,7 @@ HRESULT ShimProcess::InitializeDataTarget(const ProcessDescriptor * pProcessDesc return hr; } m_pLiveDataTarget->HookContinueStatusChanged(ShimProcess::ContinueStatusChanged, this); + m_pLiveDataTarget->SetShimProcess(this); // Ref on pDataTarget is now 1. _ASSERTE(m_pLiveDataTarget != NULL); diff --git a/src/coreclr/debug/di/shimremotedatatarget.cpp b/src/coreclr/debug/di/shimremotedatatarget.cpp index 2690de4a5b3a42..3849eaf6a92f1a 100644 --- a/src/coreclr/debug/di/shimremotedatatarget.cpp +++ b/src/coreclr/debug/di/shimremotedatatarget.cpp @@ -248,39 +248,45 @@ HRESULT STDMETHODCALLTYPE ShimRemoteDataTarget::GetPlatform( CorDebugPlatform *pPlatform) { -#ifdef TARGET_UNIX - #if defined(TARGET_X86) - *pPlatform = CORDB_PLATFORM_POSIX_X86; - #elif defined(TARGET_AMD64) - *pPlatform = CORDB_PLATFORM_POSIX_AMD64; - #elif defined(TARGET_ARM) - *pPlatform = CORDB_PLATFORM_POSIX_ARM; - #elif defined(TARGET_ARM64) - *pPlatform = CORDB_PLATFORM_POSIX_ARM64; - #elif defined(TARGET_LOONGARCH64) - *pPlatform = CORDB_PLATFORM_POSIX_LOONGARCH64; - #elif defined(TARGET_RISCV64) - *pPlatform = CORDB_PLATFORM_POSIX_RISCV64; - #else - #error Unknown Processor. - #endif -#else - #if defined(TARGET_X86) - *pPlatform = CORDB_PLATFORM_WINDOWS_X86; - #elif defined(TARGET_AMD64) - *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64; - #elif defined(TARGET_ARM) - *pPlatform = CORDB_PLATFORM_WINDOWS_ARM; - #elif defined(TARGET_ARM64) - *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64; - #elif defined(TARGET_LOONGARCH64) - *pPlatform = CORDB_PLATFORM_WINDOWS_LOONGARCH64; - #else - #error Unknown Processor. - #endif -#endif + ShimProcess * pShim = GetShimProcess(); + if (pShim != NULL) + { + CordbProcess * pProcess = static_cast(pShim->GetProcess()); + if (pProcess != NULL) + { + IDacDbiInterface::TargetInfo targetInfo; + if (SUCCEEDED(pProcess->GetTargetInfo(&targetInfo))) + { + if (targetInfo.os == IDacDbiInterface::kOSWindows) + { + switch (targetInfo.arch) + { + case IDacDbiInterface::kArchX86: *pPlatform = CORDB_PLATFORM_WINDOWS_X86; return S_OK; + case IDacDbiInterface::kArchAMD64: *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64; return S_OK; + case IDacDbiInterface::kArchArm: *pPlatform = CORDB_PLATFORM_WINDOWS_ARM; return S_OK; + case IDacDbiInterface::kArchArm64: *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64; return S_OK; + default: break; + } + } + else if (targetInfo.os == IDacDbiInterface::kOSUnix) + { + switch (targetInfo.arch) + { + case IDacDbiInterface::kArchX86: *pPlatform = CORDB_PLATFORM_POSIX_X86; return S_OK; + case IDacDbiInterface::kArchAMD64: *pPlatform = CORDB_PLATFORM_POSIX_AMD64; return S_OK; + case IDacDbiInterface::kArchArm: *pPlatform = CORDB_PLATFORM_POSIX_ARM; return S_OK; + case IDacDbiInterface::kArchArm64: *pPlatform = CORDB_PLATFORM_POSIX_ARM64; return S_OK; + case IDacDbiInterface::kArchLoongArch64: *pPlatform = CORDB_PLATFORM_POSIX_LOONGARCH64; return S_OK; + case IDacDbiInterface::kArchRiscV64: *pPlatform = CORDB_PLATFORM_POSIX_RISCV64; return S_OK; + default: break; + } + } + return S_OK; + } + } + } - return S_OK; + return E_FAIL; } // impl of interface method ICorDebugDataTarget::ReadVirtual @@ -342,7 +348,7 @@ ShimRemoteDataTarget::ReadVirtual( // pread on /proc//mem treats the offset as a file position, not a virtual address, // so the kernel does not apply TBI -- tagged pointers cause EINVAL. // See https://www.kernel.org/doc/html/latest/arch/arm64/tagged-address-abi.html -#ifdef TARGET_ARM64 +#ifdef HOST_ARM64 address &= 0x00FFFFFFFFFFFFFFULL; #endif ssize_t r = pread((int)m_memoryHandle, pBuffer, cbRequestSize, (off_t)address); diff --git a/src/coreclr/debug/di/shimstackwalk.cpp b/src/coreclr/debug/di/shimstackwalk.cpp index f289788507a54e..bd8a6310c09900 100644 --- a/src/coreclr/debug/di/shimstackwalk.cpp +++ b/src/coreclr/debug/di/shimstackwalk.cpp @@ -14,14 +14,6 @@ #include "stdafx.h" #include "primitives.h" -#if defined(TARGET_X86) -static const ULONG32 REGISTER_X86_MAX = REGISTER_X86_FPSTACK_7 + 1; -static const ULONG32 MAX_MASK_COUNT = (REGISTER_X86_MAX + 7) >> 3; -#elif defined(TARGET_AMD64) -static const ULONG32 REGISTER_AMD64_MAX = REGISTER_AMD64_XMM15 + 1; -static const ULONG32 MAX_MASK_COUNT = (REGISTER_AMD64_MAX + 7) >> 3; -#endif - ShimStackWalk::ShimStackWalk(ShimProcess * pProcess, ICorDebugThread * pThread) : m_pChainEnumList(NULL), m_pFrameEnumList(NULL) @@ -1119,12 +1111,18 @@ void ShimStackWalk::AppendChain(ChainInfo * pChainInfo, StackWalkInfo * pStackWa // We need to send an extra enter-managed chain. _ASSERTE(pChainInfo->m_fLeafNativeContextIsValid); BYTE * sp = reinterpret_cast(CORDB_ADDRESS_TO_PTR(CORDbgGetSP(&(pChainInfo->m_leafNativeContext)))); -#if !defined(TARGET_ARM) && !defined(TARGET_ARM64) + IDacDbiInterface::TargetInfo targetInfo; // Dev11 324806: on ARM we use the caller's SP for a frame's ending delimiter so we cannot - // subtract 4 bytes from the chain's ending delimiter else the frame might never be in range. + // subtract from the chain's ending delimiter else the frame might never be in range. // TODO: revisit overlapping ranges on ARM, it would be nice to make it consistent with the other architectures. - sp -= sizeof(LPVOID); -#endif + CordbProcess * pProcess = static_cast(m_pProcess->GetProcess()); + if (pProcess != NULL && + SUCCEEDED(pProcess->GetTargetInfo(&targetInfo)) && + targetInfo.arch != IDacDbiInterface::kArchArm && + targetInfo.arch != IDacDbiInterface::kArchArm64) + { + sp -= targetInfo.pointerSize; + } FramePointer fp = FramePointer::MakeFramePointer(sp); AppendChainWorker(pStackWalkInfo, diff --git a/src/coreclr/debug/di/valuehome.cpp b/src/coreclr/debug/di/valuehome.cpp index 24230bb6c85cd1..813e3038287b09 100644 --- a/src/coreclr/debug/di/valuehome.cpp +++ b/src/coreclr/debug/di/valuehome.cpp @@ -190,6 +190,7 @@ void RegValueHome::SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pCont // If the value is in a reg, then it's going to be a register's width (regardless of // the actual width of the data). // For signed types, like i2, i1, make sure we sign extend. + IDacDbiInterface::TargetInfo targetInfo; if (fIsSigned) { @@ -203,10 +204,13 @@ void RegValueHome::SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pCont extendedVal = (SSIZE_T) *(short*)newValue.StartAddress(); break; case 4: _ASSERTE(sizeof(DWORD) == 4); extendedVal = (SSIZE_T) *(int*)newValue.StartAddress(); break; -#if defined(TARGET_64BIT) - case 8: _ASSERTE(sizeof(ULONGLONG) == 8); - extendedVal = (SSIZE_T) *(ULONGLONG*)newValue.StartAddress(); break; -#endif // TARGET_64BIT + case 8: + { + IfFailThrow(m_pFrame->GetProcess()->GetTargetInfo(&targetInfo)); + _ASSERTE(targetInfo.pointerSize == 8); + extendedVal = (SSIZE_T) *(INT64*)newValue.StartAddress(); + break; + } default: _ASSERTE(!"bad size"); } } @@ -221,10 +225,13 @@ void RegValueHome::SetEnregisteredValue(MemoryRange newValue, DT_CONTEXT * pCont extendedVal = *( WORD*)newValue.StartAddress(); break; case 4: _ASSERTE(sizeof(DWORD) == 4); extendedVal = *(DWORD*)newValue.StartAddress(); break; -#if defined(TARGET_64BIT) - case 8: _ASSERTE(sizeof(ULONGLONG) == 8); - extendedVal = *(ULONGLONG*)newValue.StartAddress(); break; -#endif // TARGET_64BIT + case 8: + { + IfFailThrow(m_pFrame->GetProcess()->GetTargetInfo(&targetInfo)); + _ASSERTE(targetInfo.pointerSize == 8); + extendedVal = *(UINT64*)newValue.StartAddress(); + break; + } default: _ASSERTE(!"bad size"); } } @@ -239,9 +246,9 @@ void RegValueHome::GetEnregisteredValue(MemoryRange valueOutBuffer) { UINT_PTR* reg = m_pFrame->GetAddressOfRegister(m_reg1Info.m_kRegNumber); _ASSERTE(reg != NULL); - _ASSERTE(sizeof(*reg) == valueOutBuffer.Size()); + _ASSERTE(valueOutBuffer.Size() <= sizeof(*reg)); - memcpy(valueOutBuffer.StartAddress(), reg, sizeof(*reg)); + memcpy(valueOutBuffer.StartAddress(), reg, valueOutBuffer.Size()); } // RegValueHome::GetEnregisteredValue @@ -889,21 +896,9 @@ void RegisterValueHome::SetEnregisteredValue(MemoryRange src, bool fIsSigned) } // RegisterValueHome::SetEnregisteredValue -// Get an enregistered value from the register display of the native frame -// Arguments: -// output: dest - buffer will hold the register value -// Note: Throws E_NOTIMPL for attempts to get an enregistered value for a float register -// or for 64-bit platforms void RegisterValueHome::GetEnregisteredValue(MemoryRange dest) { -#if !defined(TARGET_X86) - _ASSERTE(!"@TODO IA64/AMD64 -- Not Yet Implemented"); ThrowHR(E_NOTIMPL); -#else // TARGET_X86 - _ASSERTE(m_pRemoteRegAddr != NULL); - - m_pRemoteRegAddr->GetEnregisteredValue(dest); // throws -#endif // !TARGET_X86 } // RegisterValueHome::GetEnregisteredValue // Is this a signed type or unsigned type? @@ -949,13 +944,15 @@ CORDB_ADDRESS HandleValueHome::GetAddress() void HandleValueHome::GetValue(MemoryRange dest) { _ASSERTE((m_pProcess != NULL) && !m_vmObjectHandle.IsNull()); - CORDB_ADDRESS objPtr = PTR_TO_CORDB_ADDRESS((void *)NULL); + CORDB_ADDRESS objPtr = 0; + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(m_pProcess->GetTargetInfo(&targetInfo)); IfFailThrow(m_pProcess->GetDAC()->GetHandleAddressFromVmHandle(m_vmObjectHandle, &objPtr)); - _ASSERTE(dest.Size() <= sizeof(void *)); + _ASSERTE(dest.Size() == targetInfo.pointerSize); _ASSERTE(dest.StartAddress() != NULL); _ASSERTE(objPtr != (CORDB_ADDRESS)NULL); - m_pProcess->SafeReadBuffer(TargetBuffer(objPtr, sizeof(void *)), (BYTE *)dest.StartAddress()); + m_pProcess->SafeReadBuffer(TargetBuffer(objPtr, targetInfo.pointerSize), (BYTE *)dest.StartAddress()); } // HandleValueHome::GetValue // Sets a location to the value provided in src @@ -964,13 +961,20 @@ void HandleValueHome::SetValue(MemoryRange src, CordbType * pType) { _ASSERTE(!m_vmObjectHandle.IsNull()); + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(m_pProcess->GetTargetInfo(&targetInfo)); + _ASSERTE(src.Size() == targetInfo.pointerSize); + + CORDB_ADDRESS newReference = 0; + memcpy(&newReference, src.StartAddress(), src.Size()); + DebuggerIPCEvent event; m_pProcess->InitIPCEvent(&event, DB_IPCE_SET_REFERENCE, true, VMPTR_AppDomain::NullPtr()); event.SetReference.objectRefAddress = (CORDB_ADDRESS)0; event.SetReference.vmObjectHandle = m_vmObjectHandle; - event.SetReference.newReference = PTR_TO_CORDB_ADDRESS(*((void **)src.StartAddress())); + event.SetReference.newReference = newReference; // Note: two-way event here... IfFailThrow(m_pProcess->SendIPCEvent(&event, sizeof(DebuggerIPCEvent))); @@ -1064,8 +1068,10 @@ RefRemoteValueHome ::RefRemoteValueHome (CordbProcess * pProcess TargetBuffer remoteValue): RemoteValueHome(pProcess, remoteValue) { + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(pProcess->GetTargetInfo(&targetInfo)); // caller supplies remoteValue, to work w/ Func-eval. - _ASSERTE((!remoteValue.IsEmpty()) && (remoteValue.cbSize == sizeof (void *))); + _ASSERTE((!remoteValue.IsEmpty()) && (remoteValue.cbSize == targetInfo.pointerSize)); } // RefRemoteValueHome::RefRemoteValueHome @@ -1081,6 +1087,13 @@ void RefRemoteValueHome::SetValue(MemoryRange src, CordbType * pType) // We had better have a remote address. _ASSERTE(!m_remoteValue.IsEmpty()); + IDacDbiInterface::TargetInfo targetInfo; + IfFailThrow(m_pProcess->GetTargetInfo(&targetInfo)); + _ASSERTE(src.Size() == targetInfo.pointerSize); + + CORDB_ADDRESS newReference = 0; + memcpy(&newReference, src.StartAddress(), src.Size()); + // send a Set Reference message to the right side with the address of this reference and whether or not // the reference points to a handle. @@ -1099,7 +1112,7 @@ void RefRemoteValueHome::SetValue(MemoryRange src, CordbType * pType) event.SetReference.objectRefAddress = m_remoteValue.pAddress; event.SetReference.vmObjectHandle = VMPTR_OBJECTHANDLE::NullPtr(); - event.SetReference.newReference = PTR_TO_CORDB_ADDRESS(*((void **)src.StartAddress())); + event.SetReference.newReference = newReference; // Note: two-way event here... IfFailThrow(m_pProcess->SendIPCEvent(&event, sizeof(DebuggerIPCEvent))); @@ -1145,4 +1158,3 @@ RefValueHome::RefValueHome(CordbProcess * pProcess, } // RefValueHome::RefValueHome - diff --git a/src/coreclr/debug/inc/dacdbiinterface.h b/src/coreclr/debug/inc/dacdbiinterface.h index 23b19097f614c7..f7ef5728796fab 100644 --- a/src/coreclr/debug/inc/dacdbiinterface.h +++ b/src/coreclr/debug/inc/dacdbiinterface.h @@ -2198,6 +2198,34 @@ IDacDbiInterface : public IUnknown VMPTR_MethodDesc vmMethod, OUT UINT32* pTokenIndex) = 0; + typedef enum + { + kArchUnknown = 0, + kArchX86, + kArchAMD64, + kArchArm, + kArchArm64, + kArchLoongArch64, + kArchRiscV64, + kArchWasm, + } TargetArchitecture; + + typedef enum + { + kOSUnknown = 0, + kOSWindows, + kOSUnix, + } TargetOperatingSystem; + + struct TargetInfo + { + TargetArchitecture arch; + TargetOperatingSystem os; + ULONG32 pointerSize; + }; + + // Returns the target's processor architecture, OS family, and pointer size. + virtual HRESULT STDMETHODCALLTYPE GetTargetInfo(OUT TargetInfo * pTargetInfo) = 0; // Get the size in bytes of the serialized read-write metadata blob for a module. // // Arguments: diff --git a/src/coreclr/inc/dacdbi.idl b/src/coreclr/inc/dacdbi.idl index b4ea7cb7c1cc35..7cf1f0980bee0f 100644 --- a/src/coreclr/inc/dacdbi.idl +++ b/src/coreclr/inc/dacdbi.idl @@ -129,6 +129,7 @@ typedef struct { void *pList; int nEntries; } DacDbiArrayList_CORDB_ADDRESS; typedef struct { void *pList; int nEntries; } DacDbiArrayList_GUID; typedef struct { void *pList; int nEntries; } DacDbiArrayList_COR_SEGMENT; typedef struct { void *pList; int nEntries; } DacDbiArrayList_COR_MEMORY_RANGE; +typedef struct { int arch; int os; int pointerSize; } TargetInfo; cpp_quote("#endif") @@ -438,6 +439,9 @@ interface IDacDbiInterface : IUnknown // Generic Arg Token HRESULT GetGenericArgTokenIndex([in] VMPTR_MethodDesc vmMethod, [out] UINT32 * pTokenIndex); + // Returns the target's processor architecture and OS family. + HRESULT GetTargetInfo([out] struct TargetInfo * pTargetInfo); + HRESULT GetReadWriteMetadataSize([in] VMPTR_Module vmModule, [out] ULONG32 * pSize); HRESULT FillReadWriteMetadata([in] VMPTR_Module vmModule, [out] BYTE * pBuffer, [in] ULONG32 cbBuffer); }; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs index 6db40172c4edd7..9ac74c409796da 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs @@ -6563,6 +6563,56 @@ public int GetGenericArgTokenIndex(ulong vmMethod, uint* pIndex) return hr; } + public int GetTargetInfo(TargetInfo* pTargetInfo) + { + int hr = HResults.S_OK; + try + { + if (pTargetInfo is null) + throw new ArgumentNullException(nameof(pTargetInfo)); + + Contracts.IRuntimeInfo runtimeInfo = _target.Contracts.RuntimeInfo; + + pTargetInfo->Arch = runtimeInfo.GetTargetArchitecture() switch + { + Contracts.RuntimeInfoArchitecture.X86 => TargetArchitecture.X86, + Contracts.RuntimeInfoArchitecture.X64 => TargetArchitecture.AMD64, + Contracts.RuntimeInfoArchitecture.Arm => TargetArchitecture.Arm, + Contracts.RuntimeInfoArchitecture.Arm64 => TargetArchitecture.Arm64, + Contracts.RuntimeInfoArchitecture.LoongArch64 => TargetArchitecture.LoongArch64, + Contracts.RuntimeInfoArchitecture.RiscV64 => TargetArchitecture.RiscV64, + Contracts.RuntimeInfoArchitecture.Wasm => TargetArchitecture.Wasm, + _ => TargetArchitecture.Unknown, + }; + + pTargetInfo->OS = runtimeInfo.GetTargetOperatingSystem() switch + { + Contracts.RuntimeInfoOperatingSystem.Windows => TargetOperatingSystem.Windows, + Contracts.RuntimeInfoOperatingSystem.Unix => TargetOperatingSystem.Unix, + Contracts.RuntimeInfoOperatingSystem.Apple => TargetOperatingSystem.Unix, + _ => TargetOperatingSystem.Unknown, + }; + } + catch (System.Exception ex) + { + hr = ex.HResult; + } +#if DEBUG + if (_legacy is not null) + { + TargetInfo targetInfoLocal; + int hrLocal = _legacy.GetTargetInfo(&targetInfoLocal); + Debug.ValidateHResult(hr, hrLocal); + if (hr == HResults.S_OK) + { + Debug.Assert(pTargetInfo->Arch == targetInfoLocal.Arch, $"cDAC: {pTargetInfo->Arch}, DAC: {targetInfoLocal.Arch}"); + Debug.Assert(pTargetInfo->OS == targetInfoLocal.OS, $"cDAC: {pTargetInfo->OS}, DAC: {targetInfoLocal.OS}"); + } + } +#endif + return hr; + } + // Fills a DebuggerIPCE_ExpandedTypeData entry for a single type parameter, falling back to System.__Canon on failure. private void FillExpandedTypeDataWithCanonFallback(IRuntimeTypeSystem rts, ITypeHandle typeHandle, ITypeHandle thCanon, DebuggerIPCE_ExpandedTypeData* pTypeInfo) { diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs index eb976953b478b1..327a7b41734e85 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs @@ -937,9 +937,37 @@ int EnumerateAsyncLocals(ulong vmMethod, ulong codeAddr, uint state, [PreserveSig] int GetGenericArgTokenIndex(ulong vmMethod, uint* pIndex); + [PreserveSig] + int GetTargetInfo(TargetInfo* pTargetInfo); + [PreserveSig] int GetReadWriteMetadataSize(ulong vmModule, uint* pSize); [PreserveSig] int FillReadWriteMetadata(ulong vmModule, byte* pBuffer, uint cbBuffer); } + +public enum TargetArchitecture +{ + Unknown = 0, + X86, + AMD64, + Arm, + Arm64, + LoongArch64, + RiscV64, + Wasm, +} + +public enum TargetOperatingSystem +{ + Unknown = 0, + Windows, + Unix, +} + +public struct TargetInfo +{ + public TargetArchitecture Arch; + public TargetOperatingSystem OS; +}