From 6117d07cfb4adcc753e68c6941fa1aa5fa6eff9f Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Thu, 16 Dec 2021 13:06:59 +0800 Subject: [PATCH 01/11] [LoongArch64] add the coreclr/pal and libunwind directory. (#59561) --- src/coreclr/pal/inc/pal.h | 160 ++ src/coreclr/pal/inc/rt/intsafe.h | 2 +- src/coreclr/pal/inc/rt/ntimage.h | 6 + src/coreclr/pal/inc/rt/palrt.h | 19 + src/coreclr/pal/inc/unixasmmacros.inc | 2 + .../pal/inc/unixasmmacrosloongarch64.inc | 486 +++++ src/coreclr/pal/prebuilt/inc/cordebug.h | 70 +- .../loongarch64/activationhandlerwrapper.S | 26 + .../pal/src/arch/loongarch64/asmconstants.h | 100 + .../loongarch64/callsignalhandlerwrapper.S | 38 + .../pal/src/arch/loongarch64/context.S | 18 + .../pal/src/arch/loongarch64/context2.S | 257 +++ .../pal/src/arch/loongarch64/debugbreak.S | 10 + .../loongarch64/dispatchexceptionwrapper.S | 53 + .../src/arch/loongarch64/exceptionhelper.S | 48 + .../pal/src/arch/loongarch64/processor.cpp | 24 + .../arch/loongarch64/signalhandlerhelper.cpp | 76 + .../pal/src/exception/remote-unwind.cpp | 45 +- src/coreclr/pal/src/exception/seh-unwind.cpp | 44 + src/coreclr/pal/src/include/pal/context.h | 152 ++ src/coreclr/pal/src/libunwind/Makefile.am | 5 + src/coreclr/pal/src/libunwind/configure.ac | 7 +- .../libunwind/include/libunwind-loongarch.h | 156 ++ .../pal/src/libunwind/include/libunwind.h.in | 2 + .../include/tdep-loongarch/dwarf-config.h | 54 + .../libunwind/include/tdep-loongarch/jmpbuf.h | 32 + .../include/tdep-loongarch/libunwind_i.h | 334 ++++ .../src/libunwind/include/tdep/dwarf-config.h | 2 + .../pal/src/libunwind/include/tdep/jmpbuf.h | 2 + .../libunwind/include/tdep/libunwind_i.h.in | 2 + src/coreclr/pal/src/libunwind/src/Makefile.am | 36 + .../src/coredump/_UCD_access_reg_linux.c | 4 + .../src/loongarch/Gcreate_addr_space.c | 66 + .../libunwind/src/loongarch/Gget_proc_info.c | 41 + .../libunwind/src/loongarch/Gget_save_loc.c | 100 + .../pal/src/libunwind/src/loongarch/Gglobal.c | 55 + .../pal/src/libunwind/src/loongarch/Ginit.c | 208 ++ .../src/libunwind/src/loongarch/Ginit_local.c | 53 + .../libunwind/src/loongarch/Ginit_remote.c | 45 + .../src/loongarch/Gis_signal_frame.c | 80 + .../pal/src/libunwind/src/loongarch/Gregs.c | 103 + .../pal/src/libunwind/src/loongarch/Gresume.c | 45 + .../pal/src/libunwind/src/loongarch/Gstep.c | 135 ++ .../src/loongarch/Lcreate_addr_space.c | 5 + .../libunwind/src/loongarch/Lget_proc_info.c | 5 + .../libunwind/src/loongarch/Lget_save_loc.c | 5 + .../pal/src/libunwind/src/loongarch/Lglobal.c | 5 + .../pal/src/libunwind/src/loongarch/Linit.c | 5 + .../src/libunwind/src/loongarch/Linit_local.c | 5 + .../libunwind/src/loongarch/Linit_remote.c | 5 + .../src/loongarch/Lis_signal_frame.c | 5 + .../pal/src/libunwind/src/loongarch/Lregs.c | 5 + .../pal/src/libunwind/src/loongarch/Lresume.c | 5 + .../pal/src/libunwind/src/loongarch/Lstep.c | 5 + .../src/libunwind/src/loongarch/getcontext.S | 94 + .../pal/src/libunwind/src/loongarch/init.h | 59 + .../src/libunwind/src/loongarch/is_fpreg.c | 35 + .../pal/src/libunwind/src/loongarch/offsets.h | 76 + .../pal/src/libunwind/src/loongarch/regname.c | 48 + .../src/libunwind/src/loongarch/siglongjmp.S | 8 + .../src/libunwind/src/loongarch/unwind_i.h | 43 + .../libunwind/src/ptrace/_UPT_reg_offset.c | 36 + src/coreclr/pal/src/misc/perfjitdump.cpp | 2 + src/coreclr/pal/src/misc/sysinfo.cpp | 2 +- src/coreclr/pal/src/thread/context.cpp | 66 +- src/coreclr/pal/src/thread/process.cpp | 2 + .../ThunkGenerator/ThunkInput.txt | 1 + .../tools/aot/jitinterface/jitinterface.h | 23 +- .../loongarch64/unwinder_loongarch64.cpp | 1676 +++++++++++++++++ .../loongarch64/unwinder_loongarch64.h | 54 + 70 files changed, 5472 insertions(+), 11 deletions(-) create mode 100644 src/coreclr/pal/inc/unixasmmacrosloongarch64.inc create mode 100644 src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S create mode 100644 src/coreclr/pal/src/arch/loongarch64/asmconstants.h create mode 100644 src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S create mode 100644 src/coreclr/pal/src/arch/loongarch64/context.S create mode 100644 src/coreclr/pal/src/arch/loongarch64/context2.S create mode 100644 src/coreclr/pal/src/arch/loongarch64/debugbreak.S create mode 100644 src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S create mode 100644 src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S create mode 100644 src/coreclr/pal/src/arch/loongarch64/processor.cpp create mode 100644 src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp create mode 100644 src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h create mode 100644 src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h create mode 100644 src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h create mode 100644 src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Linit.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/init.h create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/offsets.h create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/regname.c create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S create mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h create mode 100644 src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp create mode 100644 src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 237b75275cec96..896e1f851af807 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -94,6 +94,8 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define _M_ARM 7 #elif defined(__aarch64__) && !defined(_M_ARM64) #define _M_ARM64 1 +#elif defined(__loongarch64) && !defined(_M_LOONGARCH64) +#define _M_LOONGARCH64 1 #elif defined(__s390x__) && !defined(_M_S390X) #define _M_S390X 1 #endif @@ -106,6 +108,8 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define HOST_ARM #elif defined(_M_ARM64) && !defined(HOST_ARM64) #define HOST_ARM64 +#elif defined(_M_LOONGARCH64) && !defined(HOST_LOONGARCH64) +#define HOST_LOONGARCH64 #elif defined(_M_S390X) && !defined(HOST_S390X) #define HOST_S390X #endif @@ -2202,6 +2206,150 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; +#elif defined(HOST_LOONGARCH64) + +//Please refence "src/pal/src/arch/loongarch64/asmconstants.h" +#define CONTEXT_LOONGARCH64 0x00800000 + +#define CONTEXT_CONTROL (CONTEXT_LOONGARCH64 | 0x1) +#define CONTEXT_INTEGER (CONTEXT_LOONGARCH64 | 0x2) +#define CONTEXT_FLOATING_POINT (CONTEXT_LOONGARCH64 | 0x4) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_LOONGARCH64 | 0x8) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + +#define CONTEXT_EXCEPTION_ACTIVE 0x8000000 +#define CONTEXT_SERVICE_ACTIVE 0x10000000 +#define CONTEXT_EXCEPTION_REQUEST 0x40000000 +#define CONTEXT_EXCEPTION_REPORTING 0x80000000 + +// +// This flag is set by the unwinder if it has unwound to a call +// site, and cleared whenever it unwinds through a trap frame. +// It is used by language-specific exception handlers to help +// differentiate exception scopes during dispatching. +// + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + +// begin_ntoshvp + +// +// Specify the number of breakpoints and watchpoints that the OS +// will track. Architecturally, LOONGARCH64 supports up to 16. In practice, +// however, almost no one implements more than 4 of each. +// + +#define LOONGARCH64_MAX_BREAKPOINTS 8 +#define LOONGARCH64_MAX_WATCHPOINTS 2 + +// +// Context Frame +// +// This frame has a several purposes: 1) it is used as an argument to +// NtContinue, 2) it is used to constuct a call frame for APC delivery, +// and 3) it is used in the user level thread creation routines. +// +// +// The flags field within this record controls the contents of a CONTEXT +// record. +// +// If the context record is used as an input parameter, then for each +// portion of the context record controlled by a flag whose value is +// set, it is assumed that that portion of the context record contains +// valid context. If the context record is being used to modify a threads +// context, then only that portion of the threads context is modified. +// +// If the context record is used as an output parameter to capture the +// context of a thread, then only those portions of the thread's context +// corresponding to set flags will be returned. +// + +typedef struct DECLSPEC_ALIGN(16) _CONTEXT { + + // + // Control flags. + // + + /* +0x000 */ DWORD ContextFlags; + + // + // Integer registers, abi=N64. + // + DWORD64 R0; + DWORD64 Ra; + DWORD64 Tp; + DWORD64 Sp; + DWORD64 A0;//DWORD64 V0; + DWORD64 A1;//DWORD64 V1; + DWORD64 A2; + DWORD64 A3; + DWORD64 A4; + DWORD64 A5; + DWORD64 A6; + DWORD64 A7; + DWORD64 T0; + DWORD64 T1; + DWORD64 T2; + DWORD64 T3; + DWORD64 T4; + DWORD64 T5; + DWORD64 T6; + DWORD64 T7; + DWORD64 T8; + DWORD64 X0; + DWORD64 Fp; + DWORD64 S0; + DWORD64 S1; + DWORD64 S2; + DWORD64 S3; + DWORD64 S4; + DWORD64 S5; + DWORD64 S6; + DWORD64 S7; + DWORD64 S8; + DWORD64 Pc; + + // + // Floating Point Registers + // + //TODO: support the SIMD. + DWORD64 F[32]; + DWORD Fcsr; +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +// +// Nonvolatile context pointer record. +// + +typedef struct _KNONVOLATILE_CONTEXT_POINTERS { + + PDWORD64 S0; + PDWORD64 S1; + PDWORD64 S2; + PDWORD64 S3; + PDWORD64 S4; + PDWORD64 S5; + PDWORD64 S6; + PDWORD64 S7; + PDWORD64 S8; + PDWORD64 Fp; + PDWORD64 Tp; + PDWORD64 Ra; + + PDWORD64 F24; + PDWORD64 F25; + PDWORD64 F26; + PDWORD64 F27; + PDWORD64 F28; + PDWORD64 F29; + PDWORD64 F30; + PDWORD64 F31; +} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; + + #elif defined(HOST_S390X) // There is no context for s390x defined in winnt.h, @@ -2453,6 +2601,9 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_ #define PAL_CS_NATIVE_DATA_SIZE 56 #elif defined(__sun) && defined(__x86_64__) #define PAL_CS_NATIVE_DATA_SIZE 48 +#elif defined(__linux__) && defined(__loongarch64) +////TODO for LOONGARCH64: should confirm !!! +#define PAL_CS_NATIVE_DATA_SIZE 96 #else #warning #error PAL_CS_NATIVE_DATA_SIZE is not defined for this architecture @@ -3255,6 +3406,9 @@ FORCEINLINE void PAL_ArmInterlockedOperationBarrier() // prevent that reordering. Code generated for arm32 includes a 'dmb' after 'cbnz', so no issue there at the moment. __sync_synchronize(); #endif // HOST_ARM64 +#ifdef HOST_LOONGARCH64 + __sync_synchronize(); +#endif } /*++ @@ -3653,6 +3807,8 @@ YieldProcessor() "nop"); #elif defined(HOST_ARM) || defined(HOST_ARM64) __asm__ __volatile__( "yield"); +#elif defined(HOST_LOONGARCH64) + __asm__ volatile( "dbar 0; \n"); #else return; #endif @@ -3830,6 +3986,10 @@ typedef LPOSVERSIONINFOEXA LPOSVERSIONINFOEX; #define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian +#ifndef IMAGE_FILE_MACHINE_LOONGARCH64 +#define IMAGE_FILE_MACHINE_LOONGARCH64 0xDD64 // LOONGARCH64 Little-Endian +#endif + typedef struct _SYSTEM_INFO { WORD wProcessorArchitecture_PAL_Undefined; WORD wReserved_PAL_Undefined; // NOTE: diff from winbase.h - no obsolete dwOemId union diff --git a/src/coreclr/pal/inc/rt/intsafe.h b/src/coreclr/pal/inc/rt/intsafe.h index 2b607e3a312e12..0119eab466eefc 100644 --- a/src/coreclr/pal/inc/rt/intsafe.h +++ b/src/coreclr/pal/inc/rt/intsafe.h @@ -31,7 +31,7 @@ #define LODWORD(_qw) ((ULONG)(_qw)) #if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \ - || defined(_M_AMD64) || defined(__ARM_ARCH) || defined(_M_S390X) + || defined(_M_AMD64) || defined(__ARM_ARCH) || defined(_M_S390X) || defined(_M_LOONGARCH64) #ifndef UInt32x32To64 #define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b))) diff --git a/src/coreclr/pal/inc/rt/ntimage.h b/src/coreclr/pal/inc/rt/ntimage.h index 1880375184f057..78f350f104b7c2 100644 --- a/src/coreclr/pal/inc/rt/ntimage.h +++ b/src/coreclr/pal/inc/rt/ntimage.h @@ -239,6 +239,7 @@ typedef struct _IMAGE_FILE_HEADER { #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) #define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian #define IMAGE_FILE_MACHINE_CEE 0xC0EE +#define IMAGE_FILE_MACHINE_LOONGARCH64 0xDD64 // LOONGARCH64. // // Directory format. @@ -1025,6 +1026,11 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; #define IMAGE_REL_IA64_GPREL32 0x001C #define IMAGE_REL_IA64_ADDEND 0x001F +// +// LOONGARCH64 relocation types +// +#define IMAGE_REL_LOONGARCH64_PC 0x0004 + // // CEF relocation types. // diff --git a/src/coreclr/pal/inc/rt/palrt.h b/src/coreclr/pal/inc/rt/palrt.h index 0855f5991cd8c8..dee82f344464b9 100644 --- a/src/coreclr/pal/inc/rt/palrt.h +++ b/src/coreclr/pal/inc/rt/palrt.h @@ -950,6 +950,7 @@ typedef VOID (NTAPI *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); #define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10 #define PROCESSOR_ARCHITECTURE_NEUTRAL 11 #define PROCESSOR_ARCHITECTURE_ARM64 12 +#define PROCESSOR_ARCHITECTURE_LOONGARCH64 13 #define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF @@ -1215,6 +1216,24 @@ typedef struct _DISPATCHER_CONTEXT { BOOLEAN ControlPcIsUnwound; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; +#elif defined(HOST_LOONGARCH64) + +typedef struct _DISPATCHER_CONTEXT { + ULONG64 ControlPc; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG64 EstablisherFrame; + ULONG64 TargetPc; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PVOID HistoryTable; + ULONG64 ScopeIndex; + BOOLEAN ControlPcIsUnwound; + PBYTE NonVolatileRegisters; + ULONG64 Reserved; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + #elif defined(HOST_S390X) typedef struct _DISPATCHER_CONTEXT { diff --git a/src/coreclr/pal/inc/unixasmmacros.inc b/src/coreclr/pal/inc/unixasmmacros.inc index 1fe285eef162d2..de775eba5075be 100644 --- a/src/coreclr/pal/inc/unixasmmacros.inc +++ b/src/coreclr/pal/inc/unixasmmacros.inc @@ -43,4 +43,6 @@ #include "unixasmmacrosarm64.inc" #elif defined(HOST_S390X) #include "unixasmmacross390x.inc" +#elif defined(HOST_LOONGARCH64) +#include "unixasmmacrosloongarch64.inc" #endif diff --git a/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc b/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc new file mode 100644 index 00000000000000..6d8f5516ecab35 --- /dev/null +++ b/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc @@ -0,0 +1,486 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +.macro NESTED_ENTRY Name, Section, Handler + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler + .cfi_personality 0x1c, C_FUNC(\Handler) // 0x1c == DW_EH_PE_pcrel | DW_EH_PE_sdata8 + .endif +.endm + +.macro NESTED_END Name, Section + LEAF_END \Name, \Section +.endm + +.macro PATCH_LABEL Name + .global C_FUNC(\Name) +C_FUNC(\Name): +.endm + +.macro LEAF_ENTRY Name, Section + .global C_FUNC(\Name) + .type \Name, %function +C_FUNC(\Name): + .cfi_startproc +.endm + +.macro LEAF_END Name, Section + .size \Name, .-\Name + .cfi_endproc +.endm + +.macro LEAF_END_MARKED Name, Section +C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) + LEAF_END \Name, \Section +.endm + +.macro PREPARE_EXTERNAL_VAR Name, HelperReg + la.local \HelperReg, \Name +.endm + +.macro PROLOG_STACK_ALLOC Size + addi.d $sp, $sp, -\Size + //.cfi_adjust_cfa_offset \Size + .cfi_def_cfa 3,\Size +.endm + +.macro EPILOG_STACK_FREE Size + addi.d $sp, $sp, \Size + //.cfi_adjust_cfa_offset -\Size + .cfi_def_cfa 3,-\Size +.endm + +.macro EPILOG_STACK_RESTORE + ori $sp, $fp, 0 + .cfi_restore 3 +.endm + +////NOTE: reg must be the number and GPR type !!! +.macro PROLOG_SAVE_REG reg, ofs + st.d $r\reg, $sp, \ofs + .cfi_rel_offset \reg, \ofs +.endm + +////NOTE: reg1 and reg2 must be the number and GPR type !!! +.macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs, __def_cfa_save=0 +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssq/gslq must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssq \reg2, \reg1, \ofs(sp) +//#else + st.d $r\reg1, $sp, \ofs + st.d $r\reg2, $sp, \ofs+8 +//#endif + + .cfi_rel_offset \reg1, \ofs + .cfi_rel_offset \reg2, \ofs + 8 + .if (\__def_cfa_save == 1) + ori $fp, $sp, 0 + .cfi_def_cfa_register 22 + .endif +.endm + +////NOTE: reg1 and reg2 must be the number and GPR type !!! +.macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ssize, __def_cfa_save=1 + addi.d $sp, $sp, -\ssize + //.cfi_adjust_cfa_offset \ssize + .cfi_def_cfa 3,\ssize + + st.d $r\reg1, $sp, 0 + st.d $r\reg2, $sp, 8 + + .cfi_rel_offset \reg1, 0 + .cfi_rel_offset \reg2, 8 + .if (\__def_cfa_save == 1) + ori $fp, $sp, 0 + .cfi_def_cfa_register 22 + .endif +.endm + +.macro EPILOG_RESTORE_REG reg, ofs + ld.d $r\reg, $sp, \ofs + .cfi_restore \reg + .cfi_def_cfa_register 3 +.endm + +.macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs +//#ifdef FEATURE_LOONGSONISA +// gslq \reg2, \reg1, \ofs(sp) +//#else + ld.d $r\reg2, $sp, \ofs+8 + ld.d $r\reg1, $sp, \ofs +//#endif + .cfi_restore \reg2 + .cfi_restore \reg1 +.endm + +.macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ssize +//#ifdef FEATURE_LOONGSONISA +// gslq \reg2, \reg1, 0(sp) +//#else + ld.d $r\reg2, $sp, 8 + ld.d $r\reg1, $sp, 0 +//#endif + .cfi_restore \reg2 + .cfi_restore \reg1 + + addi.d $sp, $sp, \ssize + //.cfi_adjust_cfa_offset -\ssize + .cfi_def_cfa 3,-\ssize +.endm + +.macro EPILOG_RETURN + jirl $r0, $ra, 0 +.endm + +.macro EMIT_BREAKPOINT + break +.endm + +.macro EPILOG_BRANCH Target + b \Target + //break +.endm + +.macro EPILOG_BRANCH_REG reg + jirl $r0, \reg, 0 +.endm + +//----------------------------------------------------------------------------- +// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and +// base address to be passed in $reg +// + +// Reserve 64 bytes of memory before calling SAVE_CALLEESAVED_REGISTERS +.macro SAVE_CALLEESAVED_REGISTERS reg, ofs + + PROLOG_SAVE_REG_PAIR 23, 24, \ofs + 16 + PROLOG_SAVE_REG_PAIR 25, 26, \ofs + 32 + PROLOG_SAVE_REG_PAIR 27, 28, \ofs + 48 + PROLOG_SAVE_REG_PAIR 29, 30, \ofs + 64 + PROLOG_SAVE_REG_PAIR 31, 2, \ofs + 80 + +.endm + +// Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS +.macro SAVE_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssq/gslq must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssq a1, a0, \ofs(\reg) +// gssq a3, a2, \ofs+16(\reg) +// gssq a5, a4, \ofs+32(\reg) +// gssq a7, a6, \ofs+48(\reg) +//#else + st.d $a0, \reg, \ofs + st.d $a1, \reg, \ofs+8 + st.d $a2, \reg, \ofs+16 + st.d $a3, \reg, \ofs+24 + st.d $a4, \reg, \ofs+32 + st.d $a5, \reg, \ofs+40 + st.d $a6, \reg, \ofs+48 + st.d $a7, \reg, \ofs+56 +//#endif + +.endm + +// Reserve 64 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS +.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssqc1/gslqc1 must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssqc1 $f13, $f12, \ofs(\reg) +// gssqc1 $f15, $f14, \ofs+16(\reg) +// gssqc1 $f17, $f16, \ofs+32(\reg) +// gssqc1 $f19, $f18, \ofs+48(\reg) +//#else + fst.d $f0, \reg, \ofs + fst.d $f1, \reg, \ofs+8 + fst.d $f2, \reg, \ofs+16 + fst.d $f3, \reg, \ofs+24 + fst.d $f4, \reg, \ofs+32 + fst.d $f5, \reg, \ofs+40 + fst.d $f6, \reg, \ofs+48 + fst.d $f7, \reg, \ofs+56 +//#endif + +.endm + +// Reserve 64 bytes of memory before calling SAVE_FLOAT_CALLEESAVED_REGISTERS +.macro SAVE_FLOAT_CALLEESAVED_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssqc1/gslqc1 must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gssqc1 $f25, $f24, \ofs(\reg) +// gssqc1 $f27, $f26, \ofs+16(\reg) +// gssqc1 $f29, $f28, \ofs+32(\reg) +// gssqc1 $f31, $f30, \ofs+48(\reg) +//#else + fst.d $f24, \reg, \ofs + fst.d $f25, \reg, \ofs+8 + fst.d $f26, \reg, \ofs+16 + fst.d $f27, \reg, \ofs+24 + fst.d $f28, \reg, \ofs+32 + fst.d $f29, \reg, \ofs+40 + fst.d $f30, \reg, \ofs+48 + fst.d $f31, \reg, \ofs+56 +//#endif + +.endm + +.macro RESTORE_CALLEESAVED_REGISTERS reg, ofs + + EPILOG_RESTORE_REG_PAIR 31, 2 \ofs + 80 + + EPILOG_RESTORE_REG_PAIR 29, 30, \ofs + 64 + EPILOG_RESTORE_REG_PAIR 27, 28, \ofs + 48 + EPILOG_RESTORE_REG_PAIR 25, 26, \ofs + 32 + EPILOG_RESTORE_REG_PAIR 23, 24, \ofs + 16 +.endm + +.macro RESTORE_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssq/gslq must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gslq a7, a6, \ofs+48(\reg) +// gslq a5, a4, \ofs+32(\reg) +// gslq a3, a2, \ofs+16(\reg) +// gslq a1, a0, \ofs(\reg) +//#else + ld.d $a7, \reg, \ofs+56 + ld.d $a6, \reg, \ofs+48 + ld.d $a5, \reg, \ofs+40 + ld.d $a4, \reg, \ofs+32 + ld.d $a3, \reg, \ofs+24 + ld.d $a2, \reg, \ofs+16 + ld.d $a1, \reg, \ofs+8 + ld.d $a0, \reg, \ofs +//#endif + +.endm + +.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// gslqc1 $f19, $f18, \ofs+48(\reg) +// gslqc1 $f17, $f16, \ofs+32(\reg) +// gslqc1 $f15, $f14, \ofs+16(\reg) +// gslqc1 $f13, $f12, \ofs(\reg) +//#else + fld.d $f7, \reg, \ofs+56 + fld.d $f6, \reg, \ofs+48 + fld.d $f5, \reg, \ofs+40 + fld.d $f4, \reg, \ofs+32 + fld.d $f3, \reg, \ofs+24 + fld.d $f2, \reg, \ofs+16 + fld.d $f1, \reg, \ofs+8 + fld.d $f0, \reg, \ofs +//#endif + +.endm + +.macro RESTORE_FLOAT_CALLEESAVED_REGISTERS reg, ofs + +//#ifdef FEATURE_LOONGSONISA +// //NOTE:The offset of gssqc1/gslqc1 must be 16-bytes aligned. +// // here ofs must be 16-bytes aligned. +// gslqc1 $f25, $f24, \ofs(\reg) +// gslqc1 $f27, $f26, \ofs+16(\reg) +// gslqc1 $f29, $f28, \ofs+32(\reg) +// gslqc1 $f31, $f30, \ofs+48(\reg) +//#else + fld.d $f24, $r\reg, \ofs + fld.d $f25, $r\reg, \ofs+8 + fld.d $f26, $r\reg, \ofs+16 + fld.d $f27, $r\reg, \ofs+24 + fld.d $f28, $r\reg, \ofs+32 + fld.d $f29, $r\reg, \ofs+40 + fld.d $f30, $r\reg, \ofs+48 + fld.d $f31, $r\reg, \ofs+56 +//#endif + +.endm + +//----------------------------------------------------------------------------- +// Define the prolog for a TransitionBlock-based method. This macro should be called first in the method and +// comprises the entire prolog.The locals must be 8 byte aligned +// +// Save_argument_registers: +// GPR_a7 +// GPR_a6 +// GPR_a5 +// GPR_a4 +// GPR_a3 +// GPR_a2 +// GPR_a1 +// GPR_a0 +// +// General Registers: +// GPR_tp +// GPR_s8 +// GPR_s7 +// GPR_s6 +// GPR_s5 +// GPR_s4 +// GPR_s3 +// GPR_s2 +// GPR_s1 +// GPR_s0 +// GPR_ra +// GPR_fp +// +// Float Point: +// FPR_f31 / fs7 +// FPR_f30 / fs6 +// FPR_f29 / fs5 +// FPR_f28 / fs4 +// FPR_f27 / fs3 +// FPR_f26 / fs2 +// FPR_f25 / fs1 +// FPR_f24 / fs0 +// Extra: +// +.macro PROLOG_WITH_TRANSITION_BLOCK extraParameters = 0, extraLocals = 0, SaveFPRegs = 1 + + __PWTB_SaveFPArgs = \SaveFPRegs + + __PWTB_FloatArgumentRegisters = \extraLocals + + .if ((__PWTB_FloatArgumentRegisters % 16) != 0) + __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 + .endif + + __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + + .if (__PWTB_SaveFPArgs == 1) + __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters + .endif + + + __PWTB_CalleeSavedRegisters = __PWTB_TransitionBlock + __PWTB_ArgumentRegisters = __PWTB_TransitionBlock + 96 + + // Including fp, ra, s0-s8, tp, and (a0-a7)arguments. (1+1+9+1)*8 + 8*8. + __PWTB_StackAlloc = __PWTB_TransitionBlock + 96 + 64 + PROLOG_STACK_ALLOC __PWTB_StackAlloc + // $fp,$ra + PROLOG_SAVE_REG_PAIR 22, 1, __PWTB_CalleeSavedRegisters, 1 + + // First, Spill argument registers. + SAVE_ARGUMENT_REGISTERS $sp, __PWTB_ArgumentRegisters + + // Then, Spill callee saved registers. $sp=$r3. + SAVE_CALLEESAVED_REGISTERS 3, __PWTB_CalleeSavedRegisters + + // saving is f12-19. + .if (__PWTB_SaveFPArgs == 1) + SAVE_FLOAT_ARGUMENT_REGISTERS $sp, __PWTB_FloatArgumentRegisters + .endif + +.endm + +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN + + RESTORE_CALLEESAVED_REGISTERS 3, __PWTB_CalleeSavedRegisters + + EPILOG_RESTORE_REG_PAIR 22, 1, __PWTB_CalleeSavedRegisters + + EPILOG_STACK_FREE __PWTB_StackAlloc + + jirl $r0, $ra, 0 + +.endm + + +//----------------------------------------------------------------------------- +// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. +// Since this is a tail call argument registers are restored. +// +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + .if (__PWTB_SaveFPArgs == 1) + RESTORE_FLOAT_ARGUMENT_REGISTERS $sp, __PWTB_FloatArgumentRegisters + .endif + + RESTORE_CALLEESAVED_REGISTERS 3, __PWTB_CalleeSavedRegisters + + RESTORE_ARGUMENT_REGISTERS $sp, __PWTB_ArgumentRegisters + + EPILOG_RESTORE_REG_PAIR 22, 1, __PWTB_CalleeSavedRegisters + + EPILOG_STACK_FREE __PWTB_StackAlloc + +.endm + +// ------------------------------------------------------------------ +// Macro to generate Redirection Stubs +// +// $reason : reason for redirection +// Eg. GCThreadControl +// NOTE: If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame. +// This function is used by both the personality routine and the debugger to retrieve the original CONTEXT. +.macro GenerateRedirectedHandledJITCaseStub reason + +#if NOTYET + GBLS __RedirectionStubFuncName + GBLS __RedirectionStubEndFuncName + GBLS __RedirectionFuncName +__RedirectionStubFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_Stub" +__RedirectionStubEndFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_StubEnd" +__RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thread@@CAXXZ|" + + IMPORT $__RedirectionFuncName + + NESTED_ENTRY $__RedirectionStubFuncName + addi.d $sp, $sp, -32 // stack slot for CONTEXT * and padding + PROLOG_SAVE_REG_PAIR 22, 1, 16, 1 + + //REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame + //If CONTEXT is not saved at 0 offset from SP it must be changed as well. + ASSERT REDIRECTSTUB_SP_OFFSET_CONTEXT == 0 + + // Stack alignment. This check is necessary as this function can be + // entered before complete execution of the prolog of another function. + andi $t4, $fp, 15 + sub.d $sp, $sp, $t4 + + + // + // Save a copy of the redirect CONTEXT*. + // This is needed for the debugger to unwind the stack. + // + bl GetCurrentSavedRedirectContext + + st.d $v0, $sp, 0 + + // + // Fetch the interrupted pc and save it as our return address. + // + ld.d $a1, $a0, CONTEXT_PC + st.d $a1, $fp, 8 + + // + // Call target, which will do whatever we needed to do in the context + // of the target thread, and will RtlRestoreContext when it is done. + // + bl $__RedirectionFuncName + + EMIT_BREAKPOINT // Unreachable + +// Put a label here to tell the debugger where the end of this function is. +$__RedirectionStubEndFuncName + EXPORT $__RedirectionStubEndFuncName + + NESTED_END +#else + EMIT_BREAKPOINT +#endif +.endm diff --git a/src/coreclr/pal/prebuilt/inc/cordebug.h b/src/coreclr/pal/prebuilt/inc/cordebug.h index df876984714400..226ae1c0ca7691 100644 --- a/src/coreclr/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/pal/prebuilt/inc/cordebug.h @@ -1475,7 +1475,8 @@ enum CorDebugPlatform CORDB_PLATFORM_POSIX_AMD64 = ( CORDB_PLATFORM_WINDOWS_ARM64 + 1 ) , CORDB_PLATFORM_POSIX_X86 = ( CORDB_PLATFORM_POSIX_AMD64 + 1 ) , CORDB_PLATFORM_POSIX_ARM = ( CORDB_PLATFORM_POSIX_X86 + 1 ) , - CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) + CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) , + CORDB_PLATFORM_POSIX_LOONGARCH64 = ( CORDB_PLATFORM_POSIX_ARM64 + 1 ) } CorDebugPlatform; @@ -9191,7 +9192,72 @@ enum CorDebugRegister REGISTER_ARM64_V28 = ( REGISTER_ARM64_V27 + 1 ) , REGISTER_ARM64_V29 = ( REGISTER_ARM64_V28 + 1 ) , REGISTER_ARM64_V30 = ( REGISTER_ARM64_V29 + 1 ) , - REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) + REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) , + REGISTER_LOONGARCH64_R0 = 0, + REGISTER_LOONGARCH64_RA = ( REGISTER_LOONGARCH64_R0 + 1 ) , + REGISTER_LOONGARCH64_TP = ( REGISTER_LOONGARCH64_RA + 1 ) , + REGISTER_LOONGARCH64_SP = ( REGISTER_LOONGARCH64_TP + 1 ) , + REGISTER_LOONGARCH64_A0 = ( REGISTER_LOONGARCH64_SP + 1 ) , + REGISTER_LOONGARCH64_A1 = ( REGISTER_LOONGARCH64_A0 + 1 ) , + REGISTER_LOONGARCH64_A2 = ( REGISTER_LOONGARCH64_A1 + 1 ) , + REGISTER_LOONGARCH64_A3 = ( REGISTER_LOONGARCH64_A2 + 1 ) , + REGISTER_LOONGARCH64_A4 = ( REGISTER_LOONGARCH64_A3 + 1 ) , + REGISTER_LOONGARCH64_A5 = ( REGISTER_LOONGARCH64_A4 + 1 ) , + REGISTER_LOONGARCH64_A6 = ( REGISTER_LOONGARCH64_A5 + 1 ) , + REGISTER_LOONGARCH64_A7 = ( REGISTER_LOONGARCH64_A6 + 1 ) , + REGISTER_LOONGARCH64_T0 = ( REGISTER_LOONGARCH64_A7 + 1 ) , + REGISTER_LOONGARCH64_T1 = ( REGISTER_LOONGARCH64_T0 + 1 ) , + REGISTER_LOONGARCH64_T2 = ( REGISTER_LOONGARCH64_T1 + 1 ) , + REGISTER_LOONGARCH64_T3 = ( REGISTER_LOONGARCH64_T2 + 1 ) , + REGISTER_LOONGARCH64_T4 = ( REGISTER_LOONGARCH64_T3 + 1 ) , + REGISTER_LOONGARCH64_T5 = ( REGISTER_LOONGARCH64_T4 + 1 ) , + REGISTER_LOONGARCH64_T6 = ( REGISTER_LOONGARCH64_T5 + 1 ) , + REGISTER_LOONGARCH64_T7 = ( REGISTER_LOONGARCH64_T6 + 1 ) , + REGISTER_LOONGARCH64_T8 = ( REGISTER_LOONGARCH64_T7 + 1 ) , + REGISTER_LOONGARCH64_X0 = ( REGISTER_LOONGARCH64_T8 + 1 ) , + REGISTER_LOONGARCH64_FP = ( REGISTER_LOONGARCH64_X0 + 1 ) , + REGISTER_LOONGARCH64_S0 = ( REGISTER_LOONGARCH64_FP + 1 ) , + REGISTER_LOONGARCH64_S1 = ( REGISTER_LOONGARCH64_S0 + 1 ) , + REGISTER_LOONGARCH64_S2 = ( REGISTER_LOONGARCH64_S1 + 1 ) , + REGISTER_LOONGARCH64_S3 = ( REGISTER_LOONGARCH64_S2 + 1 ) , + REGISTER_LOONGARCH64_S4 = ( REGISTER_LOONGARCH64_S3 + 1 ) , + REGISTER_LOONGARCH64_S5 = ( REGISTER_LOONGARCH64_S4 + 1 ) , + REGISTER_LOONGARCH64_S6 = ( REGISTER_LOONGARCH64_S5 + 1 ) , + REGISTER_LOONGARCH64_S7 = ( REGISTER_LOONGARCH64_S6 + 1 ) , + REGISTER_LOONGARCH64_S8 = ( REGISTER_LOONGARCH64_S7 + 1 ) , + REGISTER_LOONGARCH64_PC = ( REGISTER_LOONGARCH64_S8 + 1 ) , + REGISTER_LOONGARCH64_F0 = ( REGISTER_LOONGARCH64_PC + 1 ) , + REGISTER_LOONGARCH64_F1 = ( REGISTER_LOONGARCH64_F0 + 1 ) , + REGISTER_LOONGARCH64_F2 = ( REGISTER_LOONGARCH64_F1 + 1 ) , + REGISTER_LOONGARCH64_F3 = ( REGISTER_LOONGARCH64_F2 + 1 ) , + REGISTER_LOONGARCH64_F4 = ( REGISTER_LOONGARCH64_F3 + 1 ) , + REGISTER_LOONGARCH64_F5 = ( REGISTER_LOONGARCH64_F4 + 1 ) , + REGISTER_LOONGARCH64_F6 = ( REGISTER_LOONGARCH64_F5 + 1 ) , + REGISTER_LOONGARCH64_F7 = ( REGISTER_LOONGARCH64_F6 + 1 ) , + REGISTER_LOONGARCH64_F8 = ( REGISTER_LOONGARCH64_F7 + 1 ) , + REGISTER_LOONGARCH64_F9 = ( REGISTER_LOONGARCH64_F8 + 1 ) , + REGISTER_LOONGARCH64_F10 = ( REGISTER_LOONGARCH64_F9 + 1 ) , + REGISTER_LOONGARCH64_F11 = ( REGISTER_LOONGARCH64_F10 + 1 ) , + REGISTER_LOONGARCH64_F12 = ( REGISTER_LOONGARCH64_F11 + 1 ) , + REGISTER_LOONGARCH64_F13 = ( REGISTER_LOONGARCH64_F12 + 1 ) , + REGISTER_LOONGARCH64_F14 = ( REGISTER_LOONGARCH64_F13 + 1 ) , + REGISTER_LOONGARCH64_F15 = ( REGISTER_LOONGARCH64_F14 + 1 ) , + REGISTER_LOONGARCH64_F16 = ( REGISTER_LOONGARCH64_F15 + 1 ) , + REGISTER_LOONGARCH64_F17 = ( REGISTER_LOONGARCH64_F16 + 1 ) , + REGISTER_LOONGARCH64_F18 = ( REGISTER_LOONGARCH64_F17 + 1 ) , + REGISTER_LOONGARCH64_F19 = ( REGISTER_LOONGARCH64_F18 + 1 ) , + REGISTER_LOONGARCH64_F20 = ( REGISTER_LOONGARCH64_F19 + 1 ) , + REGISTER_LOONGARCH64_F21 = ( REGISTER_LOONGARCH64_F20 + 1 ) , + REGISTER_LOONGARCH64_F22 = ( REGISTER_LOONGARCH64_F21 + 1 ) , + REGISTER_LOONGARCH64_F23 = ( REGISTER_LOONGARCH64_F22 + 1 ) , + REGISTER_LOONGARCH64_F24 = ( REGISTER_LOONGARCH64_F23 + 1 ) , + REGISTER_LOONGARCH64_F25 = ( REGISTER_LOONGARCH64_F24 + 1 ) , + REGISTER_LOONGARCH64_F26 = ( REGISTER_LOONGARCH64_F25 + 1 ) , + REGISTER_LOONGARCH64_F27 = ( REGISTER_LOONGARCH64_F26 + 1 ) , + REGISTER_LOONGARCH64_F28 = ( REGISTER_LOONGARCH64_F27 + 1 ) , + REGISTER_LOONGARCH64_F29 = ( REGISTER_LOONGARCH64_F28 + 1 ) , + REGISTER_LOONGARCH64_F30 = ( REGISTER_LOONGARCH64_F29 + 1 ) , + REGISTER_LOONGARCH64_F31 = ( REGISTER_LOONGARCH64_F30 + 1 ) } CorDebugRegister; diff --git a/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S b/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S new file mode 100644 index 00000000000000..2c4e5e2a2dab02 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Copyright (c) Loongson Technology. All rights reserved. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// Offset of the return address from the ActivationHandler in the ActivationHandlerWrapper +.globl C_FUNC(ActivationHandlerReturnOffset) +C_FUNC(ActivationHandlerReturnOffset): + .int LOCAL_LABEL(ActivationHandlerReturn)-C_FUNC(ActivationHandlerWrapper) + +NESTED_ENTRY ActivationHandlerWrapper, _TEXT, NoHandler + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, -(16 + CONTEXT_Size) + // Should never actually run + EMIT_BREAKPOINT + bl EXTERNAL_C_FUNC(ActivationHandler) +LOCAL_LABEL(ActivationHandlerReturn): + // Should never return + EMIT_BREAKPOINT + // $fp,$ra + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, (16 + CONTEXT_Size) + jirl $r0, $ra, 0 +NESTED_END ActivationHandlerWrapper, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/asmconstants.h b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h new file mode 100644 index 00000000000000..bdd327766714bf --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h @@ -0,0 +1,100 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +#ifndef __PAL_LOONGARCH64_ASMCONSTANTS_H__ +#define __PAL_LOONGARCH64_ASMCONSTANTS_H__ + +//Please refence "src/pal/inc/pal.h" +#define CONTEXT_LOONGARCH64 0x00800000 + +#define CONTEXT_CONTROL_BIT (0) +#define CONTEXT_INTEGER_BIT (1) +#define CONTEXT_FLOATING_POINT_BIT (2) +#define CONTEXT_DEBUG_REGISTERS_BIT (3) + +#define CONTEXT_CONTROL (CONTEXT_LOONGARCH64 | (1 << CONTEXT_CONTROL_BIT)) +#define CONTEXT_INTEGER (CONTEXT_LOONGARCH64 | (1 << CONTEXT_INTEGER_BIT)) +#define CONTEXT_FLOATING_POINT (CONTEXT_LOONGARCH64 | (1 << CONTEXT_FLOATING_POINT_BIT)) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_LOONGARCH64 | (1 << CONTEXT_DEBUG_REGISTERS_BIT)) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define SIZEOF_LOONGARCH_GPR 8 +#define SIZEOF_LOONGARCH_FPR 8 + +#define CONTEXT_ContextFlags 0 +//Note: Here CONTEXT_ContextFlags+8 for memory algin. +#define CONTEXT_R0 CONTEXT_ContextFlags+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Ra CONTEXT_R0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Tp CONTEXT_Ra+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Sp CONTEXT_Tp+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A0 CONTEXT_Sp+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A1 CONTEXT_A0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A2 CONTEXT_A1+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A3 CONTEXT_A2+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A4 CONTEXT_A3+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A5 CONTEXT_A4+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A6 CONTEXT_A5+SIZEOF_LOONGARCH_GPR +#define CONTEXT_A7 CONTEXT_A6+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T0 CONTEXT_A7+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T1 CONTEXT_T0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T2 CONTEXT_T1+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T3 CONTEXT_T2+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T4 CONTEXT_T3+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T5 CONTEXT_T4+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T6 CONTEXT_T5+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T7 CONTEXT_T6+SIZEOF_LOONGARCH_GPR +#define CONTEXT_T8 CONTEXT_T7+SIZEOF_LOONGARCH_GPR +#define CONTEXT_X0 CONTEXT_T8+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Fp CONTEXT_X0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S0 CONTEXT_Fp+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S1 CONTEXT_S0+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S2 CONTEXT_S1+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S3 CONTEXT_S2+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S4 CONTEXT_S3+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S5 CONTEXT_S4+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S6 CONTEXT_S5+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S7 CONTEXT_S6+SIZEOF_LOONGARCH_GPR +#define CONTEXT_S8 CONTEXT_S7+SIZEOF_LOONGARCH_GPR +#define CONTEXT_Pc CONTEXT_S8+SIZEOF_LOONGARCH_GPR +#define CONTEXT_FPU_OFFSET CONTEXT_Pc+SIZEOF_LOONGARCH_GPR + +#define CONTEXT_F0 0 +#define CONTEXT_F1 CONTEXT_F0+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F2 CONTEXT_F1+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F3 CONTEXT_F2+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F4 CONTEXT_F3+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F5 CONTEXT_F4+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F6 CONTEXT_F5+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F7 CONTEXT_F6+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F8 CONTEXT_F7+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F9 CONTEXT_F8+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F10 CONTEXT_F9+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F11 CONTEXT_F10+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F12 CONTEXT_F11+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F13 CONTEXT_F12+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F14 CONTEXT_F13+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F15 CONTEXT_F14+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F16 CONTEXT_F15+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F17 CONTEXT_F16+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F18 CONTEXT_F17+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F19 CONTEXT_F18+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F20 CONTEXT_F19+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F21 CONTEXT_F20+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F22 CONTEXT_F21+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F23 CONTEXT_F22+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F24 CONTEXT_F23+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F25 CONTEXT_F24+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F26 CONTEXT_F25+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F27 CONTEXT_F26+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F28 CONTEXT_F27+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F29 CONTEXT_F28+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F30 CONTEXT_F29+SIZEOF_LOONGARCH_FPR +#define CONTEXT_F31 CONTEXT_F30+SIZEOF_LOONGARCH_FPR +#define CONTEXT_FLOAT_CONTROL_OFFSET CONTEXT_F31+SIZEOF_LOONGARCH_FPR +#define CONTEXT_Size ((CONTEXT_FPU_OFFSET + 8 + 8 + 0xf) & ~0xf) + +#endif diff --git a/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S b/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S new file mode 100644 index 00000000000000..029efd80d95837 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +#include "unixasmmacros.inc" +#include "asmconstants.h" +.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment + +.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) +C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): + .dword LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) + +// This function is never called, only a fake stack frame will be setup to have a return +// address set to SignalHandlerWorkerReturn during SIGSEGV handling. +// It enables the unwinder to unwind stack from the handling code to the actual failure site. +NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler +__StackAllocationSize = (128 + 8 + 8 + \Alignment) // red zone + fp + ra + alignment + PROLOG_STACK_ALLOC __StackAllocationSize + .cfi_adjust_cfa_offset __StackAllocationSize + + // $fp,$ra + PROLOG_SAVE_REG_PAIR 22, 1, 0 + + bl signal_handler_worker + +LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): + EPILOG_RESTORE_REG_PAIR 22, 1, 0 + EPILOG_STACK_FREE __StackAllocationSize + jirl $r0, $ra, 0 + +NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT + +.endm + +CALL_SIGNAL_HANDLER_WRAPPER 0 +CALL_SIGNAL_HANDLER_WRAPPER 8 diff --git a/src/coreclr/pal/src/arch/loongarch64/context.S b/src/coreclr/pal/src/arch/loongarch64/context.S new file mode 100644 index 00000000000000..ba2536e83cc972 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/context.S @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Copyright (c) Loongson Technology. All rights reserved. + +#include "unixasmmacros.inc" + +#if defined(_DEBUG) +NESTED_ENTRY DBG_CheckStackAlignment, _TEXT, NoHandler + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, -16 + // Reading from an unaligned stack pointer will trigger a stack alignment fault + ld.d $a0, $sp + // $fp,$ra + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, 16 + jirl $r0, $ra, 0 +NESTED_END _DBG_CheckStackAlignment, _TEXT +#endif diff --git a/src/coreclr/pal/src/arch/loongarch64/context2.S b/src/coreclr/pal/src/arch/loongarch64/context2.S new file mode 100644 index 00000000000000..48c42593ce4540 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/context2.S @@ -0,0 +1,257 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +// +// Implementation of _CONTEXT_CaptureContext for the LOONGARCH platform. +// This function is processor dependent. It is used by exception handling, +// and is always apply to the current thread. +// + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +// Incoming: +// a0: Context* +// a1: Exception* +// +LEAF_ENTRY RtlRestoreContext, _TEXT +#ifdef HAS_ASAN + ld.w $r21, $a0, CONTEXT_ContextFlags + ext $r21, $r21, CONTEXT_FLOATING_POINT_BIT, 1 + beq $r21, $r0, LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT) + + addi.d $sp, $sp, -16 + st.d a0, $sp, 0 + st.d a1, $sp, 8 + + bl __asan_handle_no_return + + ld.d $a0, $sp, 0 + ld.d $a1, $sp, 8 + addi.d $sp, $sp, 16 + +LOCAL_LABEL(Restore_CONTEXT_FLOATING_POINT): +#endif + + ori $t4, $a0, 0 + ld.w $r21, $t4, CONTEXT_ContextFlags + bstrpick.w $t1, $r21, CONTEXT_FLOATING_POINT_BIT, CONTEXT_FLOATING_POINT_BIT + beq $t1, $r0, LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT) + + //64-bits FPR. + addi.d $t0, $t4, CONTEXT_FPU_OFFSET + + fld.d $f0, $t0, CONTEXT_F0 + fld.d $f1, $t0, CONTEXT_F1 + fld.d $f2, $t0, CONTEXT_F2 + fld.d $f3, $t0, CONTEXT_F3 + fld.d $f4, $t0, CONTEXT_F4 + fld.d $f5, $t0, CONTEXT_F5 + fld.d $f6, $t0, CONTEXT_F6 + fld.d $f7, $t0, CONTEXT_F7 + fld.d $f8, $t0, CONTEXT_F8 + fld.d $f9, $t0, CONTEXT_F9 + fld.d $f10, $t0, CONTEXT_F10 + fld.d $f11, $t0, CONTEXT_F11 + fld.d $f12, $t0, CONTEXT_F12 + fld.d $f13, $t0, CONTEXT_F13 + fld.d $f14, $t0, CONTEXT_F14 + fld.d $f15, $t0, CONTEXT_F15 + fld.d $f16, $t0, CONTEXT_F16 + fld.d $f17, $t0, CONTEXT_F17 + fld.d $f18, $t0, CONTEXT_F18 + fld.d $f19, $t0, CONTEXT_F19 + fld.d $f20, $t0, CONTEXT_F20 + fld.d $f21, $t0, CONTEXT_F21 + fld.d $f22, $t0, CONTEXT_F22 + fld.d $f23, $t0, CONTEXT_F23 + fld.d $f24, $t0, CONTEXT_F24 + fld.d $f25, $t0, CONTEXT_F25 + fld.d $f26, $t0, CONTEXT_F26 + fld.d $f27, $t0, CONTEXT_F27 + fld.d $f28, $t0, CONTEXT_F28 + fld.d $f29, $t0, CONTEXT_F29 + fld.d $f30, $t0, CONTEXT_F30 + fld.d $f31, $t0, CONTEXT_F31 + + ld.w $t1, $t0, CONTEXT_FLOAT_CONTROL_OFFSET + movgr2fcsr $fcsr0, $t1 + +LOCAL_LABEL(No_Restore_CONTEXT_FLOATING_POINT): + + bstrpick.w $t1, $r21, CONTEXT_INTEGER_BIT, CONTEXT_INTEGER_BIT + beq $t1, $r0, LOCAL_LABEL(No_Restore_CONTEXT_INTEGER) + + ld.d $tp, $a0, CONTEXT_Tp + ld.d $a1, $a0, CONTEXT_A1 + ld.d $a2, $a0, CONTEXT_A2 + ld.d $a3, $a0, CONTEXT_A3 + ld.d $a4, $a0, CONTEXT_A4 + ld.d $a5, $a0, CONTEXT_A5 + ld.d $a6, $a0, CONTEXT_A6 + ld.d $a7, $a0, CONTEXT_A7 + ld.d $t0, $a0, CONTEXT_T0 + ld.d $t1, $a0, CONTEXT_T1 + ld.d $t2, $a0, CONTEXT_T2 + ld.d $t3, $a0, CONTEXT_T3 + ld.d $t5, $a0, CONTEXT_T5 + ld.d $t6, $a0, CONTEXT_T6 + ld.d $t7, $a0, CONTEXT_T7 + ld.d $t8, $a0, CONTEXT_T8 + //ld.d $r21,$a0, CONTEXT_X0 + ld.d $s0, $a0, CONTEXT_S0 + ld.d $s1, $a0, CONTEXT_S1 + ld.d $s2, $a0, CONTEXT_S2 + ld.d $s3, $a0, CONTEXT_S3 + ld.d $s4, $a0, CONTEXT_S4 + ld.d $s5, $a0, CONTEXT_S5 + ld.d $s6, $a0, CONTEXT_S6 + ld.d $s7, $a0, CONTEXT_S7 +#ifndef CONTEXT_S8 +#error "----------------nodefine8" +#endif + ld.d $s8, $a0, CONTEXT_S8 + ld.d $a0, $a0, CONTEXT_A0 + +LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): + + ld.w $r21, $t4, CONTEXT_ContextFlags + bstrpick.w $r21, $r21, CONTEXT_CONTROL_BIT, CONTEXT_CONTROL_BIT + beq $r21, $r0, LOCAL_LABEL(No_Restore_CONTEXT_CONTROL) + + ld.d $ra, $t4, CONTEXT_Ra + ld.d $fp, $t4, CONTEXT_Fp + ld.d $sp, $t4, CONTEXT_Sp + ld.d $r21, $t4, CONTEXT_Pc + ld.d $t4, $t4, CONTEXT_T4 + jirl $r0, $r21, 0 + + +LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): + jirl $r0, $ra, 0 +LEAF_END RtlRestoreContext, _TEXT + +// Incoming: +// a0: Context* + +LEAF_ENTRY RtlCaptureContext, _TEXT + PROLOG_STACK_ALLOC 16 + st.d $r21, $sp, 0 + li.w $r21, CONTEXT_FULL + st.w $r21, $a0, CONTEXT_ContextFlags + ld.d $r21, $sp, 0 + EPILOG_STACK_FREE 16 + b C_FUNC(CONTEXT_CaptureContext) +LEAF_END RtlCaptureContext, _TEXT + +// Incoming: +// a0: Context* +// +LEAF_ENTRY CONTEXT_CaptureContext, _TEXT + PROLOG_STACK_ALLOC 24 + st.d $t0, $sp, 0 + st.d $t1, $sp, 8 + st.d $t3, $sp, 16 + + ld.w $t1, $a0, CONTEXT_ContextFlags + li.w $t0, CONTEXT_CONTROL + and $t3, $t1, $t0 + bne $t3, $t0, LOCAL_LABEL(Done_CONTEXT_CONTROL) + + addi.d $t0, $sp, 24 + st.d $fp, $a0, CONTEXT_Fp + st.d $t0, $a0, CONTEXT_Sp + st.d $ra, $a0, CONTEXT_Ra + st.d $ra, $a0, CONTEXT_Pc + +LOCAL_LABEL(Done_CONTEXT_CONTROL): + + li.w $t0, CONTEXT_INTEGER + and $t3, $t1, $t0 + bne $t3, $t0, LOCAL_LABEL(Done_CONTEXT_INTEGER) + + ld.d $t0, $sp, 0 + ld.d $t1, $sp, 8 + ld.d $t3, $sp, 16 + + st.d $tp, $a0, CONTEXT_Tp + st.d $a0, $a0, CONTEXT_A0 + st.d $a1, $a0, CONTEXT_A1 + st.d $a2, $a0, CONTEXT_A2 + st.d $a3, $a0, CONTEXT_A3 + st.d $a4, $a0, CONTEXT_A4 + st.d $a5, $a0, CONTEXT_A5 + st.d $a6, $a0, CONTEXT_A6 + st.d $a7, $a0, CONTEXT_A7 + st.d $t0, $a0, CONTEXT_T0 + st.d $t1, $a0, CONTEXT_T1 + st.d $t2, $a0, CONTEXT_T2 + st.d $t3, $a0, CONTEXT_T3 + st.d $t4, $a0, CONTEXT_T4 + st.d $t5, $a0, CONTEXT_T5 + st.d $t6, $a0, CONTEXT_T6 + st.d $t7, $a0, CONTEXT_T7 + st.d $t8, $a0, CONTEXT_T8 + st.d $r21,$a0, CONTEXT_X0 + st.d $s0, $a0, CONTEXT_S0 + st.d $s1, $a0, CONTEXT_S1 + st.d $s2, $a0, CONTEXT_S2 + st.d $s3, $a0, CONTEXT_S3 + st.d $s4, $a0, CONTEXT_S4 + st.d $s5, $a0, CONTEXT_S5 + st.d $s6, $a0, CONTEXT_S6 + st.d $s7, $a0, CONTEXT_S7 + st.d $s8, $a0, CONTEXT_S8 + +LOCAL_LABEL(Done_CONTEXT_INTEGER): + ld.w $t1, $a0, CONTEXT_ContextFlags + + li.w $t0, CONTEXT_FLOATING_POINT + and $t3, $t1, $t0 + bne $t3, $t0, LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT) + + addi.d $a0, $a0, CONTEXT_FPU_OFFSET + + fst.d $f0 , $a0, CONTEXT_F0 + fst.d $f1 , $a0, CONTEXT_F1 + fst.d $f2 , $a0, CONTEXT_F2 + fst.d $f3 , $a0, CONTEXT_F3 + fst.d $f4 , $a0, CONTEXT_F4 + fst.d $f5 , $a0, CONTEXT_F5 + fst.d $f6 , $a0, CONTEXT_F6 + fst.d $f7 , $a0, CONTEXT_F7 + fst.d $f8 , $a0, CONTEXT_F8 + fst.d $f9 , $a0, CONTEXT_F9 + fst.d $f10, $a0, CONTEXT_F10 + fst.d $f11, $a0, CONTEXT_F11 + fst.d $f12, $a0, CONTEXT_F12 + fst.d $f13, $a0, CONTEXT_F13 + fst.d $f14, $a0, CONTEXT_F14 + fst.d $f15, $a0, CONTEXT_F15 + fst.d $f16, $a0, CONTEXT_F16 + fst.d $f17, $a0, CONTEXT_F17 + fst.d $f18, $a0, CONTEXT_F18 + fst.d $f19, $a0, CONTEXT_F19 + fst.d $f20, $a0, CONTEXT_F20 + fst.d $f21, $a0, CONTEXT_F21 + fst.d $f22, $a0, CONTEXT_F22 + fst.d $f23, $a0, CONTEXT_F23 + fst.d $f24, $a0, CONTEXT_F24 + fst.d $f25, $a0, CONTEXT_F25 + fst.d $f26, $a0, CONTEXT_F26 + fst.d $f27, $a0, CONTEXT_F27 + fst.d $f28, $a0, CONTEXT_F28 + fst.d $f29, $a0, CONTEXT_F29 + fst.d $f30, $a0, CONTEXT_F30 + fst.d $f31, $a0, CONTEXT_F31 + movfcsr2gr $t0, $fcsr0 + st.d $t0, $a0, CONTEXT_FLOAT_CONTROL_OFFSET + +LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT): + + EPILOG_STACK_FREE 24 + jirl $r0, $ra, 0 +LEAF_END CONTEXT_CaptureContext, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/debugbreak.S b/src/coreclr/pal/src/arch/loongarch64/debugbreak.S new file mode 100644 index 00000000000000..e82b52d37f2b18 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/debugbreak.S @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +#include "unixasmmacros.inc" +LEAF_ENTRY DBG_DebugBreak, _TEXT + EMIT_BREAKPOINT +LEAF_END_MARKED DBG_DebugBreak, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S b/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S new file mode 100644 index 00000000000000..3b0aa198cbc160 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Copyright (c) Loongson Technology. All rights reserved. + +// ==++== +// + +// ==--== +// +// Implementation of the PAL_DispatchExceptionWrapper that is +// interposed between a function that caused a hardware fault +// and PAL_DispatchException that throws an SEH exception for +// the fault, to make the stack unwindable. +// + +#include "unixasmmacros.inc" + +// Offset of the return address from the PAL_DispatchException in the PAL_DispatchExceptionWrapper +.globl C_FUNC(PAL_DispatchExceptionReturnOffset) +C_FUNC(PAL_DispatchExceptionReturnOffset): + .int LOCAL_LABEL(PAL_DispatchExceptionReturn) - C_FUNC(PAL_DispatchExceptionWrapper) + +// +// PAL_DispatchExceptionWrapper will never be called; it only serves +// to be referenced from a stack frame on the faulting thread. Its +// unwinding behavior is equivalent to any standard function. +// It is analogous to the following source file. +// +// extern "C" void PAL_DispatchException(CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord, MachExceptionInfo *pMachExceptionInfo); +// +// extern "C" void PAL_DispatchExceptionWrapper() +// { +// CONTEXT Context; +// EXCEPTION_RECORD ExceptionRecord; +// MachExceptionInfo MachExceptionInfo; +// PAL_DispatchException(&Context, &ExceptionRecord, &MachExceptionInfo); +// } +// + +NESTED_ENTRY PAL_DispatchExceptionWrapper, _TEXT, NoHandler + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, -16 + // Should never actually run + EMIT_BREAKPOINT + bl EXTERNAL_C_FUNC(PAL_DispatchException) +LOCAL_LABEL(PAL_DispatchExceptionReturn): + // Should never return + EMIT_BREAKPOINT + // $fp,$ra + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, 16 + jirl $r0, $ra, 0 +NESTED_END PAL_DispatchExceptionWrapper, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S new file mode 100644 index 00000000000000..6854a884002209 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +#include "unixasmmacros.inc" +#include "asmconstants.h" + +////////////////////////////////////////////////////////////////////////// +// +// This function creates a stack frame right below the target frame, restores all callee +// saved registers, SP, and RA from the passed in context. +// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. +// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); +LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT +#ifdef HAS_ASAN +#pragma error("LLVM v3.9 ASAN unimplemented on LOONGARCH yet") +#endif + addi.d $sp, $sp, -16 + .cfi_adjust_cfa_offset 16 + + // Save the FP & RA to the stack so that the unwind can work at the instruction after + // loading the FP from the context, but before loading the SP from the context. + st.d $fp, $sp, 0 + st.d $ra, $sp, 8 + .cfi_rel_offset 22, 0 + .cfi_rel_offset 1, 8 + + ld.d $tp, $a0, CONTEXT_Tp + ld.d $s0, $a0, CONTEXT_S0 + ld.d $s1, $a0, CONTEXT_S1 + ld.d $s2, $a0, CONTEXT_S2 + ld.d $s3, $a0, CONTEXT_S3 + ld.d $s4, $a0, CONTEXT_S4 + ld.d $s5, $a0, CONTEXT_S5 + ld.d $s6, $a0, CONTEXT_S6 + ld.d $s7, $a0, CONTEXT_S7 + ld.d $s8, $a0, CONTEXT_S8 + ld.d $ra, $a0, CONTEXT_Ra + + ld.d $fp, $a0, CONTEXT_Fp + ld.d $sp, $a0, CONTEXT_Sp + + // The PAL_SEHException pointer + ori $a0, $a1, 0 + b ThrowExceptionHelper +LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/processor.cpp b/src/coreclr/pal/src/arch/loongarch64/processor.cpp new file mode 100644 index 00000000000000..260bc38f381129 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/processor.cpp @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +/*++ + + + +Module Name: + + processor.cpp + +Abstract: + + Implementation of processor related functions for the LOONGARCH64 + platform. These functions are processor dependent. + + + +--*/ + +#include "pal/palinternal.h" diff --git a/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp b/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp new file mode 100644 index 00000000000000..615e4aa414b7b1 --- /dev/null +++ b/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +#include "pal/dbgmsg.h" +SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first + +#include "pal/palinternal.h" +#include "pal/context.h" +#include "pal/signal.hpp" +#include "pal/utils.h" +#include + +/*++ +Function : + ExecuteHandlerOnCustomStack + + Execute signal handler on a custom stack, the current stack pointer is specified by the customSp + If the customSp is 0, then the handler is executed on the original stack where the signal was fired. + It installs a fake stack frame to enable stack unwinding to the signal source location. + +Parameters : + POSIX signal handler parameter list ("man sigaction" for details) + returnPoint - context to which the function returns if the common_signal_handler returns + + (no return value) +--*/ +void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) +{ + ucontext_t *ucontext = (ucontext_t *)context; + size_t faultSp = (size_t)MCREG_Sp(ucontext->uc_mcontext); + _ASSERTE(IS_ALIGNED(faultSp, 8)); + + if (customSp == 0) + { + // preserve 128 bytes long red zone and align stack pointer + customSp = ALIGN_DOWN(faultSp - 128, 16); + } + + size_t fakeFrameReturnAddress; + + if (IS_ALIGNED(faultSp, 16)) + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; + } + else + { + fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8; + } + + // preserve 128 bytes long red zone and align stack pointer + size_t* sp = (size_t*)customSp; + + // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction + // pushed RA + *--sp = (size_t)MCREG_Pc(ucontext->uc_mcontext); + // pushed frame pointer + *--sp = (size_t)MCREG_Fp(ucontext->uc_mcontext); + + // Switch the current context to the signal_handler_worker and the original stack + CONTEXT context2; + RtlCaptureContext(&context2); + + context2.Sp = (size_t)sp; + context2.Fp = (size_t)sp; + context2.Ra = fakeFrameReturnAddress; + context2.Pc = (size_t)signal_handler_worker; + context2.A0 = code; + context2.A1 = (size_t)siginfo; + context2.A2 = (size_t)context; + context2.A3 = (size_t)returnPoint; + + RtlRestoreContext(&context2, NULL); +} diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp index af0293ba5bc60c..b95e395854d4a4 100644 --- a/src/coreclr/pal/src/exception/remote-unwind.cpp +++ b/src/coreclr/pal/src/exception/remote-unwind.cpp @@ -123,7 +123,7 @@ typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size #define PRId PRId32 #define PRIA "08" #define PRIxA PRIA PRIx -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) #define PRIx PRIx64 #define PRIu PRIu64 #define PRId PRId64 @@ -1655,6 +1655,19 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_AARCH64_X27, &contextPointers->X27); GetContextPointer(cursor, unwContext, UNW_AARCH64_X28, &contextPointers->X28); GetContextPointer(cursor, unwContext, UNW_AARCH64_X29, &contextPointers->Fp); +#elif defined(TARGET_LOONGARCH64) + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R1, &contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R2, &contextPointers->Tp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R22, &contextPointers->Fp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R23, &contextPointers->S0); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R24, &contextPointers->S1); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R25, &contextPointers->S2); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R26, &contextPointers->S3); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R27, &contextPointers->S4); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R28, &contextPointers->S5); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R29, &contextPointers->S6); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R30, &contextPointers->S7); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R31, &contextPointers->S8); #elif defined(TARGET_S390X) GetContextPointer(cursor, unwContext, UNW_S390X_R6, &contextPointers->R6); GetContextPointer(cursor, unwContext, UNW_S390X_R7, &contextPointers->R7); @@ -1718,6 +1731,22 @@ static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_AARCH64_X29, (unw_word_t *) &winContext->Fp); unw_get_reg(cursor, UNW_AARCH64_X30, (unw_word_t *) &winContext->Lr); TRACE("sp %p pc %p lr %p fp %p\n", winContext->Sp, winContext->Pc, winContext->Lr, winContext->Fp); +#elif defined(TARGET_LOONGARCH64) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_LOONGARCH_R1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_LOONGARCH_R2, (unw_word_t *) &winContext->Tp); + unw_get_reg(cursor, UNW_LOONGARCH_R22, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_LOONGARCH_R23, (unw_word_t *) &winContext->S0); + unw_get_reg(cursor, UNW_LOONGARCH_R24, (unw_word_t *) &winContext->S1); + unw_get_reg(cursor, UNW_LOONGARCH_R25, (unw_word_t *) &winContext->S2); + unw_get_reg(cursor, UNW_LOONGARCH_R26, (unw_word_t *) &winContext->S3); + unw_get_reg(cursor, UNW_LOONGARCH_R27, (unw_word_t *) &winContext->S4); + unw_get_reg(cursor, UNW_LOONGARCH_R28, (unw_word_t *) &winContext->S5); + unw_get_reg(cursor, UNW_LOONGARCH_R29, (unw_word_t *) &winContext->S6); + unw_get_reg(cursor, UNW_LOONGARCH_R30, (unw_word_t *) &winContext->S7); + unw_get_reg(cursor, UNW_LOONGARCH_R31, (unw_word_t *) &winContext->S8); + TRACE("sp %p pc %p fp %p tp %p ra %p\n", winContext->Sp, winContext->Pc, winContext->Fp, winContext->Tp, winContext->Ra); #elif defined(TARGET_S390X) unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->PSWAddr); unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->R15); @@ -1819,6 +1848,20 @@ access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write case UNW_AARCH64_X30: *valp = (unw_word_t)winContext->Lr; break; case UNW_AARCH64_SP: *valp = (unw_word_t)winContext->Sp; break; case UNW_AARCH64_PC: *valp = (unw_word_t)winContext->Pc; break; +#elif defined(TARGET_LOONGARCH64) + case UNW_LOONGARCH_R1: *valp = (unw_word_t)winContext->Ra; break; + case UNW_LOONGARCH_R2: *valp = (unw_word_t)winContext->Tp; break; + case UNW_LOONGARCH_R22: *valp = (unw_word_t)winContext->Fp; break; + case UNW_LOONGARCH_R23: *valp = (unw_word_t)winContext->S0; break; + case UNW_LOONGARCH_R24: *valp = (unw_word_t)winContext->S1; break; + case UNW_LOONGARCH_R25: *valp = (unw_word_t)winContext->S2; break; + case UNW_LOONGARCH_R26: *valp = (unw_word_t)winContext->S3; break; + case UNW_LOONGARCH_R27: *valp = (unw_word_t)winContext->S4; break; + case UNW_LOONGARCH_R28: *valp = (unw_word_t)winContext->S5; break; + case UNW_LOONGARCH_R29: *valp = (unw_word_t)winContext->S6; break; + case UNW_LOONGARCH_R30: *valp = (unw_word_t)winContext->S7; break; + case UNW_LOONGARCH_R31: *valp = (unw_word_t)winContext->S8; break; + case UNW_LOONGARCH_PC: *valp = (unw_word_t)winContext->Pc; break; #elif defined(TARGET_S390X) case UNW_S390X_R6: *valp = (unw_word_t)winContext->R6; break; case UNW_S390X_R7: *valp = (unw_word_t)winContext->R7; break; diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index 4b149f941b5dc9..bc758a57e2c18c 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -176,6 +176,22 @@ enum ASSIGN_REG(R13) \ ASSIGN_REG(R14) \ ASSIGN_REG(R15) +#elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) +#define ASSIGN_UNWIND_REGS \ + ASSIGN_REG(Pc) \ + ASSIGN_REG(Tp) \ + ASSIGN_REG(Sp) \ + ASSIGN_REG(Fp) \ + ASSIGN_REG(Ra) \ + ASSIGN_REG(S0) \ + ASSIGN_REG(S1) \ + ASSIGN_REG(S2) \ + ASSIGN_REG(S3) \ + ASSIGN_REG(S4) \ + ASSIGN_REG(S5) \ + ASSIGN_REG(S6) \ + ASSIGN_REG(S7) \ + ASSIGN_REG(S8) #else #error unsupported architecture #endif @@ -404,6 +420,21 @@ void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_S390X_R12, (unw_word_t *) &winContext->R12); unw_get_reg(cursor, UNW_S390X_R13, (unw_word_t *) &winContext->R13); unw_get_reg(cursor, UNW_S390X_R14, (unw_word_t *) &winContext->R14); +#elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) + unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); + unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); + unw_get_reg(cursor, UNW_LOONGARCH_R1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_LOONGARCH_R2, (unw_word_t *) &winContext->Tp); + unw_get_reg(cursor, UNW_LOONGARCH_R22, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_LOONGARCH_R23, (unw_word_t *) &winContext->S0); + unw_get_reg(cursor, UNW_LOONGARCH_R24, (unw_word_t *) &winContext->S1); + unw_get_reg(cursor, UNW_LOONGARCH_R25, (unw_word_t *) &winContext->S2); + unw_get_reg(cursor, UNW_LOONGARCH_R26, (unw_word_t *) &winContext->S3); + unw_get_reg(cursor, UNW_LOONGARCH_R27, (unw_word_t *) &winContext->S4); + unw_get_reg(cursor, UNW_LOONGARCH_R28, (unw_word_t *) &winContext->S5); + unw_get_reg(cursor, UNW_LOONGARCH_R29, (unw_word_t *) &winContext->S6); + unw_get_reg(cursor, UNW_LOONGARCH_R30, (unw_word_t *) &winContext->S7); + unw_get_reg(cursor, UNW_LOONGARCH_R31, (unw_word_t *) &winContext->S8); #else #error unsupported architecture #endif @@ -489,6 +520,19 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL GetContextPointer(cursor, unwContext, UNW_S390X_R13, &contextPointers->R13); GetContextPointer(cursor, unwContext, UNW_S390X_R14, &contextPointers->R14); GetContextPointer(cursor, unwContext, UNW_S390X_R15, &contextPointers->R15); +#elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R1, &contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R2, &contextPointers->Tp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R22, &contextPointers->Fp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R23, &contextPointers->S0); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R24, &contextPointers->S1); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R25, &contextPointers->S2); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R26, &contextPointers->S3); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R27, &contextPointers->S4); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R28, &contextPointers->S5); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R29, &contextPointers->S6); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R30, &contextPointers->S7); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R31, &contextPointers->S8); #else #error unsupported architecture #endif diff --git a/src/coreclr/pal/src/include/pal/context.h b/src/coreclr/pal/src/include/pal/context.h index 281c418aef4d2a..fd37f92693c413 100644 --- a/src/coreclr/pal/src/include/pal/context.h +++ b/src/coreclr/pal/src/include/pal/context.h @@ -78,6 +78,43 @@ using asm_sigcontext::_xstate; #elif HAVE___GREGSET_T #ifdef HOST_64BIT + +#if defined(HOST_LOONGARCH64) +#define MCREG_R0(mc) ((mc).__gregs[0]) +#define MCREG_Ra(mc) ((mc).__gregs[1]) +#define MCREG_Tp(mc) ((mc).__gregs[2]) +#define MCREG_Sp(mc) ((mc).__gregs[3]) +#define MCREG_A0(mc) ((mc).__gregs[4]) +#define MCREG_A1(mc) ((mc).__gregs[5]) +#define MCREG_A2(mc) ((mc).__gregs[6]) +#define MCREG_A3(mc) ((mc).__gregs[7]) +#define MCREG_A4(mc) ((mc).__gregs[8]) +#define MCREG_A5(mc) ((mc).__gregs[9]) +#define MCREG_A6(mc) ((mc).__gregs[10]) +#define MCREG_A7(mc) ((mc).__gregs[11]) +#define MCREG_T0(mc) ((mc).__gregs[12]) +#define MCREG_T1(mc) ((mc).__gregs[13]) +#define MCREG_T2(mc) ((mc).__gregs[14]) +#define MCREG_T3(mc) ((mc).__gregs[15]) +#define MCREG_T4(mc) ((mc).__gregs[16]) +#define MCREG_T5(mc) ((mc).__gregs[17]) +#define MCREG_T6(mc) ((mc).__gregs[18]) +#define MCREG_T7(mc) ((mc).__gregs[19]) +#define MCREG_T8(mc) ((mc).__gregs[20]) +#define MCREG_X0(mc) ((mc).__gregs[21]) +#define MCREG_Fp(mc) ((mc).__gregs[22]) +#define MCREG_S0(mc) ((mc).__gregs[23]) +#define MCREG_S1(mc) ((mc).__gregs[24]) +#define MCREG_S2(mc) ((mc).__gregs[25]) +#define MCREG_S3(mc) ((mc).__gregs[26]) +#define MCREG_S4(mc) ((mc).__gregs[27]) +#define MCREG_S5(mc) ((mc).__gregs[28]) +#define MCREG_S6(mc) ((mc).__gregs[29]) +#define MCREG_S7(mc) ((mc).__gregs[30]) +#define MCREG_S8(mc) ((mc).__gregs[31]) +#define MCREG_Pc(mc) ((mc).__pc) + +#else // HOST_LOONGARCH64 #define MCREG_Rbx(mc) ((mc).__gregs[_REG_RBX]) #define MCREG_Rcx(mc) ((mc).__gregs[_REG_RCX]) #define MCREG_Rdx(mc) ((mc).__gregs[_REG_RDX]) @@ -112,6 +149,7 @@ using asm_sigcontext::_xstate; #define FPREG_DataSelector(uc) *((WORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_dp) + 2) #define FPREG_MxCsr(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr) #define FPREG_MxCsr_Mask(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr_mask) +#endif #else // HOST_64BIT @@ -133,6 +171,43 @@ using asm_sigcontext::_xstate; #elif HAVE_GREGSET_T #ifdef HOST_64BIT + +#if defined(HOST_LOONGARCH64) +#define MCREG_R0(mc) ((mc).gregs[0]) +#define MCREG_Ra(mc) ((mc).gregs[1]) +#define MCREG_Tp(mc) ((mc).gregs[2]) +#define MCREG_Sp(mc) ((mc).gregs[3]) +#define MCREG_A0(mc) ((mc).gregs[4]) +#define MCREG_A1(mc) ((mc).gregs[5]) +#define MCREG_A2(mc) ((mc).gregs[6]) +#define MCREG_A3(mc) ((mc).gregs[7]) +#define MCREG_A4(mc) ((mc).gregs[8]) +#define MCREG_A5(mc) ((mc).gregs[9]) +#define MCREG_A6(mc) ((mc).gregs[10]) +#define MCREG_A7(mc) ((mc).gregs[11]) +#define MCREG_T0(mc) ((mc).gregs[12]) +#define MCREG_T1(mc) ((mc).gregs[13]) +#define MCREG_T2(mc) ((mc).gregs[14]) +#define MCREG_T3(mc) ((mc).gregs[15]) +#define MCREG_T4(mc) ((mc).gregs[16]) +#define MCREG_T5(mc) ((mc).gregs[17]) +#define MCREG_T6(mc) ((mc).gregs[18]) +#define MCREG_T7(mc) ((mc).gregs[19]) +#define MCREG_T8(mc) ((mc).gregs[20]) +#define MCREG_X0(mc) ((mc).gregs[21]) +#define MCREG_Fp(mc) ((mc).gregs[22]) +#define MCREG_S0(mc) ((mc).gregs[23]) +#define MCREG_S1(mc) ((mc).gregs[24]) +#define MCREG_S2(mc) ((mc).gregs[25]) +#define MCREG_S3(mc) ((mc).gregs[26]) +#define MCREG_S4(mc) ((mc).gregs[27]) +#define MCREG_S5(mc) ((mc).gregs[28]) +#define MCREG_S6(mc) ((mc).gregs[29]) +#define MCREG_S7(mc) ((mc).gregs[30]) +#define MCREG_S8(mc) ((mc).gregs[31]) +#define MCREG_Pc(mc) ((mc).pc) +#endif // HOST_LOONGARCH64 + #define MCREG_Rbx(mc) ((mc).gregs[REG_RBX]) #define MCREG_Rcx(mc) ((mc).gregs[REG_RCX]) #define MCREG_Rdx(mc) ((mc).gregs[REG_RDX]) @@ -418,6 +493,40 @@ const _STRUCT_ARM_NEON_STATE64* GetConstNativeSigSimdContext(const native_contex #endif // TARGET_OSX +#elif defined(HOST_LOONGARCH64) +#define MCREG_R0(mc) ((mc).regs[0]) +#define MCREG_Ra(mc) ((mc).regs[1]) +#define MCREG_Tp(mc) ((mc).regs[2]) +#define MCREG_Sp(mc) ((mc).regs[3]) +#define MCREG_A0(mc) ((mc).regs[4]) +#define MCREG_A1(mc) ((mc).regs[5]) +#define MCREG_A2(mc) ((mc).regs[6]) +#define MCREG_A3(mc) ((mc).regs[7]) +#define MCREG_A4(mc) ((mc).regs[8]) +#define MCREG_A5(mc) ((mc).regs[9]) +#define MCREG_A6(mc) ((mc).regs[10]) +#define MCREG_A7(mc) ((mc).regs[11]) +#define MCREG_T0(mc) ((mc).regs[12]) +#define MCREG_T1(mc) ((mc).regs[13]) +#define MCREG_T2(mc) ((mc).regs[14]) +#define MCREG_T3(mc) ((mc).regs[15]) +#define MCREG_T4(mc) ((mc).regs[16]) +#define MCREG_T5(mc) ((mc).regs[17]) +#define MCREG_T6(mc) ((mc).regs[18]) +#define MCREG_T7(mc) ((mc).regs[19]) +#define MCREG_T8(mc) ((mc).regs[20]) +#define MCREG_X0(mc) ((mc).regs[21]) +#define MCREG_Fp(mc) ((mc).regs[22]) +#define MCREG_S0(mc) ((mc).regs[23]) +#define MCREG_S1(mc) ((mc).regs[24]) +#define MCREG_S2(mc) ((mc).regs[25]) +#define MCREG_S3(mc) ((mc).regs[26]) +#define MCREG_S4(mc) ((mc).regs[27]) +#define MCREG_S5(mc) ((mc).regs[28]) +#define MCREG_S6(mc) ((mc).regs[29]) +#define MCREG_S7(mc) ((mc).regs[30]) +#define MCREG_S8(mc) ((mc).regs[31]) +#define MCREG_Pc(mc) ((mc).pc) #else // HOST_ARM64 #ifdef TARGET_OSX @@ -610,6 +719,43 @@ const VfpSigFrame* GetConstNativeSigSimdContext(const native_context_t *mc) #if HAVE_PT_REGS #ifdef HOST_64BIT + +#if defined(HOST_LOONGARCH64) +#define PTREG_R0(ptreg) ((ptreg).regs[0]) +#define PTREG_Ra(ptreg) ((ptreg).regs[1]) +#define PTREG_Tp(ptreg) ((ptreg).regs[2]) +#define PTREG_Sp(ptreg) ((ptreg).regs[3]) +#define PTREG_A0(ptreg) ((ptreg).regs[4]) +#define PTREG_A1(ptreg) ((ptreg).regs[5]) +#define PTREG_A2(ptreg) ((ptreg).regs[6]) +#define PTREG_A3(ptreg) ((ptreg).regs[7]) +#define PTREG_A4(ptreg) ((ptreg).regs[8]) +#define PTREG_A5(ptreg) ((ptreg).regs[9]) +#define PTREG_A6(ptreg) ((ptreg).regs[10]) +#define PTREG_A7(ptreg) ((ptreg).regs[11]) +#define PTREG_T0(ptreg) ((ptreg).regs[12]) +#define PTREG_T1(ptreg) ((ptreg).regs[13]) +#define PTREG_T2(ptreg) ((ptreg).regs[14]) +#define PTREG_T3(ptreg) ((ptreg).regs[15]) +#define PTREG_T4(ptreg) ((ptreg).regs[16]) +#define PTREG_T5(ptreg) ((ptreg).regs[17]) +#define PTREG_T6(ptreg) ((ptreg).regs[18]) +#define PTREG_T7(ptreg) ((ptreg).regs[19]) +#define PTREG_T8(ptreg) ((ptreg).regs[20]) +#define PTREG_X0(ptreg) ((ptreg).regs[21]) +#define PTREG_Fp(ptreg) ((ptreg).regs[22]) +#define PTREG_S0(ptreg) ((ptreg).regs[23]) +#define PTREG_S1(ptreg) ((ptreg).regs[24]) +#define PTREG_S2(ptreg) ((ptreg).regs[25]) +#define PTREG_S3(ptreg) ((ptreg).regs[26]) +#define PTREG_S4(ptreg) ((ptreg).regs[27]) +#define PTREG_S5(ptreg) ((ptreg).regs[28]) +#define PTREG_S6(ptreg) ((ptreg).regs[29]) +#define PTREG_S7(ptreg) ((ptreg).regs[30]) +#define PTREG_S8(ptreg) ((ptreg).regs[31]) +#define PTREG_Pc(ptreg) ((ptreg).csr_epc) +#endif // HOST_LOONGARCH64 + #define PTREG_Rbx(ptreg) ((ptreg).rbx) #define PTREG_Rcx(ptreg) ((ptreg).rcx) #define PTREG_Rdx(ptreg) ((ptreg).rdx) @@ -731,6 +877,8 @@ inline static DWORD64 CONTEXTGetPC(LPCONTEXT pContext) return pContext->Eip; #elif defined(HOST_ARM64) || defined(HOST_ARM) return pContext->Pc; +#elif defined(HOST_LOONGARCH64) + return pContext->Pc; #elif defined(HOST_S390X) return pContext->PSWAddr; #else @@ -746,6 +894,8 @@ inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) pContext->Eip = pc; #elif defined(HOST_ARM64) || defined(HOST_ARM) pContext->Pc = pc; +#elif defined(HOST_LOONGARCH64) + pContext->Pc = pc; #elif defined(HOST_S390X) pContext->PSWAddr = pc; #else @@ -763,6 +913,8 @@ inline static DWORD64 CONTEXTGetFP(LPCONTEXT pContext) return pContext->R7; #elif defined(HOST_ARM64) return pContext->Fp; +#elif defined(HOST_LOONGARCH64) + return pContext->Fp; #elif defined(HOST_S390X) return pContext->R11; #else diff --git a/src/coreclr/pal/src/libunwind/Makefile.am b/src/coreclr/pal/src/libunwind/Makefile.am index 9bb2413dc984e1..7bbe9084192e8c 100644 --- a/src/coreclr/pal/src/libunwind/Makefile.am +++ b/src/coreclr/pal/src/libunwind/Makefile.am @@ -20,6 +20,9 @@ endif if ARCH_HPPA include_HEADERS += include/libunwind-hppa.h endif +if ARCH_LOONGARCH +include_HEADERS += include/libunwind-loongarch.h +endif if ARCH_MIPS include_HEADERS += include/libunwind-mips.h endif @@ -79,6 +82,8 @@ noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ include/tdep-ia64/libunwind_i.h include/tdep-ia64/script.h \ include/tdep-hppa/libunwind_i.h \ include/tdep-hppa/jmpbuf.h include/tdep-hppa/dwarf-config.h \ + include/tdep-loongarch/libunwind_i.h \ + include/tdep-loongarch/jmpbuf.h include/tdep-loongarch/dwarf-config.h \ include/tdep-mips/libunwind_i.h \ include/tdep-mips/jmpbuf.h include/tdep-mips/dwarf-config.h \ include/tdep-tilegx/libunwind_i.h \ diff --git a/src/coreclr/pal/src/libunwind/configure.ac b/src/coreclr/pal/src/libunwind/configure.ac index 2893f0cf269072..c3974dc7534a23 100644 --- a/src/coreclr/pal/src/libunwind/configure.ac +++ b/src/coreclr/pal/src/libunwind/configure.ac @@ -97,6 +97,7 @@ AC_DEFUN([SET_ARCH],[ [sh*],[$2=sh], [amd64],[$2=x86_64], [tile*],[$2=tilegx], + [loongarch*],[$2=loongarch], [riscv*],[$2=riscv], [$2=$1]) ]) dnl SET_ARCH @@ -120,7 +121,7 @@ esac AC_ARG_ENABLE(coredump, AS_HELP_STRING([--enable-coredump],[building libunwind-coredump library]),, - [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*|riscv*], [enable_coredump=yes], [enable_coredump=no])] + [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*|loongarch*|riscv*], [enable_coredump=yes], [enable_coredump=no])] ) AC_MSG_CHECKING([if we should build libunwind-coredump]) @@ -187,6 +188,7 @@ AM_CONDITIONAL(ARCH_PPC32, test x$target_arch = xppc32) AM_CONDITIONAL(ARCH_PPC64, test x$target_arch = xppc64) AM_CONDITIONAL(ARCH_SH, test x$target_arch = xsh) AM_CONDITIONAL(ARCH_TILEGX, test x$target_arch = xtilegx) +AM_CONDITIONAL(ARCH_LOONGARCH, test x$target_arch = xloongarch) AM_CONDITIONAL(ARCH_S390X, test x$target_arch = xs390x) AM_CONDITIONAL(ARCH_RISCV, test x$target_arch = xriscv) AM_CONDITIONAL(OS_LINUX, expr x$target_os : xlinux >/dev/null) @@ -199,7 +201,7 @@ AC_MSG_CHECKING([for ELF helper width]) case "${target_arch}" in (arm|hppa|ppc32|x86|sh) use_elf32=yes; AC_MSG_RESULT([32]);; (aarch64|ia64|ppc64|x86_64|s390x|tilegx) use_elf64=yes; AC_MSG_RESULT([64]);; -(mips|riscv) use_elfxx=yes; AC_MSG_RESULT([xx]);; +(mips|loongarch|riscv) use_elfxx=yes; AC_MSG_RESULT([xx]);; *) AC_MSG_ERROR([Unknown ELF target: ${target_arch}]) esac AM_CONDITIONAL(USE_ELF32, [test x$use_elf32 = xyes]) @@ -244,6 +246,7 @@ case $target_arch in aarch64*) enable_cxx_exceptions=no;; arm*) enable_cxx_exceptions=no;; mips*) enable_cxx_exceptions=no;; + loongarch*) enable_cxx_exceptions=no;; tile*) enable_cxx_exceptions=no;; s390x*) enable_cxx_exceptions=no;; *) enable_cxx_exceptions=yes;; diff --git a/src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h b/src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h new file mode 100644 index 00000000000000..64935c68a6dac9 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h @@ -0,0 +1,156 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LIBUNWIND_H +#define LIBUNWIND_H + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +#include +#include + +#ifdef loongarch +# undef loongarch +#endif + +#define UNW_TARGET loongarch +#define UNW_TARGET_LOONGARCH 1 + +#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ + +/* This needs to be big enough to accommodate "struct cursor", while + leaving some slack for future expansion. Changing this value will + require recompiling all users of this library. Stack allocation is + relatively cheap and unwind-state copying is relatively rare, so we + want to err on making it rather too big than too small. */ + +/* FIXME for LOONGARCH. Too big? What do other things use for similar tasks? */ +#define UNW_TDEP_CURSOR_LEN 4096 + +/* The size of a "word" varies on LOONGARCH. This type is used for memory + addresses and register values. To allow a single library to support + multiple ABIs, and to support N32 at all, we must use a 64-bit type + even when addresses are only 32 bits. */ +typedef uint64_t unw_word_t; +typedef int32_t unw_sword_t; + +/* FIXME: LOONGARCH ABIs. */ +typedef long double unw_tdep_fpreg_t; + +typedef enum + { + UNW_LOONGARCH_R0, + UNW_LOONGARCH_R1, + UNW_LOONGARCH_R2, + UNW_LOONGARCH_R3, + UNW_LOONGARCH_R4, + UNW_LOONGARCH_R5, + UNW_LOONGARCH_R6, + UNW_LOONGARCH_R7, + UNW_LOONGARCH_R8, + UNW_LOONGARCH_R9, + UNW_LOONGARCH_R10, + UNW_LOONGARCH_R11, + UNW_LOONGARCH_R12, + UNW_LOONGARCH_R13, + UNW_LOONGARCH_R14, + UNW_LOONGARCH_R15, + UNW_LOONGARCH_R16, + UNW_LOONGARCH_R17, + UNW_LOONGARCH_R18, + UNW_LOONGARCH_R19, + UNW_LOONGARCH_R20, + UNW_LOONGARCH_R21, + UNW_LOONGARCH_R22, + UNW_LOONGARCH_R23, + UNW_LOONGARCH_R24, + UNW_LOONGARCH_R25, + UNW_LOONGARCH_R26, + UNW_LOONGARCH_R27, + UNW_LOONGARCH_R28, + UNW_LOONGARCH_R29, + UNW_LOONGARCH_R30, + UNW_LOONGARCH_R31, + + UNW_LOONGARCH_PC = 34, + + /* FIXME: Other registers! */ + + /* For LOONGARCH, the CFA is the value of SP (r3) at the call site in the + previous frame. */ + UNW_LOONGARCH_CFA, + + UNW_TDEP_LAST_REG = UNW_LOONGARCH_R31, + + UNW_TDEP_IP = UNW_LOONGARCH_R1, + UNW_TDEP_SP = UNW_LOONGARCH_R3, + UNW_TDEP_EH = UNW_LOONGARCH_R0 /* FIXME. */ + } +loongarch_regnum_t; + +typedef enum + { + UNW_LOONGARCH_ABI_LP32, + UNW_LOONGARCH_ABI_LP64 + } +loongarch_abi_t; + +#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for LOONGARCH. */ + +typedef struct unw_tdep_save_loc + { + /* Additional target-dependent info on a save location. */ + } +unw_tdep_save_loc_t; + +/* On x86, we can directly use ucontext_t as the unwind context. FIXME for + LOONGARCH. */ +typedef ucontext_t unw_tdep_context_t; + +#include "libunwind-dynamic.h" + +typedef struct + { + /* no loongarch-specific auxiliary proc-info */ + } +unw_tdep_proc_info_t; + +#include "libunwind-common.h" + +/* There is no getcontext() on LOONGARCH. Use a stub version which only saves GP + registers. FIXME: Not ideal, may not be sufficient for all libunwind + use cases. */ +#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) +extern int unw_tdep_getcontext (ucontext_t *uc); + +#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) +extern int unw_tdep_is_fpreg (int); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif /* LIBUNWIND_H */ diff --git a/src/coreclr/pal/src/libunwind/include/libunwind.h.in b/src/coreclr/pal/src/libunwind/include/libunwind.h.in index dfea76626b622b..170ea670ad7dab 100644 --- a/src/coreclr/pal/src/libunwind/include/libunwind.h.in +++ b/src/coreclr/pal/src/libunwind/include/libunwind.h.in @@ -11,6 +11,8 @@ # include "libunwind-hppa.h" #elif defined __ia64__ # include "libunwind-ia64.h" +#elif defined __loongarch__ +# include "libunwind-loongarch.h" #elif defined __mips__ # include "libunwind-mips.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h new file mode 100644 index 00000000000000..8006d0b8dd4fe2 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h @@ -0,0 +1,54 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef dwarf_config_h +#define dwarf_config_h + +/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not + explicitly defined. */ +#define DWARF_NUM_PRESERVED_REGS 188 + +#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0) + +/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ +#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) + +/* Return the size of an address, for DWARF purposes. */ +#define dwarf_addr_size(addr_space) ((addr_space)->addr_size) + +/* Convert a pointer to a dwarf_cursor structure to a pointer to + unw_cursor_t. */ +#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) + +typedef struct dwarf_loc + { + unw_word_t val; +#ifndef UNW_LOCAL_ONLY + unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ +#endif + } +dwarf_loc_t; + +#endif /* dwarf_config_h */ diff --git a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h new file mode 100644 index 00000000000000..8d098908d105f4 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h @@ -0,0 +1,32 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ + +/* FIXME for LOONGARCH! */ + +#define JB_SP 4 +#define JB_RP 5 +#define JB_MASK_SAVED 6 +#define JB_MASK 7 diff --git a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h new file mode 100644 index 00000000000000..56c251e18c1033 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h @@ -0,0 +1,334 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef LOONGARCH_LIBUNWIND_I_H +#define LOONGARCH_LIBUNWIND_I_H + +/* Target-dependent definitions that are internal to libunwind but need + to be shared with target-independent code. */ + +#include +#include +#include + +#if !defined(UNW_REMOTE_ONLY) && _LOONGARCH_SIM == _ABILP64 +# include "elf64.h" +#else +# include "elf32.h" +#endif +#include "mempool.h" +#include "dwarf.h" + +typedef struct + { + /* no loongarch-specific fast trace */ + } +unw_tdep_frame_t; + +struct unw_addr_space + { + struct unw_accessors acc; + + int big_endian; + loongarch_abi_t abi; + unsigned int addr_size; + + unw_caching_policy_t caching_policy; + _Atomic uint32_t cache_generation; + unw_word_t dyn_generation; /* see dyn-common.h */ + unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ + struct dwarf_rs_cache global_cache; + struct unw_debug_frame_list *debug_frames; +}; + +#define tdep_big_endian(as) ((as)->big_endian) + +struct cursor + { + struct dwarf_cursor dwarf; /* must be first */ + unw_word_t sigcontext_addr; + }; + +#define DWARF_GET_LOC(l) ((l).val) + +#ifndef UNW_REMOTE_ONLY +# if _LOONGARCH_SIM == _ABILP32 +typedef long long loongarch_reg_t; +# else +typedef long loongarch_reg_t; +# endif +#endif + +#ifdef UNW_LOCAL_ONLY +# define DWARF_NULL_LOC DWARF_LOC (0, 0) +# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) +# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) +# define DWARF_IS_REG_LOC(l) 0 +# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ + tdep_uc_addr((c)->as_arg, (r)), 0)) +# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) +# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ + tdep_uc_addr((c)->as_arg, (r)), 0)) + +/* FIXME: Implement these for the LOONGARCH FPU. */ +static inline int +dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) +{ + if (!DWARF_GET_LOC (loc)) + return -1; + *val = *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc); + return 0; +} + +static inline int +dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) +{ + if (!DWARF_GET_LOC (loc)) + return -1; + *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; + return 0; +} + +static inline int +dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) +{ + if (!DWARF_GET_LOC (loc)) + return -1; + *val = *(loongarch_reg_t *) (intptr_t) DWARF_GET_LOC (loc); + return 0; +} + +static inline int +dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) +{ + if (!DWARF_GET_LOC (loc)) + return -1; + *(loongarch_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; + return 0; +} + +#else /* !UNW_LOCAL_ONLY */ +# define DWARF_LOC_TYPE_FP (1 << 0) +# define DWARF_LOC_TYPE_REG (1 << 1) +# define DWARF_NULL_LOC DWARF_LOC (0, 0) + +static inline int +dwarf_is_null_loc(dwarf_loc_t l) +{ + return l.val == 0 && l.type == 0; +} + +# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l) +# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) +# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) +# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) +# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) +# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) +# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ + | DWARF_LOC_TYPE_FP)) + +static inline int +read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val) +{ + int offset = addr & 4; + int ret; + unw_word_t memval; + + ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); + if (ret < 0) + return ret; + + if ((offset != 0) == tdep_big_endian (c->as)) + *val = (int32_t) memval; + else + *val = (int32_t) (memval >> 32); + + return 0; +} + +static inline int +write_s32 (struct dwarf_cursor *c, unw_word_t addr, const unw_word_t *val) +{ + int offset = addr & 4; + int ret; + unw_word_t memval; + + ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); + if (ret < 0) + return ret; + + if ((offset != 0) == tdep_big_endian (c->as)) + memval = (memval & ~0xffffffffLL) | (uint32_t) *val; + else + memval = (memval & 0xffffffffLL) | (uint32_t) (*val << 32); + + return (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 1, c->as_arg); +} + +/* FIXME: Implement these for the LOONGARCH FPU. */ +static inline int +dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) +{ + char *valp = (char *) &val; + unw_word_t addr; + int ret; + + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), + val, 0, c->as_arg); + + addr = DWARF_GET_LOC (loc); + if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, + 0, c->as_arg)) < 0) + return ret; + + return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, + c->as_arg); +} + +static inline int +dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) +{ + char *valp = (char *) &val; + unw_word_t addr; + int ret; + + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), + &val, 1, c->as_arg); + + addr = DWARF_GET_LOC (loc); + if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, + 1, c->as_arg)) < 0) + return ret; + + return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, + 1, c->as_arg); +} + +static inline int +dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) +{ + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + /* If a code-generator were to save a value of type unw_word_t in a + floating-point register, we would have to support this case. I + suppose it could happen with MMX registers, but does it really + happen? */ + assert (!DWARF_IS_FP_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, + 0, c->as_arg); + else if (c->as->abi == UNW_LOONGARCH_ABI_LP32) + return read_s32 (c, DWARF_GET_LOC (loc), val); + else + return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, + 0, c->as_arg); +} + +static inline int +dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) +{ + if (DWARF_IS_NULL_LOC (loc)) + return -UNW_EBADREG; + + /* If a code-generator were to save a value of type unw_word_t in a + floating-point register, we would have to support this case. I + suppose it could happen with MMX registers, but does it really + happen? */ + assert (!DWARF_IS_FP_LOC (loc)); + + if (DWARF_IS_REG_LOC (loc)) + return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, + 1, c->as_arg); + else if (c->as->abi == UNW_LOONGARCH_ABI_LP32) + return write_s32 (c, DWARF_GET_LOC (loc), &val); + else + return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, + 1, c->as_arg); +} + +#endif /* !UNW_LOCAL_ONLY */ + +#define tdep_getcontext_trace unw_getcontext +#define tdep_init_done UNW_OBJ(init_done) +#define tdep_init UNW_OBJ(init) +/* Platforms that support UNW_INFO_FORMAT_TABLE need to define + tdep_search_unwind_table. */ +#define tdep_search_unwind_table dwarf_search_unwind_table +#define tdep_find_unwind_table dwarf_find_unwind_table +#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) +#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) +#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) +#define tdep_access_reg UNW_OBJ(access_reg) +#define tdep_access_fpreg UNW_OBJ(access_fpreg) +#define tdep_fetch_frame(c,ip,n) do {} while(0) +#define tdep_cache_frame(c) 0 +#define tdep_reuse_frame(c,rs) do {} while(0) +#define tdep_stash_frame(c,rs) do {} while(0) +#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) + +#ifdef UNW_LOCAL_ONLY +# define tdep_find_proc_info(c,ip,n) \ + dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ + (c)->as_arg) +# define tdep_put_unwind_info(as,pi,arg) \ + dwarf_put_unwind_info((as), (pi), (arg)) +#else +# define tdep_find_proc_info(c,ip,n) \ + (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ + (c)->as_arg) +# define tdep_put_unwind_info(as,pi,arg) \ + (*(as)->acc.put_unwind_info)((as), (pi), (arg)) +#endif + +#define tdep_get_as(c) ((c)->dwarf.as) +#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) +#define tdep_get_ip(c) ((c)->dwarf.ip) + +extern atomic_bool tdep_init_done; + +extern void tdep_init (void); +extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, + unw_dyn_info_t *di, unw_proc_info_t *pi, + int need_unwind_info, void *arg); +extern void *tdep_uc_addr (ucontext_t *uc, int reg); +extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, + unsigned long *segbase, unsigned long *mapoff, + char *path, size_t pathlen); +extern void tdep_get_exe_image_path (char *path); +extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, + unw_word_t *valp, int write); +extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, + unw_fpreg_t *valp, int write); + +#endif /* LOONGARCH_LIBUNWIND_I_H */ diff --git a/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h b/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h index 0cfd079e66ca64..24075a60d3af74 100644 --- a/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h +++ b/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h @@ -9,6 +9,8 @@ # include "tdep-hppa/dwarf-config.h" #elif defined __ia64__ # include "tdep-ia64/dwarf-config.h" +#elif defined __loongarch__ +# include "tdep-loongarch/dwarf-config.h" #elif defined __mips__ # include "tdep-mips/dwarf-config.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h b/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h index 77d35c3da4de17..4ae751954a27e0 100644 --- a/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h +++ b/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h @@ -11,6 +11,8 @@ # include "tdep-hppa/jmpbuf.h" #elif defined __ia64__ # include "tdep-ia64/jmpbuf.h" +#elif defined __loongarch__ +# include "tdep-loongarch/jmpbuf.h" #elif defined __mips__ # include "tdep-mips/jmpbuf.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in b/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in index a40f7cf6112b27..fe7883e2ad64a0 100644 --- a/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in +++ b/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in @@ -11,6 +11,8 @@ # include "tdep-hppa/libunwind_i.h" #elif defined __ia64__ # include "tdep-ia64/libunwind_i.h" +#elif defined __loongarch__ +# include "tdep-loongarch/libunwind_i.h" #elif defined __mips__ # include "tdep-mips/libunwind_i.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/src/Makefile.am b/src/coreclr/pal/src/libunwind/src/Makefile.am index 2b5b02959e99eb..211869b35dc162 100644 --- a/src/coreclr/pal/src/libunwind/src/Makefile.am +++ b/src/coreclr/pal/src/libunwind/src/Makefile.am @@ -297,6 +297,27 @@ libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \ hppa/Gis_signal_frame.c hppa/Gget_proc_info.c hppa/Gregs.c \ hppa/Gresume.c hppa/Gstep.c +# The list of files that go info libunwind and libunwind-loongarch: +noinst_HEADERS += loongarch/init.h loongarch/offsets.h loongarch/unwind_i.h +libunwind_la_SOURCES_loongarch_common = $(libunwind_la_SOURCES_common) \ + loongarch/is_fpreg.c loongarch/regname.c + +# The list of files that go into libunwind: +libunwind_la_SOURCES_loongarch = $(libunwind_la_SOURCES_loongarch_common) \ + $(libunwind_la_SOURCES_local) \ + loongarch/getcontext.S \ + loongarch/Lapply_reg_state.c loongarch/Lreg_states_iterate.c \ + loongarch/Lcreate_addr_space.c loongarch/Lget_proc_info.c loongarch/Lget_save_loc.c \ + loongarch/Lglobal.c loongarch/Linit.c loongarch/Linit_local.c loongarch/Linit_remote.c \ + loongarch/Lis_signal_frame.c loongarch/Lregs.c loongarch/Lresume.c loongarch/Lstep.c + +libunwind_loongarch_la_SOURCES_loongarch = $(libunwind_la_SOURCES_loongarch_common) \ + $(libunwind_la_SOURCES_generic) \ + loongarch/Gapply_reg_state.c loongarch/Greg_states_iterate.c \ + loongarch/Gcreate_addr_space.c loongarch/Gget_proc_info.c loongarch/Gget_save_loc.c \ + loongarch/Gglobal.c loongarch/Ginit.c loongarch/Ginit_local.c loongarch/Ginit_remote.c \ + loongarch/Gis_signal_frame.c loongarch/Gregs.c loongarch/Gresume.c loongarch/Gstep.c + # The list of files that go info libunwind and libunwind-mips: noinst_HEADERS += mips/init.h mips/offsets.h mips/unwind_i.h libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \ @@ -626,6 +647,18 @@ endif libunwind_setjmp_la_SOURCES += ia64/setjmp.S ia64/sigsetjmp.S \ ia64/longjmp.S ia64/siglongjmp.S else +if ARCH_LOONGARCH + lib_LTLIBRARIES += libunwind-loongarch.la + libunwind_la_SOURCES = $(libunwind_la_SOURCES_loongarch) + libunwind_loongarch_la_SOURCES = $(libunwind_loongarch_la_SOURCES_loongarch) + libunwind_loongarch_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) + libunwind_loongarch_la_LIBADD = libunwind-dwarf-generic.la + libunwind_loongarch_la_LIBADD += libunwind-elfxx.la +if !REMOTE_ONLY + libunwind_loongarch_la_LIBADD += libunwind.la -lc +endif + libunwind_setjmp_la_SOURCES += loongarch/siglongjmp.S +else if ARCH_HPPA lib_LTLIBRARIES += libunwind-hppa.la libunwind_la_SOURCES = $(libunwind_la_SOURCES_hppa) @@ -755,6 +788,7 @@ endif # ARCH_RISCV endif # ARCH_TILEGX endif # ARCH_MIPS endif # ARCH_HPPA +endif # ARCH_LOONGARCH endif # ARCH_IA64 endif # ARCH_ARM endif # ARCH_AARCH64 @@ -783,6 +817,7 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ $(libunwind_la_SOURCES_hppa) \ $(libunwind_la_SOURCES_ia64) \ $(libunwind_la_EXTRAS_ia64) \ + $(libunwind_la_SOURCES_loongarch) \ $(libunwind_la_SOURCES_mips) \ $(libunwind_la_SOURCES_sh) \ $(libunwind_la_SOURCES_x86) \ @@ -798,6 +833,7 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ $(libunwind_arm_la_SOURCES_arm) \ $(libunwind_hppa_la_SOURCES_hppa) \ $(libunwind_ia64_la_SOURCES_ia64) \ + $(libunwind_loongarch_la_SOURCES_loongarch) \ $(libunwind_mips_la_SOURCES_mips) \ $(libunwind_sh_la_SOURCES_sh) \ $(libunwind_x86_la_SOURCES_x86) \ diff --git a/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c b/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c index 27eef123867947..56d547956c0722 100644 --- a/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c +++ b/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c @@ -54,6 +54,10 @@ _UCD_access_reg (unw_addr_space_t as, #elif defined(UNW_TARGET_TILEGX) if (regnum > UNW_TILEGX_CFA) goto badreg; +#elif defined(UNW_TARGET_LOONGARCH) + if (regnum >= 32) + goto badreg; + #elif defined(UNW_TARGET_S390X) if (regnum > UNW_S390X_R15) goto badreg; diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c new file mode 100644 index 00000000000000..20836ae19ddf1d --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c @@ -0,0 +1,66 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include + +#include "unwind_i.h" + +unw_addr_space_t +unw_create_addr_space (unw_accessors_t *a, int byte_order) +{ +#ifdef UNW_LOCAL_ONLY + return NULL; +#else + unw_addr_space_t as; + + /* + * LOONGARCH supports only big or little-endian, not weird stuff like + * PDP_ENDIAN. + */ + if (byte_order != 0 + && byte_order != __LITTLE_ENDIAN + && byte_order != __BIG_ENDIAN) + return NULL; + + as = malloc (sizeof (*as)); + if (!as) + return NULL; + + memset (as, 0, sizeof (*as)); + + as->acc = *a; + + if (byte_order == 0) + /* use host default: */ + as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); + else + as->big_endian = (byte_order == __BIG_ENDIAN); + + /* FIXME! There is no way to specify the ABI. */ + as->abi = UNW_LOONGARCH_ABI_LP32; + as->addr_size = 4; + + return as; +#endif +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c new file mode 100644 index 00000000000000..7b84be87b917db --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c @@ -0,0 +1,41 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +int +unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + /* We can only unwind using Dwarf into on MIPS: return failure code + if it's not present. */ + ret = dwarf_make_proc_info (&c->dwarf); + if (ret < 0) + return ret; + + *pi = c->dwarf.pi; + return 0; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c new file mode 100644 index 00000000000000..684ddc51181af4 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c @@ -0,0 +1,100 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* FIXME for LOONGARCH. */ + +int +unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) +{ + struct cursor *c = (struct cursor *) cursor; + dwarf_loc_t loc; + + loc = DWARF_NULL_LOC; /* default to "not saved" */ + + switch (reg) + { + case UNW_LOONGARCH_R0: + case UNW_LOONGARCH_R1: + case UNW_LOONGARCH_R2: + case UNW_LOONGARCH_R3: + case UNW_LOONGARCH_R4: + case UNW_LOONGARCH_R5: + case UNW_LOONGARCH_R6: + case UNW_LOONGARCH_R7: + case UNW_LOONGARCH_R8: + case UNW_LOONGARCH_R9: + case UNW_LOONGARCH_R10: + case UNW_LOONGARCH_R11: + case UNW_LOONGARCH_R12: + case UNW_LOONGARCH_R13: + case UNW_LOONGARCH_R14: + case UNW_LOONGARCH_R15: + case UNW_LOONGARCH_R16: + case UNW_LOONGARCH_R17: + case UNW_LOONGARCH_R18: + case UNW_LOONGARCH_R19: + case UNW_LOONGARCH_R20: + case UNW_LOONGARCH_R21: + case UNW_LOONGARCH_R22: + case UNW_LOONGARCH_R23: + case UNW_LOONGARCH_R24: + case UNW_LOONGARCH_R25: + case UNW_LOONGARCH_R26: + case UNW_LOONGARCH_R27: + case UNW_LOONGARCH_R28: + case UNW_LOONGARCH_R29: + case UNW_LOONGARCH_R30: + case UNW_LOONGARCH_R31: + case UNW_LOONGARCH_PC: + loc = c->dwarf.loc[reg - UNW_LOONGARCH_R0]; + break; + + default: + break; + } + + memset (sloc, 0, sizeof (*sloc)); + + if (DWARF_IS_NULL_LOC (loc)) + { + sloc->type = UNW_SLT_NONE; + return 0; + } + +#if !defined(UNW_LOCAL_ONLY) + if (DWARF_IS_REG_LOC (loc)) + { + sloc->type = UNW_SLT_REG; + sloc->u.regnum = DWARF_GET_LOC (loc); + } + else +#endif + { + sloc->type = UNW_SLT_MEMORY; + sloc->u.addr = DWARF_GET_LOC (loc); + } + return 0; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c new file mode 100644 index 00000000000000..7508f9358d01e5 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c @@ -0,0 +1,55 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "dwarf_i.h" + +HIDDEN define_lock (loongarch_lock); +HIDDEN atomic_bool tdep_init_done; + +HIDDEN void +tdep_init (void) +{ + intrmask_t saved_mask; + + sigfillset (&unwi_full_mask); + + lock_acquire (&loongarch_lock, saved_mask); + { + if (tdep_init_done) + /* another thread else beat us to it... */ + goto out; + + mi_init (); + + dwarf_init (); + +#ifndef UNW_REMOTE_ONLY + loongarch_local_addr_space_init (); +#endif + tdep_init_done = 1; /* signal that we're initialized... */ + } + out: + lock_release (&loongarch_lock, saved_mask); +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c new file mode 100644 index 00000000000000..01fa9056a823d7 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c @@ -0,0 +1,208 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include +#include + +#include "unwind_i.h" + +#ifdef UNW_REMOTE_ONLY + +/* unw_local_addr_space is a NULL pointer in this case. */ +unw_addr_space_t unw_local_addr_space; + +#else /* !UNW_REMOTE_ONLY */ + +static struct unw_addr_space local_addr_space; + +unw_addr_space_t unw_local_addr_space = &local_addr_space; + +/* Return the address of the 64-bit slot in UC for REG (even for o32, + where registers are 32-bit, the slots are still 64-bit). */ + +static inline void * +uc_addr (ucontext_t *uc, int reg) +{ + if (reg >= UNW_LOONGARCH_R0 && reg < UNW_LOONGARCH_R0 + 32) + return &uc->uc_mcontext.__gregs[reg - UNW_LOONGARCH_R0]; + else if (reg == UNW_LOONGARCH_PC) + return &uc->uc_mcontext.__pc; + else + return NULL; +} + +# ifdef UNW_LOCAL_ONLY + +HIDDEN void * +tdep_uc_addr (ucontext_t *uc, int reg) +{ + char *addr = uc_addr (uc, reg); + + if (reg >= UNW_LOONGARCH_R0 && reg <= UNW_LOONGARCH_R31 + && tdep_big_endian (unw_local_addr_space) + && unw_local_addr_space->abi == UNW_LOONGARCH_ABI_LP32) + addr += 4; + + return addr; +} + +# endif /* UNW_LOCAL_ONLY */ + +HIDDEN unw_dyn_info_list_t _U_dyn_info_list; + +/* XXX fix me: there is currently no way to locate the dyn-info list + by a remote unwinder. On ia64, this is done via a special + unwind-table entry. Perhaps something similar can be done with + DWARF2 unwind info. */ + +static void +put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) +{ + /* it's a no-op */ +} + +static int +get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, + void *arg) +{ + *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list; + return 0; +} + +static int +access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, + void *arg) +{ + if (write) + { + Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); + *(unw_word_t *) (intptr_t) addr = *val; + } + else + { + *val = *(unw_word_t *) (intptr_t) addr; + Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); + } + return 0; +} + +static int +access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, + void *arg) +{ + unw_word_t *addr; + ucontext_t *uc = arg; + + if (unw_is_fpreg (reg)) + goto badreg; + + Debug (16, "reg = %s\n", unw_regname (reg)); + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + *(unw_word_t *) (intptr_t) addr = (loongarch_reg_t) *val; + Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); + } + else + { + *val = (loongarch_reg_t) *(unw_word_t *) (intptr_t) addr; + Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} + +static int +access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, + int write, void *arg) +{ + ucontext_t *uc = arg; + unw_fpreg_t *addr; + + if (!unw_is_fpreg (reg)) + goto badreg; + + if (!(addr = uc_addr (uc, reg))) + goto badreg; + + if (write) + { + Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + *(unw_fpreg_t *) (intptr_t) addr = *val; + } + else + { + *val = *(unw_fpreg_t *) (intptr_t) addr; + Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), + ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); + } + return 0; + + badreg: + Debug (1, "bad register number %u\n", reg); + /* attempt to access a non-preserved register */ + return -UNW_EBADREG; +} + +static int +get_static_proc_name (unw_addr_space_t as, unw_word_t ip, + char *buf, size_t buf_len, unw_word_t *offp, + void *arg) +{ + + return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); +} + +HIDDEN void +loongarch_local_addr_space_init (void) +{ + memset (&local_addr_space, 0, sizeof (local_addr_space)); + local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); +#if _LOONGARCH_SIM == _ABILP32 + local_addr_space.abi = UNW_LOONGARCH_ABI_LP32; +#elif _LOONGARCH_SIM == _ABILP64 + local_addr_space.abi = UNW_LOONGARCH_ABI_LP64; +#else +# error Unsupported ABI +#endif + local_addr_space.addr_size = sizeof (void *); + local_addr_space.caching_policy = UNW_CACHE_GLOBAL; + local_addr_space.acc.find_proc_info = dwarf_find_proc_info; + local_addr_space.acc.put_unwind_info = put_unwind_info; + local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; + local_addr_space.acc.access_mem = access_mem; + local_addr_space.acc.access_reg = access_reg; + local_addr_space.acc.access_fpreg = access_fpreg; + local_addr_space.acc.resume = NULL; /* loongarch_local_resume? FIXME! */ + local_addr_space.acc.get_proc_name = get_static_proc_name; + unw_flush_cache (&local_addr_space, 0, 0); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c new file mode 100644 index 00000000000000..212c35f1955c89 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c @@ -0,0 +1,53 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "init.h" + +#ifdef UNW_REMOTE_ONLY + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + return -UNW_EINVAL; +} + +#else /* !UNW_REMOTE_ONLY */ + +int +unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) +{ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = unw_local_addr_space; + c->dwarf.as_arg = uc; + return common_init (c, 1); +} + +#endif /* !UNW_REMOTE_ONLY */ diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c new file mode 100644 index 00000000000000..9b8ba5b89def1a --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c @@ -0,0 +1,45 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "init.h" +#include "unwind_i.h" + +int +unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) +{ +#ifdef UNW_LOCAL_ONLY + return -UNW_EINVAL; +#else /* !UNW_LOCAL_ONLY */ + struct cursor *c = (struct cursor *) cursor; + + if (!tdep_init_done) + tdep_init (); + + Debug (1, "(cursor=%p)\n", c); + + c->dwarf.as = as; + c->dwarf.as_arg = as_arg; + return common_init (c, 0); +#endif /* !UNW_LOCAL_ONLY */ +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c new file mode 100644 index 00000000000000..e81d3dc93c9c21 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c @@ -0,0 +1,80 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2015 Imagination Technologies Limited + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include + +int +unw_is_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t w0, w1, ip; + unw_addr_space_t as; + unw_accessors_t *a; + void *arg; + int ret; + + ip = c->dwarf.ip; + + as = c->dwarf.as; + a = unw_get_accessors (as); + arg = c->dwarf.as_arg; + + /* syscall */ + /* FIXME for LOONGARCH: should confirm--- why is "ip+4" !!! */ + //if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) + if ((ret = (*a->access_mem) (as, ip - 4, &w1, 0, arg)) < 0) + return 0; + if ((w1 & 0xffffffff) != 0x002b0000) + return 0; + + /* addi.w a7,r0,??? */ + //if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) + if ((ret = (*a->access_mem) (as, ip - 8, &w0, 0, arg)) < 0) + return 0; + + switch (c->dwarf.as->abi) + { + case UNW_LOONGARCH_ABI_LP32: + /* FIXME for LOONGARCH32! not supported!!! */ + //switch (w0 & 0xffffffff) + // { + // case 0x0: + // return 1; + // default: + return 0; + // } + case UNW_LOONGARCH_ABI_LP64: + switch (w0 & 0xffffffff) + {//addi.w a7,139 should confirm further! + case 0x02822c0b: + return 1; + default: + return 0; + } + default: + return 0; + } +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c new file mode 100644 index 00000000000000..55f7cde55a8e1c --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c @@ -0,0 +1,103 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +/* FIXME: The following is probably unfinished and/or at least partly bogus. */ + +HIDDEN int +tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, + int write) +{ + dwarf_loc_t loc = DWARF_NULL_LOC; + + switch (reg) + { + case UNW_LOONGARCH_R0: + case UNW_LOONGARCH_R1: + case UNW_LOONGARCH_R2: + case UNW_LOONGARCH_R4: + case UNW_LOONGARCH_R5: + case UNW_LOONGARCH_R6: + case UNW_LOONGARCH_R7: + case UNW_LOONGARCH_R8: + case UNW_LOONGARCH_R9: + case UNW_LOONGARCH_R10: + case UNW_LOONGARCH_R11: + case UNW_LOONGARCH_R12: + case UNW_LOONGARCH_R13: + case UNW_LOONGARCH_R14: + case UNW_LOONGARCH_R15: + case UNW_LOONGARCH_R16: + case UNW_LOONGARCH_R17: + case UNW_LOONGARCH_R18: + case UNW_LOONGARCH_R19: + case UNW_LOONGARCH_R20: + case UNW_LOONGARCH_R21: + case UNW_LOONGARCH_R22: + case UNW_LOONGARCH_R23: + case UNW_LOONGARCH_R24: + case UNW_LOONGARCH_R25: + case UNW_LOONGARCH_R26: + case UNW_LOONGARCH_R27: + case UNW_LOONGARCH_R28: + case UNW_LOONGARCH_R29: + case UNW_LOONGARCH_R30: + case UNW_LOONGARCH_R31: + loc = c->dwarf.loc[reg - UNW_LOONGARCH_R0]; + break; + + case UNW_LOONGARCH_PC: + loc = c->dwarf.loc[reg]; + break; + + case UNW_LOONGARCH_R3: + case UNW_LOONGARCH_CFA: + if (write) + return -UNW_EREADONLYREG; + *valp = c->dwarf.cfa; + return 0; + + /* FIXME: IP? Copro & shadow registers? */ + + default: + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; + } + + if (write) + return dwarf_put (&c->dwarf, loc, *valp); + else + return dwarf_get (&c->dwarf, loc, valp); +} + +/* FIXME for LOONGARCH. */ + +HIDDEN int +tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, + int write) +{ + Debug (1, "bad register number %u\n", reg); + return -UNW_EBADREG; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c new file mode 100644 index 00000000000000..cdfed3b3fe75b1 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c @@ -0,0 +1,45 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* FIXME for LOONGARCH. */ + +#include + +#include "unwind_i.h" + +#ifndef UNW_REMOTE_ONLY + +HIDDEN inline int +loongarch_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) +{ + return -UNW_EINVAL; +} + +#endif /* !UNW_REMOTE_ONLY */ + +int +unw_resume (unw_cursor_t *cursor) +{ + return -UNW_EINVAL; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c new file mode 100644 index 00000000000000..1fb6f1da14fa4f --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c @@ -0,0 +1,135 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2015 Imagination Technologies Limited + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" +#include "offsets.h" + +#define unw_handle_signal_frame UNW_OBJ(unw_handle_signal_frame) + +int +unw_handle_signal_frame (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; + unw_word_t ra, fp; + int ret; + + switch (unw_is_signal_frame (cursor)) { + case 1: + sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + + LINUX_UC_MCONTEXT_OFF; + break; + case 2: + /* FIXME for LOONGARCH32: should confirm - not support !!! */ + sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; + break; + default: + return -UNW_EUNSPEC; + } + + if (tdep_big_endian(c->dwarf.as)) + sc_addr += 4; + + c->sigcontext_addr = sc_addr; + + /* Update the dwarf cursor. */ + c->dwarf.loc[UNW_LOONGARCH_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); + c->dwarf.loc[UNW_LOONGARCH_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); + + /* Set SP/CFA and PC/IP. */ + dwarf_get (&c->dwarf, c->dwarf.loc[UNW_LOONGARCH_R3], &c->dwarf.cfa); + + if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), + &c->dwarf.ip)) < 0) + return ret; + + if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0), + &ra)) < 0) + return ret; + if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0), + &fp)) < 0) + return ret; + + Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", + (unsigned long long)c->dwarf.ip, (unsigned long long)ra, + (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); + + c->dwarf.pi_valid = 0; + c->dwarf.use_prev_instr = 0; + + return 1; +} + +int +unw_step (unw_cursor_t *cursor) +{ + struct cursor *c = (struct cursor *) cursor; + int ret; + + ret = unw_handle_signal_frame (cursor); + if (ret < 0) + /* Not a signal frame, try DWARF-based unwinding. */ + ret = dwarf_step (&c->dwarf); + + if (unlikely (ret == -UNW_ESTOPUNWIND)) + return ret; + + /* Dwarf unwinding didn't work, stop. */ + if (unlikely (ret < 0)) + return 0; + + return (c->dwarf.ip == 0) ? 0 : 1; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c new file mode 100644 index 00000000000000..0f2dc6be901453 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gcreate_addr_space.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c new file mode 100644 index 00000000000000..69028b019fcd51 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_proc_info.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c new file mode 100644 index 00000000000000..9ea048a9076ba8 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gget_save_loc.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c new file mode 100644 index 00000000000000..6d7b489e14bd9f --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gglobal.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Linit.c b/src/coreclr/pal/src/libunwind/src/loongarch/Linit.c new file mode 100644 index 00000000000000..e9abfdd46a3e0f --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Linit.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c b/src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c new file mode 100644 index 00000000000000..68a1687e85444b --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_local.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c b/src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c new file mode 100644 index 00000000000000..58cb04ab7cd1fd --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Ginit_remote.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c new file mode 100644 index 00000000000000..b9a7c4f51ad9fa --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gis_signal_frame.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c new file mode 100644 index 00000000000000..2c9c75cd7d9a1e --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gregs.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c new file mode 100644 index 00000000000000..41a8cf003de4ac --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gresume.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c new file mode 100644 index 00000000000000..c1ac3c7547f00d --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c @@ -0,0 +1,5 @@ +#define UNW_LOCAL_ONLY +#include +#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) +#include "Gstep.c" +#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S b/src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S new file mode 100644 index 00000000000000..896069a7e3c43e --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S @@ -0,0 +1,94 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + Copyright (C) 2012 Tommi Rantala + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "offsets.h" +#include + + .text + +#if _LOONGARCH_SIM == _ABILP32 +# if __BYTE_ORDER == __BIG_ENDIAN +# define OFFSET 4 +# else +# define OFFSET 0 +# endif +# define SREG(X) \ + sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \ + sra $1, $X, 31; \ + sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4) +/* Yes, we save the return address to PC. */ +# define SPC \ + sw $31, (LINUX_UC_MCONTEXT_PC + OFFSET) ($4); \ + sra $1, $31, 31; \ + sw $1, (LINUX_UC_MCONTEXT_PC + 4 - OFFSET) ($4) +#else +.macro SREG x + st.d $r\x, $r4 , (LINUX_UC_MCONTEXT_GREGS + 8 * \x) +.endm +# define SPC st.d $r1, $r4 , LINUX_UC_MCONTEXT_PC +#endif + + .global _Uloongarch_getcontext + .type _Uloongarch_getcontext, %function + # This is a stub version of getcontext() for LOONGARCH which only stores core + # registers. +_Uloongarch_getcontext: + SREG 1 + SREG 0 + SREG 2 + SREG 3 + SREG 4 + SREG 5 + SREG 6 + SREG 7 + SREG 8 + SREG 9 + SREG 10 + SREG 11 + SREG 12 + SREG 13 + SREG 14 + SREG 15 + SREG 16 + SREG 17 + SREG 18 + SREG 19 + SREG 20 + SREG 21 + SREG 22 + SREG 23 + SREG 24 + SREG 25 + SREG 26 + SREG 27 + SREG 28 + SREG 29 + SREG 30 + SREG 31 + SPC + ori $r4, $r0, 0 + jirl $r0,$r1,0 + + .size _Uloongarch_getcontext, .-_Uloongarch_getcontext diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/init.h b/src/coreclr/pal/src/libunwind/src/loongarch/init.h new file mode 100644 index 00000000000000..bf08dd57239d6d --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/init.h @@ -0,0 +1,59 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static inline int +common_init (struct cursor *c, unsigned use_prev_instr) +{ + int ret, i; + + for (i = 0; i < 32; i++) + c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH_R0 + i); + for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i) + c->dwarf.loc[i] = DWARF_NULL_LOC; + + c->dwarf.loc[UNW_LOONGARCH_PC] = DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH_PC); + + ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_LOONGARCH_PC], &c->dwarf.ip); + if (ret < 0) + return ret; + + ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH_R3), + &c->dwarf.cfa); + if (ret < 0) + return ret; + + /* FIXME: Initialisation for other registers. */ + + c->dwarf.args_size = 0; + c->dwarf.stash_frames = 0; + c->dwarf.use_prev_instr = use_prev_instr; + c->dwarf.pi_valid = 0; + c->dwarf.pi_is_dynamic = 0; + c->dwarf.hint = 0; + c->dwarf.prev_rs = 0; + + return 0; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c b/src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c new file mode 100644 index 00000000000000..ab70d6a6df3e37 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c @@ -0,0 +1,35 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "libunwind_i.h" + +/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful + on LOONGARCH. */ + +int +unw_is_fpreg (int regnum) +{ + /* FIXME: Support FP. */ + return 0; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/offsets.h b/src/coreclr/pal/src/libunwind/src/loongarch/offsets.h new file mode 100644 index 00000000000000..8ca011ffcccfca --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/offsets.h @@ -0,0 +1,76 @@ +/* Linux-specific definitions: */ + +/* Define various structure offsets to simplify cross-compilation. */ + +/* FIXME: Currently these are only used in getcontext.S, which is only used + for a local unwinder, so we can use the compile-time ABI. At a later date + we will want all three here, to use for signal handlers. Also, because + of the three ABIs, gen-offsets.c can not quite generate this file. */ + +/* Offsets for LOONGARCH Linux "ucontext_t": */ + +/* First 24 bytes in sigframe are argument save space and padding for +what used to be signal trampolines. Ref: arch/mips/kernel/signal.c */ +#define LINUX_SF_TRAMP_SIZE 0x18 + +#if _LOONGARCH_SIM == _ABILP32 + +# define LINUX_UC_FLAGS_OFF 0x0 +# define LINUX_UC_LINK_OFF 0x4 +# define LINUX_UC_STACK_OFF 0x8 +# define LINUX_UC_MCONTEXT_OFF 0x18 +# define LINUX_UC_SIGMASK_OFF 0x268 +# define LINUX_UC_MCONTEXT_PC 0x20 +# define LINUX_UC_MCONTEXT_GREGS 0x28 + +#elif _LOONGARCH_SIM == _ABILP64 + +# define LINUX_UC_FLAGS_OFF 0x0 +# define LINUX_UC_LINK_OFF 0x8 +# define LINUX_UC_STACK_OFF 0x10 +# define LINUX_UC_MCONTEXT_OFF 0x28 +# define LINUX_UC_SIGMASK_OFF 0x280 +# define LINUX_UC_MCONTEXT_PC 0x268 +# define LINUX_UC_MCONTEXT_GREGS 0x28 + +#else + +#error Unsupported ABI + +#endif + +#define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF) +#define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8) +#define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8) +#define LINUX_SC_R3_OFF (LINUX_SC_R0_OFF + 3*8) +#define LINUX_SC_R4_OFF (LINUX_SC_R0_OFF + 4*8) +#define LINUX_SC_R5_OFF (LINUX_SC_R0_OFF + 5*8) +#define LINUX_SC_R6_OFF (LINUX_SC_R0_OFF + 6*8) +#define LINUX_SC_R7_OFF (LINUX_SC_R0_OFF + 7*8) +#define LINUX_SC_R8_OFF (LINUX_SC_R0_OFF + 8*8) +#define LINUX_SC_R9_OFF (LINUX_SC_R0_OFF + 9*8) +#define LINUX_SC_R10_OFF (LINUX_SC_R0_OFF + 10*8) +#define LINUX_SC_R11_OFF (LINUX_SC_R0_OFF + 11*8) +#define LINUX_SC_R12_OFF (LINUX_SC_R0_OFF + 12*8) +#define LINUX_SC_R13_OFF (LINUX_SC_R0_OFF + 13*8) +#define LINUX_SC_R14_OFF (LINUX_SC_R0_OFF + 14*8) +#define LINUX_SC_R15_OFF (LINUX_SC_R0_OFF + 15*8) +#define LINUX_SC_R16_OFF (LINUX_SC_R0_OFF + 16*8) +#define LINUX_SC_R17_OFF (LINUX_SC_R0_OFF + 17*8) +#define LINUX_SC_R18_OFF (LINUX_SC_R0_OFF + 18*8) +#define LINUX_SC_R19_OFF (LINUX_SC_R0_OFF + 19*8) +#define LINUX_SC_R20_OFF (LINUX_SC_R0_OFF + 20*8) +#define LINUX_SC_R21_OFF (LINUX_SC_R0_OFF + 21*8) +#define LINUX_SC_R22_OFF (LINUX_SC_R0_OFF + 22*8) +#define LINUX_SC_R23_OFF (LINUX_SC_R0_OFF + 23*8) +#define LINUX_SC_R24_OFF (LINUX_SC_R0_OFF + 24*8) +#define LINUX_SC_R25_OFF (LINUX_SC_R0_OFF + 25*8) +#define LINUX_SC_R26_OFF (LINUX_SC_R0_OFF + 26*8) +#define LINUX_SC_R27_OFF (LINUX_SC_R0_OFF + 27*8) +#define LINUX_SC_R28_OFF (LINUX_SC_R0_OFF + 28*8) +#define LINUX_SC_R29_OFF (LINUX_SC_R0_OFF + 29*8) +#define LINUX_SC_R30_OFF (LINUX_SC_R0_OFF + 30*8) +#define LINUX_SC_R31_OFF (LINUX_SC_R0_OFF + 31*8) + +#define LINUX_SC_SP_OFF LINUX_SC_R29_OFF +#define LINUX_SC_PC_OFF (LINUX_UC_MCONTEXT_PC - LINUX_UC_MCONTEXT_OFF) diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/regname.c b/src/coreclr/pal/src/libunwind/src/loongarch/regname.c new file mode 100644 index 00000000000000..35bc7f136a6045 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/regname.c @@ -0,0 +1,48 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include "unwind_i.h" + +static const char *regname[] = + { + /* 0. */ + "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", + /* 8. */ + "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", + /* 16. */ + "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", + /* 24. */ + "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31", + }; + +const char * +unw_regname (unw_regnum_t reg) +{ + if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) + return regname[reg]; + else if (reg == UNW_LOONGARCH_PC) + return "pc"; + else + return "???"; +} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S b/src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S new file mode 100644 index 00000000000000..12610e294402bd --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S @@ -0,0 +1,8 @@ + /* Dummy implementation for now. */ + + .globl _UI_siglongjmp_cont + .globl _UI_longjmp_cont + +_UI_siglongjmp_cont: +_UI_longjmp_cont: + jirl $r0,$r1,0 diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h b/src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h new file mode 100644 index 00000000000000..1ea2e123496b56 --- /dev/null +++ b/src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h @@ -0,0 +1,43 @@ +/* libunwind - a platform-independent unwind library + Copyright (C) 2008 CodeSourcery + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef unwind_i_h +#define unwind_i_h + +#include + +#include + +#include "libunwind_i.h" + +#define loongarch_lock UNW_OBJ(lock) +#define loongarch_local_resume UNW_OBJ(local_resume) +#define loongarch_local_addr_space_init UNW_OBJ(local_addr_space_init) + +extern int loongarch_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, + void *arg); + +extern void loongarch_local_addr_space_init (void); + +#endif /* unwind_i_h */ diff --git a/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c b/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c index b7dd3b79a8afea..873c053a9f28a2 100644 --- a/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c +++ b/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c @@ -551,6 +551,42 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] = #else #error Fix me #endif +#elif defined(UNW_TARGET_LOONGARCH) +# include + + [UNW_LOONGARCH64_R0] = LOONGARCH64_EF_R0, + [UNW_LOONGARCH64_R1] = LOONGARCH64_EF_R1, + [UNW_LOONGARCH64_R2] = LOONGARCH64_EF_R2, + [UNW_LOONGARCH64_R3] = LOONGARCH64_EF_R3, + [UNW_LOONGARCH64_R4] = LOONGARCH64_EF_R4, + [UNW_LOONGARCH64_R5] = LOONGARCH64_EF_R5, + [UNW_LOONGARCH64_R6] = LOONGARCH64_EF_R6, + [UNW_LOONGARCH64_R7] = LOONGARCH64_EF_R7, + [UNW_LOONGARCH64_R8] = LOONGARCH64_EF_R8, + [UNW_LOONGARCH64_R9] = LOONGARCH64_EF_R9, + [UNW_LOONGARCH64_R10] = LOONGARCH64_EF_R10, + [UNW_LOONGARCH64_R11] = LOONGARCH64_EF_R11, + [UNW_LOONGARCH64_R12] = LOONGARCH64_EF_R12, + [UNW_LOONGARCH64_R13] = LOONGARCH64_EF_R13, + [UNW_LOONGARCH64_R14] = LOONGARCH64_EF_R14, + [UNW_LOONGARCH64_R15] = LOONGARCH64_EF_R15, + [UNW_LOONGARCH64_R16] = LOONGARCH64_EF_R16, + [UNW_LOONGARCH64_R17] = LOONGARCH64_EF_R17, + [UNW_LOONGARCH64_R18] = LOONGARCH64_EF_R18, + [UNW_LOONGARCH64_R19] = LOONGARCH64_EF_R19, + [UNW_LOONGARCH64_R20] = LOONGARCH64_EF_R20, + [UNW_LOONGARCH64_R21] = LOONGARCH64_EF_R21, + [UNW_LOONGARCH64_R22] = LOONGARCH64_EF_R22, + [UNW_LOONGARCH64_R23] = LOONGARCH64_EF_R23, + [UNW_LOONGARCH64_R24] = LOONGARCH64_EF_R24, + [UNW_LOONGARCH64_R25] = LOONGARCH64_EF_R25, + [UNW_LOONGARCH64_R26] = LOONGARCH64_EF_R26, + [UNW_LOONGARCH64_R27] = LOONGARCH64_EF_R27, + [UNW_LOONGARCH64_R28] = LOONGARCH64_EF_R28, + [UNW_LOONGARCH64_R29] = LOONGARCH64_EF_R29, + [UNW_LOONGARCH64_R30] = LOONGARCH64_EF_R30, + [UNW_LOONGARCH64_R31] = LOONGARCH64_EF_R31, + [UNW_LOONGARCH64_PC] = LOONGARCH64_EF_CSR_EPC #elif defined(UNW_TARGET_MIPS) [UNW_MIPS_R0] = 0, [UNW_MIPS_R1] = 1, diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index d80bd58038cbad..f0c980a61efab7 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -46,6 +46,8 @@ namespace ELF_MACHINE = EM_X86_64, #elif defined(HOST_ARM64) ELF_MACHINE = EM_AARCH64, +#elif defined(HOST_LOONGARCH64) + ELF_MACHINE = EM_LOONGARCH, #elif defined(HOST_S390X) ELF_MACHINE = EM_S390, #else diff --git a/src/coreclr/pal/src/misc/sysinfo.cpp b/src/coreclr/pal/src/misc/sysinfo.cpp index 8f935b3e3ea1a8..f08db81244a505 100644 --- a/src/coreclr/pal/src/misc/sysinfo.cpp +++ b/src/coreclr/pal/src/misc/sysinfo.cpp @@ -581,7 +581,7 @@ PAL_GetLogicalProcessorCacheSizeFromOS() } #endif -#if defined(HOST_ARM64) && !defined(TARGET_OSX) +#if (defined(HOST_ARM64) || defined(HOST_LOONGARCH64)) && !defined(TARGET_OSX) if (cacheSize == 0) { // It is currently expected to be missing cache size info diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index 8d630fa170fb43..a227a87d8d50af 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -45,6 +45,8 @@ extern PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode; #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #elif defined(HOST_ARM64) #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT +#elif defined(HOST_LOONGARCH64) +#define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #elif defined(HOST_S390X) #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #else @@ -171,6 +173,45 @@ typedef int __ptrace_request; ASSIGN_REG(X27) \ ASSIGN_REG(X28) +#elif defined(HOST_LOONGARCH64) +#define ASSIGN_CONTROL_REGS \ + ASSIGN_REG(Fp) \ + ASSIGN_REG(Sp) \ + ASSIGN_REG(Ra) \ + ASSIGN_REG(Pc) + + +#define ASSIGN_INTEGER_REGS \ + ASSIGN_REG(R0) \ + ASSIGN_REG(Tp) \ + ASSIGN_REG(A0) \ + ASSIGN_REG(A1) \ + ASSIGN_REG(A2) \ + ASSIGN_REG(A3) \ + ASSIGN_REG(A4) \ + ASSIGN_REG(A5) \ + ASSIGN_REG(A6) \ + ASSIGN_REG(A7) \ + ASSIGN_REG(T0) \ + ASSIGN_REG(T1) \ + ASSIGN_REG(T2) \ + ASSIGN_REG(T3) \ + ASSIGN_REG(T4) \ + ASSIGN_REG(T5) \ + ASSIGN_REG(T6) \ + ASSIGN_REG(T7) \ + ASSIGN_REG(T8) \ + ASSIGN_REG(S0) \ + ASSIGN_REG(S1) \ + ASSIGN_REG(S2) \ + ASSIGN_REG(S3) \ + ASSIGN_REG(S4) \ + ASSIGN_REG(S5) \ + ASSIGN_REG(S6) \ + ASSIGN_REG(S7) \ + ASSIGN_REG(S8) \ + ASSIGN_REG(X0) + #elif defined(HOST_S390X) #define ASSIGN_CONTROL_REGS \ ASSIGN_REG(PSWMask) \ @@ -227,7 +268,11 @@ BOOL CONTEXT_GetRegisters(DWORD processId, LPCONTEXT lpContext) if (processId == GetCurrentProcessId()) { +#ifndef HOST_LOONGARCH64 CONTEXT_CaptureContext(lpContext); +#else + _ASSERT(!"unimplemented on LOONGARCH64 yet"); +#endif } else { @@ -462,7 +507,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) #undef ASSIGN_REG #if !HAVE_FPREGS_WITH_CW -#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) +#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) #if HAVE_GREGSET_T if (native->uc_mcontext.fpregs == nullptr) #elif HAVE___GREGSET_T @@ -474,7 +519,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) // whether CONTEXT_FLOATING_POINT is set in the CONTEXT's flags. return; } -#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X +#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X && !HOST_LOONGARCH64 #endif // !HAVE_FPREGS_WITH_CW if ((lpContext->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) @@ -539,6 +584,11 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) fpregset_t *fp = &native->uc_mcontext.fpregs; static_assert_no_msg(sizeof(fp->fprs) == sizeof(lpContext->Fpr)); memcpy(fp->fprs, lpContext->Fpr, sizeof(lpContext->Fpr)); +#elif defined(HOST_LOONGARCH64) + for (int i = 0; i < 32; i++) + { + native->uc_mcontext.__fpregs[i].__val64[0] = lpContext->F[i]; + } #endif } @@ -592,7 +642,7 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex #undef ASSIGN_REG #if !HAVE_FPREGS_WITH_CW -#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) +#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) #if HAVE_GREGSET_T if (native->uc_mcontext.fpregs == nullptr) #elif HAVE___GREGSET_T @@ -684,6 +734,12 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex const fpregset_t *fp = &native->uc_mcontext.fpregs; static_assert_no_msg(sizeof(fp->fprs) == sizeof(lpContext->Fpr)); memcpy(lpContext->Fpr, fp->fprs, sizeof(lpContext->Fpr)); +#elif defined(HOST_LOONGARCH64) + lpContext->Fcsr = native->uc_mcontext.__fcsr; + for (int i = 0; i < 32; i++) + { + lpContext->F[i] = native->uc_mcontext.__fpregs[i].__val64[0]; + } #endif } @@ -733,6 +789,8 @@ LPVOID GetNativeContextPC(const native_context_t *context) return (LPVOID) MCREG_Pc(context->uc_mcontext); #elif defined(HOST_ARM64) return (LPVOID) MCREG_Pc(context->uc_mcontext); +#elif defined(HOST_LOONGARCH64) + return (LPVOID) MCREG_Pc(context->uc_mcontext); #elif defined(HOST_S390X) return (LPVOID) MCREG_PSWAddr(context->uc_mcontext); #else @@ -763,6 +821,8 @@ LPVOID GetNativeContextSP(const native_context_t *context) return (LPVOID) MCREG_Sp(context->uc_mcontext); #elif defined(HOST_ARM64) return (LPVOID) MCREG_Sp(context->uc_mcontext); +#elif defined(HOST_LOONGARCH64) + return (LPVOID) MCREG_Sp(context->uc_mcontext); #elif defined(HOST_S390X) return (LPVOID) MCREG_R15(context->uc_mcontext); #else diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 76135d655f9349..457f046a126814 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -73,6 +73,8 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d # define __NR_membarrier 389 # elif defined(__aarch64__) # define __NR_membarrier 283 +# elif defined(__loongarch64) +# define __NR_membarrier 283 # elif # error Unknown architecture # endif diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index dbe775e1e0246e..53194e69528e8c 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -271,6 +271,7 @@ FUNCTIONS unsigned getMethodHash(CORINFO_METHOD_HANDLE ftn); size_t findNameOfToken(CORINFO_MODULE_HANDLE moduleHandle,mdToken token, char * szFQName,size_t FQNameCapacity); bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); + uint32_t getFieldTypeByHnd(CORINFO_CLASS_HANDLE cls); uint32_t getThreadTLSIndex(void **ppIndirection); const void * getInlinedCallFrameVptr(void **ppIndirection); int32_t * getAddrOfCaptureThreadGlobal(void **ppIndirection); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index f0158199fea1a3..2220b66faee1db 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -111,7 +111,12 @@ struct JitInterfaceCallbacks void* (* allocateArray)(void * thisHandle, CorInfoExceptionClass** ppException, size_t cBytes); void (* freeArray)(void * thisHandle, CorInfoExceptionClass** ppException, void* array); CORINFO_ARG_LIST_HANDLE (* getArgNext)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_ARG_LIST_HANDLE args); +#if defined(TARGET_LOONGARCH64) + CorInfoTypeWithMod (* getArgType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, CORINFO_CLASS_HANDLE* vcTypeRet, int *flags); +#else CorInfoTypeWithMod (* getArgType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, CORINFO_CLASS_HANDLE* vcTypeRet); +#endif + uint32_t (* getFieldTypeByHnd)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CORINFO_CLASS_HANDLE (* getArgClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args); CorInfoHFAElemType (* getHFAType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE hClass); JITINTERFACE_HRESULT (* GetErrorHRESULT)(void * thisHandle, CorInfoExceptionClass** ppException, struct _EXCEPTION_POINTERS* pExceptionPointers); @@ -1173,10 +1178,26 @@ class JitInterfaceWrapper : public ICorJitInfo virtual CorInfoTypeWithMod getArgType( CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, - CORINFO_CLASS_HANDLE* vcTypeRet) + CORINFO_CLASS_HANDLE* vcTypeRet +#if defined(TARGET_LOONGARCH64) + ,int *flags = NULL +#endif + ) { CorInfoExceptionClass* pException = nullptr; +#if defined(TARGET_LOONGARCH64) + CorInfoTypeWithMod temp = _callbacks->getArgType(_thisHandle, &pException, sig, args, vcTypeRet, flags); +#else CorInfoTypeWithMod temp = _callbacks->getArgType(_thisHandle, &pException, sig, args, vcTypeRet); +#endif + if (pException != nullptr) throw pException; + return temp; +} + + virtual uint32_t getFieldTypeByHnd(CORINFO_CLASS_HANDLE cls) +{ + CorInfoExceptionClass* pException = nullptr; + uint32_t temp = _callbacks->getFieldTypeByHnd(_thisHandle, &pException, cls); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp b/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp new file mode 100644 index 00000000000000..c65e09c725334d --- /dev/null +++ b/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp @@ -0,0 +1,1676 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +// + +#include "stdafx.h" +#include "utilcode.h" +#include "crosscomp.h" + +#include "unwinder_loongarch64.h" + +typedef struct _LOONGARCH64_KTRAP_FRAME { + +// +// Exception active indicator. +// +// 0 - interrupt frame. +// 1 - exception frame. +// 2 - service frame. +// + + /* +0x000 */ UCHAR ExceptionActive; // always valid + /* +0x001 */ UCHAR ContextFromKFramesUnwound; // set if KeContextFromKFrames created this frame + /* +0x002 */ UCHAR DebugRegistersValid; // always valid + /* +0x003 */ union { + UCHAR PreviousMode; // system services only + UCHAR PreviousIrql; // interrupts only + }; + +// +// Page fault information (page faults only) +// Previous trap frame address (system services only) +// +// Organized this way to allow first couple words to be used +// for scratch space in the general case +// + + /* +0x004 */ ULONG FaultStatus; // page faults only + /* +0x008 */ union { + ULONG64 FaultAddress; // page faults only + ULONG64 TrapFrame; // system services only + }; + +// +// The LOONGARCH architecture does not have an architectural trap frame. On +// an exception or interrupt, the processor switches to an +// exception-specific processor mode in which at least the RA and SP +// registers are banked. Software is responsible for preserving +// registers which reflect the processor state in which the +// exception occurred rather than any intermediate processor modes. +// + +// +// Volatile floating point state is dynamically allocated; this +// pointer may be NULL if the FPU was not enabled at the time the +// trap was taken. +// + + /* +0x010 */ PVOID VfpState; + +// +// Volatile registers +// + ULONG64 R[19]; + ULONG64 Tp; + ULONG64 Sp; + ULONG64 Fp; + ULONG64 Ra; + ULONG64 Pc; + +} LOONGARCH64_KTRAP_FRAME, *PLOONGARCH64_KTRAP_FRAME; + +typedef struct _LOONGARCH64_VFP_STATE +{ + struct _LOONGARCH64_VFP_STATE *Link; // link to next state entry + ULONG Fcsr; // FCSR register + ULONG64 F[32]; // All F registers (0-31) +} LOONGARCH64_VFP_STATE, *PLOONGARCH64_VFP_STATE, KLOONGARCH64_VFP_STATE, *PKLOONGARCH64_VFP_STATE; + +// +// Parameters describing the unwind codes. +// + +#define STATUS_UNWIND_UNSUPPORTED_VERSION STATUS_UNSUCCESSFUL +#define STATUS_UNWIND_NOT_IN_FUNCTION STATUS_UNSUCCESSFUL +#define STATUS_UNWIND_INVALID_SEQUENCE STATUS_UNSUCCESSFUL + +// +// Macros for accessing memory. These can be overridden if other code +// (in particular the debugger) needs to use them. + +#define MEMORY_READ_BYTE(params, addr) (*dac_cast(addr)) +#define MEMORY_READ_DWORD(params, addr) (*dac_cast(addr)) +#define MEMORY_READ_QWORD(params, addr) (*dac_cast(addr)) + +typedef struct _LOONGARCH64_UNWIND_PARAMS +{ + PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers; +} LOONGARCH64_UNWIND_PARAMS, *PLOONGARCH64_UNWIND_PARAMS; + + +#define UNWIND_PARAMS_SET_TRAP_FRAME(Params, Address, Size) +#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ +do { \ + if (ARGUMENT_PRESENT(Params)) { \ + PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ + if (ARGUMENT_PRESENT(ContextPointers)) { \ + if (RegisterNumber == 22) \ + ContextPointers->Fp = (PDWORD64)Address; \ + else if (RegisterNumber >= 23 && RegisterNumber <= 31) { \ + (&ContextPointers->S0)[RegisterNumber - 23] = (PDWORD64)Address; \ + } \ + } \ + } \ +} while (0) + + +#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ +do { \ + if (ARGUMENT_PRESENT(Params)) { \ + PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ + if (ARGUMENT_PRESENT(ContextPointers) && \ + (RegisterNumber >= 24) && \ + (RegisterNumber <= 31)) { \ + \ + (&ContextPointers->F24)[RegisterNumber - 24] = (PDWORD64)Address; \ + } \ + } \ +} while (0) + +#define VALIDATE_STACK_ADDRESS_EX(Params, Context, Address, DataSize, Alignment, OutStatus) +#define VALIDATE_STACK_ADDRESS(Params, Context, DataSize, Alignment, OutStatus) + +// +// Macros to clarify opcode parsing +// + +#define OPCODE_IS_END(Op) (((Op) & 0xfe) == 0xe4) + +// +// This table describes the size of each unwind code, in bytes +// + +static const BYTE UnwindCodeSizeTable[256] = +{ + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 3,2,2,2,3,2,2,2, 3,2,2,2,2,2,3,2, 3,2,3,2,3,2,2,2, + 4,1,3,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1 +}; + +NTSTATUS +RtlpUnwindCustom( + __inout PT_CONTEXT ContextRecord, + __in BYTE Opcode, + __in PLOONGARCH64_UNWIND_PARAMS UnwindParams + ) + +/*++ + +Routine Description: + + Handles custom unwinding operations involving machine-specific + frames. + +Arguments: + + ContextRecord - Supplies the address of a context record. + + Opcode - The opcode to decode. + + UnwindParams - Additional parameters shared with caller. + +Return Value: + + An NTSTATUS indicating either STATUS_SUCCESS if everything went ok, or + another status code if there were problems. + +--*/ + +{ + ULONG Fcsr; + ULONG RegIndex; + ULONG_PTR SourceAddress; + ULONG_PTR StartingSp; + NTSTATUS Status; + ULONG_PTR VfpStateAddress; + + StartingSp = ContextRecord->Sp; + Status = STATUS_SUCCESS; + + // + // The opcode describes the special-case stack + // + + switch (Opcode) + { + + // + // Trap frame case + // + + case 0xe8: // MSFT_OP_TRAP_FRAME: + + // + // Ensure there is enough valid space for the trap frame + // + + VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, sizeof(LOONGARCH64_KTRAP_FRAME), 16, &Status); + if (!NT_SUCCESS(Status)) { + return Status; + } + + // + // Restore R0-R15, and F0-F32 + // + SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, R); + for (RegIndex = 0; RegIndex < 16; RegIndex++) { + UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); +#ifdef __GNUC__ + *(&ContextRecord->R0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); +#else + ContextRecord->R[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); +#endif + SourceAddress += sizeof(ULONG_PTR); + } + + SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, VfpState); + VfpStateAddress = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + if (VfpStateAddress != 0) { + + SourceAddress = VfpStateAddress + FIELD_OFFSET(KLOONGARCH64_VFP_STATE, Fcsr); + Fcsr = MEMORY_READ_DWORD(UnwindParams, SourceAddress); + if (Fcsr != (ULONG)-1) { + + ContextRecord->Fcsr = Fcsr; + + SourceAddress = VfpStateAddress + FIELD_OFFSET(KLOONGARCH64_VFP_STATE, F); + for (RegIndex = 0; RegIndex < 32; RegIndex++) { + UPDATE_FP_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); + ContextRecord->F[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + SourceAddress += 2 * sizeof(ULONGLONG); + } + } + } + + // + // Restore SP, RA, PC, and the status registers + // + + //SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Tp);//TP + //ContextRecord->Tp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Sp); + ContextRecord->Sp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Fp); + ContextRecord->Fp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Ra); + ContextRecord->Ra = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Pc); + ContextRecord->Pc = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + // + // Set the trap frame and clear the unwound-to-call flag + // + + UNWIND_PARAMS_SET_TRAP_FRAME(UnwindParams, StartingSp, sizeof(LOONGARCH64_KTRAP_FRAME)); + ContextRecord->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL; + break; + + // + // Context case + // + + case 0xea: // MSFT_OP_CONTEXT: + + // + // Ensure there is enough valid space for the full CONTEXT structure + // + + VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, sizeof(CONTEXT), 16, &Status); + if (!NT_SUCCESS(Status)) { + return Status; + } + + // + // Restore R0-R23, and F0-F31 + // + + SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, R0); + for (RegIndex = 0; RegIndex < 23; RegIndex++) { + UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); +#ifdef __GNUC__ + *(&ContextRecord->R0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); +#else + ContextRecord->R[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); +#endif + SourceAddress += sizeof(ULONG_PTR); + } + + SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, F); + for (RegIndex = 0; RegIndex < 32; RegIndex++) { + UPDATE_FP_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); + ContextRecord->F[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + SourceAddress += 2 * sizeof(ULONGLONG); + } + + // + // Restore SP, RA, PC, and the status registers + // + + SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Fp); + ContextRecord->Fp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Sp); + ContextRecord->Sp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Pc); + ContextRecord->Pc = MEMORY_READ_QWORD(UnwindParams, SourceAddress); + + SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Fcsr); + ContextRecord->Fcsr = MEMORY_READ_DWORD(UnwindParams, SourceAddress); + + // + // Inherit the unwound-to-call flag from this context + // + + SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, ContextFlags); + ContextRecord->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL; + ContextRecord->ContextFlags |= + MEMORY_READ_DWORD(UnwindParams, SourceAddress) & CONTEXT_UNWOUND_TO_CALL; + break; + + default: + return STATUS_UNSUCCESSFUL; + } + + return STATUS_SUCCESS; +} + +ULONG +RtlpComputeScopeSize( + __in ULONG_PTR UnwindCodePtr, + __in ULONG_PTR UnwindCodesEndPtr, + __in BOOLEAN IsEpilog, + __in PLOONGARCH64_UNWIND_PARAMS UnwindParams + ) + +/*++ + +Routine Description: + + Computes the size of an prolog or epilog, in words. + +Arguments: + + UnwindCodePtr - Supplies a pointer to the start of the unwind + code sequence. + + UnwindCodesEndPtr - Supplies a pointer to the byte immediately + following the unwind code table, as described by the header. + + IsEpilog - Specifies TRUE if the scope describes an epilog, + or FALSE if it describes a prolog. + + UnwindParams - Additional parameters shared with caller. + +Return Value: + + The size of the scope described by the unwind codes, in halfword units. + +--*/ + +{ + ULONG ScopeSize; + BYTE Opcode; + + // + // Iterate through the unwind codes until we hit an end marker. + // While iterating, accumulate the total scope size. + // + + ScopeSize = 0; + Opcode = 0; + while (UnwindCodePtr < UnwindCodesEndPtr) { + Opcode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + if (OPCODE_IS_END(Opcode)) { + break; + } + + UnwindCodePtr += UnwindCodeSizeTable[Opcode]; + ScopeSize++; + } + + // + // Epilogs have one extra instruction at the end that needs to be + // accounted for. + // + + if (IsEpilog) { + ScopeSize++; + } + + return ScopeSize; +} + +NTSTATUS +RtlpUnwindRestoreRegisterRange( + __inout PT_CONTEXT ContextRecord, + __in LONG SpOffset, + __in ULONG FirstRegister, + __in ULONG RegisterCount, + __in PLOONGARCH64_UNWIND_PARAMS UnwindParams + ) + +/*++ + +Routine Description: + + Restores a series of integer registers from the stack. + +Arguments: + + ContextRecord - Supplies the address of a context record. + + SpOffset - Specifies a stack offset. Positive values are simply used + as a base offset. Negative values assume a predecrement behavior: + a 0 offset is used for restoration, but the absoute value of the + offset is added to the final Sp. + + FirstRegister - Specifies the index of the first register to restore. + + RegisterCount - Specifies the number of registers to restore. + + UnwindParams - Additional parameters shared with caller. + +Return Value: + + None. + +--*/ + +{ + ULONG_PTR CurAddress; + ULONG RegIndex; + NTSTATUS Status; + + // + // Compute the source address and validate it. + // + + CurAddress = ContextRecord->Sp; + if (SpOffset >= 0) { + CurAddress += SpOffset; + } + + Status = STATUS_SUCCESS; + VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, 8 * RegisterCount, 8, &Status); + if (Status != STATUS_SUCCESS) { + return Status; + } + + // + // Restore the registers + // + for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { + UPDATE_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); +#ifdef __GNUC__ + *(&ContextRecord->R0 + FirstRegister + RegIndex) = MEMORY_READ_QWORD(UnwindParams, CurAddress); +#else + ContextRecord->R[FirstRegister + RegIndex] = MEMORY_READ_QWORD(UnwindParams, CurAddress); +#endif + CurAddress += 8; + } + if (SpOffset < 0) { + ContextRecord->Sp -= SpOffset; + } + + return STATUS_SUCCESS; +} + +NTSTATUS +RtlpUnwindRestoreFpRegisterRange( + __inout PT_CONTEXT ContextRecord, + __in LONG SpOffset, + __in ULONG FirstRegister, + __in ULONG RegisterCount, + __in PLOONGARCH64_UNWIND_PARAMS UnwindParams + ) + +/*++ + +Routine Description: + + Restores a series of floating-point registers from the stack. + +Arguments: + + ContextRecord - Supplies the address of a context record. + + SpOffset - Specifies a stack offset. Positive values are simply used + as a base offset. Negative values assume a predecrement behavior: + a 0 offset is used for restoration, but the absoute value of the + offset is added to the final Sp. + + FirstRegister - Specifies the index of the first register to restore. + + RegisterCount - Specifies the number of registers to restore. + + UnwindParams - Additional parameters shared with caller. + +Return Value: + + None. + +--*/ + +{ + ULONG_PTR CurAddress; + ULONG RegIndex; + NTSTATUS Status; + + // + // Compute the source address and validate it. + // + + CurAddress = ContextRecord->Sp; + if (SpOffset >= 0) { + CurAddress += SpOffset; + } + + Status = STATUS_SUCCESS; + VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, 8 * RegisterCount, 8, &Status); + if (Status != STATUS_SUCCESS) { + return Status; + } + + // + // Restore the registers + // + + for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { + UPDATE_FP_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); + ContextRecord->F[FirstRegister + RegIndex] = MEMORY_READ_QWORD(UnwindParams, CurAddress); + CurAddress += 8; + } + if (SpOffset < 0) { + ContextRecord->Sp -= SpOffset; + } + + return STATUS_SUCCESS; +} + +NTSTATUS +RtlpUnwindFunctionFull( + __in DWORD64 ControlPcRva, + __in ULONG_PTR ImageBase, + __in PT_RUNTIME_FUNCTION FunctionEntry, + __inout T_CONTEXT *ContextRecord, + __out PDWORD64 EstablisherFrame, + __deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine, + __out PVOID *HandlerData, + __in PLOONGARCH64_UNWIND_PARAMS UnwindParams + ) + +/*++ + +Routine Description: + + This function virtually unwinds the specified function by parsing the + .xdata record to determine where in the function the provided ControlPc + is, and then executing unwind codes that map to the function's prolog + or epilog behavior. + + If a context pointers record is specified (in the UnwindParams), then + the address where each nonvolatile register is restored from is recorded + in the appropriate element of the context pointers record. + +Arguments: + + ControlPcRva - Supplies the address where control left the specified + function, as an offset relative to the IamgeBase. + + ImageBase - Supplies the base address of the image that contains the + function being unwound. + + FunctionEntry - Supplies the address of the function table entry for the + specified function. If appropriate, this should have araeady been + probed. + + ContextRecord - Supplies the address of a context record. + + EstablisherFrame - Supplies a pointer to a variable that receives the + the establisher frame pointer value. + + HandlerRoutine - Supplies an optional pointer to a variable that receives + the handler routine address. If control did not leave the specified + function in either the prolog or an epilog and a handler of the + proper type is associated with the function, then the address of the + language specific exception handler is returned. Otherwise, NULL is + returned. + + HandlerData - Supplies a pointer to a variable that receives a pointer + the the language handler data. + + UnwindParams - Additional parameters shared with caller. + +Return Value: + + STATUS_SUCCESS if the unwind could be completed, a failure status otherwise. + Unwind can only fail when validation bounds are specified. + +--*/ + +{ + ULONG AccumulatedSaveNexts; + ULONG CurCode; + ULONG EpilogScopeCount; + PEXCEPTION_ROUTINE ExceptionHandler; + PVOID ExceptionHandlerData; + BOOLEAN FinalPcFromRa; + ULONG FunctionLength; + ULONG HeaderWord; + ULONG NextCode, NextCode1, NextCode2; + DWORD64 OffsetInFunction; + ULONG ScopeNum; + ULONG ScopeSize; + ULONG ScopeStart; + DWORD64 SkipWords; + NTSTATUS Status; + ULONG_PTR UnwindCodePtr; + ULONG_PTR UnwindCodesEndPtr; + ULONG_PTR UnwindDataPtr; + ULONG UnwindIndex; + ULONG UnwindWords; + + // + // Unless a special frame is enountered, assume that any unwinding + // will return us to the return address of a call and set the flag + // appropriately (it will be cleared again if the special cases apply). + // + + ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; + + // + // By default, unwinding is done by popping to the RA, then copying + // that RA to the PC. However, some special opcodes require different + // behavior. + // + + FinalPcFromRa = TRUE; + + // + // Fetch the header word from the .xdata blob + // + + UnwindDataPtr = ImageBase + FunctionEntry->UnwindData; + HeaderWord = MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr); + UnwindDataPtr += 4; + + // + // Verify the version before we do anything else + // + + if (((HeaderWord >> 18) & 3) != 0) { + assert(!"ShouldNotReachHere"); + return STATUS_UNWIND_UNSUPPORTED_VERSION; + } + + FunctionLength = HeaderWord & 0x3ffff; + OffsetInFunction = (ControlPcRva - FunctionEntry->BeginAddress) / 4; + + // + // Determine the number of epilog scope records and the maximum number + // of unwind codes. + // + + UnwindWords = (HeaderWord >> 27) & 31; + EpilogScopeCount = (HeaderWord >> 22) & 31; + if (EpilogScopeCount == 0 && UnwindWords == 0) { + EpilogScopeCount = MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr); + UnwindDataPtr += 4; + UnwindWords = (EpilogScopeCount >> 16) & 0xff; + EpilogScopeCount &= 0xffff; + } + if ((HeaderWord & (1 << 21)) != 0) { + UnwindIndex = EpilogScopeCount; + EpilogScopeCount = 0; + } + + // + // If exception data is present, extract it now. + // + + ExceptionHandler = NULL; + ExceptionHandlerData = NULL; + if ((HeaderWord & (1 << 20)) != 0) { + ExceptionHandler = (PEXCEPTION_ROUTINE)(ImageBase + + MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr + 4 * (EpilogScopeCount + UnwindWords))); + ExceptionHandlerData = (PVOID)(UnwindDataPtr + 4 * (EpilogScopeCount + UnwindWords + 1)); + } + + // + // Unless we are in a prolog/epilog, we execute the unwind codes + // that immediately follow the epilog scope list. + // + + UnwindCodePtr = UnwindDataPtr + 4 * EpilogScopeCount; + UnwindCodesEndPtr = UnwindCodePtr + 4 * UnwindWords; + SkipWords = 0; + + // + // If we're near the start of the function, and this function has a prolog, + // compute the size of the prolog from the unwind codes. If we're in the + // midst of it, we still execute starting at unwind code index 0, but we may + // need to skip some to account for partial execution of the prolog. + // + // N.B. As an optimization here, note that each byte of unwind codes can + // describe at most one 32-bit instruction. Thus, the largest prologue + // that could possibly be described by UnwindWords (which is 4 * the + // number of unwind code bytes) is 4 * UnwindWords words. If + // OffsetInFunction is larger than this value, it is guaranteed to be + // in the body of the function. + // + + if (OffsetInFunction < 4 * UnwindWords) { + ScopeSize = RtlpComputeScopeSize(UnwindCodePtr, UnwindCodesEndPtr, FALSE, UnwindParams); + + if (OffsetInFunction < ScopeSize) { + SkipWords = ScopeSize - OffsetInFunction; + ExceptionHandler = NULL; + ExceptionHandlerData = NULL; + goto ExecuteCodes; + } + } + + // + // We're not in the prolog, now check to see if we are in the epilog. + // In the simple case, the 'E' bit is set indicating there is a single + // epilog that lives at the end of the function. If we're near the end + // of the function, compute the actual size of the epilog from the + // unwind codes. If we're in the midst of it, adjust the unwind code + // pointer to the start of the codes and determine how many we need to skip. + // + // N.B. Similar to the prolog case above, the maximum number of halfwords + // that an epilog can cover is limited by UnwindWords. In the epilog + // case, however, the starting index within the unwind code table is + // non-zero, and so the maximum number of unwind codes that can pertain + // to an epilog is (UnwindWords * 4 - UnwindIndex), thus further + // constraining the bounds of the epilog. + // + + if ((HeaderWord & (1 << 21)) != 0) { + if (OffsetInFunction + (4 * UnwindWords - UnwindIndex) >= FunctionLength) { + ScopeSize = RtlpComputeScopeSize(UnwindCodePtr + UnwindIndex, UnwindCodesEndPtr, TRUE, UnwindParams); + ScopeStart = FunctionLength - ScopeSize; + + if (OffsetInFunction >= ScopeStart) { + UnwindCodePtr += UnwindIndex; + SkipWords = OffsetInFunction - ScopeStart; + ExceptionHandler = NULL; + ExceptionHandlerData = NULL; + } + } + } + + // + // In the multiple-epilog case, we scan forward to see if we are within + // shooting distance of any of the epilogs. If we are, we compute the + // actual size of the epilog from the unwind codes and proceed like the + // simple case above. + // + + else { + for (ScopeNum = 0; ScopeNum < EpilogScopeCount; ScopeNum++) { + HeaderWord = MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr); + UnwindDataPtr += 4; + + // + // The scope records are stored in order. If we hit a record that + // starts after our current position, we must not be in an epilog. + // + + ScopeStart = HeaderWord & 0x3ffff; + if (OffsetInFunction < ScopeStart) { + break; + } + + UnwindIndex = HeaderWord >> 22; + if (OffsetInFunction < ScopeStart + (4 * UnwindWords - UnwindIndex)) { + ScopeSize = RtlpComputeScopeSize(UnwindCodePtr + UnwindIndex, UnwindCodesEndPtr, TRUE, UnwindParams); + + if (OffsetInFunction < ScopeStart + ScopeSize) { + + UnwindCodePtr += UnwindIndex; + SkipWords = OffsetInFunction - ScopeStart; + ExceptionHandler = NULL; + ExceptionHandlerData = NULL; + break; + } + } + } + } + +ExecuteCodes: + + // + // Skip over unwind codes until we account for the number of halfwords + // to skip. + // + + while (UnwindCodePtr < UnwindCodesEndPtr && SkipWords > 0) { + CurCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + if (OPCODE_IS_END(CurCode)) { + break; + } + UnwindCodePtr += UnwindCodeSizeTable[CurCode]; + SkipWords--; + } + + // + // Now execute codes until we hit the end. + // + + Status = STATUS_SUCCESS; + AccumulatedSaveNexts = 0; + while (UnwindCodePtr < UnwindCodesEndPtr && Status == STATUS_SUCCESS) { + + CurCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr += 1; + + // + // alloc_s (000xxxxx): allocate small stack with size < 1024 (2^5 * 16) + // + + if (CurCode <= 0x1f) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + ContextRecord->Sp += 16 * (CurCode & 0x1f); + } + +#if 0 + // Not used for LOONGARCH!!! + // save_s0s1_x (001zzzzz): save pair at [sp-#Z*8]!, pre-indexed offset >= -248 + // + + else if (CurCode <= 0x3f) { + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + -8 * (CurCode & 0x1f), + 16, /* TODO for LOONGARCH64: reg is not 16 */ + 2 + 2 * AccumulatedSaveNexts, + UnwindParams); + AccumulatedSaveNexts = 0; + } + + // + // save_fpra (0100zzzz|zzzzzzzz): save pair at [sp+#Z*8], offset <= 32767 + // + + else if (CurCode <= 0x4f) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + 8 * (((CurCode & 0xf) << 8) + NextCode), + 30, /* TODO for LOONGARCH64: reg is not 30*/ + 2, + UnwindParams); + } + + // + // save_fpra_x (1000zzzz|zzzzzzzz): save pair at [sp-(#Z+1)*8]!, pre-indexed offset >= -32768 + // + + else if (CurCode <= 0x8f) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + -8 * (((CurCode & 0xf) << 8) + NextCode + 1), + 30, /* TODO for LOONGARCH64: reg is not 30*/ + 2, + UnwindParams); + } +#endif + + // + // alloc_m (11000xxx|xxxxxxxx): allocate large stack with size < 32k (2^11 * 16). + // + + else if (CurCode <= 0xc7) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + ContextRecord->Sp += 16 * ((CurCode & 7) << 8); + ContextRecord->Sp += 16 * MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + } +#if 0 + // Not used for LOONGARCH!!! + // save_regp (11001000|0xxxzzzz|zzzzzzzz): save r(16+#X) pair at [sp+#Z*8], offset <= 32767 + // + + else if (CurCode == 0xc8) { + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + 8 * (((NextCode & 0xf) << 8) + NextCode1), + 16 + (NextCode >> 4), + 2 + 2 * AccumulatedSaveNexts, + UnwindParams); + AccumulatedSaveNexts = 0; + } + + // + // save_regp_x (11001100|0xxxzzzz|zzzzzzzz): save pair r(16+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -32768 + // + + else if (CurCode == 0xcc) { + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + -8 * (((NextCode & 0xf) << 8) + NextCode1 + 1), + 16 + (NextCode >> 4), + 2 + 2 * AccumulatedSaveNexts, + UnwindParams); + AccumulatedSaveNexts = 0; + } +#endif + + // + // save_reg (11010000|000xxxxx|zzzzzzzz): save reg r(1+#X) at [sp+#Z*8], offset <= 2047 + // + + else if (CurCode == 0xd0) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = (uint8_t)MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + 8 * NextCode1, + 1 + NextCode, + 1, + UnwindParams); + } + +#if 0 + // Not used for LOONGARCH!!! + // save_reg_x (1101010x|xxxzzzzz): save reg r(16+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -256 + // + + else if (CurCode <= 0xd5) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + -8 * ((NextCode & 0x1f) + 1), + 16 + ((CurCode & 1) << 3) + (NextCode >> 5), + 1, + UnwindParams); + } + + // + // save_rapair (11010110|0xxxzzzz|zzzzzzzz): save pair at [sp+#Z*8], offset <= 32767 + // + + else if (CurCode == 0xd6) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + 8 * (((NextCode & 0xf) << 8) + NextCode1), + 16 + (NextCode >> 4), + 1, + UnwindParams); + if (Status == STATUS_SUCCESS) { + RtlpUnwindRestoreRegisterRange( + ContextRecord, + 8 + 8 * (((NextCode & 0xf) << 8) + NextCode1), + 31, + 1, + UnwindParams); + } + } + + // + // save_fregp (11011000|0xxxzzzz|zzzzzzzz): save pair f(24+#X) at [sp+#Z*8], offset <= 32767 + // + + else if (CurCode == 0xd8) { + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreFpRegisterRange( + ContextRecord, + 8 * (((NextCode & 0xf) << 8) + NextCode1), + 24 + (NextCode >> 4), + 2 + AccumulatedSaveNexts, + UnwindParams); + AccumulatedSaveNexts = 0; + } + + // + // save_fregp_x (11011010|0xxxzzzz|zzzzzzzz): save pair f(24+#X), at [sp-(#Z+1)*8]!, pre-indexed offset >= -32768 + // + + else if (CurCode == 0xda) { + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreFpRegisterRange( + ContextRecord, + -8 * (((NextCode & 0xf) << 8) + NextCode1 + 1), + 24 + (NextCode >> 4), + 2 + AccumulatedSaveNexts, + UnwindParams); + AccumulatedSaveNexts = 0; + } +#endif + + // + // save_freg (11011100|0xxxzzzz|zzzzzzzz): save reg f(24+#X) at [sp+#Z*8], offset <= 32767 + // + + else if (CurCode == 0xdc) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreFpRegisterRange( + ContextRecord, + 8 * (((NextCode & 0xf) << 8) + NextCode1), + 24 + (NextCode >> 4), + 1, + UnwindParams); + } + +#if 0 + // Not used for LOONGARCH!!! + // save_freg_x (11011110|xxxzzzzz): save reg f(24+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -256 + // + + else if (CurCode == 0xde) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + Status = RtlpUnwindRestoreFpRegisterRange( + ContextRecord, + -8 * ((NextCode & 0x1f) + 1), + 24 + (NextCode >> 5), + 1, + UnwindParams); + } +#endif + + // + // alloc_l (11100000|xxxxxxxx|xxxxxxxx|xxxxxxxx): allocate large stack with size < 256M + // + + else if (CurCode == 0xe0) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + ContextRecord->Sp += 16 * (MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr) << 16); + UnwindCodePtr++; + ContextRecord->Sp += 16 * (MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr) << 8); + UnwindCodePtr++; + ContextRecord->Sp += 16 * MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + } + + // + // set_fp (11100001): set up fp: with: ori fp,sp,0 + // + + else if (CurCode == 0xe1) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + ContextRecord->Sp = ContextRecord->Fp; + } + + // + // add_fp (11100010|000xxxxx|xxxxxxxx): set up fp with: addi.d fp,sp,#x*8 + // + + else if (CurCode == 0xe2) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); + UnwindCodePtr++; + ContextRecord->Sp = ContextRecord->Fp - 8 * ((NextCode << 8) | NextCode1); + } + + // + // nop (11100011): no unwind operation is required + // + + else if (CurCode == 0xe3) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + } + + // + // end (11100100): end of unwind code + // + + else if (CurCode == 0xe4) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + goto finished; + } + + // + // end_c (11100101): end of unwind code in current chained scope + // + + else if (CurCode == 0xe5) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + goto finished; + } + +#if 0 + // Not used for LOONGARCH!!! + // save_next (11100110): save next non-volatile Int or FP register pair. + // + + else if (CurCode == 0xe6) { + AccumulatedSaveNexts++; + } +#endif + + // + // custom_0 (111010xx): restore custom structure + // + + else if (CurCode >= 0xe8 && CurCode <= 0xeb) { + if (AccumulatedSaveNexts != 0) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + Status = RtlpUnwindCustom(ContextRecord, (BYTE) CurCode, UnwindParams); + FinalPcFromRa = FALSE; + } + + // + // Anything else is invalid + // + + else { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + } + + // + // If we succeeded, post-process the results a bit + // +finished: + if (Status == STATUS_SUCCESS) { + + // + // Since we always POP to the RA, recover the final PC from there, unless + // it was overwritten due to a special case custom unwinding operation. + // Also set the establisher frame equal to the final stack pointer. + // + + if (FinalPcFromRa) { + ContextRecord->Pc = ContextRecord->Ra; + } + + *EstablisherFrame = ContextRecord->Sp; + + if (ARGUMENT_PRESENT(HandlerRoutine)) { + *HandlerRoutine = ExceptionHandler; + } + *HandlerData = ExceptionHandlerData; + } + + return Status; +} + +NTSTATUS +RtlpUnwindFunctionCompact( + __in DWORD64 ControlPcRva, + __in PT_RUNTIME_FUNCTION FunctionEntry, + __inout T_CONTEXT *ContextRecord, + __out PDWORD64 EstablisherFrame, + __deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine, + __out PVOID *HandlerData, + __in PLOONGARCH64_UNWIND_PARAMS UnwindParams + ) + +/*++ + +Routine Description: + + This function virtually unwinds the specified function by parsing the + compact .pdata record to determine where in the function the provided + ControlPc is, and then executing a standard, well-defined set of + operations. + + If a context pointers record is specified (in the UnwindParams), then + the address where each nonvolatile register is restored from is recorded + in the appropriate element of the context pointers record. + +Arguments: + + ControlPcRva - Supplies the address where control left the specified + function, as an offset relative to the IamgeBase. + + FunctionEntry - Supplies the address of the function table entry for the + specified function. If appropriate, this should have araeady been + probed. + + ContextRecord - Supplies the address of a context record. + + EstablisherFrame - Supplies a pointer to a variable that receives the + the establisher frame pointer value. + + HandlerRoutine - Supplies an optional pointer to a variable that receives + the handler routine address. If control did not leave the specified + function in either the prolog or an epilog and a handler of the + proper type is associated with the function, then the address of the + language specific exception handler is returned. Otherwise, NULL is + returned. + + HandlerData - Supplies a pointer to a variable that receives a pointer + the the language handler data. + + UnwindParams - Additional parameters shared with caller. + +Return Value: + + STATUS_SUCCESS if the unwind could be completed, a failure status otherwise. + Unwind can only fail when validation bounds are specified. + +--*/ + +{ + ULONG Count; + ULONG Cr; + ULONG CurrentOffset; + ULONG EpilogLength; + ULONG Flag; + ULONG FloatSize; + ULONG FrameSize; + ULONG FRegOpcodes; + ULONG FunctionLength; + ULONG HBit; + ULONG HOpcodes; + ULONG IRegOpcodes; + ULONG IntSize; + ULONG LocalSize; + DWORD64 OffsetInFunction; + DWORD64 OffsetInScope; + ULONG PrologLength; + ULONG RegF; + ULONG RegI; + ULONG RegSize; + ULONG ScopeStart; + ULONG StackAdjustOpcodes; + NTSTATUS Status; + ULONG UnwindData; + + UnwindData = FunctionEntry->UnwindData; + Status = STATUS_SUCCESS; + + // + // Compact records always describe an unwind to a call. + // + + ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; + + // + // Extract the basic information about how to do a full unwind. + // + + Flag = UnwindData & 3; + FunctionLength = (UnwindData >> 2) & 0x7ff; + RegF = (UnwindData >> 13) & 7; + RegI = (UnwindData >> 16) & 0xf; + HBit = (UnwindData >> 20) & 1; + Cr = (UnwindData >> 21) & 3; + FrameSize = (UnwindData >> 23) & 0x1ff; + + assert(!"---------------LOONGARCH64 ShouldNotReachHere"); + if (Flag == 3) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + if (Cr == 2) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + + // + // Determine the size of the locals + // + + IntSize = RegI * 8; + if (Cr == 1) { + IntSize += 8; + } + FloatSize = (RegF == 0) ? 0 : (RegF + 1) * 8; + RegSize = (IntSize + FloatSize + 8*8 * HBit + 0xf) & ~0xf; + if (RegSize > 16 * FrameSize) { + return STATUS_UNWIND_INVALID_SEQUENCE; + } + LocalSize = 16 * FrameSize - RegSize; + + // + // If we're near the start of the function (within 17 words), + // see if we are within the prolog. + // + // N.B. If the low 2 bits of the UnwindData are 2, then we have + // no prolog. + // + + OffsetInFunction = (ControlPcRva - FunctionEntry->BeginAddress) / 4; + OffsetInScope = 0; + if (OffsetInFunction < 17 && Flag != 2) { + + // + // Compute sizes for each opcode in the prolog. + // + + IRegOpcodes = (IntSize + 8) / 16; + FRegOpcodes = (FloatSize + 8) / 16; + HOpcodes = 4 * HBit; + StackAdjustOpcodes = (Cr == 3) ? 1 : 0; + if (Cr != 3 || LocalSize > 512) {///TODO for LOONGARCH64: 512 is smaller than real! + StackAdjustOpcodes += (LocalSize > 4088) ? 2 : (LocalSize > 0) ? 1 : 0; + } + + // + // Compute the total prolog length and determine if we are within + // its scope. + // + // N.B. We must execute prolog operations backwards to unwind, so + // our final scope offset in this case is the distance from the end. + // + + PrologLength = IRegOpcodes + FRegOpcodes + HOpcodes + StackAdjustOpcodes; + + if (OffsetInFunction < PrologLength) { + OffsetInScope = PrologLength - OffsetInFunction; + } + } + + // + // If we're near the end of the function (within 15 words), see if + // we are within the epilog. + // + // N.B. If the low 2 bits of the UnwindData are 2, then we have + // no epilog. + // + + if (OffsetInScope == 0 && OffsetInFunction + 15 >= FunctionLength && Flag != 2) { + + // + // Compute sizes for each opcode in the epilog. + // + + IRegOpcodes = (IntSize + 8) / 16; + FRegOpcodes = (FloatSize + 8) / 16; + HOpcodes = HBit; + StackAdjustOpcodes = (Cr == 3) ? 1 : 0; + if (Cr != 3 || LocalSize > 512) {///TODO for LOONGARCH64: 512 is smaller than real! + StackAdjustOpcodes += (LocalSize > 4088) ? 2 : (LocalSize > 0) ? 1 : 0; + } + + // + // Compute the total epilog length and determine if we are within + // its scope. + // + + EpilogLength = IRegOpcodes + FRegOpcodes + HOpcodes + StackAdjustOpcodes + 1; + + ScopeStart = FunctionLength - EpilogLength; + if (OffsetInFunction > ScopeStart) { + OffsetInScope = OffsetInFunction - ScopeStart; + } + } + + // + // Process operations backwards, in the order: stack/frame deallocation, + // VFP register popping, integer register popping, parameter home + // area recovery. + // + // First case is simple: we process everything with no regard for + // the current offset within the scope. + // + + Status = STATUS_SUCCESS; + if (OffsetInScope == 0) { + + if (Cr == 3) { + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, 0, 22, 1, UnwindParams);///fp + assert(Status == STATUS_SUCCESS); + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, 0, 1, 1, UnwindParams);//ra + } + ContextRecord->Sp += LocalSize; + + if (RegF != 0 && Status == STATUS_SUCCESS) { + Status = RtlpUnwindRestoreFpRegisterRange(ContextRecord, IntSize, 24, RegF + 1, UnwindParams);//fs0 + } + + if (Cr == 1 && Status == STATUS_SUCCESS) { + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 8, 1, 1, UnwindParams);//ra + } + if (RegI > 0 && Status == STATUS_SUCCESS) { + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, 0, 23, RegI, UnwindParams);//s0 + } + ContextRecord->Sp += RegSize; + } + + // + // Second case is more complex: we must step along each operation + // to ensure it should be executed. + // + + else { + + CurrentOffset = 0; + if (Cr == 3) { + if (LocalSize <= 512) {///TODO for LOONGARCH64: 512 is smaller! + if (CurrentOffset++ >= OffsetInScope) { + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, -(LONG)LocalSize, 22, 1, UnwindParams); + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, -(LONG)LocalSize, 1, 1, UnwindParams); + } + LocalSize = 0; + } + } + while (LocalSize != 0) { + Count = (LocalSize + 4087) % 4088 + 1;///TODO: should amend the LOONGARCH64 ! + if (CurrentOffset++ >= OffsetInScope) { + ContextRecord->Sp += Count; + } + LocalSize -= Count; + } + + if (HBit != 0) { + CurrentOffset += 4; + } + + if (RegF != 0 && Status == STATUS_SUCCESS) { + RegF++; + while (RegF != 0) { + Count = 2 - (RegF & 1); + RegF -= Count; + if (CurrentOffset++ >= OffsetInScope) { + Status = RtlpUnwindRestoreFpRegisterRange( + ContextRecord, + (RegF == 0 && RegI == 0) ? (-(LONG)RegSize) : (IntSize + 8 * RegF), + 24 + RegF, + Count, + UnwindParams); + } + } + } + + if (Cr == 1 && Status == STATUS_SUCCESS) { + if (RegI % 2 == 0) { + if (CurrentOffset++ >= OffsetInScope) { + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 8, 31, 1, UnwindParams);//s8 ? + } + } else { + if (CurrentOffset++ >= OffsetInScope) { + RegI--; + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 8, 2, 1, UnwindParams);//tp ? + if (Status == STATUS_SUCCESS) { + Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 16, 23 + RegI, 1, UnwindParams); + } + } + } + } + + while (RegI != 0 && Status == STATUS_SUCCESS) { + Count = 2 - (RegI & 1); + RegI -= Count; + if (CurrentOffset++ >= OffsetInScope) { + Status = RtlpUnwindRestoreRegisterRange( + ContextRecord, + (RegI == 0) ? (-(LONG)RegSize) : (8 * RegI), + 23 + RegI, + Count, + UnwindParams); + } + } + } + + // + // If we succeeded, post-process the results a bit + // + + if (Status == STATUS_SUCCESS) { + + ContextRecord->Pc = ContextRecord->Ra; + *EstablisherFrame = ContextRecord->Sp; + + if (ARGUMENT_PRESENT(HandlerRoutine)) { + *HandlerRoutine = NULL; + } + *HandlerData = NULL; + } + + return Status; +} + +BOOL OOPStackUnwinderLoongarch64::Unwind(T_CONTEXT * pContext) +{ + DWORD64 ImageBase = 0; + HRESULT hr = GetModuleBase(pContext->Pc, &ImageBase); + if (hr != S_OK) + return FALSE; + + PEXCEPTION_ROUTINE DummyHandlerRoutine; + PVOID DummyHandlerData; + DWORD64 DummyEstablisherFrame; + + DWORD64 startingPc = pContext->Pc; + DWORD64 startingSp = pContext->Sp; + + T_RUNTIME_FUNCTION Rfe; + if (FAILED(GetFunctionEntry(pContext->Pc, &Rfe, sizeof(Rfe)))) + return FALSE; + + if ((Rfe.UnwindData & 3) != 0) + { + hr = RtlpUnwindFunctionCompact(pContext->Pc - ImageBase, + &Rfe, + pContext, + &DummyEstablisherFrame, + &DummyHandlerRoutine, + &DummyHandlerData, + NULL); + + } + else + { + hr = RtlpUnwindFunctionFull(pContext->Pc - ImageBase, + ImageBase, + &Rfe, + pContext, + &DummyEstablisherFrame, + &DummyHandlerRoutine, + &DummyHandlerData, + NULL); + } + + // PC == 0 means unwinding is finished. + // Same if no forward progress is made + if (pContext->Pc == 0 || (startingPc == pContext->Pc && startingSp == pContext->Sp)) + return FALSE; + + return TRUE; +} + +BOOL DacUnwindStackFrame(T_CONTEXT *pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers) +{ + OOPStackUnwinderLoongarch64 unwinder; + BOOL res = unwinder.Unwind(pContext); + + if (res && pContextPointers) + { + for (int i = 0; i < 9; i++) + { + *(&pContextPointers->S0 + i) = &pContext->S0 + i; + } + pContextPointers->Fp = &pContext->Fp; + pContextPointers->Ra = &pContext->Ra; + } + + return res; +} + +#if defined(HOST_UNIX) +PEXCEPTION_ROUTINE +RtlVirtualUnwind( + IN ULONG HandlerType, + IN ULONG64 ImageBase, + IN ULONG64 ControlPc, + IN PT_RUNTIME_FUNCTION FunctionEntry, + IN OUT PCONTEXT ContextRecord, + OUT PVOID *HandlerData, + OUT PULONG64 EstablisherFrame, + IN OUT PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL + ) +{ + PEXCEPTION_ROUTINE handlerRoutine; + HRESULT hr; + + DWORD64 startingPc = ControlPc; + DWORD64 startingSp = ContextRecord->Sp; + + T_RUNTIME_FUNCTION rfe; + + rfe.BeginAddress = FunctionEntry->BeginAddress; + rfe.UnwindData = FunctionEntry->UnwindData; + + LOONGARCH64_UNWIND_PARAMS unwindParams; + unwindParams.ContextPointers = ContextPointers; + + if ((rfe.UnwindData & 3) != 0) + { + hr = RtlpUnwindFunctionCompact(ControlPc - ImageBase, + &rfe, + ContextRecord, + EstablisherFrame, + &handlerRoutine, + HandlerData, + &unwindParams); + + } + else + { + hr = RtlpUnwindFunctionFull(ControlPc - ImageBase, + ImageBase, + &rfe, + ContextRecord, + EstablisherFrame, + &handlerRoutine, + HandlerData, + &unwindParams); + } + + return handlerRoutine; +} +#endif diff --git a/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h b/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h new file mode 100644 index 00000000000000..2b309a4a6f5fa1 --- /dev/null +++ b/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Copyright (c) Loongson Technology. All rights reserved. + +// + +#ifndef __unwinder_loongarch64__ +#define __unwinder_loongarch64__ + +#include "unwinder.h" + +//--------------------------------------------------------------------------------------- +// +// See the comment for the base class code:OOPStackUnwinder. +// + +class OOPStackUnwinderLoongarch64 : public OOPStackUnwinder +{ +public: + // Unwind the given CONTEXT to the caller CONTEXT. The CONTEXT will be overwritten. + BOOL Unwind(T_CONTEXT * pContext); + + // + // Everything below comes from dbghelp.dll. + // + +protected: + HRESULT UnwindPrologue(__in DWORD64 ImageBase, + __in DWORD64 ControlPc, + __in DWORD64 FrameBase, + __in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, + __inout PT_CONTEXT ContextRecord); + + HRESULT VirtualUnwind(__in DWORD64 ImageBase, + __in DWORD64 ControlPc, + __in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, + __inout PT_CONTEXT ContextRecord, + __out PDWORD64 EstablisherFrame); + + DWORD64 LookupPrimaryUnwindInfo + (__in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, + __in DWORD64 ImageBase, + __out _PIMAGE_RUNTIME_FUNCTION_ENTRY PrimaryEntry); + + _PIMAGE_RUNTIME_FUNCTION_ENTRY SameFunction + (__in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, + __in DWORD64 ImageBase, + __in DWORD64 ControlPc, + __out _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionReturnBuffer); +}; + +#endif // __unwinder_loongarch64__ From 4b1395d2ce625e0e3009076e3df1617883e1f750 Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Sat, 18 Dec 2021 13:50:46 +0800 Subject: [PATCH 02/11] [LoongArch64] delete the libunwind for LoongArch64. It will be commited within a new PR. --- src/coreclr/pal/src/libunwind/Makefile.am | 5 - src/coreclr/pal/src/libunwind/configure.ac | 7 +- .../libunwind/include/libunwind-loongarch.h | 156 -------- .../pal/src/libunwind/include/libunwind.h.in | 2 - .../include/tdep-loongarch/dwarf-config.h | 54 --- .../libunwind/include/tdep-loongarch/jmpbuf.h | 32 -- .../include/tdep-loongarch/libunwind_i.h | 334 ------------------ .../src/libunwind/include/tdep/dwarf-config.h | 2 - .../pal/src/libunwind/include/tdep/jmpbuf.h | 2 - .../libunwind/include/tdep/libunwind_i.h.in | 2 - src/coreclr/pal/src/libunwind/src/Makefile.am | 36 -- .../src/coredump/_UCD_access_reg_linux.c | 4 - .../src/loongarch/Gcreate_addr_space.c | 66 ---- .../libunwind/src/loongarch/Gget_proc_info.c | 41 --- .../libunwind/src/loongarch/Gget_save_loc.c | 100 ------ .../pal/src/libunwind/src/loongarch/Gglobal.c | 55 --- .../pal/src/libunwind/src/loongarch/Ginit.c | 208 ----------- .../src/libunwind/src/loongarch/Ginit_local.c | 53 --- .../libunwind/src/loongarch/Ginit_remote.c | 45 --- .../src/loongarch/Gis_signal_frame.c | 80 ----- .../pal/src/libunwind/src/loongarch/Gregs.c | 103 ------ .../pal/src/libunwind/src/loongarch/Gresume.c | 45 --- .../pal/src/libunwind/src/loongarch/Gstep.c | 135 ------- .../src/loongarch/Lcreate_addr_space.c | 5 - .../libunwind/src/loongarch/Lget_proc_info.c | 5 - .../libunwind/src/loongarch/Lget_save_loc.c | 5 - .../pal/src/libunwind/src/loongarch/Lglobal.c | 5 - .../pal/src/libunwind/src/loongarch/Linit.c | 5 - .../src/libunwind/src/loongarch/Linit_local.c | 5 - .../libunwind/src/loongarch/Linit_remote.c | 5 - .../src/loongarch/Lis_signal_frame.c | 5 - .../pal/src/libunwind/src/loongarch/Lregs.c | 5 - .../pal/src/libunwind/src/loongarch/Lresume.c | 5 - .../pal/src/libunwind/src/loongarch/Lstep.c | 5 - .../src/libunwind/src/loongarch/getcontext.S | 94 ----- .../pal/src/libunwind/src/loongarch/init.h | 59 ---- .../src/libunwind/src/loongarch/is_fpreg.c | 35 -- .../pal/src/libunwind/src/loongarch/offsets.h | 76 ---- .../pal/src/libunwind/src/loongarch/regname.c | 48 --- .../src/libunwind/src/loongarch/siglongjmp.S | 8 - .../src/libunwind/src/loongarch/unwind_i.h | 43 --- .../libunwind/src/ptrace/_UPT_reg_offset.c | 36 -- 42 files changed, 2 insertions(+), 2019 deletions(-) delete mode 100644 src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h delete mode 100644 src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h delete mode 100644 src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h delete mode 100644 src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Linit.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/init.h delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/offsets.h delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/regname.c delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S delete mode 100644 src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h diff --git a/src/coreclr/pal/src/libunwind/Makefile.am b/src/coreclr/pal/src/libunwind/Makefile.am index 7bbe9084192e8c..9bb2413dc984e1 100644 --- a/src/coreclr/pal/src/libunwind/Makefile.am +++ b/src/coreclr/pal/src/libunwind/Makefile.am @@ -20,9 +20,6 @@ endif if ARCH_HPPA include_HEADERS += include/libunwind-hppa.h endif -if ARCH_LOONGARCH -include_HEADERS += include/libunwind-loongarch.h -endif if ARCH_MIPS include_HEADERS += include/libunwind-mips.h endif @@ -82,8 +79,6 @@ noinst_HEADERS = include/dwarf.h include/dwarf_i.h include/dwarf-eh.h \ include/tdep-ia64/libunwind_i.h include/tdep-ia64/script.h \ include/tdep-hppa/libunwind_i.h \ include/tdep-hppa/jmpbuf.h include/tdep-hppa/dwarf-config.h \ - include/tdep-loongarch/libunwind_i.h \ - include/tdep-loongarch/jmpbuf.h include/tdep-loongarch/dwarf-config.h \ include/tdep-mips/libunwind_i.h \ include/tdep-mips/jmpbuf.h include/tdep-mips/dwarf-config.h \ include/tdep-tilegx/libunwind_i.h \ diff --git a/src/coreclr/pal/src/libunwind/configure.ac b/src/coreclr/pal/src/libunwind/configure.ac index c3974dc7534a23..2893f0cf269072 100644 --- a/src/coreclr/pal/src/libunwind/configure.ac +++ b/src/coreclr/pal/src/libunwind/configure.ac @@ -97,7 +97,6 @@ AC_DEFUN([SET_ARCH],[ [sh*],[$2=sh], [amd64],[$2=x86_64], [tile*],[$2=tilegx], - [loongarch*],[$2=loongarch], [riscv*],[$2=riscv], [$2=$1]) ]) dnl SET_ARCH @@ -121,7 +120,7 @@ esac AC_ARG_ENABLE(coredump, AS_HELP_STRING([--enable-coredump],[building libunwind-coredump library]),, - [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*|loongarch*|riscv*], [enable_coredump=yes], [enable_coredump=no])] + [AS_CASE([$host_arch], [aarch64*|arm*|mips*|sh*|x86*|tile*|riscv*], [enable_coredump=yes], [enable_coredump=no])] ) AC_MSG_CHECKING([if we should build libunwind-coredump]) @@ -188,7 +187,6 @@ AM_CONDITIONAL(ARCH_PPC32, test x$target_arch = xppc32) AM_CONDITIONAL(ARCH_PPC64, test x$target_arch = xppc64) AM_CONDITIONAL(ARCH_SH, test x$target_arch = xsh) AM_CONDITIONAL(ARCH_TILEGX, test x$target_arch = xtilegx) -AM_CONDITIONAL(ARCH_LOONGARCH, test x$target_arch = xloongarch) AM_CONDITIONAL(ARCH_S390X, test x$target_arch = xs390x) AM_CONDITIONAL(ARCH_RISCV, test x$target_arch = xriscv) AM_CONDITIONAL(OS_LINUX, expr x$target_os : xlinux >/dev/null) @@ -201,7 +199,7 @@ AC_MSG_CHECKING([for ELF helper width]) case "${target_arch}" in (arm|hppa|ppc32|x86|sh) use_elf32=yes; AC_MSG_RESULT([32]);; (aarch64|ia64|ppc64|x86_64|s390x|tilegx) use_elf64=yes; AC_MSG_RESULT([64]);; -(mips|loongarch|riscv) use_elfxx=yes; AC_MSG_RESULT([xx]);; +(mips|riscv) use_elfxx=yes; AC_MSG_RESULT([xx]);; *) AC_MSG_ERROR([Unknown ELF target: ${target_arch}]) esac AM_CONDITIONAL(USE_ELF32, [test x$use_elf32 = xyes]) @@ -246,7 +244,6 @@ case $target_arch in aarch64*) enable_cxx_exceptions=no;; arm*) enable_cxx_exceptions=no;; mips*) enable_cxx_exceptions=no;; - loongarch*) enable_cxx_exceptions=no;; tile*) enable_cxx_exceptions=no;; s390x*) enable_cxx_exceptions=no;; *) enable_cxx_exceptions=yes;; diff --git a/src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h b/src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h deleted file mode 100644 index 64935c68a6dac9..00000000000000 --- a/src/coreclr/pal/src/libunwind/include/libunwind-loongarch.h +++ /dev/null @@ -1,156 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LIBUNWIND_H -#define LIBUNWIND_H - -#if defined(__cplusplus) || defined(c_plusplus) -extern "C" { -#endif - -#include -#include - -#ifdef loongarch -# undef loongarch -#endif - -#define UNW_TARGET loongarch -#define UNW_TARGET_LOONGARCH 1 - -#define _U_TDEP_QP_TRUE 0 /* see libunwind-dynamic.h */ - -/* This needs to be big enough to accommodate "struct cursor", while - leaving some slack for future expansion. Changing this value will - require recompiling all users of this library. Stack allocation is - relatively cheap and unwind-state copying is relatively rare, so we - want to err on making it rather too big than too small. */ - -/* FIXME for LOONGARCH. Too big? What do other things use for similar tasks? */ -#define UNW_TDEP_CURSOR_LEN 4096 - -/* The size of a "word" varies on LOONGARCH. This type is used for memory - addresses and register values. To allow a single library to support - multiple ABIs, and to support N32 at all, we must use a 64-bit type - even when addresses are only 32 bits. */ -typedef uint64_t unw_word_t; -typedef int32_t unw_sword_t; - -/* FIXME: LOONGARCH ABIs. */ -typedef long double unw_tdep_fpreg_t; - -typedef enum - { - UNW_LOONGARCH_R0, - UNW_LOONGARCH_R1, - UNW_LOONGARCH_R2, - UNW_LOONGARCH_R3, - UNW_LOONGARCH_R4, - UNW_LOONGARCH_R5, - UNW_LOONGARCH_R6, - UNW_LOONGARCH_R7, - UNW_LOONGARCH_R8, - UNW_LOONGARCH_R9, - UNW_LOONGARCH_R10, - UNW_LOONGARCH_R11, - UNW_LOONGARCH_R12, - UNW_LOONGARCH_R13, - UNW_LOONGARCH_R14, - UNW_LOONGARCH_R15, - UNW_LOONGARCH_R16, - UNW_LOONGARCH_R17, - UNW_LOONGARCH_R18, - UNW_LOONGARCH_R19, - UNW_LOONGARCH_R20, - UNW_LOONGARCH_R21, - UNW_LOONGARCH_R22, - UNW_LOONGARCH_R23, - UNW_LOONGARCH_R24, - UNW_LOONGARCH_R25, - UNW_LOONGARCH_R26, - UNW_LOONGARCH_R27, - UNW_LOONGARCH_R28, - UNW_LOONGARCH_R29, - UNW_LOONGARCH_R30, - UNW_LOONGARCH_R31, - - UNW_LOONGARCH_PC = 34, - - /* FIXME: Other registers! */ - - /* For LOONGARCH, the CFA is the value of SP (r3) at the call site in the - previous frame. */ - UNW_LOONGARCH_CFA, - - UNW_TDEP_LAST_REG = UNW_LOONGARCH_R31, - - UNW_TDEP_IP = UNW_LOONGARCH_R1, - UNW_TDEP_SP = UNW_LOONGARCH_R3, - UNW_TDEP_EH = UNW_LOONGARCH_R0 /* FIXME. */ - } -loongarch_regnum_t; - -typedef enum - { - UNW_LOONGARCH_ABI_LP32, - UNW_LOONGARCH_ABI_LP64 - } -loongarch_abi_t; - -#define UNW_TDEP_NUM_EH_REGS 2 /* FIXME for LOONGARCH. */ - -typedef struct unw_tdep_save_loc - { - /* Additional target-dependent info on a save location. */ - } -unw_tdep_save_loc_t; - -/* On x86, we can directly use ucontext_t as the unwind context. FIXME for - LOONGARCH. */ -typedef ucontext_t unw_tdep_context_t; - -#include "libunwind-dynamic.h" - -typedef struct - { - /* no loongarch-specific auxiliary proc-info */ - } -unw_tdep_proc_info_t; - -#include "libunwind-common.h" - -/* There is no getcontext() on LOONGARCH. Use a stub version which only saves GP - registers. FIXME: Not ideal, may not be sufficient for all libunwind - use cases. */ -#define unw_tdep_getcontext UNW_ARCH_OBJ(getcontext) -extern int unw_tdep_getcontext (ucontext_t *uc); - -#define unw_tdep_is_fpreg UNW_ARCH_OBJ(is_fpreg) -extern int unw_tdep_is_fpreg (int); - -#if defined(__cplusplus) || defined(c_plusplus) -} -#endif - -#endif /* LIBUNWIND_H */ diff --git a/src/coreclr/pal/src/libunwind/include/libunwind.h.in b/src/coreclr/pal/src/libunwind/include/libunwind.h.in index 170ea670ad7dab..dfea76626b622b 100644 --- a/src/coreclr/pal/src/libunwind/include/libunwind.h.in +++ b/src/coreclr/pal/src/libunwind/include/libunwind.h.in @@ -11,8 +11,6 @@ # include "libunwind-hppa.h" #elif defined __ia64__ # include "libunwind-ia64.h" -#elif defined __loongarch__ -# include "libunwind-loongarch.h" #elif defined __mips__ # include "libunwind-mips.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h deleted file mode 100644 index 8006d0b8dd4fe2..00000000000000 --- a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/dwarf-config.h +++ /dev/null @@ -1,54 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef dwarf_config_h -#define dwarf_config_h - -/* This is FIRST_PSEUDO_REGISTER in GCC, since DWARF_FRAME_REGISTERS is not - explicitly defined. */ -#define DWARF_NUM_PRESERVED_REGS 188 - -#define dwarf_to_unw_regnum(reg) (((reg) < 32) ? (reg) : 0) - -/* Return TRUE if the ADDR_SPACE uses big-endian byte-order. */ -#define dwarf_is_big_endian(addr_space) ((addr_space)->big_endian) - -/* Return the size of an address, for DWARF purposes. */ -#define dwarf_addr_size(addr_space) ((addr_space)->addr_size) - -/* Convert a pointer to a dwarf_cursor structure to a pointer to - unw_cursor_t. */ -#define dwarf_to_cursor(c) ((unw_cursor_t *) (c)) - -typedef struct dwarf_loc - { - unw_word_t val; -#ifndef UNW_LOCAL_ONLY - unw_word_t type; /* see DWARF_LOC_TYPE_* macros. */ -#endif - } -dwarf_loc_t; - -#endif /* dwarf_config_h */ diff --git a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h deleted file mode 100644 index 8d098908d105f4..00000000000000 --- a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/jmpbuf.h +++ /dev/null @@ -1,32 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* Use glibc's jump-buffer indices; NPTL peeks at SP: */ - -/* FIXME for LOONGARCH! */ - -#define JB_SP 4 -#define JB_RP 5 -#define JB_MASK_SAVED 6 -#define JB_MASK 7 diff --git a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h b/src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h deleted file mode 100644 index 56c251e18c1033..00000000000000 --- a/src/coreclr/pal/src/libunwind/include/tdep-loongarch/libunwind_i.h +++ /dev/null @@ -1,334 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef LOONGARCH_LIBUNWIND_I_H -#define LOONGARCH_LIBUNWIND_I_H - -/* Target-dependent definitions that are internal to libunwind but need - to be shared with target-independent code. */ - -#include -#include -#include - -#if !defined(UNW_REMOTE_ONLY) && _LOONGARCH_SIM == _ABILP64 -# include "elf64.h" -#else -# include "elf32.h" -#endif -#include "mempool.h" -#include "dwarf.h" - -typedef struct - { - /* no loongarch-specific fast trace */ - } -unw_tdep_frame_t; - -struct unw_addr_space - { - struct unw_accessors acc; - - int big_endian; - loongarch_abi_t abi; - unsigned int addr_size; - - unw_caching_policy_t caching_policy; - _Atomic uint32_t cache_generation; - unw_word_t dyn_generation; /* see dyn-common.h */ - unw_word_t dyn_info_list_addr; /* (cached) dyn_info_list_addr */ - struct dwarf_rs_cache global_cache; - struct unw_debug_frame_list *debug_frames; -}; - -#define tdep_big_endian(as) ((as)->big_endian) - -struct cursor - { - struct dwarf_cursor dwarf; /* must be first */ - unw_word_t sigcontext_addr; - }; - -#define DWARF_GET_LOC(l) ((l).val) - -#ifndef UNW_REMOTE_ONLY -# if _LOONGARCH_SIM == _ABILP32 -typedef long long loongarch_reg_t; -# else -typedef long loongarch_reg_t; -# endif -#endif - -#ifdef UNW_LOCAL_ONLY -# define DWARF_NULL_LOC DWARF_LOC (0, 0) -# define DWARF_IS_NULL_LOC(l) (DWARF_GET_LOC (l) == 0) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r) }) -# define DWARF_IS_REG_LOC(l) 0 -# define DWARF_REG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) (DWARF_LOC((unw_word_t) (intptr_t) \ - tdep_uc_addr((c)->as_arg, (r)), 0)) - -/* FIXME: Implement these for the LOONGARCH FPU. */ -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(unw_fpreg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; - return 0; -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *val = *(loongarch_reg_t *) (intptr_t) DWARF_GET_LOC (loc); - return 0; -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (!DWARF_GET_LOC (loc)) - return -1; - *(loongarch_reg_t *) (intptr_t) DWARF_GET_LOC (loc) = val; - return 0; -} - -#else /* !UNW_LOCAL_ONLY */ -# define DWARF_LOC_TYPE_FP (1 << 0) -# define DWARF_LOC_TYPE_REG (1 << 1) -# define DWARF_NULL_LOC DWARF_LOC (0, 0) - -static inline int -dwarf_is_null_loc(dwarf_loc_t l) -{ - return l.val == 0 && l.type == 0; -} - -# define DWARF_IS_NULL_LOC(l) dwarf_is_null_loc(l) -# define DWARF_LOC(r, t) ((dwarf_loc_t) { .val = (r), .type = (t) }) -# define DWARF_IS_REG_LOC(l) (((l).type & DWARF_LOC_TYPE_REG) != 0) -# define DWARF_IS_FP_LOC(l) (((l).type & DWARF_LOC_TYPE_FP) != 0) -# define DWARF_REG_LOC(c,r) DWARF_LOC((r), DWARF_LOC_TYPE_REG) -# define DWARF_MEM_LOC(c,m) DWARF_LOC ((m), 0) -# define DWARF_FPREG_LOC(c,r) DWARF_LOC((r), (DWARF_LOC_TYPE_REG \ - | DWARF_LOC_TYPE_FP)) - -static inline int -read_s32 (struct dwarf_cursor *c, unw_word_t addr, unw_word_t *val) -{ - int offset = addr & 4; - int ret; - unw_word_t memval; - - ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); - if (ret < 0) - return ret; - - if ((offset != 0) == tdep_big_endian (c->as)) - *val = (int32_t) memval; - else - *val = (int32_t) (memval >> 32); - - return 0; -} - -static inline int -write_s32 (struct dwarf_cursor *c, unw_word_t addr, const unw_word_t *val) -{ - int offset = addr & 4; - int ret; - unw_word_t memval; - - ret = (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 0, c->as_arg); - if (ret < 0) - return ret; - - if ((offset != 0) == tdep_big_endian (c->as)) - memval = (memval & ~0xffffffffLL) | (uint32_t) *val; - else - memval = (memval & 0xffffffffLL) | (uint32_t) (*val << 32); - - return (*c->as->acc.access_mem) (c->as, addr - offset, &memval, 1, c->as_arg); -} - -/* FIXME: Implement these for the LOONGARCH FPU. */ -static inline int -dwarf_getfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t *val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - val, 0, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 0, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, 0, - c->as_arg); -} - -static inline int -dwarf_putfp (struct dwarf_cursor *c, dwarf_loc_t loc, unw_fpreg_t val) -{ - char *valp = (char *) &val; - unw_word_t addr; - int ret; - - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_fpreg) (c->as, DWARF_GET_LOC (loc), - &val, 1, c->as_arg); - - addr = DWARF_GET_LOC (loc); - if ((ret = (*c->as->acc.access_mem) (c->as, addr + 0, (unw_word_t *) valp, - 1, c->as_arg)) < 0) - return ret; - - return (*c->as->acc.access_mem) (c->as, addr + 4, (unw_word_t *) valp + 1, - 1, c->as_arg); -} - -static inline int -dwarf_get (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t *val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); - else if (c->as->abi == UNW_LOONGARCH_ABI_LP32) - return read_s32 (c, DWARF_GET_LOC (loc), val); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), val, - 0, c->as_arg); -} - -static inline int -dwarf_put (struct dwarf_cursor *c, dwarf_loc_t loc, unw_word_t val) -{ - if (DWARF_IS_NULL_LOC (loc)) - return -UNW_EBADREG; - - /* If a code-generator were to save a value of type unw_word_t in a - floating-point register, we would have to support this case. I - suppose it could happen with MMX registers, but does it really - happen? */ - assert (!DWARF_IS_FP_LOC (loc)); - - if (DWARF_IS_REG_LOC (loc)) - return (*c->as->acc.access_reg) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); - else if (c->as->abi == UNW_LOONGARCH_ABI_LP32) - return write_s32 (c, DWARF_GET_LOC (loc), &val); - else - return (*c->as->acc.access_mem) (c->as, DWARF_GET_LOC (loc), &val, - 1, c->as_arg); -} - -#endif /* !UNW_LOCAL_ONLY */ - -#define tdep_getcontext_trace unw_getcontext -#define tdep_init_done UNW_OBJ(init_done) -#define tdep_init UNW_OBJ(init) -/* Platforms that support UNW_INFO_FORMAT_TABLE need to define - tdep_search_unwind_table. */ -#define tdep_search_unwind_table dwarf_search_unwind_table -#define tdep_find_unwind_table dwarf_find_unwind_table -#define tdep_uc_addr UNW_ARCH_OBJ(uc_addr) -#define tdep_get_elf_image UNW_ARCH_OBJ(get_elf_image) -#define tdep_get_exe_image_path UNW_ARCH_OBJ(get_exe_image_path) -#define tdep_access_reg UNW_OBJ(access_reg) -#define tdep_access_fpreg UNW_OBJ(access_fpreg) -#define tdep_fetch_frame(c,ip,n) do {} while(0) -#define tdep_cache_frame(c) 0 -#define tdep_reuse_frame(c,rs) do {} while(0) -#define tdep_stash_frame(c,rs) do {} while(0) -#define tdep_trace(cur,addr,n) (-UNW_ENOINFO) - -#ifdef UNW_LOCAL_ONLY -# define tdep_find_proc_info(c,ip,n) \ - dwarf_find_proc_info((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - dwarf_put_unwind_info((as), (pi), (arg)) -#else -# define tdep_find_proc_info(c,ip,n) \ - (*(c)->as->acc.find_proc_info)((c)->as, (ip), &(c)->pi, (n), \ - (c)->as_arg) -# define tdep_put_unwind_info(as,pi,arg) \ - (*(as)->acc.put_unwind_info)((as), (pi), (arg)) -#endif - -#define tdep_get_as(c) ((c)->dwarf.as) -#define tdep_get_as_arg(c) ((c)->dwarf.as_arg) -#define tdep_get_ip(c) ((c)->dwarf.ip) - -extern atomic_bool tdep_init_done; - -extern void tdep_init (void); -extern int tdep_search_unwind_table (unw_addr_space_t as, unw_word_t ip, - unw_dyn_info_t *di, unw_proc_info_t *pi, - int need_unwind_info, void *arg); -extern void *tdep_uc_addr (ucontext_t *uc, int reg); -extern int tdep_get_elf_image (struct elf_image *ei, pid_t pid, unw_word_t ip, - unsigned long *segbase, unsigned long *mapoff, - char *path, size_t pathlen); -extern void tdep_get_exe_image_path (char *path); -extern int tdep_access_reg (struct cursor *c, unw_regnum_t reg, - unw_word_t *valp, int write); -extern int tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, - unw_fpreg_t *valp, int write); - -#endif /* LOONGARCH_LIBUNWIND_I_H */ diff --git a/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h b/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h index 24075a60d3af74..0cfd079e66ca64 100644 --- a/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h +++ b/src/coreclr/pal/src/libunwind/include/tdep/dwarf-config.h @@ -9,8 +9,6 @@ # include "tdep-hppa/dwarf-config.h" #elif defined __ia64__ # include "tdep-ia64/dwarf-config.h" -#elif defined __loongarch__ -# include "tdep-loongarch/dwarf-config.h" #elif defined __mips__ # include "tdep-mips/dwarf-config.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h b/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h index 4ae751954a27e0..77d35c3da4de17 100644 --- a/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h +++ b/src/coreclr/pal/src/libunwind/include/tdep/jmpbuf.h @@ -11,8 +11,6 @@ # include "tdep-hppa/jmpbuf.h" #elif defined __ia64__ # include "tdep-ia64/jmpbuf.h" -#elif defined __loongarch__ -# include "tdep-loongarch/jmpbuf.h" #elif defined __mips__ # include "tdep-mips/jmpbuf.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in b/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in index fe7883e2ad64a0..a40f7cf6112b27 100644 --- a/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in +++ b/src/coreclr/pal/src/libunwind/include/tdep/libunwind_i.h.in @@ -11,8 +11,6 @@ # include "tdep-hppa/libunwind_i.h" #elif defined __ia64__ # include "tdep-ia64/libunwind_i.h" -#elif defined __loongarch__ -# include "tdep-loongarch/libunwind_i.h" #elif defined __mips__ # include "tdep-mips/libunwind_i.h" #elif defined __powerpc__ && !defined __powerpc64__ diff --git a/src/coreclr/pal/src/libunwind/src/Makefile.am b/src/coreclr/pal/src/libunwind/src/Makefile.am index 211869b35dc162..2b5b02959e99eb 100644 --- a/src/coreclr/pal/src/libunwind/src/Makefile.am +++ b/src/coreclr/pal/src/libunwind/src/Makefile.am @@ -297,27 +297,6 @@ libunwind_hppa_la_SOURCES_hppa = $(libunwind_la_SOURCES_hppa_common) \ hppa/Gis_signal_frame.c hppa/Gget_proc_info.c hppa/Gregs.c \ hppa/Gresume.c hppa/Gstep.c -# The list of files that go info libunwind and libunwind-loongarch: -noinst_HEADERS += loongarch/init.h loongarch/offsets.h loongarch/unwind_i.h -libunwind_la_SOURCES_loongarch_common = $(libunwind_la_SOURCES_common) \ - loongarch/is_fpreg.c loongarch/regname.c - -# The list of files that go into libunwind: -libunwind_la_SOURCES_loongarch = $(libunwind_la_SOURCES_loongarch_common) \ - $(libunwind_la_SOURCES_local) \ - loongarch/getcontext.S \ - loongarch/Lapply_reg_state.c loongarch/Lreg_states_iterate.c \ - loongarch/Lcreate_addr_space.c loongarch/Lget_proc_info.c loongarch/Lget_save_loc.c \ - loongarch/Lglobal.c loongarch/Linit.c loongarch/Linit_local.c loongarch/Linit_remote.c \ - loongarch/Lis_signal_frame.c loongarch/Lregs.c loongarch/Lresume.c loongarch/Lstep.c - -libunwind_loongarch_la_SOURCES_loongarch = $(libunwind_la_SOURCES_loongarch_common) \ - $(libunwind_la_SOURCES_generic) \ - loongarch/Gapply_reg_state.c loongarch/Greg_states_iterate.c \ - loongarch/Gcreate_addr_space.c loongarch/Gget_proc_info.c loongarch/Gget_save_loc.c \ - loongarch/Gglobal.c loongarch/Ginit.c loongarch/Ginit_local.c loongarch/Ginit_remote.c \ - loongarch/Gis_signal_frame.c loongarch/Gregs.c loongarch/Gresume.c loongarch/Gstep.c - # The list of files that go info libunwind and libunwind-mips: noinst_HEADERS += mips/init.h mips/offsets.h mips/unwind_i.h libunwind_la_SOURCES_mips_common = $(libunwind_la_SOURCES_common) \ @@ -647,18 +626,6 @@ endif libunwind_setjmp_la_SOURCES += ia64/setjmp.S ia64/sigsetjmp.S \ ia64/longjmp.S ia64/siglongjmp.S else -if ARCH_LOONGARCH - lib_LTLIBRARIES += libunwind-loongarch.la - libunwind_la_SOURCES = $(libunwind_la_SOURCES_loongarch) - libunwind_loongarch_la_SOURCES = $(libunwind_loongarch_la_SOURCES_loongarch) - libunwind_loongarch_la_LDFLAGS = $(COMMON_SO_LDFLAGS) -version-info $(SOVERSION) - libunwind_loongarch_la_LIBADD = libunwind-dwarf-generic.la - libunwind_loongarch_la_LIBADD += libunwind-elfxx.la -if !REMOTE_ONLY - libunwind_loongarch_la_LIBADD += libunwind.la -lc -endif - libunwind_setjmp_la_SOURCES += loongarch/siglongjmp.S -else if ARCH_HPPA lib_LTLIBRARIES += libunwind-hppa.la libunwind_la_SOURCES = $(libunwind_la_SOURCES_hppa) @@ -788,7 +755,6 @@ endif # ARCH_RISCV endif # ARCH_TILEGX endif # ARCH_MIPS endif # ARCH_HPPA -endif # ARCH_LOONGARCH endif # ARCH_IA64 endif # ARCH_ARM endif # ARCH_AARCH64 @@ -817,7 +783,6 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ $(libunwind_la_SOURCES_hppa) \ $(libunwind_la_SOURCES_ia64) \ $(libunwind_la_EXTRAS_ia64) \ - $(libunwind_la_SOURCES_loongarch) \ $(libunwind_la_SOURCES_mips) \ $(libunwind_la_SOURCES_sh) \ $(libunwind_la_SOURCES_x86) \ @@ -833,7 +798,6 @@ EXTRA_DIST = $(libunwind_la_SOURCES_aarch64) \ $(libunwind_arm_la_SOURCES_arm) \ $(libunwind_hppa_la_SOURCES_hppa) \ $(libunwind_ia64_la_SOURCES_ia64) \ - $(libunwind_loongarch_la_SOURCES_loongarch) \ $(libunwind_mips_la_SOURCES_mips) \ $(libunwind_sh_la_SOURCES_sh) \ $(libunwind_x86_la_SOURCES_x86) \ diff --git a/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c b/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c index 56d547956c0722..27eef123867947 100644 --- a/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c +++ b/src/coreclr/pal/src/libunwind/src/coredump/_UCD_access_reg_linux.c @@ -54,10 +54,6 @@ _UCD_access_reg (unw_addr_space_t as, #elif defined(UNW_TARGET_TILEGX) if (regnum > UNW_TILEGX_CFA) goto badreg; -#elif defined(UNW_TARGET_LOONGARCH) - if (regnum >= 32) - goto badreg; - #elif defined(UNW_TARGET_S390X) if (regnum > UNW_S390X_R15) goto badreg; diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c deleted file mode 100644 index 20836ae19ddf1d..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gcreate_addr_space.c +++ /dev/null @@ -1,66 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include - -#include "unwind_i.h" - -unw_addr_space_t -unw_create_addr_space (unw_accessors_t *a, int byte_order) -{ -#ifdef UNW_LOCAL_ONLY - return NULL; -#else - unw_addr_space_t as; - - /* - * LOONGARCH supports only big or little-endian, not weird stuff like - * PDP_ENDIAN. - */ - if (byte_order != 0 - && byte_order != __LITTLE_ENDIAN - && byte_order != __BIG_ENDIAN) - return NULL; - - as = malloc (sizeof (*as)); - if (!as) - return NULL; - - memset (as, 0, sizeof (*as)); - - as->acc = *a; - - if (byte_order == 0) - /* use host default: */ - as->big_endian = (__BYTE_ORDER == __BIG_ENDIAN); - else - as->big_endian = (byte_order == __BIG_ENDIAN); - - /* FIXME! There is no way to specify the ABI. */ - as->abi = UNW_LOONGARCH_ABI_LP32; - as->addr_size = 4; - - return as; -#endif -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c deleted file mode 100644 index 7b84be87b917db..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gget_proc_info.c +++ /dev/null @@ -1,41 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -int -unw_get_proc_info (unw_cursor_t *cursor, unw_proc_info_t *pi) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - /* We can only unwind using Dwarf into on MIPS: return failure code - if it's not present. */ - ret = dwarf_make_proc_info (&c->dwarf); - if (ret < 0) - return ret; - - *pi = c->dwarf.pi; - return 0; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c deleted file mode 100644 index 684ddc51181af4..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gget_save_loc.c +++ /dev/null @@ -1,100 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* FIXME for LOONGARCH. */ - -int -unw_get_save_loc (unw_cursor_t *cursor, int reg, unw_save_loc_t *sloc) -{ - struct cursor *c = (struct cursor *) cursor; - dwarf_loc_t loc; - - loc = DWARF_NULL_LOC; /* default to "not saved" */ - - switch (reg) - { - case UNW_LOONGARCH_R0: - case UNW_LOONGARCH_R1: - case UNW_LOONGARCH_R2: - case UNW_LOONGARCH_R3: - case UNW_LOONGARCH_R4: - case UNW_LOONGARCH_R5: - case UNW_LOONGARCH_R6: - case UNW_LOONGARCH_R7: - case UNW_LOONGARCH_R8: - case UNW_LOONGARCH_R9: - case UNW_LOONGARCH_R10: - case UNW_LOONGARCH_R11: - case UNW_LOONGARCH_R12: - case UNW_LOONGARCH_R13: - case UNW_LOONGARCH_R14: - case UNW_LOONGARCH_R15: - case UNW_LOONGARCH_R16: - case UNW_LOONGARCH_R17: - case UNW_LOONGARCH_R18: - case UNW_LOONGARCH_R19: - case UNW_LOONGARCH_R20: - case UNW_LOONGARCH_R21: - case UNW_LOONGARCH_R22: - case UNW_LOONGARCH_R23: - case UNW_LOONGARCH_R24: - case UNW_LOONGARCH_R25: - case UNW_LOONGARCH_R26: - case UNW_LOONGARCH_R27: - case UNW_LOONGARCH_R28: - case UNW_LOONGARCH_R29: - case UNW_LOONGARCH_R30: - case UNW_LOONGARCH_R31: - case UNW_LOONGARCH_PC: - loc = c->dwarf.loc[reg - UNW_LOONGARCH_R0]; - break; - - default: - break; - } - - memset (sloc, 0, sizeof (*sloc)); - - if (DWARF_IS_NULL_LOC (loc)) - { - sloc->type = UNW_SLT_NONE; - return 0; - } - -#if !defined(UNW_LOCAL_ONLY) - if (DWARF_IS_REG_LOC (loc)) - { - sloc->type = UNW_SLT_REG; - sloc->u.regnum = DWARF_GET_LOC (loc); - } - else -#endif - { - sloc->type = UNW_SLT_MEMORY; - sloc->u.addr = DWARF_GET_LOC (loc); - } - return 0; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c deleted file mode 100644 index 7508f9358d01e5..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gglobal.c +++ /dev/null @@ -1,55 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "dwarf_i.h" - -HIDDEN define_lock (loongarch_lock); -HIDDEN atomic_bool tdep_init_done; - -HIDDEN void -tdep_init (void) -{ - intrmask_t saved_mask; - - sigfillset (&unwi_full_mask); - - lock_acquire (&loongarch_lock, saved_mask); - { - if (tdep_init_done) - /* another thread else beat us to it... */ - goto out; - - mi_init (); - - dwarf_init (); - -#ifndef UNW_REMOTE_ONLY - loongarch_local_addr_space_init (); -#endif - tdep_init_done = 1; /* signal that we're initialized... */ - } - out: - lock_release (&loongarch_lock, saved_mask); -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c deleted file mode 100644 index 01fa9056a823d7..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit.c +++ /dev/null @@ -1,208 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include -#include - -#include "unwind_i.h" - -#ifdef UNW_REMOTE_ONLY - -/* unw_local_addr_space is a NULL pointer in this case. */ -unw_addr_space_t unw_local_addr_space; - -#else /* !UNW_REMOTE_ONLY */ - -static struct unw_addr_space local_addr_space; - -unw_addr_space_t unw_local_addr_space = &local_addr_space; - -/* Return the address of the 64-bit slot in UC for REG (even for o32, - where registers are 32-bit, the slots are still 64-bit). */ - -static inline void * -uc_addr (ucontext_t *uc, int reg) -{ - if (reg >= UNW_LOONGARCH_R0 && reg < UNW_LOONGARCH_R0 + 32) - return &uc->uc_mcontext.__gregs[reg - UNW_LOONGARCH_R0]; - else if (reg == UNW_LOONGARCH_PC) - return &uc->uc_mcontext.__pc; - else - return NULL; -} - -# ifdef UNW_LOCAL_ONLY - -HIDDEN void * -tdep_uc_addr (ucontext_t *uc, int reg) -{ - char *addr = uc_addr (uc, reg); - - if (reg >= UNW_LOONGARCH_R0 && reg <= UNW_LOONGARCH_R31 - && tdep_big_endian (unw_local_addr_space) - && unw_local_addr_space->abi == UNW_LOONGARCH_ABI_LP32) - addr += 4; - - return addr; -} - -# endif /* UNW_LOCAL_ONLY */ - -HIDDEN unw_dyn_info_list_t _U_dyn_info_list; - -/* XXX fix me: there is currently no way to locate the dyn-info list - by a remote unwinder. On ia64, this is done via a special - unwind-table entry. Perhaps something similar can be done with - DWARF2 unwind info. */ - -static void -put_unwind_info (unw_addr_space_t as, unw_proc_info_t *proc_info, void *arg) -{ - /* it's a no-op */ -} - -static int -get_dyn_info_list_addr (unw_addr_space_t as, unw_word_t *dyn_info_list_addr, - void *arg) -{ - *dyn_info_list_addr = (unw_word_t) (intptr_t) &_U_dyn_info_list; - return 0; -} - -static int -access_mem (unw_addr_space_t as, unw_word_t addr, unw_word_t *val, int write, - void *arg) -{ - if (write) - { - Debug (16, "mem[%llx] <- %llx\n", (long long) addr, (long long) *val); - *(unw_word_t *) (intptr_t) addr = *val; - } - else - { - *val = *(unw_word_t *) (intptr_t) addr; - Debug (16, "mem[%llx] -> %llx\n", (long long) addr, (long long) *val); - } - return 0; -} - -static int -access_reg (unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val, int write, - void *arg) -{ - unw_word_t *addr; - ucontext_t *uc = arg; - - if (unw_is_fpreg (reg)) - goto badreg; - - Debug (16, "reg = %s\n", unw_regname (reg)); - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - *(unw_word_t *) (intptr_t) addr = (loongarch_reg_t) *val; - Debug (12, "%s <- %llx\n", unw_regname (reg), (long long) *val); - } - else - { - *val = (loongarch_reg_t) *(unw_word_t *) (intptr_t) addr; - Debug (12, "%s -> %llx\n", unw_regname (reg), (long long) *val); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} - -static int -access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val, - int write, void *arg) -{ - ucontext_t *uc = arg; - unw_fpreg_t *addr; - - if (!unw_is_fpreg (reg)) - goto badreg; - - if (!(addr = uc_addr (uc, reg))) - goto badreg; - - if (write) - { - Debug (12, "%s <- %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - *(unw_fpreg_t *) (intptr_t) addr = *val; - } - else - { - *val = *(unw_fpreg_t *) (intptr_t) addr; - Debug (12, "%s -> %08lx.%08lx.%08lx\n", unw_regname (reg), - ((long *)val)[0], ((long *)val)[1], ((long *)val)[2]); - } - return 0; - - badreg: - Debug (1, "bad register number %u\n", reg); - /* attempt to access a non-preserved register */ - return -UNW_EBADREG; -} - -static int -get_static_proc_name (unw_addr_space_t as, unw_word_t ip, - char *buf, size_t buf_len, unw_word_t *offp, - void *arg) -{ - - return elf_w (get_proc_name) (as, getpid (), ip, buf, buf_len, offp); -} - -HIDDEN void -loongarch_local_addr_space_init (void) -{ - memset (&local_addr_space, 0, sizeof (local_addr_space)); - local_addr_space.big_endian = (__BYTE_ORDER == __BIG_ENDIAN); -#if _LOONGARCH_SIM == _ABILP32 - local_addr_space.abi = UNW_LOONGARCH_ABI_LP32; -#elif _LOONGARCH_SIM == _ABILP64 - local_addr_space.abi = UNW_LOONGARCH_ABI_LP64; -#else -# error Unsupported ABI -#endif - local_addr_space.addr_size = sizeof (void *); - local_addr_space.caching_policy = UNW_CACHE_GLOBAL; - local_addr_space.acc.find_proc_info = dwarf_find_proc_info; - local_addr_space.acc.put_unwind_info = put_unwind_info; - local_addr_space.acc.get_dyn_info_list_addr = get_dyn_info_list_addr; - local_addr_space.acc.access_mem = access_mem; - local_addr_space.acc.access_reg = access_reg; - local_addr_space.acc.access_fpreg = access_fpreg; - local_addr_space.acc.resume = NULL; /* loongarch_local_resume? FIXME! */ - local_addr_space.acc.get_proc_name = get_static_proc_name; - unw_flush_cache (&local_addr_space, 0, 0); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c deleted file mode 100644 index 212c35f1955c89..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_local.c +++ /dev/null @@ -1,53 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "init.h" - -#ifdef UNW_REMOTE_ONLY - -int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - return -UNW_EINVAL; -} - -#else /* !UNW_REMOTE_ONLY */ - -int -unw_init_local (unw_cursor_t *cursor, ucontext_t *uc) -{ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = unw_local_addr_space; - c->dwarf.as_arg = uc; - return common_init (c, 1); -} - -#endif /* !UNW_REMOTE_ONLY */ diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c b/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c deleted file mode 100644 index 9b8ba5b89def1a..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Ginit_remote.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "init.h" -#include "unwind_i.h" - -int -unw_init_remote (unw_cursor_t *cursor, unw_addr_space_t as, void *as_arg) -{ -#ifdef UNW_LOCAL_ONLY - return -UNW_EINVAL; -#else /* !UNW_LOCAL_ONLY */ - struct cursor *c = (struct cursor *) cursor; - - if (!tdep_init_done) - tdep_init (); - - Debug (1, "(cursor=%p)\n", c); - - c->dwarf.as = as; - c->dwarf.as_arg = as_arg; - return common_init (c, 0); -#endif /* !UNW_LOCAL_ONLY */ -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c deleted file mode 100644 index e81d3dc93c9c21..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gis_signal_frame.c +++ /dev/null @@ -1,80 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2015 Imagination Technologies Limited - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include - -int -unw_is_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t w0, w1, ip; - unw_addr_space_t as; - unw_accessors_t *a; - void *arg; - int ret; - - ip = c->dwarf.ip; - - as = c->dwarf.as; - a = unw_get_accessors (as); - arg = c->dwarf.as_arg; - - /* syscall */ - /* FIXME for LOONGARCH: should confirm--- why is "ip+4" !!! */ - //if ((ret = (*a->access_mem) (as, ip + 4, &w1, 0, arg)) < 0) - if ((ret = (*a->access_mem) (as, ip - 4, &w1, 0, arg)) < 0) - return 0; - if ((w1 & 0xffffffff) != 0x002b0000) - return 0; - - /* addi.w a7,r0,??? */ - //if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0) - if ((ret = (*a->access_mem) (as, ip - 8, &w0, 0, arg)) < 0) - return 0; - - switch (c->dwarf.as->abi) - { - case UNW_LOONGARCH_ABI_LP32: - /* FIXME for LOONGARCH32! not supported!!! */ - //switch (w0 & 0xffffffff) - // { - // case 0x0: - // return 1; - // default: - return 0; - // } - case UNW_LOONGARCH_ABI_LP64: - switch (w0 & 0xffffffff) - {//addi.w a7,139 should confirm further! - case 0x02822c0b: - return 1; - default: - return 0; - } - default: - return 0; - } -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c deleted file mode 100644 index 55f7cde55a8e1c..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gregs.c +++ /dev/null @@ -1,103 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -/* FIXME: The following is probably unfinished and/or at least partly bogus. */ - -HIDDEN int -tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp, - int write) -{ - dwarf_loc_t loc = DWARF_NULL_LOC; - - switch (reg) - { - case UNW_LOONGARCH_R0: - case UNW_LOONGARCH_R1: - case UNW_LOONGARCH_R2: - case UNW_LOONGARCH_R4: - case UNW_LOONGARCH_R5: - case UNW_LOONGARCH_R6: - case UNW_LOONGARCH_R7: - case UNW_LOONGARCH_R8: - case UNW_LOONGARCH_R9: - case UNW_LOONGARCH_R10: - case UNW_LOONGARCH_R11: - case UNW_LOONGARCH_R12: - case UNW_LOONGARCH_R13: - case UNW_LOONGARCH_R14: - case UNW_LOONGARCH_R15: - case UNW_LOONGARCH_R16: - case UNW_LOONGARCH_R17: - case UNW_LOONGARCH_R18: - case UNW_LOONGARCH_R19: - case UNW_LOONGARCH_R20: - case UNW_LOONGARCH_R21: - case UNW_LOONGARCH_R22: - case UNW_LOONGARCH_R23: - case UNW_LOONGARCH_R24: - case UNW_LOONGARCH_R25: - case UNW_LOONGARCH_R26: - case UNW_LOONGARCH_R27: - case UNW_LOONGARCH_R28: - case UNW_LOONGARCH_R29: - case UNW_LOONGARCH_R30: - case UNW_LOONGARCH_R31: - loc = c->dwarf.loc[reg - UNW_LOONGARCH_R0]; - break; - - case UNW_LOONGARCH_PC: - loc = c->dwarf.loc[reg]; - break; - - case UNW_LOONGARCH_R3: - case UNW_LOONGARCH_CFA: - if (write) - return -UNW_EREADONLYREG; - *valp = c->dwarf.cfa; - return 0; - - /* FIXME: IP? Copro & shadow registers? */ - - default: - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; - } - - if (write) - return dwarf_put (&c->dwarf, loc, *valp); - else - return dwarf_get (&c->dwarf, loc, valp); -} - -/* FIXME for LOONGARCH. */ - -HIDDEN int -tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, unw_fpreg_t *valp, - int write) -{ - Debug (1, "bad register number %u\n", reg); - return -UNW_EBADREG; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c deleted file mode 100644 index cdfed3b3fe75b1..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gresume.c +++ /dev/null @@ -1,45 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -/* FIXME for LOONGARCH. */ - -#include - -#include "unwind_i.h" - -#ifndef UNW_REMOTE_ONLY - -HIDDEN inline int -loongarch_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg) -{ - return -UNW_EINVAL; -} - -#endif /* !UNW_REMOTE_ONLY */ - -int -unw_resume (unw_cursor_t *cursor) -{ - return -UNW_EINVAL; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c b/src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c deleted file mode 100644 index 1fb6f1da14fa4f..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Gstep.c +++ /dev/null @@ -1,135 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2015 Imagination Technologies Limited - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" -#include "offsets.h" - -#define unw_handle_signal_frame UNW_OBJ(unw_handle_signal_frame) - -int -unw_handle_signal_frame (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - unw_word_t sc_addr, sp, sp_addr = c->dwarf.cfa; - unw_word_t ra, fp; - int ret; - - switch (unw_is_signal_frame (cursor)) { - case 1: - sc_addr = sp_addr + LINUX_SF_TRAMP_SIZE + sizeof (siginfo_t) + - LINUX_UC_MCONTEXT_OFF; - break; - case 2: - /* FIXME for LOONGARCH32: should confirm - not support !!! */ - sc_addr = sp_addr + LINUX_UC_MCONTEXT_OFF; - break; - default: - return -UNW_EUNSPEC; - } - - if (tdep_big_endian(c->dwarf.as)) - sc_addr += 4; - - c->sigcontext_addr = sc_addr; - - /* Update the dwarf cursor. */ - c->dwarf.loc[UNW_LOONGARCH_R0] = DWARF_LOC (sc_addr + LINUX_SC_R0_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R1] = DWARF_LOC (sc_addr + LINUX_SC_R1_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R2] = DWARF_LOC (sc_addr + LINUX_SC_R2_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R3] = DWARF_LOC (sc_addr + LINUX_SC_R3_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R4] = DWARF_LOC (sc_addr + LINUX_SC_R4_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R5] = DWARF_LOC (sc_addr + LINUX_SC_R5_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R6] = DWARF_LOC (sc_addr + LINUX_SC_R6_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R7] = DWARF_LOC (sc_addr + LINUX_SC_R7_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R8] = DWARF_LOC (sc_addr + LINUX_SC_R8_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R9] = DWARF_LOC (sc_addr + LINUX_SC_R9_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R10] = DWARF_LOC (sc_addr + LINUX_SC_R10_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R11] = DWARF_LOC (sc_addr + LINUX_SC_R11_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R12] = DWARF_LOC (sc_addr + LINUX_SC_R12_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R13] = DWARF_LOC (sc_addr + LINUX_SC_R13_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R14] = DWARF_LOC (sc_addr + LINUX_SC_R14_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R15] = DWARF_LOC (sc_addr + LINUX_SC_R15_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R16] = DWARF_LOC (sc_addr + LINUX_SC_R16_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R17] = DWARF_LOC (sc_addr + LINUX_SC_R17_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R18] = DWARF_LOC (sc_addr + LINUX_SC_R18_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R19] = DWARF_LOC (sc_addr + LINUX_SC_R19_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R20] = DWARF_LOC (sc_addr + LINUX_SC_R20_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R21] = DWARF_LOC (sc_addr + LINUX_SC_R21_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R22] = DWARF_LOC (sc_addr + LINUX_SC_R22_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R23] = DWARF_LOC (sc_addr + LINUX_SC_R23_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R24] = DWARF_LOC (sc_addr + LINUX_SC_R24_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R25] = DWARF_LOC (sc_addr + LINUX_SC_R25_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R26] = DWARF_LOC (sc_addr + LINUX_SC_R26_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R27] = DWARF_LOC (sc_addr + LINUX_SC_R27_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R28] = DWARF_LOC (sc_addr + LINUX_SC_R28_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R29] = DWARF_LOC (sc_addr + LINUX_SC_R29_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R30] = DWARF_LOC (sc_addr + LINUX_SC_R30_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_R31] = DWARF_LOC (sc_addr + LINUX_SC_R31_OFF, 0); - c->dwarf.loc[UNW_LOONGARCH_PC] = DWARF_LOC (sc_addr + LINUX_SC_PC_OFF, 0); - - /* Set SP/CFA and PC/IP. */ - dwarf_get (&c->dwarf, c->dwarf.loc[UNW_LOONGARCH_R3], &c->dwarf.cfa); - - if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_PC_OFF, 0), - &c->dwarf.ip)) < 0) - return ret; - - if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R31_OFF, 0), - &ra)) < 0) - return ret; - if ((ret = dwarf_get(&c->dwarf, DWARF_LOC(sc_addr + LINUX_SC_R30_OFF, 0), - &fp)) < 0) - return ret; - - Debug (2, "SH (ip=0x%016llx, ra=0x%016llx, sp=0x%016llx, fp=0x%016llx)\n", - (unsigned long long)c->dwarf.ip, (unsigned long long)ra, - (unsigned long long)c->dwarf.cfa, (unsigned long long)fp); - - c->dwarf.pi_valid = 0; - c->dwarf.use_prev_instr = 0; - - return 1; -} - -int -unw_step (unw_cursor_t *cursor) -{ - struct cursor *c = (struct cursor *) cursor; - int ret; - - ret = unw_handle_signal_frame (cursor); - if (ret < 0) - /* Not a signal frame, try DWARF-based unwinding. */ - ret = dwarf_step (&c->dwarf); - - if (unlikely (ret == -UNW_ESTOPUNWIND)) - return ret; - - /* Dwarf unwinding didn't work, stop. */ - if (unlikely (ret < 0)) - return 0; - - return (c->dwarf.ip == 0) ? 0 : 1; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c deleted file mode 100644 index 0f2dc6be901453..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lcreate_addr_space.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gcreate_addr_space.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c deleted file mode 100644 index 69028b019fcd51..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lget_proc_info.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_proc_info.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c deleted file mode 100644 index 9ea048a9076ba8..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lget_save_loc.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gget_save_loc.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c deleted file mode 100644 index 6d7b489e14bd9f..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lglobal.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gglobal.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Linit.c b/src/coreclr/pal/src/libunwind/src/loongarch/Linit.c deleted file mode 100644 index e9abfdd46a3e0f..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Linit.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c b/src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c deleted file mode 100644 index 68a1687e85444b..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Linit_local.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_local.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c b/src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c deleted file mode 100644 index 58cb04ab7cd1fd..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Linit_remote.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Ginit_remote.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c deleted file mode 100644 index b9a7c4f51ad9fa..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lis_signal_frame.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gis_signal_frame.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c deleted file mode 100644 index 2c9c75cd7d9a1e..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lregs.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gregs.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c deleted file mode 100644 index 41a8cf003de4ac..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lresume.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gresume.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c b/src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c deleted file mode 100644 index c1ac3c7547f00d..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/Lstep.c +++ /dev/null @@ -1,5 +0,0 @@ -#define UNW_LOCAL_ONLY -#include -#if defined(UNW_LOCAL_ONLY) && !defined(UNW_REMOTE_ONLY) -#include "Gstep.c" -#endif diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S b/src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S deleted file mode 100644 index 896069a7e3c43e..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/getcontext.S +++ /dev/null @@ -1,94 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - Copyright (C) 2012 Tommi Rantala - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "offsets.h" -#include - - .text - -#if _LOONGARCH_SIM == _ABILP32 -# if __BYTE_ORDER == __BIG_ENDIAN -# define OFFSET 4 -# else -# define OFFSET 0 -# endif -# define SREG(X) \ - sw $X, (LINUX_UC_MCONTEXT_GREGS + 8 * X + OFFSET) ($4); \ - sra $1, $X, 31; \ - sw $1, (LINUX_UC_MCONTEXT_GREGS + 8 * X + 4 - OFFSET) ($4) -/* Yes, we save the return address to PC. */ -# define SPC \ - sw $31, (LINUX_UC_MCONTEXT_PC + OFFSET) ($4); \ - sra $1, $31, 31; \ - sw $1, (LINUX_UC_MCONTEXT_PC + 4 - OFFSET) ($4) -#else -.macro SREG x - st.d $r\x, $r4 , (LINUX_UC_MCONTEXT_GREGS + 8 * \x) -.endm -# define SPC st.d $r1, $r4 , LINUX_UC_MCONTEXT_PC -#endif - - .global _Uloongarch_getcontext - .type _Uloongarch_getcontext, %function - # This is a stub version of getcontext() for LOONGARCH which only stores core - # registers. -_Uloongarch_getcontext: - SREG 1 - SREG 0 - SREG 2 - SREG 3 - SREG 4 - SREG 5 - SREG 6 - SREG 7 - SREG 8 - SREG 9 - SREG 10 - SREG 11 - SREG 12 - SREG 13 - SREG 14 - SREG 15 - SREG 16 - SREG 17 - SREG 18 - SREG 19 - SREG 20 - SREG 21 - SREG 22 - SREG 23 - SREG 24 - SREG 25 - SREG 26 - SREG 27 - SREG 28 - SREG 29 - SREG 30 - SREG 31 - SPC - ori $r4, $r0, 0 - jirl $r0,$r1,0 - - .size _Uloongarch_getcontext, .-_Uloongarch_getcontext diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/init.h b/src/coreclr/pal/src/libunwind/src/loongarch/init.h deleted file mode 100644 index bf08dd57239d6d..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/init.h +++ /dev/null @@ -1,59 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static inline int -common_init (struct cursor *c, unsigned use_prev_instr) -{ - int ret, i; - - for (i = 0; i < 32; i++) - c->dwarf.loc[i] = DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH_R0 + i); - for (i = 32; i < DWARF_NUM_PRESERVED_REGS; ++i) - c->dwarf.loc[i] = DWARF_NULL_LOC; - - c->dwarf.loc[UNW_LOONGARCH_PC] = DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH_PC); - - ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_LOONGARCH_PC], &c->dwarf.ip); - if (ret < 0) - return ret; - - ret = dwarf_get (&c->dwarf, DWARF_REG_LOC (&c->dwarf, UNW_LOONGARCH_R3), - &c->dwarf.cfa); - if (ret < 0) - return ret; - - /* FIXME: Initialisation for other registers. */ - - c->dwarf.args_size = 0; - c->dwarf.stash_frames = 0; - c->dwarf.use_prev_instr = use_prev_instr; - c->dwarf.pi_valid = 0; - c->dwarf.pi_is_dynamic = 0; - c->dwarf.hint = 0; - c->dwarf.prev_rs = 0; - - return 0; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c b/src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c deleted file mode 100644 index ab70d6a6df3e37..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/is_fpreg.c +++ /dev/null @@ -1,35 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "libunwind_i.h" - -/* FIXME: I'm not sure if libunwind's GP/FP register distinction is very useful - on LOONGARCH. */ - -int -unw_is_fpreg (int regnum) -{ - /* FIXME: Support FP. */ - return 0; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/offsets.h b/src/coreclr/pal/src/libunwind/src/loongarch/offsets.h deleted file mode 100644 index 8ca011ffcccfca..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/offsets.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Linux-specific definitions: */ - -/* Define various structure offsets to simplify cross-compilation. */ - -/* FIXME: Currently these are only used in getcontext.S, which is only used - for a local unwinder, so we can use the compile-time ABI. At a later date - we will want all three here, to use for signal handlers. Also, because - of the three ABIs, gen-offsets.c can not quite generate this file. */ - -/* Offsets for LOONGARCH Linux "ucontext_t": */ - -/* First 24 bytes in sigframe are argument save space and padding for -what used to be signal trampolines. Ref: arch/mips/kernel/signal.c */ -#define LINUX_SF_TRAMP_SIZE 0x18 - -#if _LOONGARCH_SIM == _ABILP32 - -# define LINUX_UC_FLAGS_OFF 0x0 -# define LINUX_UC_LINK_OFF 0x4 -# define LINUX_UC_STACK_OFF 0x8 -# define LINUX_UC_MCONTEXT_OFF 0x18 -# define LINUX_UC_SIGMASK_OFF 0x268 -# define LINUX_UC_MCONTEXT_PC 0x20 -# define LINUX_UC_MCONTEXT_GREGS 0x28 - -#elif _LOONGARCH_SIM == _ABILP64 - -# define LINUX_UC_FLAGS_OFF 0x0 -# define LINUX_UC_LINK_OFF 0x8 -# define LINUX_UC_STACK_OFF 0x10 -# define LINUX_UC_MCONTEXT_OFF 0x28 -# define LINUX_UC_SIGMASK_OFF 0x280 -# define LINUX_UC_MCONTEXT_PC 0x268 -# define LINUX_UC_MCONTEXT_GREGS 0x28 - -#else - -#error Unsupported ABI - -#endif - -#define LINUX_SC_R0_OFF (LINUX_UC_MCONTEXT_GREGS - LINUX_UC_MCONTEXT_OFF) -#define LINUX_SC_R1_OFF (LINUX_SC_R0_OFF + 1*8) -#define LINUX_SC_R2_OFF (LINUX_SC_R0_OFF + 2*8) -#define LINUX_SC_R3_OFF (LINUX_SC_R0_OFF + 3*8) -#define LINUX_SC_R4_OFF (LINUX_SC_R0_OFF + 4*8) -#define LINUX_SC_R5_OFF (LINUX_SC_R0_OFF + 5*8) -#define LINUX_SC_R6_OFF (LINUX_SC_R0_OFF + 6*8) -#define LINUX_SC_R7_OFF (LINUX_SC_R0_OFF + 7*8) -#define LINUX_SC_R8_OFF (LINUX_SC_R0_OFF + 8*8) -#define LINUX_SC_R9_OFF (LINUX_SC_R0_OFF + 9*8) -#define LINUX_SC_R10_OFF (LINUX_SC_R0_OFF + 10*8) -#define LINUX_SC_R11_OFF (LINUX_SC_R0_OFF + 11*8) -#define LINUX_SC_R12_OFF (LINUX_SC_R0_OFF + 12*8) -#define LINUX_SC_R13_OFF (LINUX_SC_R0_OFF + 13*8) -#define LINUX_SC_R14_OFF (LINUX_SC_R0_OFF + 14*8) -#define LINUX_SC_R15_OFF (LINUX_SC_R0_OFF + 15*8) -#define LINUX_SC_R16_OFF (LINUX_SC_R0_OFF + 16*8) -#define LINUX_SC_R17_OFF (LINUX_SC_R0_OFF + 17*8) -#define LINUX_SC_R18_OFF (LINUX_SC_R0_OFF + 18*8) -#define LINUX_SC_R19_OFF (LINUX_SC_R0_OFF + 19*8) -#define LINUX_SC_R20_OFF (LINUX_SC_R0_OFF + 20*8) -#define LINUX_SC_R21_OFF (LINUX_SC_R0_OFF + 21*8) -#define LINUX_SC_R22_OFF (LINUX_SC_R0_OFF + 22*8) -#define LINUX_SC_R23_OFF (LINUX_SC_R0_OFF + 23*8) -#define LINUX_SC_R24_OFF (LINUX_SC_R0_OFF + 24*8) -#define LINUX_SC_R25_OFF (LINUX_SC_R0_OFF + 25*8) -#define LINUX_SC_R26_OFF (LINUX_SC_R0_OFF + 26*8) -#define LINUX_SC_R27_OFF (LINUX_SC_R0_OFF + 27*8) -#define LINUX_SC_R28_OFF (LINUX_SC_R0_OFF + 28*8) -#define LINUX_SC_R29_OFF (LINUX_SC_R0_OFF + 29*8) -#define LINUX_SC_R30_OFF (LINUX_SC_R0_OFF + 30*8) -#define LINUX_SC_R31_OFF (LINUX_SC_R0_OFF + 31*8) - -#define LINUX_SC_SP_OFF LINUX_SC_R29_OFF -#define LINUX_SC_PC_OFF (LINUX_UC_MCONTEXT_PC - LINUX_UC_MCONTEXT_OFF) diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/regname.c b/src/coreclr/pal/src/libunwind/src/loongarch/regname.c deleted file mode 100644 index 35bc7f136a6045..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/regname.c +++ /dev/null @@ -1,48 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "unwind_i.h" - -static const char *regname[] = - { - /* 0. */ - "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", - /* 8. */ - "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$r15", - /* 16. */ - "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", - /* 24. */ - "$r24", "$r25", "$r26", "$r27", "$r28", "$r29", "$r30", "$r31", - }; - -const char * -unw_regname (unw_regnum_t reg) -{ - if (reg < (unw_regnum_t) ARRAY_SIZE (regname)) - return regname[reg]; - else if (reg == UNW_LOONGARCH_PC) - return "pc"; - else - return "???"; -} diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S b/src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S deleted file mode 100644 index 12610e294402bd..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/siglongjmp.S +++ /dev/null @@ -1,8 +0,0 @@ - /* Dummy implementation for now. */ - - .globl _UI_siglongjmp_cont - .globl _UI_longjmp_cont - -_UI_siglongjmp_cont: -_UI_longjmp_cont: - jirl $r0,$r1,0 diff --git a/src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h b/src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h deleted file mode 100644 index 1ea2e123496b56..00000000000000 --- a/src/coreclr/pal/src/libunwind/src/loongarch/unwind_i.h +++ /dev/null @@ -1,43 +0,0 @@ -/* libunwind - a platform-independent unwind library - Copyright (C) 2008 CodeSourcery - -This file is part of libunwind. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef unwind_i_h -#define unwind_i_h - -#include - -#include - -#include "libunwind_i.h" - -#define loongarch_lock UNW_OBJ(lock) -#define loongarch_local_resume UNW_OBJ(local_resume) -#define loongarch_local_addr_space_init UNW_OBJ(local_addr_space_init) - -extern int loongarch_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, - void *arg); - -extern void loongarch_local_addr_space_init (void); - -#endif /* unwind_i_h */ diff --git a/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c b/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c index 873c053a9f28a2..b7dd3b79a8afea 100644 --- a/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c +++ b/src/coreclr/pal/src/libunwind/src/ptrace/_UPT_reg_offset.c @@ -551,42 +551,6 @@ const int _UPT_reg_offset[UNW_REG_LAST + 1] = #else #error Fix me #endif -#elif defined(UNW_TARGET_LOONGARCH) -# include - - [UNW_LOONGARCH64_R0] = LOONGARCH64_EF_R0, - [UNW_LOONGARCH64_R1] = LOONGARCH64_EF_R1, - [UNW_LOONGARCH64_R2] = LOONGARCH64_EF_R2, - [UNW_LOONGARCH64_R3] = LOONGARCH64_EF_R3, - [UNW_LOONGARCH64_R4] = LOONGARCH64_EF_R4, - [UNW_LOONGARCH64_R5] = LOONGARCH64_EF_R5, - [UNW_LOONGARCH64_R6] = LOONGARCH64_EF_R6, - [UNW_LOONGARCH64_R7] = LOONGARCH64_EF_R7, - [UNW_LOONGARCH64_R8] = LOONGARCH64_EF_R8, - [UNW_LOONGARCH64_R9] = LOONGARCH64_EF_R9, - [UNW_LOONGARCH64_R10] = LOONGARCH64_EF_R10, - [UNW_LOONGARCH64_R11] = LOONGARCH64_EF_R11, - [UNW_LOONGARCH64_R12] = LOONGARCH64_EF_R12, - [UNW_LOONGARCH64_R13] = LOONGARCH64_EF_R13, - [UNW_LOONGARCH64_R14] = LOONGARCH64_EF_R14, - [UNW_LOONGARCH64_R15] = LOONGARCH64_EF_R15, - [UNW_LOONGARCH64_R16] = LOONGARCH64_EF_R16, - [UNW_LOONGARCH64_R17] = LOONGARCH64_EF_R17, - [UNW_LOONGARCH64_R18] = LOONGARCH64_EF_R18, - [UNW_LOONGARCH64_R19] = LOONGARCH64_EF_R19, - [UNW_LOONGARCH64_R20] = LOONGARCH64_EF_R20, - [UNW_LOONGARCH64_R21] = LOONGARCH64_EF_R21, - [UNW_LOONGARCH64_R22] = LOONGARCH64_EF_R22, - [UNW_LOONGARCH64_R23] = LOONGARCH64_EF_R23, - [UNW_LOONGARCH64_R24] = LOONGARCH64_EF_R24, - [UNW_LOONGARCH64_R25] = LOONGARCH64_EF_R25, - [UNW_LOONGARCH64_R26] = LOONGARCH64_EF_R26, - [UNW_LOONGARCH64_R27] = LOONGARCH64_EF_R27, - [UNW_LOONGARCH64_R28] = LOONGARCH64_EF_R28, - [UNW_LOONGARCH64_R29] = LOONGARCH64_EF_R29, - [UNW_LOONGARCH64_R30] = LOONGARCH64_EF_R30, - [UNW_LOONGARCH64_R31] = LOONGARCH64_EF_R31, - [UNW_LOONGARCH64_PC] = LOONGARCH64_EF_CSR_EPC #elif defined(UNW_TARGET_MIPS) [UNW_MIPS_R0] = 0, [UNW_MIPS_R1] = 1, From f70f07a60146359a5508709f0d92fe374c649dbe Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Sat, 18 Dec 2021 15:08:47 +0800 Subject: [PATCH 03/11] [LoongArch64] add config files from #62889. --- src/coreclr/pal/src/CMakeLists.txt | 12 ++++++++++++ src/coreclr/pal/src/configure.cmake | 6 +++++- .../eventprovider/lttngprovider/CMakeLists.txt | 17 ++++++++++++++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 4f071b21046b07..20a442b541e2fb 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -47,6 +47,8 @@ elseif(CLR_CMAKE_HOST_ARCH_ARM) set(PAL_ARCH_SOURCES_DIR arm) elseif(CLR_CMAKE_HOST_ARCH_ARM64) set(PAL_ARCH_SOURCES_DIR arm64) +elseif(CLR_CMAKE_HOST_ARCH_LOONGARCH64) + set(PAL_ARCH_SOURCES_DIR loongarch64) elseif(CLR_CMAKE_HOST_ARCH_I386) set(PAL_ARCH_SOURCES_DIR i386) elseif(CLR_CMAKE_HOST_ARCH_S390X) @@ -297,11 +299,21 @@ endif(CLR_CMAKE_TARGET_FREEBSD) if(CLR_CMAKE_TARGET_LINUX) # On Android, we don't need to link with gcc_s, pthread and rt if(NOT CLR_CMAKE_TARGET_ANDROID) + if(NOT CLR_CMAKE_TARGET_ARCH_LOONGARCH64) target_link_libraries(coreclrpal gcc_s pthread rt ) + else() + find_library(LZMA NAMES lzma) + target_link_libraries(coreclrpal + gcc_s + pthread + rt + lzma + ) + endif() else(NOT CLR_CMAKE_TARGET_ANDROID) target_link_libraries(coreclrpal ${ANDROID_GLOB} diff --git a/src/coreclr/pal/src/configure.cmake b/src/coreclr/pal/src/configure.cmake index ee4a3241196eaa..5928bbd9aea920 100644 --- a/src/coreclr/pal/src/configure.cmake +++ b/src/coreclr/pal/src/configure.cmake @@ -21,7 +21,11 @@ elseif(NOT CLR_CMAKE_TARGET_FREEBSD AND NOT CLR_CMAKE_TARGET_NETBSD) endif() if(CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ANDROID) - set(CMAKE_RT_LIBS rt) + if(NOT CLR_CMAKE_HOST_ARCH_LOONGARCH64) + set(CMAKE_RT_LIBS rt) + elseif() + set(CMAKE_RT_LIBS rt pthread) + endif() elseif(CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) set(CMAKE_RT_LIBS rt) else() diff --git a/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt b/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt index 8773cd797bcfb6..b35f05d1c32e0c 100644 --- a/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt +++ b/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt @@ -62,9 +62,20 @@ add_dependencies(coreclrtraceptprovider generated_eventing_headers) find_library(LTTNG NAMES lttng-ust) -target_link_libraries(coreclrtraceptprovider - ${LTTNG} -) +if(NOT CLR_CMAKE_TARGET_ARCH_LOONGARCH64) + target_link_libraries(coreclrtraceptprovider + ${LTTNG} + ) +else() + target_link_libraries(coreclrtraceptprovider + lttng-ust-tracepoint + urcu + urcu-bp + urcu-cds + urcu-common + ${LTTNG} + ) +endif() set_target_properties(coreclrtraceptprovider PROPERTIES LINKER_LANGUAGE CXX) From 63cc4dd2394ab0485609b0704354650f459fa137 Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Sat, 18 Dec 2021 16:29:48 +0800 Subject: [PATCH 04/11] [LoongArch64] revert some files when moved from #62889. --- src/coreclr/pal/src/CMakeLists.txt | 10 ---------- src/coreclr/pal/src/configure.cmake | 6 +----- .../eventprovider/lttngprovider/CMakeLists.txt | 17 +++-------------- 3 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 20a442b541e2fb..6dcd847eaf3da2 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -299,21 +299,11 @@ endif(CLR_CMAKE_TARGET_FREEBSD) if(CLR_CMAKE_TARGET_LINUX) # On Android, we don't need to link with gcc_s, pthread and rt if(NOT CLR_CMAKE_TARGET_ANDROID) - if(NOT CLR_CMAKE_TARGET_ARCH_LOONGARCH64) target_link_libraries(coreclrpal gcc_s pthread rt ) - else() - find_library(LZMA NAMES lzma) - target_link_libraries(coreclrpal - gcc_s - pthread - rt - lzma - ) - endif() else(NOT CLR_CMAKE_TARGET_ANDROID) target_link_libraries(coreclrpal ${ANDROID_GLOB} diff --git a/src/coreclr/pal/src/configure.cmake b/src/coreclr/pal/src/configure.cmake index 5928bbd9aea920..ee4a3241196eaa 100644 --- a/src/coreclr/pal/src/configure.cmake +++ b/src/coreclr/pal/src/configure.cmake @@ -21,11 +21,7 @@ elseif(NOT CLR_CMAKE_TARGET_FREEBSD AND NOT CLR_CMAKE_TARGET_NETBSD) endif() if(CLR_CMAKE_TARGET_LINUX AND NOT CLR_CMAKE_TARGET_ANDROID) - if(NOT CLR_CMAKE_HOST_ARCH_LOONGARCH64) - set(CMAKE_RT_LIBS rt) - elseif() - set(CMAKE_RT_LIBS rt pthread) - endif() + set(CMAKE_RT_LIBS rt) elseif(CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_NETBSD) set(CMAKE_RT_LIBS rt) else() diff --git a/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt b/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt index b35f05d1c32e0c..c9e352c40ee13c 100644 --- a/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt +++ b/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt @@ -62,20 +62,9 @@ add_dependencies(coreclrtraceptprovider generated_eventing_headers) find_library(LTTNG NAMES lttng-ust) -if(NOT CLR_CMAKE_TARGET_ARCH_LOONGARCH64) - target_link_libraries(coreclrtraceptprovider - ${LTTNG} - ) -else() - target_link_libraries(coreclrtraceptprovider - lttng-ust-tracepoint - urcu - urcu-bp - urcu-cds - urcu-common - ${LTTNG} - ) -endif() +target_link_libraries(coreclrtraceptprovider + ${LTTNG} +) set_target_properties(coreclrtraceptprovider PROPERTIES LINKER_LANGUAGE CXX) From dbf71fcf10ac67eb296bbeb79cddf52f304d8362 Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Tue, 21 Dec 2021 09:01:27 +0800 Subject: [PATCH 05/11] [LoongArch64] compiling is sucessfully. --- src/coreclr/pal/inc/pal.h | 2 +- src/coreclr/pal/inc/rt/ntimage.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 896e1f851af807..719d0933b0c42e 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -3987,7 +3987,7 @@ typedef LPOSVERSIONINFOEXA LPOSVERSIONINFOEX; #define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian #ifndef IMAGE_FILE_MACHINE_LOONGARCH64 -#define IMAGE_FILE_MACHINE_LOONGARCH64 0xDD64 // LOONGARCH64 Little-Endian +#define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 // LOONGARCH64 Little-Endian #endif typedef struct _SYSTEM_INFO { diff --git a/src/coreclr/pal/inc/rt/ntimage.h b/src/coreclr/pal/inc/rt/ntimage.h index 78f350f104b7c2..1880375184f057 100644 --- a/src/coreclr/pal/inc/rt/ntimage.h +++ b/src/coreclr/pal/inc/rt/ntimage.h @@ -239,7 +239,6 @@ typedef struct _IMAGE_FILE_HEADER { #define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) #define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian #define IMAGE_FILE_MACHINE_CEE 0xC0EE -#define IMAGE_FILE_MACHINE_LOONGARCH64 0xDD64 // LOONGARCH64. // // Directory format. @@ -1026,11 +1025,6 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; #define IMAGE_REL_IA64_GPREL32 0x001C #define IMAGE_REL_IA64_ADDEND 0x001F -// -// LOONGARCH64 relocation types -// -#define IMAGE_REL_LOONGARCH64_PC 0x0004 - // // CEF relocation types. // From c46968c7946cccfc5b097df47ea1ae8f97454194 Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Tue, 21 Dec 2021 12:18:49 +0800 Subject: [PATCH 06/11] [LoongArch64] delete the define IMAGE_FILE_MACHINE_LOONGARCH64 for #62886. --- src/coreclr/pal/inc/pal.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 719d0933b0c42e..a9e265a406bb58 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -3986,10 +3986,6 @@ typedef LPOSVERSIONINFOEXA LPOSVERSIONINFOEX; #define IMAGE_FILE_MACHINE_I386 0x014c #define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian -#ifndef IMAGE_FILE_MACHINE_LOONGARCH64 -#define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 // LOONGARCH64 Little-Endian -#endif - typedef struct _SYSTEM_INFO { WORD wProcessorArchitecture_PAL_Undefined; WORD wReserved_PAL_Undefined; // NOTE: diff from winbase.h - no obsolete dwOemId union From d43f51b65763fd4703c5122e2a5d6f7a22cfd33f Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Wed, 22 Dec 2021 14:37:14 +0800 Subject: [PATCH 07/11] [LoongArch64] exclude some files from pal directory. --- src/coreclr/pal/inc/rt/ntimage.h | 5 + .../lttngprovider/CMakeLists.txt | 2 +- .../ThunkGenerator/ThunkInput.txt | 1 - .../tools/aot/jitinterface/jitinterface.h | 23 +- .../loongarch64/unwinder_loongarch64.cpp | 1676 ----------------- .../loongarch64/unwinder_loongarch64.h | 54 - 6 files changed, 7 insertions(+), 1754 deletions(-) delete mode 100644 src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp delete mode 100644 src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h diff --git a/src/coreclr/pal/inc/rt/ntimage.h b/src/coreclr/pal/inc/rt/ntimage.h index 1880375184f057..ee873027b388e7 100644 --- a/src/coreclr/pal/inc/rt/ntimage.h +++ b/src/coreclr/pal/inc/rt/ntimage.h @@ -1025,6 +1025,11 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; #define IMAGE_REL_IA64_GPREL32 0x001C #define IMAGE_REL_IA64_ADDEND 0x001F +// +// LOONGARCH64 relocation types +// +#define IMAGE_REL_LOONGARCH64_PC 0x0004 + // // CEF relocation types. // diff --git a/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt b/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt index c9e352c40ee13c..8773cd797bcfb6 100644 --- a/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt +++ b/src/coreclr/pal/src/eventprovider/lttngprovider/CMakeLists.txt @@ -63,7 +63,7 @@ add_dependencies(coreclrtraceptprovider generated_eventing_headers) find_library(LTTNG NAMES lttng-ust) target_link_libraries(coreclrtraceptprovider - ${LTTNG} + ${LTTNG} ) set_target_properties(coreclrtraceptprovider PROPERTIES LINKER_LANGUAGE CXX) diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 53194e69528e8c..dbe775e1e0246e 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -271,7 +271,6 @@ FUNCTIONS unsigned getMethodHash(CORINFO_METHOD_HANDLE ftn); size_t findNameOfToken(CORINFO_MODULE_HANDLE moduleHandle,mdToken token, char * szFQName,size_t FQNameCapacity); bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); - uint32_t getFieldTypeByHnd(CORINFO_CLASS_HANDLE cls); uint32_t getThreadTLSIndex(void **ppIndirection); const void * getInlinedCallFrameVptr(void **ppIndirection); int32_t * getAddrOfCaptureThreadGlobal(void **ppIndirection); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 2220b66faee1db..f0158199fea1a3 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -111,12 +111,7 @@ struct JitInterfaceCallbacks void* (* allocateArray)(void * thisHandle, CorInfoExceptionClass** ppException, size_t cBytes); void (* freeArray)(void * thisHandle, CorInfoExceptionClass** ppException, void* array); CORINFO_ARG_LIST_HANDLE (* getArgNext)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_ARG_LIST_HANDLE args); -#if defined(TARGET_LOONGARCH64) - CorInfoTypeWithMod (* getArgType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, CORINFO_CLASS_HANDLE* vcTypeRet, int *flags); -#else CorInfoTypeWithMod (* getArgType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, CORINFO_CLASS_HANDLE* vcTypeRet); -#endif - uint32_t (* getFieldTypeByHnd)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CORINFO_CLASS_HANDLE (* getArgClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args); CorInfoHFAElemType (* getHFAType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE hClass); JITINTERFACE_HRESULT (* GetErrorHRESULT)(void * thisHandle, CorInfoExceptionClass** ppException, struct _EXCEPTION_POINTERS* pExceptionPointers); @@ -1178,26 +1173,10 @@ class JitInterfaceWrapper : public ICorJitInfo virtual CorInfoTypeWithMod getArgType( CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, - CORINFO_CLASS_HANDLE* vcTypeRet -#if defined(TARGET_LOONGARCH64) - ,int *flags = NULL -#endif - ) + CORINFO_CLASS_HANDLE* vcTypeRet) { CorInfoExceptionClass* pException = nullptr; -#if defined(TARGET_LOONGARCH64) - CorInfoTypeWithMod temp = _callbacks->getArgType(_thisHandle, &pException, sig, args, vcTypeRet, flags); -#else CorInfoTypeWithMod temp = _callbacks->getArgType(_thisHandle, &pException, sig, args, vcTypeRet); -#endif - if (pException != nullptr) throw pException; - return temp; -} - - virtual uint32_t getFieldTypeByHnd(CORINFO_CLASS_HANDLE cls) -{ - CorInfoExceptionClass* pException = nullptr; - uint32_t temp = _callbacks->getFieldTypeByHnd(_thisHandle, &pException, cls); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp b/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp deleted file mode 100644 index c65e09c725334d..00000000000000 --- a/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.cpp +++ /dev/null @@ -1,1676 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. - -// - -#include "stdafx.h" -#include "utilcode.h" -#include "crosscomp.h" - -#include "unwinder_loongarch64.h" - -typedef struct _LOONGARCH64_KTRAP_FRAME { - -// -// Exception active indicator. -// -// 0 - interrupt frame. -// 1 - exception frame. -// 2 - service frame. -// - - /* +0x000 */ UCHAR ExceptionActive; // always valid - /* +0x001 */ UCHAR ContextFromKFramesUnwound; // set if KeContextFromKFrames created this frame - /* +0x002 */ UCHAR DebugRegistersValid; // always valid - /* +0x003 */ union { - UCHAR PreviousMode; // system services only - UCHAR PreviousIrql; // interrupts only - }; - -// -// Page fault information (page faults only) -// Previous trap frame address (system services only) -// -// Organized this way to allow first couple words to be used -// for scratch space in the general case -// - - /* +0x004 */ ULONG FaultStatus; // page faults only - /* +0x008 */ union { - ULONG64 FaultAddress; // page faults only - ULONG64 TrapFrame; // system services only - }; - -// -// The LOONGARCH architecture does not have an architectural trap frame. On -// an exception or interrupt, the processor switches to an -// exception-specific processor mode in which at least the RA and SP -// registers are banked. Software is responsible for preserving -// registers which reflect the processor state in which the -// exception occurred rather than any intermediate processor modes. -// - -// -// Volatile floating point state is dynamically allocated; this -// pointer may be NULL if the FPU was not enabled at the time the -// trap was taken. -// - - /* +0x010 */ PVOID VfpState; - -// -// Volatile registers -// - ULONG64 R[19]; - ULONG64 Tp; - ULONG64 Sp; - ULONG64 Fp; - ULONG64 Ra; - ULONG64 Pc; - -} LOONGARCH64_KTRAP_FRAME, *PLOONGARCH64_KTRAP_FRAME; - -typedef struct _LOONGARCH64_VFP_STATE -{ - struct _LOONGARCH64_VFP_STATE *Link; // link to next state entry - ULONG Fcsr; // FCSR register - ULONG64 F[32]; // All F registers (0-31) -} LOONGARCH64_VFP_STATE, *PLOONGARCH64_VFP_STATE, KLOONGARCH64_VFP_STATE, *PKLOONGARCH64_VFP_STATE; - -// -// Parameters describing the unwind codes. -// - -#define STATUS_UNWIND_UNSUPPORTED_VERSION STATUS_UNSUCCESSFUL -#define STATUS_UNWIND_NOT_IN_FUNCTION STATUS_UNSUCCESSFUL -#define STATUS_UNWIND_INVALID_SEQUENCE STATUS_UNSUCCESSFUL - -// -// Macros for accessing memory. These can be overridden if other code -// (in particular the debugger) needs to use them. - -#define MEMORY_READ_BYTE(params, addr) (*dac_cast(addr)) -#define MEMORY_READ_DWORD(params, addr) (*dac_cast(addr)) -#define MEMORY_READ_QWORD(params, addr) (*dac_cast(addr)) - -typedef struct _LOONGARCH64_UNWIND_PARAMS -{ - PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers; -} LOONGARCH64_UNWIND_PARAMS, *PLOONGARCH64_UNWIND_PARAMS; - - -#define UNWIND_PARAMS_SET_TRAP_FRAME(Params, Address, Size) -#define UPDATE_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ -do { \ - if (ARGUMENT_PRESENT(Params)) { \ - PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ - if (ARGUMENT_PRESENT(ContextPointers)) { \ - if (RegisterNumber == 22) \ - ContextPointers->Fp = (PDWORD64)Address; \ - else if (RegisterNumber >= 23 && RegisterNumber <= 31) { \ - (&ContextPointers->S0)[RegisterNumber - 23] = (PDWORD64)Address; \ - } \ - } \ - } \ -} while (0) - - -#define UPDATE_FP_CONTEXT_POINTERS(Params, RegisterNumber, Address) \ -do { \ - if (ARGUMENT_PRESENT(Params)) { \ - PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers = (Params)->ContextPointers; \ - if (ARGUMENT_PRESENT(ContextPointers) && \ - (RegisterNumber >= 24) && \ - (RegisterNumber <= 31)) { \ - \ - (&ContextPointers->F24)[RegisterNumber - 24] = (PDWORD64)Address; \ - } \ - } \ -} while (0) - -#define VALIDATE_STACK_ADDRESS_EX(Params, Context, Address, DataSize, Alignment, OutStatus) -#define VALIDATE_STACK_ADDRESS(Params, Context, DataSize, Alignment, OutStatus) - -// -// Macros to clarify opcode parsing -// - -#define OPCODE_IS_END(Op) (((Op) & 0xfe) == 0xe4) - -// -// This table describes the size of each unwind code, in bytes -// - -static const BYTE UnwindCodeSizeTable[256] = -{ - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2, 3,2,2,2,3,2,2,2, 3,2,2,2,2,2,3,2, 3,2,3,2,3,2,2,2, - 4,1,3,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1 -}; - -NTSTATUS -RtlpUnwindCustom( - __inout PT_CONTEXT ContextRecord, - __in BYTE Opcode, - __in PLOONGARCH64_UNWIND_PARAMS UnwindParams - ) - -/*++ - -Routine Description: - - Handles custom unwinding operations involving machine-specific - frames. - -Arguments: - - ContextRecord - Supplies the address of a context record. - - Opcode - The opcode to decode. - - UnwindParams - Additional parameters shared with caller. - -Return Value: - - An NTSTATUS indicating either STATUS_SUCCESS if everything went ok, or - another status code if there were problems. - ---*/ - -{ - ULONG Fcsr; - ULONG RegIndex; - ULONG_PTR SourceAddress; - ULONG_PTR StartingSp; - NTSTATUS Status; - ULONG_PTR VfpStateAddress; - - StartingSp = ContextRecord->Sp; - Status = STATUS_SUCCESS; - - // - // The opcode describes the special-case stack - // - - switch (Opcode) - { - - // - // Trap frame case - // - - case 0xe8: // MSFT_OP_TRAP_FRAME: - - // - // Ensure there is enough valid space for the trap frame - // - - VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, sizeof(LOONGARCH64_KTRAP_FRAME), 16, &Status); - if (!NT_SUCCESS(Status)) { - return Status; - } - - // - // Restore R0-R15, and F0-F32 - // - SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, R); - for (RegIndex = 0; RegIndex < 16; RegIndex++) { - UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); -#ifdef __GNUC__ - *(&ContextRecord->R0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); -#else - ContextRecord->R[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); -#endif - SourceAddress += sizeof(ULONG_PTR); - } - - SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, VfpState); - VfpStateAddress = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - if (VfpStateAddress != 0) { - - SourceAddress = VfpStateAddress + FIELD_OFFSET(KLOONGARCH64_VFP_STATE, Fcsr); - Fcsr = MEMORY_READ_DWORD(UnwindParams, SourceAddress); - if (Fcsr != (ULONG)-1) { - - ContextRecord->Fcsr = Fcsr; - - SourceAddress = VfpStateAddress + FIELD_OFFSET(KLOONGARCH64_VFP_STATE, F); - for (RegIndex = 0; RegIndex < 32; RegIndex++) { - UPDATE_FP_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); - ContextRecord->F[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - SourceAddress += 2 * sizeof(ULONGLONG); - } - } - } - - // - // Restore SP, RA, PC, and the status registers - // - - //SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Tp);//TP - //ContextRecord->Tp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Sp); - ContextRecord->Sp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Fp); - ContextRecord->Fp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Ra); - ContextRecord->Ra = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - SourceAddress = StartingSp + FIELD_OFFSET(LOONGARCH64_KTRAP_FRAME, Pc); - ContextRecord->Pc = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - // - // Set the trap frame and clear the unwound-to-call flag - // - - UNWIND_PARAMS_SET_TRAP_FRAME(UnwindParams, StartingSp, sizeof(LOONGARCH64_KTRAP_FRAME)); - ContextRecord->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL; - break; - - // - // Context case - // - - case 0xea: // MSFT_OP_CONTEXT: - - // - // Ensure there is enough valid space for the full CONTEXT structure - // - - VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, sizeof(CONTEXT), 16, &Status); - if (!NT_SUCCESS(Status)) { - return Status; - } - - // - // Restore R0-R23, and F0-F31 - // - - SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, R0); - for (RegIndex = 0; RegIndex < 23; RegIndex++) { - UPDATE_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); -#ifdef __GNUC__ - *(&ContextRecord->R0 + RegIndex) = MEMORY_READ_QWORD(UnwindParams, SourceAddress); -#else - ContextRecord->R[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); -#endif - SourceAddress += sizeof(ULONG_PTR); - } - - SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, F); - for (RegIndex = 0; RegIndex < 32; RegIndex++) { - UPDATE_FP_CONTEXT_POINTERS(UnwindParams, RegIndex, SourceAddress); - ContextRecord->F[RegIndex] = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - SourceAddress += 2 * sizeof(ULONGLONG); - } - - // - // Restore SP, RA, PC, and the status registers - // - - SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Fp); - ContextRecord->Fp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Sp); - ContextRecord->Sp = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Pc); - ContextRecord->Pc = MEMORY_READ_QWORD(UnwindParams, SourceAddress); - - SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, Fcsr); - ContextRecord->Fcsr = MEMORY_READ_DWORD(UnwindParams, SourceAddress); - - // - // Inherit the unwound-to-call flag from this context - // - - SourceAddress = StartingSp + FIELD_OFFSET(T_CONTEXT, ContextFlags); - ContextRecord->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL; - ContextRecord->ContextFlags |= - MEMORY_READ_DWORD(UnwindParams, SourceAddress) & CONTEXT_UNWOUND_TO_CALL; - break; - - default: - return STATUS_UNSUCCESSFUL; - } - - return STATUS_SUCCESS; -} - -ULONG -RtlpComputeScopeSize( - __in ULONG_PTR UnwindCodePtr, - __in ULONG_PTR UnwindCodesEndPtr, - __in BOOLEAN IsEpilog, - __in PLOONGARCH64_UNWIND_PARAMS UnwindParams - ) - -/*++ - -Routine Description: - - Computes the size of an prolog or epilog, in words. - -Arguments: - - UnwindCodePtr - Supplies a pointer to the start of the unwind - code sequence. - - UnwindCodesEndPtr - Supplies a pointer to the byte immediately - following the unwind code table, as described by the header. - - IsEpilog - Specifies TRUE if the scope describes an epilog, - or FALSE if it describes a prolog. - - UnwindParams - Additional parameters shared with caller. - -Return Value: - - The size of the scope described by the unwind codes, in halfword units. - ---*/ - -{ - ULONG ScopeSize; - BYTE Opcode; - - // - // Iterate through the unwind codes until we hit an end marker. - // While iterating, accumulate the total scope size. - // - - ScopeSize = 0; - Opcode = 0; - while (UnwindCodePtr < UnwindCodesEndPtr) { - Opcode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - if (OPCODE_IS_END(Opcode)) { - break; - } - - UnwindCodePtr += UnwindCodeSizeTable[Opcode]; - ScopeSize++; - } - - // - // Epilogs have one extra instruction at the end that needs to be - // accounted for. - // - - if (IsEpilog) { - ScopeSize++; - } - - return ScopeSize; -} - -NTSTATUS -RtlpUnwindRestoreRegisterRange( - __inout PT_CONTEXT ContextRecord, - __in LONG SpOffset, - __in ULONG FirstRegister, - __in ULONG RegisterCount, - __in PLOONGARCH64_UNWIND_PARAMS UnwindParams - ) - -/*++ - -Routine Description: - - Restores a series of integer registers from the stack. - -Arguments: - - ContextRecord - Supplies the address of a context record. - - SpOffset - Specifies a stack offset. Positive values are simply used - as a base offset. Negative values assume a predecrement behavior: - a 0 offset is used for restoration, but the absoute value of the - offset is added to the final Sp. - - FirstRegister - Specifies the index of the first register to restore. - - RegisterCount - Specifies the number of registers to restore. - - UnwindParams - Additional parameters shared with caller. - -Return Value: - - None. - ---*/ - -{ - ULONG_PTR CurAddress; - ULONG RegIndex; - NTSTATUS Status; - - // - // Compute the source address and validate it. - // - - CurAddress = ContextRecord->Sp; - if (SpOffset >= 0) { - CurAddress += SpOffset; - } - - Status = STATUS_SUCCESS; - VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, 8 * RegisterCount, 8, &Status); - if (Status != STATUS_SUCCESS) { - return Status; - } - - // - // Restore the registers - // - for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { - UPDATE_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); -#ifdef __GNUC__ - *(&ContextRecord->R0 + FirstRegister + RegIndex) = MEMORY_READ_QWORD(UnwindParams, CurAddress); -#else - ContextRecord->R[FirstRegister + RegIndex] = MEMORY_READ_QWORD(UnwindParams, CurAddress); -#endif - CurAddress += 8; - } - if (SpOffset < 0) { - ContextRecord->Sp -= SpOffset; - } - - return STATUS_SUCCESS; -} - -NTSTATUS -RtlpUnwindRestoreFpRegisterRange( - __inout PT_CONTEXT ContextRecord, - __in LONG SpOffset, - __in ULONG FirstRegister, - __in ULONG RegisterCount, - __in PLOONGARCH64_UNWIND_PARAMS UnwindParams - ) - -/*++ - -Routine Description: - - Restores a series of floating-point registers from the stack. - -Arguments: - - ContextRecord - Supplies the address of a context record. - - SpOffset - Specifies a stack offset. Positive values are simply used - as a base offset. Negative values assume a predecrement behavior: - a 0 offset is used for restoration, but the absoute value of the - offset is added to the final Sp. - - FirstRegister - Specifies the index of the first register to restore. - - RegisterCount - Specifies the number of registers to restore. - - UnwindParams - Additional parameters shared with caller. - -Return Value: - - None. - ---*/ - -{ - ULONG_PTR CurAddress; - ULONG RegIndex; - NTSTATUS Status; - - // - // Compute the source address and validate it. - // - - CurAddress = ContextRecord->Sp; - if (SpOffset >= 0) { - CurAddress += SpOffset; - } - - Status = STATUS_SUCCESS; - VALIDATE_STACK_ADDRESS(UnwindParams, ContextRecord, 8 * RegisterCount, 8, &Status); - if (Status != STATUS_SUCCESS) { - return Status; - } - - // - // Restore the registers - // - - for (RegIndex = 0; RegIndex < RegisterCount; RegIndex++) { - UPDATE_FP_CONTEXT_POINTERS(UnwindParams, FirstRegister + RegIndex, CurAddress); - ContextRecord->F[FirstRegister + RegIndex] = MEMORY_READ_QWORD(UnwindParams, CurAddress); - CurAddress += 8; - } - if (SpOffset < 0) { - ContextRecord->Sp -= SpOffset; - } - - return STATUS_SUCCESS; -} - -NTSTATUS -RtlpUnwindFunctionFull( - __in DWORD64 ControlPcRva, - __in ULONG_PTR ImageBase, - __in PT_RUNTIME_FUNCTION FunctionEntry, - __inout T_CONTEXT *ContextRecord, - __out PDWORD64 EstablisherFrame, - __deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine, - __out PVOID *HandlerData, - __in PLOONGARCH64_UNWIND_PARAMS UnwindParams - ) - -/*++ - -Routine Description: - - This function virtually unwinds the specified function by parsing the - .xdata record to determine where in the function the provided ControlPc - is, and then executing unwind codes that map to the function's prolog - or epilog behavior. - - If a context pointers record is specified (in the UnwindParams), then - the address where each nonvolatile register is restored from is recorded - in the appropriate element of the context pointers record. - -Arguments: - - ControlPcRva - Supplies the address where control left the specified - function, as an offset relative to the IamgeBase. - - ImageBase - Supplies the base address of the image that contains the - function being unwound. - - FunctionEntry - Supplies the address of the function table entry for the - specified function. If appropriate, this should have araeady been - probed. - - ContextRecord - Supplies the address of a context record. - - EstablisherFrame - Supplies a pointer to a variable that receives the - the establisher frame pointer value. - - HandlerRoutine - Supplies an optional pointer to a variable that receives - the handler routine address. If control did not leave the specified - function in either the prolog or an epilog and a handler of the - proper type is associated with the function, then the address of the - language specific exception handler is returned. Otherwise, NULL is - returned. - - HandlerData - Supplies a pointer to a variable that receives a pointer - the the language handler data. - - UnwindParams - Additional parameters shared with caller. - -Return Value: - - STATUS_SUCCESS if the unwind could be completed, a failure status otherwise. - Unwind can only fail when validation bounds are specified. - ---*/ - -{ - ULONG AccumulatedSaveNexts; - ULONG CurCode; - ULONG EpilogScopeCount; - PEXCEPTION_ROUTINE ExceptionHandler; - PVOID ExceptionHandlerData; - BOOLEAN FinalPcFromRa; - ULONG FunctionLength; - ULONG HeaderWord; - ULONG NextCode, NextCode1, NextCode2; - DWORD64 OffsetInFunction; - ULONG ScopeNum; - ULONG ScopeSize; - ULONG ScopeStart; - DWORD64 SkipWords; - NTSTATUS Status; - ULONG_PTR UnwindCodePtr; - ULONG_PTR UnwindCodesEndPtr; - ULONG_PTR UnwindDataPtr; - ULONG UnwindIndex; - ULONG UnwindWords; - - // - // Unless a special frame is enountered, assume that any unwinding - // will return us to the return address of a call and set the flag - // appropriately (it will be cleared again if the special cases apply). - // - - ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; - - // - // By default, unwinding is done by popping to the RA, then copying - // that RA to the PC. However, some special opcodes require different - // behavior. - // - - FinalPcFromRa = TRUE; - - // - // Fetch the header word from the .xdata blob - // - - UnwindDataPtr = ImageBase + FunctionEntry->UnwindData; - HeaderWord = MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr); - UnwindDataPtr += 4; - - // - // Verify the version before we do anything else - // - - if (((HeaderWord >> 18) & 3) != 0) { - assert(!"ShouldNotReachHere"); - return STATUS_UNWIND_UNSUPPORTED_VERSION; - } - - FunctionLength = HeaderWord & 0x3ffff; - OffsetInFunction = (ControlPcRva - FunctionEntry->BeginAddress) / 4; - - // - // Determine the number of epilog scope records and the maximum number - // of unwind codes. - // - - UnwindWords = (HeaderWord >> 27) & 31; - EpilogScopeCount = (HeaderWord >> 22) & 31; - if (EpilogScopeCount == 0 && UnwindWords == 0) { - EpilogScopeCount = MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr); - UnwindDataPtr += 4; - UnwindWords = (EpilogScopeCount >> 16) & 0xff; - EpilogScopeCount &= 0xffff; - } - if ((HeaderWord & (1 << 21)) != 0) { - UnwindIndex = EpilogScopeCount; - EpilogScopeCount = 0; - } - - // - // If exception data is present, extract it now. - // - - ExceptionHandler = NULL; - ExceptionHandlerData = NULL; - if ((HeaderWord & (1 << 20)) != 0) { - ExceptionHandler = (PEXCEPTION_ROUTINE)(ImageBase + - MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr + 4 * (EpilogScopeCount + UnwindWords))); - ExceptionHandlerData = (PVOID)(UnwindDataPtr + 4 * (EpilogScopeCount + UnwindWords + 1)); - } - - // - // Unless we are in a prolog/epilog, we execute the unwind codes - // that immediately follow the epilog scope list. - // - - UnwindCodePtr = UnwindDataPtr + 4 * EpilogScopeCount; - UnwindCodesEndPtr = UnwindCodePtr + 4 * UnwindWords; - SkipWords = 0; - - // - // If we're near the start of the function, and this function has a prolog, - // compute the size of the prolog from the unwind codes. If we're in the - // midst of it, we still execute starting at unwind code index 0, but we may - // need to skip some to account for partial execution of the prolog. - // - // N.B. As an optimization here, note that each byte of unwind codes can - // describe at most one 32-bit instruction. Thus, the largest prologue - // that could possibly be described by UnwindWords (which is 4 * the - // number of unwind code bytes) is 4 * UnwindWords words. If - // OffsetInFunction is larger than this value, it is guaranteed to be - // in the body of the function. - // - - if (OffsetInFunction < 4 * UnwindWords) { - ScopeSize = RtlpComputeScopeSize(UnwindCodePtr, UnwindCodesEndPtr, FALSE, UnwindParams); - - if (OffsetInFunction < ScopeSize) { - SkipWords = ScopeSize - OffsetInFunction; - ExceptionHandler = NULL; - ExceptionHandlerData = NULL; - goto ExecuteCodes; - } - } - - // - // We're not in the prolog, now check to see if we are in the epilog. - // In the simple case, the 'E' bit is set indicating there is a single - // epilog that lives at the end of the function. If we're near the end - // of the function, compute the actual size of the epilog from the - // unwind codes. If we're in the midst of it, adjust the unwind code - // pointer to the start of the codes and determine how many we need to skip. - // - // N.B. Similar to the prolog case above, the maximum number of halfwords - // that an epilog can cover is limited by UnwindWords. In the epilog - // case, however, the starting index within the unwind code table is - // non-zero, and so the maximum number of unwind codes that can pertain - // to an epilog is (UnwindWords * 4 - UnwindIndex), thus further - // constraining the bounds of the epilog. - // - - if ((HeaderWord & (1 << 21)) != 0) { - if (OffsetInFunction + (4 * UnwindWords - UnwindIndex) >= FunctionLength) { - ScopeSize = RtlpComputeScopeSize(UnwindCodePtr + UnwindIndex, UnwindCodesEndPtr, TRUE, UnwindParams); - ScopeStart = FunctionLength - ScopeSize; - - if (OffsetInFunction >= ScopeStart) { - UnwindCodePtr += UnwindIndex; - SkipWords = OffsetInFunction - ScopeStart; - ExceptionHandler = NULL; - ExceptionHandlerData = NULL; - } - } - } - - // - // In the multiple-epilog case, we scan forward to see if we are within - // shooting distance of any of the epilogs. If we are, we compute the - // actual size of the epilog from the unwind codes and proceed like the - // simple case above. - // - - else { - for (ScopeNum = 0; ScopeNum < EpilogScopeCount; ScopeNum++) { - HeaderWord = MEMORY_READ_DWORD(UnwindParams, UnwindDataPtr); - UnwindDataPtr += 4; - - // - // The scope records are stored in order. If we hit a record that - // starts after our current position, we must not be in an epilog. - // - - ScopeStart = HeaderWord & 0x3ffff; - if (OffsetInFunction < ScopeStart) { - break; - } - - UnwindIndex = HeaderWord >> 22; - if (OffsetInFunction < ScopeStart + (4 * UnwindWords - UnwindIndex)) { - ScopeSize = RtlpComputeScopeSize(UnwindCodePtr + UnwindIndex, UnwindCodesEndPtr, TRUE, UnwindParams); - - if (OffsetInFunction < ScopeStart + ScopeSize) { - - UnwindCodePtr += UnwindIndex; - SkipWords = OffsetInFunction - ScopeStart; - ExceptionHandler = NULL; - ExceptionHandlerData = NULL; - break; - } - } - } - } - -ExecuteCodes: - - // - // Skip over unwind codes until we account for the number of halfwords - // to skip. - // - - while (UnwindCodePtr < UnwindCodesEndPtr && SkipWords > 0) { - CurCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - if (OPCODE_IS_END(CurCode)) { - break; - } - UnwindCodePtr += UnwindCodeSizeTable[CurCode]; - SkipWords--; - } - - // - // Now execute codes until we hit the end. - // - - Status = STATUS_SUCCESS; - AccumulatedSaveNexts = 0; - while (UnwindCodePtr < UnwindCodesEndPtr && Status == STATUS_SUCCESS) { - - CurCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr += 1; - - // - // alloc_s (000xxxxx): allocate small stack with size < 1024 (2^5 * 16) - // - - if (CurCode <= 0x1f) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - ContextRecord->Sp += 16 * (CurCode & 0x1f); - } - -#if 0 - // Not used for LOONGARCH!!! - // save_s0s1_x (001zzzzz): save pair at [sp-#Z*8]!, pre-indexed offset >= -248 - // - - else if (CurCode <= 0x3f) { - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - -8 * (CurCode & 0x1f), - 16, /* TODO for LOONGARCH64: reg is not 16 */ - 2 + 2 * AccumulatedSaveNexts, - UnwindParams); - AccumulatedSaveNexts = 0; - } - - // - // save_fpra (0100zzzz|zzzzzzzz): save pair at [sp+#Z*8], offset <= 32767 - // - - else if (CurCode <= 0x4f) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - 8 * (((CurCode & 0xf) << 8) + NextCode), - 30, /* TODO for LOONGARCH64: reg is not 30*/ - 2, - UnwindParams); - } - - // - // save_fpra_x (1000zzzz|zzzzzzzz): save pair at [sp-(#Z+1)*8]!, pre-indexed offset >= -32768 - // - - else if (CurCode <= 0x8f) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - -8 * (((CurCode & 0xf) << 8) + NextCode + 1), - 30, /* TODO for LOONGARCH64: reg is not 30*/ - 2, - UnwindParams); - } -#endif - - // - // alloc_m (11000xxx|xxxxxxxx): allocate large stack with size < 32k (2^11 * 16). - // - - else if (CurCode <= 0xc7) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - ContextRecord->Sp += 16 * ((CurCode & 7) << 8); - ContextRecord->Sp += 16 * MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - } -#if 0 - // Not used for LOONGARCH!!! - // save_regp (11001000|0xxxzzzz|zzzzzzzz): save r(16+#X) pair at [sp+#Z*8], offset <= 32767 - // - - else if (CurCode == 0xc8) { - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - 8 * (((NextCode & 0xf) << 8) + NextCode1), - 16 + (NextCode >> 4), - 2 + 2 * AccumulatedSaveNexts, - UnwindParams); - AccumulatedSaveNexts = 0; - } - - // - // save_regp_x (11001100|0xxxzzzz|zzzzzzzz): save pair r(16+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -32768 - // - - else if (CurCode == 0xcc) { - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - -8 * (((NextCode & 0xf) << 8) + NextCode1 + 1), - 16 + (NextCode >> 4), - 2 + 2 * AccumulatedSaveNexts, - UnwindParams); - AccumulatedSaveNexts = 0; - } -#endif - - // - // save_reg (11010000|000xxxxx|zzzzzzzz): save reg r(1+#X) at [sp+#Z*8], offset <= 2047 - // - - else if (CurCode == 0xd0) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = (uint8_t)MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - 8 * NextCode1, - 1 + NextCode, - 1, - UnwindParams); - } - -#if 0 - // Not used for LOONGARCH!!! - // save_reg_x (1101010x|xxxzzzzz): save reg r(16+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -256 - // - - else if (CurCode <= 0xd5) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - -8 * ((NextCode & 0x1f) + 1), - 16 + ((CurCode & 1) << 3) + (NextCode >> 5), - 1, - UnwindParams); - } - - // - // save_rapair (11010110|0xxxzzzz|zzzzzzzz): save pair at [sp+#Z*8], offset <= 32767 - // - - else if (CurCode == 0xd6) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - 8 * (((NextCode & 0xf) << 8) + NextCode1), - 16 + (NextCode >> 4), - 1, - UnwindParams); - if (Status == STATUS_SUCCESS) { - RtlpUnwindRestoreRegisterRange( - ContextRecord, - 8 + 8 * (((NextCode & 0xf) << 8) + NextCode1), - 31, - 1, - UnwindParams); - } - } - - // - // save_fregp (11011000|0xxxzzzz|zzzzzzzz): save pair f(24+#X) at [sp+#Z*8], offset <= 32767 - // - - else if (CurCode == 0xd8) { - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreFpRegisterRange( - ContextRecord, - 8 * (((NextCode & 0xf) << 8) + NextCode1), - 24 + (NextCode >> 4), - 2 + AccumulatedSaveNexts, - UnwindParams); - AccumulatedSaveNexts = 0; - } - - // - // save_fregp_x (11011010|0xxxzzzz|zzzzzzzz): save pair f(24+#X), at [sp-(#Z+1)*8]!, pre-indexed offset >= -32768 - // - - else if (CurCode == 0xda) { - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreFpRegisterRange( - ContextRecord, - -8 * (((NextCode & 0xf) << 8) + NextCode1 + 1), - 24 + (NextCode >> 4), - 2 + AccumulatedSaveNexts, - UnwindParams); - AccumulatedSaveNexts = 0; - } -#endif - - // - // save_freg (11011100|0xxxzzzz|zzzzzzzz): save reg f(24+#X) at [sp+#Z*8], offset <= 32767 - // - - else if (CurCode == 0xdc) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreFpRegisterRange( - ContextRecord, - 8 * (((NextCode & 0xf) << 8) + NextCode1), - 24 + (NextCode >> 4), - 1, - UnwindParams); - } - -#if 0 - // Not used for LOONGARCH!!! - // save_freg_x (11011110|xxxzzzzz): save reg f(24+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -256 - // - - else if (CurCode == 0xde) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - Status = RtlpUnwindRestoreFpRegisterRange( - ContextRecord, - -8 * ((NextCode & 0x1f) + 1), - 24 + (NextCode >> 5), - 1, - UnwindParams); - } -#endif - - // - // alloc_l (11100000|xxxxxxxx|xxxxxxxx|xxxxxxxx): allocate large stack with size < 256M - // - - else if (CurCode == 0xe0) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - ContextRecord->Sp += 16 * (MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr) << 16); - UnwindCodePtr++; - ContextRecord->Sp += 16 * (MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr) << 8); - UnwindCodePtr++; - ContextRecord->Sp += 16 * MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - } - - // - // set_fp (11100001): set up fp: with: ori fp,sp,0 - // - - else if (CurCode == 0xe1) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - ContextRecord->Sp = ContextRecord->Fp; - } - - // - // add_fp (11100010|000xxxxx|xxxxxxxx): set up fp with: addi.d fp,sp,#x*8 - // - - else if (CurCode == 0xe2) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - NextCode = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - NextCode1 = MEMORY_READ_BYTE(UnwindParams, UnwindCodePtr); - UnwindCodePtr++; - ContextRecord->Sp = ContextRecord->Fp - 8 * ((NextCode << 8) | NextCode1); - } - - // - // nop (11100011): no unwind operation is required - // - - else if (CurCode == 0xe3) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - } - - // - // end (11100100): end of unwind code - // - - else if (CurCode == 0xe4) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - goto finished; - } - - // - // end_c (11100101): end of unwind code in current chained scope - // - - else if (CurCode == 0xe5) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - goto finished; - } - -#if 0 - // Not used for LOONGARCH!!! - // save_next (11100110): save next non-volatile Int or FP register pair. - // - - else if (CurCode == 0xe6) { - AccumulatedSaveNexts++; - } -#endif - - // - // custom_0 (111010xx): restore custom structure - // - - else if (CurCode >= 0xe8 && CurCode <= 0xeb) { - if (AccumulatedSaveNexts != 0) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - Status = RtlpUnwindCustom(ContextRecord, (BYTE) CurCode, UnwindParams); - FinalPcFromRa = FALSE; - } - - // - // Anything else is invalid - // - - else { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - } - - // - // If we succeeded, post-process the results a bit - // -finished: - if (Status == STATUS_SUCCESS) { - - // - // Since we always POP to the RA, recover the final PC from there, unless - // it was overwritten due to a special case custom unwinding operation. - // Also set the establisher frame equal to the final stack pointer. - // - - if (FinalPcFromRa) { - ContextRecord->Pc = ContextRecord->Ra; - } - - *EstablisherFrame = ContextRecord->Sp; - - if (ARGUMENT_PRESENT(HandlerRoutine)) { - *HandlerRoutine = ExceptionHandler; - } - *HandlerData = ExceptionHandlerData; - } - - return Status; -} - -NTSTATUS -RtlpUnwindFunctionCompact( - __in DWORD64 ControlPcRva, - __in PT_RUNTIME_FUNCTION FunctionEntry, - __inout T_CONTEXT *ContextRecord, - __out PDWORD64 EstablisherFrame, - __deref_opt_out_opt PEXCEPTION_ROUTINE *HandlerRoutine, - __out PVOID *HandlerData, - __in PLOONGARCH64_UNWIND_PARAMS UnwindParams - ) - -/*++ - -Routine Description: - - This function virtually unwinds the specified function by parsing the - compact .pdata record to determine where in the function the provided - ControlPc is, and then executing a standard, well-defined set of - operations. - - If a context pointers record is specified (in the UnwindParams), then - the address where each nonvolatile register is restored from is recorded - in the appropriate element of the context pointers record. - -Arguments: - - ControlPcRva - Supplies the address where control left the specified - function, as an offset relative to the IamgeBase. - - FunctionEntry - Supplies the address of the function table entry for the - specified function. If appropriate, this should have araeady been - probed. - - ContextRecord - Supplies the address of a context record. - - EstablisherFrame - Supplies a pointer to a variable that receives the - the establisher frame pointer value. - - HandlerRoutine - Supplies an optional pointer to a variable that receives - the handler routine address. If control did not leave the specified - function in either the prolog or an epilog and a handler of the - proper type is associated with the function, then the address of the - language specific exception handler is returned. Otherwise, NULL is - returned. - - HandlerData - Supplies a pointer to a variable that receives a pointer - the the language handler data. - - UnwindParams - Additional parameters shared with caller. - -Return Value: - - STATUS_SUCCESS if the unwind could be completed, a failure status otherwise. - Unwind can only fail when validation bounds are specified. - ---*/ - -{ - ULONG Count; - ULONG Cr; - ULONG CurrentOffset; - ULONG EpilogLength; - ULONG Flag; - ULONG FloatSize; - ULONG FrameSize; - ULONG FRegOpcodes; - ULONG FunctionLength; - ULONG HBit; - ULONG HOpcodes; - ULONG IRegOpcodes; - ULONG IntSize; - ULONG LocalSize; - DWORD64 OffsetInFunction; - DWORD64 OffsetInScope; - ULONG PrologLength; - ULONG RegF; - ULONG RegI; - ULONG RegSize; - ULONG ScopeStart; - ULONG StackAdjustOpcodes; - NTSTATUS Status; - ULONG UnwindData; - - UnwindData = FunctionEntry->UnwindData; - Status = STATUS_SUCCESS; - - // - // Compact records always describe an unwind to a call. - // - - ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; - - // - // Extract the basic information about how to do a full unwind. - // - - Flag = UnwindData & 3; - FunctionLength = (UnwindData >> 2) & 0x7ff; - RegF = (UnwindData >> 13) & 7; - RegI = (UnwindData >> 16) & 0xf; - HBit = (UnwindData >> 20) & 1; - Cr = (UnwindData >> 21) & 3; - FrameSize = (UnwindData >> 23) & 0x1ff; - - assert(!"---------------LOONGARCH64 ShouldNotReachHere"); - if (Flag == 3) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - if (Cr == 2) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - - // - // Determine the size of the locals - // - - IntSize = RegI * 8; - if (Cr == 1) { - IntSize += 8; - } - FloatSize = (RegF == 0) ? 0 : (RegF + 1) * 8; - RegSize = (IntSize + FloatSize + 8*8 * HBit + 0xf) & ~0xf; - if (RegSize > 16 * FrameSize) { - return STATUS_UNWIND_INVALID_SEQUENCE; - } - LocalSize = 16 * FrameSize - RegSize; - - // - // If we're near the start of the function (within 17 words), - // see if we are within the prolog. - // - // N.B. If the low 2 bits of the UnwindData are 2, then we have - // no prolog. - // - - OffsetInFunction = (ControlPcRva - FunctionEntry->BeginAddress) / 4; - OffsetInScope = 0; - if (OffsetInFunction < 17 && Flag != 2) { - - // - // Compute sizes for each opcode in the prolog. - // - - IRegOpcodes = (IntSize + 8) / 16; - FRegOpcodes = (FloatSize + 8) / 16; - HOpcodes = 4 * HBit; - StackAdjustOpcodes = (Cr == 3) ? 1 : 0; - if (Cr != 3 || LocalSize > 512) {///TODO for LOONGARCH64: 512 is smaller than real! - StackAdjustOpcodes += (LocalSize > 4088) ? 2 : (LocalSize > 0) ? 1 : 0; - } - - // - // Compute the total prolog length and determine if we are within - // its scope. - // - // N.B. We must execute prolog operations backwards to unwind, so - // our final scope offset in this case is the distance from the end. - // - - PrologLength = IRegOpcodes + FRegOpcodes + HOpcodes + StackAdjustOpcodes; - - if (OffsetInFunction < PrologLength) { - OffsetInScope = PrologLength - OffsetInFunction; - } - } - - // - // If we're near the end of the function (within 15 words), see if - // we are within the epilog. - // - // N.B. If the low 2 bits of the UnwindData are 2, then we have - // no epilog. - // - - if (OffsetInScope == 0 && OffsetInFunction + 15 >= FunctionLength && Flag != 2) { - - // - // Compute sizes for each opcode in the epilog. - // - - IRegOpcodes = (IntSize + 8) / 16; - FRegOpcodes = (FloatSize + 8) / 16; - HOpcodes = HBit; - StackAdjustOpcodes = (Cr == 3) ? 1 : 0; - if (Cr != 3 || LocalSize > 512) {///TODO for LOONGARCH64: 512 is smaller than real! - StackAdjustOpcodes += (LocalSize > 4088) ? 2 : (LocalSize > 0) ? 1 : 0; - } - - // - // Compute the total epilog length and determine if we are within - // its scope. - // - - EpilogLength = IRegOpcodes + FRegOpcodes + HOpcodes + StackAdjustOpcodes + 1; - - ScopeStart = FunctionLength - EpilogLength; - if (OffsetInFunction > ScopeStart) { - OffsetInScope = OffsetInFunction - ScopeStart; - } - } - - // - // Process operations backwards, in the order: stack/frame deallocation, - // VFP register popping, integer register popping, parameter home - // area recovery. - // - // First case is simple: we process everything with no regard for - // the current offset within the scope. - // - - Status = STATUS_SUCCESS; - if (OffsetInScope == 0) { - - if (Cr == 3) { - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, 0, 22, 1, UnwindParams);///fp - assert(Status == STATUS_SUCCESS); - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, 0, 1, 1, UnwindParams);//ra - } - ContextRecord->Sp += LocalSize; - - if (RegF != 0 && Status == STATUS_SUCCESS) { - Status = RtlpUnwindRestoreFpRegisterRange(ContextRecord, IntSize, 24, RegF + 1, UnwindParams);//fs0 - } - - if (Cr == 1 && Status == STATUS_SUCCESS) { - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 8, 1, 1, UnwindParams);//ra - } - if (RegI > 0 && Status == STATUS_SUCCESS) { - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, 0, 23, RegI, UnwindParams);//s0 - } - ContextRecord->Sp += RegSize; - } - - // - // Second case is more complex: we must step along each operation - // to ensure it should be executed. - // - - else { - - CurrentOffset = 0; - if (Cr == 3) { - if (LocalSize <= 512) {///TODO for LOONGARCH64: 512 is smaller! - if (CurrentOffset++ >= OffsetInScope) { - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, -(LONG)LocalSize, 22, 1, UnwindParams); - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, -(LONG)LocalSize, 1, 1, UnwindParams); - } - LocalSize = 0; - } - } - while (LocalSize != 0) { - Count = (LocalSize + 4087) % 4088 + 1;///TODO: should amend the LOONGARCH64 ! - if (CurrentOffset++ >= OffsetInScope) { - ContextRecord->Sp += Count; - } - LocalSize -= Count; - } - - if (HBit != 0) { - CurrentOffset += 4; - } - - if (RegF != 0 && Status == STATUS_SUCCESS) { - RegF++; - while (RegF != 0) { - Count = 2 - (RegF & 1); - RegF -= Count; - if (CurrentOffset++ >= OffsetInScope) { - Status = RtlpUnwindRestoreFpRegisterRange( - ContextRecord, - (RegF == 0 && RegI == 0) ? (-(LONG)RegSize) : (IntSize + 8 * RegF), - 24 + RegF, - Count, - UnwindParams); - } - } - } - - if (Cr == 1 && Status == STATUS_SUCCESS) { - if (RegI % 2 == 0) { - if (CurrentOffset++ >= OffsetInScope) { - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 8, 31, 1, UnwindParams);//s8 ? - } - } else { - if (CurrentOffset++ >= OffsetInScope) { - RegI--; - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 8, 2, 1, UnwindParams);//tp ? - if (Status == STATUS_SUCCESS) { - Status = RtlpUnwindRestoreRegisterRange(ContextRecord, IntSize - 16, 23 + RegI, 1, UnwindParams); - } - } - } - } - - while (RegI != 0 && Status == STATUS_SUCCESS) { - Count = 2 - (RegI & 1); - RegI -= Count; - if (CurrentOffset++ >= OffsetInScope) { - Status = RtlpUnwindRestoreRegisterRange( - ContextRecord, - (RegI == 0) ? (-(LONG)RegSize) : (8 * RegI), - 23 + RegI, - Count, - UnwindParams); - } - } - } - - // - // If we succeeded, post-process the results a bit - // - - if (Status == STATUS_SUCCESS) { - - ContextRecord->Pc = ContextRecord->Ra; - *EstablisherFrame = ContextRecord->Sp; - - if (ARGUMENT_PRESENT(HandlerRoutine)) { - *HandlerRoutine = NULL; - } - *HandlerData = NULL; - } - - return Status; -} - -BOOL OOPStackUnwinderLoongarch64::Unwind(T_CONTEXT * pContext) -{ - DWORD64 ImageBase = 0; - HRESULT hr = GetModuleBase(pContext->Pc, &ImageBase); - if (hr != S_OK) - return FALSE; - - PEXCEPTION_ROUTINE DummyHandlerRoutine; - PVOID DummyHandlerData; - DWORD64 DummyEstablisherFrame; - - DWORD64 startingPc = pContext->Pc; - DWORD64 startingSp = pContext->Sp; - - T_RUNTIME_FUNCTION Rfe; - if (FAILED(GetFunctionEntry(pContext->Pc, &Rfe, sizeof(Rfe)))) - return FALSE; - - if ((Rfe.UnwindData & 3) != 0) - { - hr = RtlpUnwindFunctionCompact(pContext->Pc - ImageBase, - &Rfe, - pContext, - &DummyEstablisherFrame, - &DummyHandlerRoutine, - &DummyHandlerData, - NULL); - - } - else - { - hr = RtlpUnwindFunctionFull(pContext->Pc - ImageBase, - ImageBase, - &Rfe, - pContext, - &DummyEstablisherFrame, - &DummyHandlerRoutine, - &DummyHandlerData, - NULL); - } - - // PC == 0 means unwinding is finished. - // Same if no forward progress is made - if (pContext->Pc == 0 || (startingPc == pContext->Pc && startingSp == pContext->Sp)) - return FALSE; - - return TRUE; -} - -BOOL DacUnwindStackFrame(T_CONTEXT *pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers) -{ - OOPStackUnwinderLoongarch64 unwinder; - BOOL res = unwinder.Unwind(pContext); - - if (res && pContextPointers) - { - for (int i = 0; i < 9; i++) - { - *(&pContextPointers->S0 + i) = &pContext->S0 + i; - } - pContextPointers->Fp = &pContext->Fp; - pContextPointers->Ra = &pContext->Ra; - } - - return res; -} - -#if defined(HOST_UNIX) -PEXCEPTION_ROUTINE -RtlVirtualUnwind( - IN ULONG HandlerType, - IN ULONG64 ImageBase, - IN ULONG64 ControlPc, - IN PT_RUNTIME_FUNCTION FunctionEntry, - IN OUT PCONTEXT ContextRecord, - OUT PVOID *HandlerData, - OUT PULONG64 EstablisherFrame, - IN OUT PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL - ) -{ - PEXCEPTION_ROUTINE handlerRoutine; - HRESULT hr; - - DWORD64 startingPc = ControlPc; - DWORD64 startingSp = ContextRecord->Sp; - - T_RUNTIME_FUNCTION rfe; - - rfe.BeginAddress = FunctionEntry->BeginAddress; - rfe.UnwindData = FunctionEntry->UnwindData; - - LOONGARCH64_UNWIND_PARAMS unwindParams; - unwindParams.ContextPointers = ContextPointers; - - if ((rfe.UnwindData & 3) != 0) - { - hr = RtlpUnwindFunctionCompact(ControlPc - ImageBase, - &rfe, - ContextRecord, - EstablisherFrame, - &handlerRoutine, - HandlerData, - &unwindParams); - - } - else - { - hr = RtlpUnwindFunctionFull(ControlPc - ImageBase, - ImageBase, - &rfe, - ContextRecord, - EstablisherFrame, - &handlerRoutine, - HandlerData, - &unwindParams); - } - - return handlerRoutine; -} -#endif diff --git a/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h b/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h deleted file mode 100644 index 2b309a4a6f5fa1..00000000000000 --- a/src/coreclr/unwinder/loongarch64/unwinder_loongarch64.h +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. - -// - -#ifndef __unwinder_loongarch64__ -#define __unwinder_loongarch64__ - -#include "unwinder.h" - -//--------------------------------------------------------------------------------------- -// -// See the comment for the base class code:OOPStackUnwinder. -// - -class OOPStackUnwinderLoongarch64 : public OOPStackUnwinder -{ -public: - // Unwind the given CONTEXT to the caller CONTEXT. The CONTEXT will be overwritten. - BOOL Unwind(T_CONTEXT * pContext); - - // - // Everything below comes from dbghelp.dll. - // - -protected: - HRESULT UnwindPrologue(__in DWORD64 ImageBase, - __in DWORD64 ControlPc, - __in DWORD64 FrameBase, - __in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, - __inout PT_CONTEXT ContextRecord); - - HRESULT VirtualUnwind(__in DWORD64 ImageBase, - __in DWORD64 ControlPc, - __in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, - __inout PT_CONTEXT ContextRecord, - __out PDWORD64 EstablisherFrame); - - DWORD64 LookupPrimaryUnwindInfo - (__in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, - __in DWORD64 ImageBase, - __out _PIMAGE_RUNTIME_FUNCTION_ENTRY PrimaryEntry); - - _PIMAGE_RUNTIME_FUNCTION_ENTRY SameFunction - (__in _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionEntry, - __in DWORD64 ImageBase, - __in DWORD64 ControlPc, - __out _PIMAGE_RUNTIME_FUNCTION_ENTRY FunctionReturnBuffer); -}; - -#endif // __unwinder_loongarch64__ From 80b233a7f38d582874ef90c36182de8d15a47c8c Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Thu, 13 Jan 2022 12:11:03 +0800 Subject: [PATCH 08/11] [LoongArch64] rename the `UNW_LOONGARCH_*` with `UNW_LOONGARCH64_*` --- .../pal/src/exception/remote-unwind.cpp | 74 +++++++++---------- src/coreclr/pal/src/exception/seh-unwind.cpp | 48 ++++++------ 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp index 97efcd3d09ea87..e8f3ac005e4dd4 100644 --- a/src/coreclr/pal/src/exception/remote-unwind.cpp +++ b/src/coreclr/pal/src/exception/remote-unwind.cpp @@ -1684,18 +1684,18 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_AARCH64_X28, &contextPointers->X28); GetContextPointer(cursor, unwContext, UNW_AARCH64_X29, &contextPointers->Fp); #elif defined(TARGET_LOONGARCH64) - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R1, &contextPointers->Ra); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R2, &contextPointers->Tp); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R22, &contextPointers->Fp); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R23, &contextPointers->S0); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R24, &contextPointers->S1); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R25, &contextPointers->S2); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R26, &contextPointers->S3); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R27, &contextPointers->S4); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R28, &contextPointers->S5); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R29, &contextPointers->S6); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R30, &contextPointers->S7); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R31, &contextPointers->S8); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R1, &contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R2, &contextPointers->Tp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R22, &contextPointers->Fp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R23, &contextPointers->S0); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R24, &contextPointers->S1); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R25, &contextPointers->S2); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R26, &contextPointers->S3); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R27, &contextPointers->S4); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R28, &contextPointers->S5); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R29, &contextPointers->S6); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R30, &contextPointers->S7); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R31, &contextPointers->S8); #elif defined(TARGET_S390X) GetContextPointer(cursor, unwContext, UNW_S390X_R6, &contextPointers->R6); GetContextPointer(cursor, unwContext, UNW_S390X_R7, &contextPointers->R7); @@ -1768,18 +1768,18 @@ static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) #elif defined(TARGET_LOONGARCH64) unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); - unw_get_reg(cursor, UNW_LOONGARCH_R1, (unw_word_t *) &winContext->Ra); - unw_get_reg(cursor, UNW_LOONGARCH_R2, (unw_word_t *) &winContext->Tp); - unw_get_reg(cursor, UNW_LOONGARCH_R22, (unw_word_t *) &winContext->Fp); - unw_get_reg(cursor, UNW_LOONGARCH_R23, (unw_word_t *) &winContext->S0); - unw_get_reg(cursor, UNW_LOONGARCH_R24, (unw_word_t *) &winContext->S1); - unw_get_reg(cursor, UNW_LOONGARCH_R25, (unw_word_t *) &winContext->S2); - unw_get_reg(cursor, UNW_LOONGARCH_R26, (unw_word_t *) &winContext->S3); - unw_get_reg(cursor, UNW_LOONGARCH_R27, (unw_word_t *) &winContext->S4); - unw_get_reg(cursor, UNW_LOONGARCH_R28, (unw_word_t *) &winContext->S5); - unw_get_reg(cursor, UNW_LOONGARCH_R29, (unw_word_t *) &winContext->S6); - unw_get_reg(cursor, UNW_LOONGARCH_R30, (unw_word_t *) &winContext->S7); - unw_get_reg(cursor, UNW_LOONGARCH_R31, (unw_word_t *) &winContext->S8); + unw_get_reg(cursor, UNW_LOONGARCH64_R1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_LOONGARCH64_R2, (unw_word_t *) &winContext->Tp); + unw_get_reg(cursor, UNW_LOONGARCH64_R22, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_LOONGARCH64_R23, (unw_word_t *) &winContext->S0); + unw_get_reg(cursor, UNW_LOONGARCH64_R24, (unw_word_t *) &winContext->S1); + unw_get_reg(cursor, UNW_LOONGARCH64_R25, (unw_word_t *) &winContext->S2); + unw_get_reg(cursor, UNW_LOONGARCH64_R26, (unw_word_t *) &winContext->S3); + unw_get_reg(cursor, UNW_LOONGARCH64_R27, (unw_word_t *) &winContext->S4); + unw_get_reg(cursor, UNW_LOONGARCH64_R28, (unw_word_t *) &winContext->S5); + unw_get_reg(cursor, UNW_LOONGARCH64_R29, (unw_word_t *) &winContext->S6); + unw_get_reg(cursor, UNW_LOONGARCH64_R30, (unw_word_t *) &winContext->S7); + unw_get_reg(cursor, UNW_LOONGARCH64_R31, (unw_word_t *) &winContext->S8); TRACE("sp %p pc %p fp %p tp %p ra %p\n", winContext->Sp, winContext->Pc, winContext->Fp, winContext->Tp, winContext->Ra); #elif defined(TARGET_S390X) unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->PSWAddr); @@ -1883,19 +1883,19 @@ access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write case UNW_AARCH64_SP: *valp = (unw_word_t)winContext->Sp; break; case UNW_AARCH64_PC: *valp = (unw_word_t)winContext->Pc; break; #elif defined(TARGET_LOONGARCH64) - case UNW_LOONGARCH_R1: *valp = (unw_word_t)winContext->Ra; break; - case UNW_LOONGARCH_R2: *valp = (unw_word_t)winContext->Tp; break; - case UNW_LOONGARCH_R22: *valp = (unw_word_t)winContext->Fp; break; - case UNW_LOONGARCH_R23: *valp = (unw_word_t)winContext->S0; break; - case UNW_LOONGARCH_R24: *valp = (unw_word_t)winContext->S1; break; - case UNW_LOONGARCH_R25: *valp = (unw_word_t)winContext->S2; break; - case UNW_LOONGARCH_R26: *valp = (unw_word_t)winContext->S3; break; - case UNW_LOONGARCH_R27: *valp = (unw_word_t)winContext->S4; break; - case UNW_LOONGARCH_R28: *valp = (unw_word_t)winContext->S5; break; - case UNW_LOONGARCH_R29: *valp = (unw_word_t)winContext->S6; break; - case UNW_LOONGARCH_R30: *valp = (unw_word_t)winContext->S7; break; - case UNW_LOONGARCH_R31: *valp = (unw_word_t)winContext->S8; break; - case UNW_LOONGARCH_PC: *valp = (unw_word_t)winContext->Pc; break; + case UNW_LOONGARCH64_R1: *valp = (unw_word_t)winContext->Ra; break; + case UNW_LOONGARCH64_R2: *valp = (unw_word_t)winContext->Tp; break; + case UNW_LOONGARCH64_R22: *valp = (unw_word_t)winContext->Fp; break; + case UNW_LOONGARCH64_R23: *valp = (unw_word_t)winContext->S0; break; + case UNW_LOONGARCH64_R24: *valp = (unw_word_t)winContext->S1; break; + case UNW_LOONGARCH64_R25: *valp = (unw_word_t)winContext->S2; break; + case UNW_LOONGARCH64_R26: *valp = (unw_word_t)winContext->S3; break; + case UNW_LOONGARCH64_R27: *valp = (unw_word_t)winContext->S4; break; + case UNW_LOONGARCH64_R28: *valp = (unw_word_t)winContext->S5; break; + case UNW_LOONGARCH64_R29: *valp = (unw_word_t)winContext->S6; break; + case UNW_LOONGARCH64_R30: *valp = (unw_word_t)winContext->S7; break; + case UNW_LOONGARCH64_R31: *valp = (unw_word_t)winContext->S8; break; + case UNW_LOONGARCH64_PC: *valp = (unw_word_t)winContext->Pc; break; #elif defined(TARGET_S390X) case UNW_S390X_R6: *valp = (unw_word_t)winContext->R6; break; case UNW_S390X_R7: *valp = (unw_word_t)winContext->R7; break; diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index bc758a57e2c18c..17c4d618f302df 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -423,18 +423,18 @@ void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) #elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Pc); unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->Sp); - unw_get_reg(cursor, UNW_LOONGARCH_R1, (unw_word_t *) &winContext->Ra); - unw_get_reg(cursor, UNW_LOONGARCH_R2, (unw_word_t *) &winContext->Tp); - unw_get_reg(cursor, UNW_LOONGARCH_R22, (unw_word_t *) &winContext->Fp); - unw_get_reg(cursor, UNW_LOONGARCH_R23, (unw_word_t *) &winContext->S0); - unw_get_reg(cursor, UNW_LOONGARCH_R24, (unw_word_t *) &winContext->S1); - unw_get_reg(cursor, UNW_LOONGARCH_R25, (unw_word_t *) &winContext->S2); - unw_get_reg(cursor, UNW_LOONGARCH_R26, (unw_word_t *) &winContext->S3); - unw_get_reg(cursor, UNW_LOONGARCH_R27, (unw_word_t *) &winContext->S4); - unw_get_reg(cursor, UNW_LOONGARCH_R28, (unw_word_t *) &winContext->S5); - unw_get_reg(cursor, UNW_LOONGARCH_R29, (unw_word_t *) &winContext->S6); - unw_get_reg(cursor, UNW_LOONGARCH_R30, (unw_word_t *) &winContext->S7); - unw_get_reg(cursor, UNW_LOONGARCH_R31, (unw_word_t *) &winContext->S8); + unw_get_reg(cursor, UNW_LOONGARCH64_R1, (unw_word_t *) &winContext->Ra); + unw_get_reg(cursor, UNW_LOONGARCH64_R2, (unw_word_t *) &winContext->Tp); + unw_get_reg(cursor, UNW_LOONGARCH64_R22, (unw_word_t *) &winContext->Fp); + unw_get_reg(cursor, UNW_LOONGARCH64_R23, (unw_word_t *) &winContext->S0); + unw_get_reg(cursor, UNW_LOONGARCH64_R24, (unw_word_t *) &winContext->S1); + unw_get_reg(cursor, UNW_LOONGARCH64_R25, (unw_word_t *) &winContext->S2); + unw_get_reg(cursor, UNW_LOONGARCH64_R26, (unw_word_t *) &winContext->S3); + unw_get_reg(cursor, UNW_LOONGARCH64_R27, (unw_word_t *) &winContext->S4); + unw_get_reg(cursor, UNW_LOONGARCH64_R28, (unw_word_t *) &winContext->S5); + unw_get_reg(cursor, UNW_LOONGARCH64_R29, (unw_word_t *) &winContext->S6); + unw_get_reg(cursor, UNW_LOONGARCH64_R30, (unw_word_t *) &winContext->S7); + unw_get_reg(cursor, UNW_LOONGARCH64_R31, (unw_word_t *) &winContext->S8); #else #error unsupported architecture #endif @@ -521,18 +521,18 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL GetContextPointer(cursor, unwContext, UNW_S390X_R14, &contextPointers->R14); GetContextPointer(cursor, unwContext, UNW_S390X_R15, &contextPointers->R15); #elif (defined(HOST_UNIX) && defined(HOST_LOONGARCH64)) - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R1, &contextPointers->Ra); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R2, &contextPointers->Tp); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R22, &contextPointers->Fp); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R23, &contextPointers->S0); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R24, &contextPointers->S1); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R25, &contextPointers->S2); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R26, &contextPointers->S3); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R27, &contextPointers->S4); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R28, &contextPointers->S5); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R29, &contextPointers->S6); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R30, &contextPointers->S7); - GetContextPointer(cursor, unwContext, UNW_LOONGARCH_R31, &contextPointers->S8); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R1, &contextPointers->Ra); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R2, &contextPointers->Tp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R22, &contextPointers->Fp); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R23, &contextPointers->S0); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R24, &contextPointers->S1); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R25, &contextPointers->S2); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R26, &contextPointers->S3); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R27, &contextPointers->S4); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R28, &contextPointers->S5); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R29, &contextPointers->S6); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R30, &contextPointers->S7); + GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R31, &contextPointers->S8); #else #error unsupported architecture #endif From 422145b652db84d3dbfeef472478189775e11cf3 Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Wed, 19 Jan 2022 10:08:18 +0800 Subject: [PATCH 09/11] [LoongArch64] update the version of the `LICENSE description`. --- src/coreclr/pal/inc/unixasmmacrosloongarch64.inc | 3 --- .../pal/src/arch/loongarch64/activationhandlerwrapper.S | 2 -- src/coreclr/pal/src/arch/loongarch64/asmconstants.h | 3 --- .../pal/src/arch/loongarch64/callsignalhandlerwrapper.S | 3 --- src/coreclr/pal/src/arch/loongarch64/context.S | 2 -- src/coreclr/pal/src/arch/loongarch64/context2.S | 4 ---- src/coreclr/pal/src/arch/loongarch64/debugbreak.S | 3 --- .../pal/src/arch/loongarch64/dispatchexceptionwrapper.S | 2 -- src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S | 3 --- src/coreclr/pal/src/arch/loongarch64/processor.cpp | 3 --- src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp | 3 --- 11 files changed, 31 deletions(-) diff --git a/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc b/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc index 6d8f5516ecab35..5a150db94bf788 100644 --- a/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc +++ b/src/coreclr/pal/inc/unixasmmacrosloongarch64.inc @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. .macro NESTED_ENTRY Name, Section, Handler LEAF_ENTRY \Name, \Section diff --git a/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S b/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S index 2c4e5e2a2dab02..9cc8663fedf4fc 100644 --- a/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S +++ b/src/coreclr/pal/src/arch/loongarch64/activationhandlerwrapper.S @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// Copyright (c) Loongson Technology. All rights reserved. - #include "unixasmmacros.inc" #include "asmconstants.h" diff --git a/src/coreclr/pal/src/arch/loongarch64/asmconstants.h b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h index bdd327766714bf..ca728c2745e141 100644 --- a/src/coreclr/pal/src/arch/loongarch64/asmconstants.h +++ b/src/coreclr/pal/src/arch/loongarch64/asmconstants.h @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. #ifndef __PAL_LOONGARCH64_ASMCONSTANTS_H__ #define __PAL_LOONGARCH64_ASMCONSTANTS_H__ diff --git a/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S b/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S index 029efd80d95837..8084d1e3d6995c 100644 --- a/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S +++ b/src/coreclr/pal/src/arch/loongarch64/callsignalhandlerwrapper.S @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. #include "unixasmmacros.inc" #include "asmconstants.h" diff --git a/src/coreclr/pal/src/arch/loongarch64/context.S b/src/coreclr/pal/src/arch/loongarch64/context.S index ba2536e83cc972..64e8464308ca65 100644 --- a/src/coreclr/pal/src/arch/loongarch64/context.S +++ b/src/coreclr/pal/src/arch/loongarch64/context.S @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// Copyright (c) Loongson Technology. All rights reserved. - #include "unixasmmacros.inc" #if defined(_DEBUG) diff --git a/src/coreclr/pal/src/arch/loongarch64/context2.S b/src/coreclr/pal/src/arch/loongarch64/context2.S index 48c42593ce4540..ff0b6e040b42d9 100644 --- a/src/coreclr/pal/src/arch/loongarch64/context2.S +++ b/src/coreclr/pal/src/arch/loongarch64/context2.S @@ -1,9 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. - // // Implementation of _CONTEXT_CaptureContext for the LOONGARCH platform. // This function is processor dependent. It is used by exception handling, diff --git a/src/coreclr/pal/src/arch/loongarch64/debugbreak.S b/src/coreclr/pal/src/arch/loongarch64/debugbreak.S index e82b52d37f2b18..93fdfd8c4c5be8 100644 --- a/src/coreclr/pal/src/arch/loongarch64/debugbreak.S +++ b/src/coreclr/pal/src/arch/loongarch64/debugbreak.S @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. #include "unixasmmacros.inc" LEAF_ENTRY DBG_DebugBreak, _TEXT diff --git a/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S b/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S index 3b0aa198cbc160..bad79eeb254625 100644 --- a/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S +++ b/src/coreclr/pal/src/arch/loongarch64/dispatchexceptionwrapper.S @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// Copyright (c) Loongson Technology. All rights reserved. - // ==++== // diff --git a/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S index 6854a884002209..157e4149df5eb4 100644 --- a/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S +++ b/src/coreclr/pal/src/arch/loongarch64/exceptionhelper.S @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. #include "unixasmmacros.inc" #include "asmconstants.h" diff --git a/src/coreclr/pal/src/arch/loongarch64/processor.cpp b/src/coreclr/pal/src/arch/loongarch64/processor.cpp index 260bc38f381129..c0cc5beb851ec0 100644 --- a/src/coreclr/pal/src/arch/loongarch64/processor.cpp +++ b/src/coreclr/pal/src/arch/loongarch64/processor.cpp @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. /*++ diff --git a/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp b/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp index 615e4aa414b7b1..1ad1d7b0d041c5 100644 --- a/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp +++ b/src/coreclr/pal/src/arch/loongarch64/signalhandlerhelper.cpp @@ -1,8 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// Copyright (c) Loongson Technology. All rights reserved. #include "pal/dbgmsg.h" SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first From 5647e5c30a1c3f6c9cc6f4e1fcf7299651d3495b Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Tue, 15 Feb 2022 15:45:51 +0800 Subject: [PATCH 10/11] [LoongArch64] revert the `pal/inc/rt/ntimage.h`. --- src/coreclr/pal/inc/rt/ntimage.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/coreclr/pal/inc/rt/ntimage.h b/src/coreclr/pal/inc/rt/ntimage.h index ee873027b388e7..1880375184f057 100644 --- a/src/coreclr/pal/inc/rt/ntimage.h +++ b/src/coreclr/pal/inc/rt/ntimage.h @@ -1025,11 +1025,6 @@ typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; #define IMAGE_REL_IA64_GPREL32 0x001C #define IMAGE_REL_IA64_ADDEND 0x001F -// -// LOONGARCH64 relocation types -// -#define IMAGE_REL_LOONGARCH64_PC 0x0004 - // // CEF relocation types. // From f6d3a93404e68bcec299216fd426c902f539e5fc Mon Sep 17 00:00:00 2001 From: qiaopengcheng Date: Tue, 15 Feb 2022 18:13:02 +0800 Subject: [PATCH 11/11] [LoongArch64] delete unused assert and update the `DAC_CS_NATIVE_DATA_SIZE` --- src/coreclr/inc/crosscomp.h | 2 ++ src/coreclr/pal/inc/pal.h | 1 - src/coreclr/pal/src/thread/context.cpp | 4 ---- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index 84b6f81606f3fa..8d515a174385cf 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -426,6 +426,8 @@ enum #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_S390X) #define DAC_CS_NATIVE_DATA_SIZE 96 +#elif defined(TARGET_LINUX) && defined(TARGET_LOONGARCH64) +#define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_ARM) diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index a9e265a406bb58..11aae3f98e1dee 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -2602,7 +2602,6 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_ #elif defined(__sun) && defined(__x86_64__) #define PAL_CS_NATIVE_DATA_SIZE 48 #elif defined(__linux__) && defined(__loongarch64) -////TODO for LOONGARCH64: should confirm !!! #define PAL_CS_NATIVE_DATA_SIZE 96 #else #warning diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index a227a87d8d50af..80a5e3a90ffeef 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -268,11 +268,7 @@ BOOL CONTEXT_GetRegisters(DWORD processId, LPCONTEXT lpContext) if (processId == GetCurrentProcessId()) { -#ifndef HOST_LOONGARCH64 CONTEXT_CaptureContext(lpContext); -#else - _ASSERT(!"unimplemented on LOONGARCH64 yet"); -#endif } else {