39
39
#include < sys/uio.h>
40
40
#include < unistd.h>
41
41
#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
42
+ #define _LIBUNWIND_CHECK_SIGRETURN 1
43
+ #endif
44
+
45
+ #if defined(_LIBUNWIND_TARGET_FREEBSD) && defined(_LIBUNWIND_TARGET_AARCH64)
46
+ #include < machine/frame.h>
47
+ #include < sys/sysctl.h>
48
+ #include < sys/ucontext.h>
49
+ #include < sys/user.h>
50
+ #include < unistd.h>
51
+ #define _LIBUNWIND_CHECK_FREEBSD_SIGRETURN 1
52
+ #define _LIBUNWIND_CHECK_SIGRETURN 1
42
53
#endif
43
54
44
55
#include " AddressSpace.hpp"
@@ -983,7 +994,7 @@ class UnwindCursor : public AbstractUnwindCursor{
983
994
}
984
995
#endif
985
996
986
- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN )
997
+ #if defined(_LIBUNWIND_CHECK_SIGRETURN )
987
998
bool setInfoForSigReturn () {
988
999
R dummy;
989
1000
return setInfoForSigReturn (dummy);
@@ -1011,7 +1022,7 @@ class UnwindCursor : public AbstractUnwindCursor{
1011
1022
template <typename Registers> int stepThroughSigReturn (Registers &) {
1012
1023
return UNW_STEP_END;
1013
1024
}
1014
- #endif
1025
+ #endif // defined(_LIBUNWIND_CHECK_SIGRETURN)
1015
1026
1016
1027
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1017
1028
bool getInfoFromFdeCie (const typename CFI_Parser<A>::FDE_Info &fdeInfo,
@@ -1314,9 +1325,14 @@ class UnwindCursor : public AbstractUnwindCursor{
1314
1325
unw_proc_info_t _info;
1315
1326
bool _unwindInfoMissing;
1316
1327
bool _isSignalFrame;
1317
- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN )
1328
+ #if defined(_LIBUNWIND_CHECK_SIGRETURN )
1318
1329
bool _isSigReturn = false ;
1330
+ #if defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN)
1331
+ bool _isSigTrampDetermined = false ;
1332
+ pint_t _sigTrampStart;
1333
+ pint_t _sigTrampEnd;
1319
1334
#endif
1335
+ #endif // defined(_LIBUNWIND_CHECK_SIGRETURN)
1320
1336
};
1321
1337
1322
1338
@@ -2558,7 +2574,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2558
2574
2559
2575
template <typename A, typename R>
2560
2576
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2561
- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN )
2577
+ #if defined(_LIBUNWIND_CHECK_SIGRETURN )
2562
2578
_isSigReturn = false ;
2563
2579
#endif
2564
2580
@@ -2673,7 +2689,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2673
2689
}
2674
2690
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2675
2691
2676
- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN )
2692
+ #if defined(_LIBUNWIND_CHECK_SIGRETURN )
2677
2693
if (setInfoForSigReturn ())
2678
2694
return ;
2679
2695
#endif
@@ -2909,6 +2925,63 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
2909
2925
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2910
2926
// defined(_LIBUNWIND_TARGET_S390X)
2911
2927
2928
+ #if defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) && \
2929
+ defined (_LIBUNWIND_TARGET_AARCH64)
2930
+ template <typename A, typename R>
2931
+ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2932
+ // Look for the sigreturn trampoline.
2933
+ //
2934
+ // https://cgit.freebsd.org/src/tree/sys/arm64/arm64/sigtramp.S
2935
+ const pint_t pc = static_cast <pint_t >(this ->getReg (UNW_REG_IP));
2936
+
2937
+ if (_isSigTrampDetermined == false ) {
2938
+ struct kinfo_sigtramp kst = {0 };
2939
+ size_t len = sizeof (kst);
2940
+ int mib[4 ] = {CTL_KERN, KERN_PROC, KERN_PROC_SIGTRAMP, getpid ()};
2941
+ if (sysctl (mib, 4 , &kst, &len, NULL , 0 ) == 0 ) {
2942
+ _isSigTrampDetermined = true ;
2943
+ _sigTrampStart = reinterpret_cast <pint_t >(kst.ksigtramp_start );
2944
+ _sigTrampEnd = reinterpret_cast <pint_t >(kst.ksigtramp_end );
2945
+ }
2946
+ }
2947
+
2948
+ if (_isSigTrampDetermined == false ||
2949
+ (pc < _sigTrampStart || pc >= _sigTrampEnd))
2950
+ return false ;
2951
+
2952
+ _info = {};
2953
+ _info.start_ip = _sigTrampStart;
2954
+ _info.end_ip = _sigTrampEnd;
2955
+ _isSigReturn = true ;
2956
+ return true ;
2957
+ }
2958
+
2959
+ template <typename A, typename R>
2960
+ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
2961
+ // In the signal trampoline frame, sp points to a sigframe
2962
+ const pint_t kOffsetSpToSigcontext =
2963
+ offsetof (struct sigframe , sf_uc) + offsetof (ucontext_t , uc_mcontext);
2964
+
2965
+ // Offsets from mcontext_t to each register.
2966
+ const pint_t kOffsetGprs = offsetof (struct gpregs , gp_x[0 ]);
2967
+ const pint_t kOffsetSp = offsetof (struct gpregs , gp_sp);
2968
+ const pint_t kOffsetPc = offsetof (struct gpregs , gp_lr);
2969
+
2970
+ pint_t sigctx = _registers.getSP () + kOffsetSpToSigcontext ;
2971
+
2972
+ for (int i = 0 ; i <= 29 ; ++i) {
2973
+ uint64_t value =
2974
+ _addressSpace.get64 (sigctx + kOffsetGprs + static_cast <pint_t >(i * 8 ));
2975
+ _registers.setRegister (UNW_AARCH64_X0 + i, value);
2976
+ }
2977
+ _registers.setSP (_addressSpace.get64 (sigctx + kOffsetSp ));
2978
+ _registers.setIP (_addressSpace.get64 (sigctx + kOffsetPc ));
2979
+ _isSignalFrame = true ;
2980
+ return UNW_STEP_SUCCESS;
2981
+ }
2982
+ #endif // defined(_LIBUNWIND_CHECK_FREEBSD_SIGRETURN) &&
2983
+ // defined(_LIBUNWIND_TARGET_AARCH64)
2984
+
2912
2985
template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
2913
2986
(void )stage2;
2914
2987
// Bottom of stack is defined is when unwind info cannot be found.
@@ -2917,7 +2990,7 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
2917
2990
2918
2991
// Use unwinding info to modify register set as if function returned.
2919
2992
int result;
2920
- #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN )
2993
+ #if defined(_LIBUNWIND_CHECK_SIGRETURN )
2921
2994
if (_isSigReturn) {
2922
2995
result = this ->stepThroughSigReturn ();
2923
2996
} else
0 commit comments