31
31
#endif
32
32
33
33
#if defined(_LIBUNWIND_TARGET_LINUX) && \
34
- (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X))
34
+ (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
35
+ defined (_LIBUNWIND_TARGET_S390X))
35
36
#include < sys/syscall.h>
36
37
#include < sys/uio.h>
37
38
#include < unistd.h>
@@ -506,7 +507,14 @@ class UnwindCursor : public AbstractUnwindCursor {
506
507
#endif
507
508
508
509
DISPATCHER_CONTEXT *getDispatcherContext () { return &_dispContext; }
509
- void setDispatcherContext (DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
510
+ void setDispatcherContext (DISPATCHER_CONTEXT *disp) {
511
+ _dispContext = *disp;
512
+ _info.lsda = reinterpret_cast <unw_word_t >(_dispContext.HandlerData );
513
+ if (_dispContext.LanguageHandler ) {
514
+ _info.handler = reinterpret_cast <unw_word_t >(__libunwind_seh_personality);
515
+ } else
516
+ _info.handler = 0 ;
517
+ }
510
518
511
519
// libunwind does not and should not depend on C++ library which means that we
512
520
// need our own definition of inline placement new.
@@ -568,10 +576,12 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
568
576
" UnwindCursor<> requires more alignment than unw_cursor_t" );
569
577
memset (&_info, 0 , sizeof (_info));
570
578
memset (&_histTable, 0 , sizeof (_histTable));
579
+ memset (&_dispContext, 0 , sizeof (_dispContext));
571
580
_dispContext.ContextRecord = &_msContext;
572
581
_dispContext.HistoryTable = &_histTable;
573
582
// Initialize MS context from ours.
574
583
R r (context);
584
+ RtlCaptureContext (&_msContext);
575
585
_msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
576
586
#if defined(_LIBUNWIND_TARGET_X86_64)
577
587
_msContext.Rax = r.getRegister (UNW_X86_64_RAX);
@@ -669,6 +679,7 @@ UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
669
679
" UnwindCursor<> does not fit in unw_cursor_t" );
670
680
memset (&_info, 0 , sizeof (_info));
671
681
memset (&_histTable, 0 , sizeof (_histTable));
682
+ memset (&_dispContext, 0 , sizeof (_dispContext));
672
683
_dispContext.ContextRecord = &_msContext;
673
684
_dispContext.HistoryTable = &_histTable;
674
685
_msContext = *context;
@@ -679,7 +690,7 @@ template <typename A, typename R>
679
690
bool UnwindCursor<A, R>::validReg(int regNum) {
680
691
if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true ;
681
692
#if defined(_LIBUNWIND_TARGET_X86_64)
682
- if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15 ) return true ;
693
+ if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP ) return true ;
683
694
#elif defined(_LIBUNWIND_TARGET_ARM)
684
695
if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) ||
685
696
regNum == UNW_ARM_RA_AUTH_CODE)
@@ -694,6 +705,7 @@ template <typename A, typename R>
694
705
unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
695
706
switch (regNum) {
696
707
#if defined(_LIBUNWIND_TARGET_X86_64)
708
+ case UNW_X86_64_RIP:
697
709
case UNW_REG_IP: return _msContext.Rip ;
698
710
case UNW_X86_64_RAX: return _msContext.Rax ;
699
711
case UNW_X86_64_RDX: return _msContext.Rdx ;
@@ -744,6 +756,7 @@ template <typename A, typename R>
744
756
void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
745
757
switch (regNum) {
746
758
#if defined(_LIBUNWIND_TARGET_X86_64)
759
+ case UNW_X86_64_RIP:
747
760
case UNW_REG_IP: _msContext.Rip = value; break ;
748
761
case UNW_X86_64_RAX: _msContext.Rax = value; break ;
749
762
case UNW_X86_64_RDX: _msContext.Rdx = value; break ;
@@ -981,6 +994,10 @@ class UnwindCursor : public AbstractUnwindCursor{
981
994
bool setInfoForSigReturn (Registers_arm64 &);
982
995
int stepThroughSigReturn (Registers_arm64 &);
983
996
#endif
997
+ #if defined(_LIBUNWIND_TARGET_RISCV)
998
+ bool setInfoForSigReturn (Registers_riscv &);
999
+ int stepThroughSigReturn (Registers_riscv &);
1000
+ #endif
984
1001
#if defined(_LIBUNWIND_TARGET_S390X)
985
1002
bool setInfoForSigReturn (Registers_s390x &);
986
1003
int stepThroughSigReturn (Registers_s390x &);
@@ -1978,6 +1995,9 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
1978
1995
uint32_t lastcode = (xdata->CountOfCodes + 1 ) & ~1 ;
1979
1996
const uint32_t *handler = reinterpret_cast <uint32_t *>(&xdata->UnwindCodes [lastcode]);
1980
1997
_info.lsda = reinterpret_cast <unw_word_t >(handler+1 );
1998
+ _dispContext.HandlerData = reinterpret_cast <void *>(_info.lsda );
1999
+ _dispContext.LanguageHandler =
2000
+ reinterpret_cast <EXCEPTION_ROUTINE *>(base + *handler);
1981
2001
if (*handler) {
1982
2002
_info.handler = reinterpret_cast <unw_word_t >(__libunwind_seh_personality);
1983
2003
} else
@@ -2705,6 +2725,60 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
2705
2725
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2706
2726
// defined(_LIBUNWIND_TARGET_AARCH64)
2707
2727
2728
+ #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2729
+ defined (_LIBUNWIND_TARGET_RISCV)
2730
+ template <typename A, typename R>
2731
+ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
2732
+ const pint_t pc = static_cast <pint_t >(getReg (UNW_REG_IP));
2733
+ uint32_t instructions[2 ];
2734
+ struct iovec local_iov = {&instructions, sizeof instructions};
2735
+ struct iovec remote_iov = {reinterpret_cast <void *>(pc), sizeof instructions};
2736
+ long bytesRead =
2737
+ syscall (SYS_process_vm_readv, getpid (), &local_iov, 1 , &remote_iov, 1 , 0 );
2738
+ // Look for the two instructions used in the sigreturn trampoline
2739
+ // __vdso_rt_sigreturn:
2740
+ //
2741
+ // 0x08b00893 li a7,0x8b
2742
+ // 0x00000073 ecall
2743
+ if (bytesRead != sizeof instructions || instructions[0 ] != 0x08b00893 ||
2744
+ instructions[1 ] != 0x00000073 )
2745
+ return false ;
2746
+
2747
+ _info = {};
2748
+ _info.start_ip = pc;
2749
+ _info.end_ip = pc + 4 ;
2750
+ _isSigReturn = true ;
2751
+ return true ;
2752
+ }
2753
+
2754
+ template <typename A, typename R>
2755
+ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_riscv &) {
2756
+ // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2757
+ // - 128-byte siginfo struct
2758
+ // - ucontext_t struct:
2759
+ // - 8-byte long (__uc_flags)
2760
+ // - 8-byte pointer (*uc_link)
2761
+ // - 24-byte uc_stack
2762
+ // - 8-byte uc_sigmask
2763
+ // - 120-byte of padding to allow sigset_t to be expanded in the future
2764
+ // - 8 bytes of padding because sigcontext has 16-byte alignment
2765
+ // - struct sigcontext uc_mcontext
2766
+ // [1]
2767
+ // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
2768
+ const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128 ;
2769
+
2770
+ const pint_t sigctx = _registers.getSP () + kOffsetSpToSigcontext ;
2771
+ _registers.setIP (_addressSpace.get64 (sigctx));
2772
+ for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) {
2773
+ uint64_t value = _addressSpace.get64 (sigctx + static_cast <pint_t >(i * 8 ));
2774
+ _registers.setRegister (i, value);
2775
+ }
2776
+ _isSignalFrame = true ;
2777
+ return UNW_STEP_SUCCESS;
2778
+ }
2779
+ #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2780
+ // defined(_LIBUNWIND_TARGET_RISCV)
2781
+
2708
2782
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2709
2783
defined (_LIBUNWIND_TARGET_S390X)
2710
2784
template <typename A, typename R>
0 commit comments