|
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>
|
@@ -993,6 +994,10 @@ class UnwindCursor : public AbstractUnwindCursor{
|
993 | 994 | bool setInfoForSigReturn(Registers_arm64 &);
|
994 | 995 | int stepThroughSigReturn(Registers_arm64 &);
|
995 | 996 | #endif
|
| 997 | +#if defined(_LIBUNWIND_TARGET_RISCV) |
| 998 | + bool setInfoForSigReturn(Registers_riscv &); |
| 999 | + int stepThroughSigReturn(Registers_riscv &); |
| 1000 | +#endif |
996 | 1001 | #if defined(_LIBUNWIND_TARGET_S390X)
|
997 | 1002 | bool setInfoForSigReturn(Registers_s390x &);
|
998 | 1003 | int stepThroughSigReturn(Registers_s390x &);
|
@@ -2720,6 +2725,60 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
|
2720 | 2725 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
2721 | 2726 | // defined(_LIBUNWIND_TARGET_AARCH64)
|
2722 | 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 | + |
2723 | 2782 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
|
2724 | 2783 | defined(_LIBUNWIND_TARGET_S390X)
|
2725 | 2784 | template <typename A, typename R>
|
|
0 commit comments