contextType = typeof(ArmContext);
break;
+ case (Architecture)9 /* Architecture.RiscV64 */:
+ _contextSize = RiscV64Context.Size;
+ _contextFlags = RiscV64Context.ContextControl | RiscV64Context.ContextInteger | RiscV64Context.ContextFloatingPoint;
+ contextType = typeof(RiscV64Context);
+ break;
+
default:
throw new PlatformNotSupportedException($"Unsupported architecture: {Target.Architecture}");
}
IMAGE_FILE_MACHINE.THUMB2 => Architecture.Arm,
IMAGE_FILE_MACHINE.AMD64 => Architecture.X64,
IMAGE_FILE_MACHINE.ARM64 => Architecture.Arm64,
+ IMAGE_FILE_MACHINE.RISCV64 => (Architecture)9 /* Architecture.RiscV64 */,
_ => throw new PlatformNotSupportedException($"Machine type not supported: {type}"),
};
}
Architecture.X86 => IMAGE_FILE_MACHINE.I386,
Architecture.Arm => IMAGE_FILE_MACHINE.THUMB2,
Architecture.Arm64 => IMAGE_FILE_MACHINE.ARM64,
+ (Architecture)9 /* Architecture.RiscV64 */ => IMAGE_FILE_MACHINE.RISCV64,
_ => IMAGE_FILE_MACHINE.UNKNOWN,
};
return HResult.S_OK;
AMD64 = 0x8664, // AMD64 (K8)
M32R = 0x9041, // M32R little-endian
ARM64 = 0xAA64, // ARM64 Little-endian
- CEE = 0xC0EE
+ CEE = 0xC0EE,
+ RISCV64 = 0x5064
}
}
case Architecture.Arm64:
*type = IMAGE_FILE_MACHINE.ARM64;
break;
+ case (Architecture)9 /* Architecture.RiscV64 */:
+ *type = IMAGE_FILE_MACHINE.RISCV64;
+ break;
default:
*type = IMAGE_FILE_MACHINE.UNKNOWN;
break;
set(SOS_SOURCES_ARCH
disasmARM64.cpp
)
+elseif(CLR_CMAKE_HOST_ARCH_RISCV64)
+ set(SOS_SOURCES_ARCH
+ disasmRISCV64.cpp
+ )
endif()
list(APPEND SOS_SOURCES ${SOS_SOURCES_ARCH})
#endif // SOS_TARGET_ARM64
+#ifdef SOS_TARGET_RISCV64
+///
+/// RISCV64Machine implementation
+///
+LPCSTR RISCV64Machine::s_DumpStackHeading = "ChildFP RetAddr Caller, Callee\n";
+LPCSTR RISCV64Machine::s_GCRegs[30] = {"r0", "ra", "gp", "tp", "t0", "t1", "t2", "s1", "a0",
+ "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3",
+ "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
+ "t3", "t4", "t5", "t6"};
+LPCSTR RISCV64Machine::s_SPName = "sp";
+
+#endif // SOS_TARGET_RISCV64
+
//
// GCEncodingInfo class member implementations
//
}; // class ARM64Machine
#endif // SOS_TARGET_ARM64
+
+
+#ifdef SOS_TARGET_RISCV64
+
+/// RISCV64 Machine specific code
+class RISCV64Machine : public IMachine
+{
+public:
+ typedef RISCV64_CONTEXT TGT_CTXT;
+
+ static IMachine* GetInstance()
+ { static RISCV64Machine s_RISCV64MachineInstance; return &s_RISCV64MachineInstance; }
+
+ ULONG GetPlatform() const { return IMAGE_FILE_MACHINE_RISCV64; }
+ ULONG GetContextSize() const { return sizeof(RISCV64_CONTEXT); }
+ ULONG GetFullContextFlags() const { return 0x01000007L; }
+ void SetContextFlags(BYTE* context, ULONG32 contextFlags) { ((RISCV64_CONTEXT*)context)->ContextFlags = contextFlags; };
+
+ virtual void Unassembly(
+ TADDR IPBegin,
+ TADDR IPEnd,
+ TADDR IPAskedFor,
+ TADDR GCStressCodeCopy,
+ GCEncodingInfo *pGCEncodingInfo,
+ SOSEHInfo *pEHInfo,
+ BOOL bSuppressLines,
+ BOOL bDisplayOffsets,
+ std::function<void(ULONG*, UINT*, BYTE*)> displayIL) const;
+ virtual void IsReturnAddress(
+ TADDR retAddr,
+ TADDR* whereCalled) const;
+ virtual BOOL GetExceptionContext (
+ TADDR stack,
+ TADDR PC,
+ TADDR *cxrAddr,
+ CROSS_PLATFORM_CONTEXT * cxr,
+ TADDR *exrAddr,
+ PEXCEPTION_RECORD exr) const;
+
+ // retrieve stack pointer, frame pointer, and instruction pointer from the target context
+ virtual TADDR GetSP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.RiscV64Context.Sp; }
+ virtual TADDR GetBP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.RiscV64Context.Fp; }
+ virtual TADDR GetIP(const CROSS_PLATFORM_CONTEXT & ctx) const { return ctx.RiscV64Context.Pc; }
+
+ virtual void FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const;
+ virtual void FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx = 0) const;
+
+ virtual LPCSTR GetDumpStackHeading() const { return s_DumpStackHeading; }
+ virtual LPCSTR GetSPName() const { return s_SPName; }
+ virtual void GetGCRegisters(LPCSTR** regNames, unsigned int* cntRegs) const
+ { _ASSERTE(cntRegs != NULL); *regNames = s_GCRegs; *cntRegs = ARRAY_SIZE(s_GCRegs);}
+
+ virtual void DumpGCInfo(GCInfoToken gcInfoToken, unsigned methodSize, printfFtn gcPrintf, bool encBytes, bool bPrintHeader) const;
+
+ int StackWalkIPAdjustOffset() const { return 4; }
+
+private:
+ RISCV64Machine() {}
+ ~RISCV64Machine() {}
+ RISCV64Machine(const RISCV64Machine& machine); // undefined
+ RISCV64Machine & operator=(const RISCV64Machine&); // undefined
+
+ static LPCSTR s_DumpStackHeading;
+ static LPCSTR s_GCRegs[30];
+ static LPCSTR s_SPName;
+
+}; // class RISCV64Machine
+
+#endif // SOS_TARGET_RISCV64
+
#ifdef _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
}
#endif // SOS_TARGET_ARM64
+#ifdef SOS_TARGET_RISCV64
+inline void RISCV64Machine::FillSimpleContext(StackTrace_SimpleContext * dest, LPVOID srcCtx) const
+{
+ TGT_CTXT& src = *(TGT_CTXT*) srcCtx;
+ dest->StackOffset = src.Sp;
+ dest->FrameOffset = src.Fp;
+ dest->InstructionOffset = src.Pc;
+}
+
+inline void RISCV64Machine::FillTargetContext(LPVOID destCtx, LPVOID srcCtx, int idx /*= 0*/) const
+{
+ TGT_CTXT* dest = (TGT_CTXT*)destCtx + idx;
+ *dest = *(TGT_CTXT*)srcCtx;
+}
+#endif // SOS_TARGET_RISCV64
#endif // __disasm_h__
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#undef _TARGET_AMD64_
+#ifndef _TARGET_RISCV64_
+#define _TARGET_RISCV64_
+#endif
+
+#undef TARGET_AMD64
+#ifndef TARGET_RISCV64
+#define TARGET_RISCV64
+#endif
+
+#include "strike.h"
+#include "util.h"
+#include <dbghelp.h>
+
+#include "disasm.h"
+
+#include "corhdr.h"
+#include "cor.h"
+#include "dacprivate.h"
+
+namespace RISCV64GCDump
+{
+#undef TARGET_X86
+#undef LIMITED_METHOD_CONTRACT
+#define LIMITED_METHOD_DAC_CONTRACT ((void)0)
+#define SUPPORTS_DAC ((void)0)
+#define LF_GCROOTS
+#define LL_INFO1000
+#define LOG(x)
+#define LOG_PIPTR(pObjRef, gcFlags, hCallBack)
+#define DAC_ARG(x)
+#include "gcdumpnonx86.cpp"
+}
+
+#if !defined(_TARGET_WIN64_)
+#error This file only supports SOS targeting RISCV64 from a 64-bit debugger
+#endif
+
+#if !defined(SOS_TARGET_RISCV64)
+#error This file should be used to support SOS targeting RISCV64 debuggees
+#endif
+
+
+void RISCV64Machine::IsReturnAddress(TADDR retAddr, TADDR* whereCalled) const
+{
+ *whereCalled = 0;
+ _ASSERTE("RISCV64:NYI");
+}
+
+// Determine if a value is MT/MD/Obj
+static void HandleValue(TADDR value)
+{
+ // A MethodTable?
+ if (IsMethodTable(value))
+ {
+ NameForMT_s (value, g_mdName,mdNameLen);
+ ExtOut (" (MT: %S)", g_mdName);
+ return;
+ }
+
+ // A Managed Object?
+ TADDR dwMTAddr;
+ move_xp (dwMTAddr, value);
+ if (IsStringObject(value))
+ {
+ ExtOut (" (\"");
+ StringObjectContent (value, TRUE);
+ ExtOut ("\")");
+ return;
+ }
+ else if (IsMethodTable(dwMTAddr))
+ {
+ NameForMT_s (dwMTAddr, g_mdName,mdNameLen);
+ ExtOut (" (Object: %S)", g_mdName);
+ return;
+ }
+
+ // A MethodDesc?
+ if (IsMethodDesc(value))
+ {
+ NameForMD_s (value, g_mdName,mdNameLen);
+ ExtOut (" (MD: %S)", g_mdName);
+ return;
+ }
+
+ // A JitHelper?
+ const char* name = HelperFuncName(value);
+ if (name) {
+ ExtOut (" (JitHelp: %s)", name);
+ return;
+ }
+
+ // A call to managed code?
+ // RISCV64TODO: not (yet) implemented. perhaps we don't need it at all.
+
+ // Random symbol.
+ char Symbol[1024];
+ if (SUCCEEDED(g_ExtSymbols->GetNameByOffset(TO_CDADDR(value), Symbol, 1024,
+ NULL, NULL)))
+ {
+ if (Symbol[0] != '\0')
+ {
+ ExtOut (" (%s)", Symbol);
+ return;
+ }
+ }
+
+}
+
+/**********************************************************************\
+* Routine Description: *
+* *
+* Unassembly a managed code. Translating managed object, *
+* call. *
+* *
+\**********************************************************************/
+void RISCV64Machine::Unassembly (
+ TADDR PCBegin,
+ TADDR PCEnd,
+ TADDR PCAskedFor,
+ TADDR GCStressCodeCopy,
+ GCEncodingInfo *pGCEncodingInfo,
+ SOSEHInfo *pEHInfo,
+ BOOL bSuppressLines,
+ BOOL bDisplayOffsets,
+ std::function<void(ULONG*, UINT*, BYTE*)> displayIL) const
+{
+ _ASSERTE("RISCV64:NYI");
+}
+
+BOOL RISCV64Machine::GetExceptionContext (TADDR stack, TADDR PC, TADDR *cxrAddr, CROSS_PLATFORM_CONTEXT * cxr,
+ TADDR * exrAddr, PEXCEPTION_RECORD exr) const
+{
+ _ASSERTE("RISCV64:NYI");
+ return FALSE;
+}
+
+///
+/// Dump RISCV GCInfo table
+///
+void RISCV64Machine::DumpGCInfo(GCInfoToken gcInfoToken, unsigned methodSize, printfFtn gcPrintf, bool encBytes, bool bPrintHeader) const
+{
+ if (bPrintHeader)
+ {
+ ExtOut("Pointer table:\n");
+ }
+
+ RISCV64GCDump::GCDump gcDump(gcInfoToken.Version, encBytes, 5, true);
+ gcDump.gcPrintf = gcPrintf;
+
+ gcDump.DumpGCTable(dac_cast<PTR_BYTE>(gcInfoToken.Info), methodSize, 0);
+}
+
targetMachine = ARM64Machine::GetInstance();
}
#endif // SOS_TARGET_ARM64
+#ifdef SOS_TARGET_RISCV64
+ if (processorType == IMAGE_FILE_MACHINE_RISCV64)
+ {
+ targetMachine = RISCV64Machine::GetInstance();
+ }
+#endif // SOS_TARGET_RISCV64
return targetMachine;
}
case IMAGE_FILE_MACHINE_ARM64:
architecture = "arm64";
break;
+ case IMAGE_FILE_MACHINE_RISCV64:
+ architecture = "riscv64";
+ break;
}
ExtErr("SOS does not support the current target architecture '%s' (0x%04x). A 32 bit target may require a 32 bit debugger or vice versa. In general, try to use the same bitness for the debugger and target process.\n",
architecture, processorType);
// printing CDA values.
#define CDA_TO_UL64(cda) ((ULONG64)(TO_TADDR(cda)))
+#ifndef IMAGE_FILE_MACHINE_RISCV64
+#define IMAGE_FILE_MACHINE_RISCV64 0x5064 // RISCV64
+#endif // !IMAGE_FILE_MACHINE_RISCV64
+
typedef struct _TADDR_RANGE
{
TADDR start;
inline BOOL IsDbgTargetAmd64() { return g_targetMachine->GetPlatform() == IMAGE_FILE_MACHINE_AMD64; }
inline BOOL IsDbgTargetArm() { return g_targetMachine->GetPlatform() == IMAGE_FILE_MACHINE_ARMNT; }
inline BOOL IsDbgTargetArm64() { return g_targetMachine->GetPlatform() == IMAGE_FILE_MACHINE_ARM64; }
+inline BOOL IsDbgTargetRiscV64(){ return g_targetMachine->GetPlatform() == IMAGE_FILE_MACHINE_RISCV64; }
inline BOOL IsDbgTargetWin64() { return IsDbgTargetAmd64(); }
/* Returns the instruction pointer for the given CONTEXT. We need this and its family of
ExtOut(" cpsr=%08x fpcr=%08x fpsr=%08x\n", context.Arm64Context.Cpsr, context.Arm64Context.Fpcr, context.Arm64Context.Fpsr);
}
#endif
+#if defined(SOS_TARGET_RISCV64)
+ if (IsDbgTargetRiscV64())
+ {
+ ExtOut("RISCV64:NYI\n");
+ }
+#endif
+
if (!foundPlatform)
{
ExtOut("Can't display register values for this platform\n");
} ARM64_CONTEXT;
+///RISCV64 Context
+#define RISCV64_MAX_BREAKPOINTS 8
+#define RISCV64_MAX_WATCHPOINTS 2
+typedef struct {
+
+ DWORD ContextFlags;
+
+ DWORD64 R0;
+ DWORD64 Ra;
+ DWORD64 Sp;
+ DWORD64 Gp;
+ DWORD64 Tp;
+ DWORD64 T0;
+ DWORD64 T1;
+ DWORD64 T2;
+ DWORD64 Fp;
+ DWORD64 S1;
+ DWORD64 A0;
+ DWORD64 A1;
+ DWORD64 A2;
+ DWORD64 A3;
+ DWORD64 A4;
+ DWORD64 A5;
+ DWORD64 A6;
+ DWORD64 A7;
+ DWORD64 S2;
+ DWORD64 S3;
+ DWORD64 S4;
+ DWORD64 S5;
+ DWORD64 S6;
+ DWORD64 S7;
+ DWORD64 S8;
+ DWORD64 S9;
+ DWORD64 S10;
+ DWORD64 S11;
+ DWORD64 T3;
+ DWORD64 T4;
+ DWORD64 T5;
+ DWORD64 T6;
+ DWORD64 Pc;
+
+ ULONGLONG F[32];
+ DWORD Fcsr;
+
+ DWORD Padding[3];
+
+} RISCV64_CONTEXT;
+
typedef struct _CROSS_PLATFORM_CONTEXT {
_CROSS_PLATFORM_CONTEXT() {}
AMD64_CONTEXT Amd64Context;
ARM_CONTEXT ArmContext;
ARM64_CONTEXT Arm64Context;
+ RISCV64_CONTEXT RiscV64Context;
};
} CROSS_PLATFORM_CONTEXT, *PCROSS_PLATFORM_CONTEXT;
_snprintf_s(szRegName, ARRAY_SIZE(szRegName), sizeof(szRegName), "r%u", regnum);
return szRegName;
+#elif defined(TARGET_RISCV64)
+ switch (regnum)
+ {
+ case 0: return "r0";
+ case 1: return "ra";
+ case 2: return "sp";
+ case 3: return "gp";
+ case 4: return "tp";
+ case 5: return "t0";
+ case 6: return "t1";
+ case 7: return "t2";
+ case 8: return "fp";
+ case 9: return "s1";
+ case 10: return "a0";
+ case 11: return "a1";
+ case 12: return "a2";
+ case 13: return "a3";
+ case 14: return "a4";
+ case 15: return "a5";
+ case 16: return "a6";
+ case 17: return "a7";
+ case 18: return "s2";
+ case 19: return "s3";
+ case 20: return "s4";
+ case 21: return "s5";
+ case 22: return "s6";
+ case 23: return "s7";
+ case 24: return "s8";
+ case 25: return "s9";
+ case 26: return "s10";
+ case 27: return "s11";
+ case 28: return "t3";
+ case 29: return "t4";
+ case 30: return "t5";
+ case 31: return "t6";
+ case 32: return "pc";
+ }
+
+ return "???";
#endif
}
| DECODE_GC_LIFETIMES
| DECODE_PROLOG_LENGTH
| DECODE_RETURN_KIND
-#if defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
| DECODE_HAS_TAILCALLS
#endif
),
#ifdef TARGET_AMD64
gcPrintf("Wants Report Only Leaf: %u\n", hdrdecoder.WantsReportOnlyLeaf());
-#elif defined(TARGET_ARM) || defined(TARGET_ARM64)
+#elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
gcPrintf("Has tailcalls: %u\n", hdrdecoder.HasTailCalls());
#endif // TARGET_AMD64
#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA
int hasStackBaseRegister = headerFlags & GC_INFO_HAS_STACK_BASE_REGISTER;
#ifdef TARGET_AMD64
m_WantsReportOnlyLeaf = ((headerFlags & GC_INFO_WANTS_REPORT_ONLY_LEAF) != 0);
-#elif defined(TARGET_ARM) || defined(TARGET_ARM64)
+#elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
m_HasTailCalls = ((headerFlags & GC_INFO_HAS_TAILCALLS) != 0);
#endif // TARGET_AMD64
int hasSizeOfEditAndContinuePreservedArea = headerFlags & GC_INFO_HAS_EDIT_AND_CONTINUE_PRESERVED_SLOTS;
if(m_NumSafePoints == 0)
return false;
-#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64)|| defined(TARGET_RISCV64)
// Safepoints are encoded with a -1 adjustment
codeOffset--;
#endif
const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength));
UINT32 result = m_NumSafePoints;
-#if defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
// Safepoints are encoded with a -1 adjustment
// but normalizing them masks off the low order bit
// Thus only bother looking if the address is odd
UINT32 normOffset = (UINT32)m_Reader.Read(numBitsPerOffset);
UINT32 offset = DENORMALIZE_CODE_OFFSET(normOffset) + 2;
-#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64)
+#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
// Safepoints are encoded with a -1 adjustment
offset--;
#endif
}
#endif // TARGET_UNIX && !FEATURE_REDHAWK
+#elif defined(TARGET_RISCV64)
+
+#if defined(TARGET_UNIX) && !defined(FEATURE_REDHAWK)
+OBJECTREF* GcInfoDecoder::GetCapturedRegister(
+ int regNum,
+ PREGDISPLAY pRD
+ )
+{
+ _ASSERTE(regNum >= 1 && regNum <= 31);
+
+ // The fields of CONTEXT are in the same order as
+ // the processor encoding numbers.
+
+ DWORD64 *pR0 = &pRD->pCurrentContext->R0;
+
+ return (OBJECTREF*)(pR0 + regNum);
+}
+#endif // TARGET_UNIX && !FEATURE_REDHAWK
+
+OBJECTREF* GcInfoDecoder::GetRegisterSlot(
+ int regNum,
+ PREGDISPLAY pRD
+ )
+{
+ _ASSERTE((regNum == 1) || (regNum >= 5 && regNum <= 31));
+
+#ifdef FEATURE_REDHAWK
+ PTR_UIntNative* ppReg = &pRD->pR0;
+
+ return (OBJECTREF*)*(ppReg + regNum);
+#else
+ if(regNum == 1)
+ {
+ return (OBJECTREF*) pRD->pCurrentContextPointers->Ra;
+ }
+ else if (regNum < 8)
+ {
+ return (OBJECTREF*)*(DWORD64**)(&pRD->volatileCurrContextPointers.T0 + (regNum - 5));
+ }
+ else if(regNum == 8)
+ {
+ return (OBJECTREF*) pRD->pCurrentContextPointers->Fp;
+ }
+ else if (regNum == 9)
+ {
+ return (OBJECTREF*) pRD->pCurrentContextPointers->S1;
+ }
+ else if (regNum < 18)
+ {
+ return (OBJECTREF*)*(DWORD64**)(&pRD->volatileCurrContextPointers.A0 + (regNum - 10));
+ }
+ else if (regNum < 28)
+ {
+ return (OBJECTREF*)*(DWORD64**)(&pRD->pCurrentContextPointers->S2 + (regNum-18));
+ }
+ return (OBJECTREF*)*(DWORD64**)(&pRD->volatileCurrContextPointers.T3 + (regNum-28));
+#endif
+}
+
+bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD)
+{
+ _ASSERTE(regNum >= 0 && regNum <= 31);
+
+ return (regNum >= 5 && regNum <= 7) || (regNum >= 10 and regNum <= 17) || regNum >= 28 || regNum == 1;
+}
+
+bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD)
+{
+#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA
+ _ASSERTE( m_Flags & DECODE_GC_LIFETIMES );
+
+ TADDR pSlot = (TADDR) GetStackSlot(spOffset, spBase, pRD);
+ _ASSERTE(pSlot >= pRD->SP);
+
+ return (pSlot < pRD->SP + m_SizeOfStackOutgoingAndScratchArea);
+#else
+ return FALSE;
+#endif
+}
+
+void GcInfoDecoder::ReportRegisterToGC(
+ int regNum,
+ unsigned gcFlags,
+ PREGDISPLAY pRD,
+ unsigned flags,
+ GCEnumCallback pCallBack,
+ void * hCallBack)
+{
+ GCINFODECODER_CONTRACT;
+
+ _ASSERTE(regNum > 0 && regNum <= 31);
+
+ LOG((LF_GCROOTS, LL_INFO1000, "Reporting " FMT_REG, regNum ));
+
+ OBJECTREF* pObjRef = GetRegisterSlot( regNum, pRD );
+#if defined(TARGET_UNIX) && !defined(FEATURE_REDHAWK) && !defined(SOS_TARGET_RISCV64)
+ // On PAL, we don't always have the context pointers available due to
+ // a limitation of an unwinding library. In such case, the context
+ // pointers for some nonvolatile registers are NULL.
+ // In such case, we let the pObjRef point to the captured register
+ // value in the context and pin the object itself.
+ if (pObjRef == NULL)
+ {
+ // Report a pinned object to GC only in the promotion phase when the
+ // GC is scanning roots.
+ GCCONTEXT* pGCCtx = (GCCONTEXT*)(hCallBack);
+ if (!pGCCtx->sc->promotion)
+ {
+ return;
+ }
+
+ pObjRef = GetCapturedRegister(regNum, pRD);
+
+ gcFlags |= GC_CALL_PINNED;
+ }
+#endif // TARGET_UNIX && !SOS_TARGET_RISCV64
+
+#ifdef _DEBUG
+ if(IsScratchRegister(regNum, pRD))
+ {
+ // Scratch registers cannot be reported for non-leaf frames
+ _ASSERTE(flags & ActiveStackFrame);
+ }
+
+ LOG((LF_GCROOTS, LL_INFO1000, /* Part Two */
+ "at" FMT_ADDR "as ", DBG_ADDR(pObjRef) ));
+
+ VALIDATE_ROOT((gcFlags & GC_CALL_INTERIOR), hCallBack, pObjRef);
+
+ LOG_PIPTR(pObjRef, gcFlags, hCallBack);
+#endif //_DEBUG
+
+ gcFlags |= CHECK_APP_DOMAIN;
+
+ pCallBack(hCallBack, pObjRef, gcFlags DAC_ARG(DacSlotLocation(regNum, 0, false)));
+}
+
#else // Unknown platform
OBJECTREF* GcInfoDecoder::GetRegisterSlot(
int esp = 13;
#elif defined(TARGET_ARM64)
int esp = 31;
+#elif defined(TARGET_RISCV64)
+ int esp = 2;
#endif
if( GC_SP_REL == spBase )
REG(Lr, Lr),
{ FIELD_OFFSET(T_CONTEXT, Sp) },
#undef REG
+#elif defined(TARGET_RISCV64)
+#undef REG
+#define REG(reg, field) { offsetof(RiscV64VolatileContextPointer, field) }
+ REG(zero, R0),
+ REG(a0, A0),
+ REG(a1, A1),
+ REG(a2, A2),
+ REG(a3, A3),
+ REG(a4, A4),
+ REG(a5, A5),
+ REG(a6, A6),
+ REG(a7, A7),
+ REG(t0, T0),
+ REG(t1, T1),
+ REG(t2, T2),
+ REG(t3, T3),
+ REG(t4, T4),
+ REG(t5, T5),
+ REG(t6, T6),
+#undef REG
+#define REG(reg, field) { offsetof(T_KNONVOLATILE_CONTEXT_POINTERS, field) }
+ REG(s1, S1),
+ REG(s2, S2),
+ REG(s3, S3),
+ REG(s4, S4),
+ REG(s5, S5),
+ REG(s6, S6),
+ REG(s7, S7),
+ REG(s8, S8),
+ REG(s9, S9),
+ REG(s10, S10),
+ REG(s11, S11),
+ REG(ra, Ra),
+ REG(gp, Gp),
+ REG(tp, Tp),
+ REG(fp, Fp),
+ { offsetof(T_CONTEXT, Sp) },
+#undef REG
#else
PORTABILITY_ASSERT("GcInfoDumper::ReportPointerRecord is not implemented on this platform.")
#endif
#elif defined(TARGET_ARM)
iSPRegister = (FIELD_OFFSET(T_CONTEXT, Sp) - FIELD_OFFSET(T_CONTEXT, R0)) / sizeof(ULONG);
UINT iBFRegister = m_StackBaseRegister;
+#elif defined(TARGET_RISCV64)
+ assert(!"unimplemented on RISCV64 yet");
+ iSPRegister = 0;
#endif
#if defined(TARGET_ARM) || defined(TARGET_ARM64)
{
*(ppVolatileReg+iReg) = ®disp.pCurrentContext->X0 + iReg;
}
+#elif defined(TARGET_RISCV64)
+#pragma message("Unimplemented for RISCV64 yet.")
+ assert(!"unimplemented on RISCV64 yet");
#else
PORTABILITY_ASSERT("GcInfoDumper::EnumerateStateChanges is not implemented on this platform.")
#endif
return (TADDR)context->Sp;
#elif defined(TARGET_ARM64)
return (TADDR)context->Sp;
+#elif defined(TARGET_RISCV64)
+ return (TADDR)context->Sp;
#else
_ASSERTE(!"nyi for platform");
#endif
return (PCODE)context->Pc;
#elif defined(TARGET_ARM64)
return (PCODE)context->Pc;
+#elif defined(TARGET_RISCV64)
+ return (PCODE)context->Pc;
#else
_ASSERTE(!"nyi for platform");
#endif
DECODE_RETURN_KIND = 0x2000,
#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_RISCV64)
DECODE_HAS_TAILCALLS = 0x4000,
-#endif // TARGET_ARM || TARGET_ARM64
+#endif // TARGET_ARM || TARGET_ARM64 || TARGET_RISCV64
};
enum GcInfoHeaderFlags