2020#include " libunwind_ext.h"
2121#include " shadow_stack_unwind.h"
2222
23+ #if __has_include(<sys/auxv.h>)
24+ #include < sys/auxv.h>
25+ #define HAVE_SYS_AUXV_H
26+ #endif
27+
2328namespace libunwind {
2429
2530// For emulating 128-bit registers
@@ -1828,6 +1833,7 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) {
18281833// / process.
18291834class _LIBUNWIND_HIDDEN Registers_arm64;
18301835extern " C" void __libunwind_Registers_arm64_jumpto (Registers_arm64 *);
1836+ extern " C" bool __libunwind_Registers_arm64_za_disable ();
18311837
18321838#if defined(_LIBUNWIND_USE_GCS)
18331839extern " C" void *__libunwind_shstk_get_jump_target () {
@@ -1837,7 +1843,7 @@ extern "C" void *__libunwind_shstk_get_jump_target() {
18371843
18381844class _LIBUNWIND_HIDDEN Registers_arm64 {
18391845public:
1840- Registers_arm64 ();
1846+ Registers_arm64 () = default ;
18411847 Registers_arm64 (const void *registers);
18421848 Registers_arm64 (const Registers_arm64 &);
18431849 Registers_arm64 &operator =(const Registers_arm64 &);
@@ -1855,7 +1861,10 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
18551861 v128 getVectorRegister (int num) const ;
18561862 void setVectorRegister (int num, v128 value);
18571863 static const char *getRegisterName (int num);
1858- void jumpto () { __libunwind_Registers_arm64_jumpto (this ); }
1864+ void jumpto () {
1865+ zaDisable ();
1866+ __libunwind_Registers_arm64_jumpto (this );
1867+ }
18591868 static constexpr int lastDwarfRegNum () {
18601869 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
18611870 }
@@ -1908,25 +1917,43 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
19081917private:
19091918 uint64_t lazyGetVG () const ;
19101919
1920+ void zaDisable () const {
1921+ if (!_misc_registers.__has_sme )
1922+ return ;
1923+ if (!__libunwind_Registers_arm64_za_disable ())
1924+ _LIBUNWIND_ABORT (" SME ZA disable failed" );
1925+ }
1926+
1927+ static bool checkHasSME () {
1928+ #if defined(HAVE_SYS_AUXV_H)
1929+ constexpr int hwcap2_sme = (1 << 23 );
1930+ unsigned long hwcap2 = getauxval (AT_HWCAP2);
1931+ return (hwcap2 & hwcap2_sme) != 0 ;
1932+ #endif
1933+ // TODO: Support other platforms.
1934+ return false ;
1935+ }
1936+
19111937 struct GPRs {
1912- uint64_t __x[29 ]; // x0-x28
1913- uint64_t __fp; // Frame pointer x29
1914- uint64_t __lr; // Link register x30
1915- uint64_t __sp; // Stack pointer x31
1916- uint64_t __pc; // Program counter
1917- uint64_t __ra_sign_state; // RA sign state register
1938+ uint64_t __x[29 ] = {}; // x0-x28
1939+ uint64_t __fp = 0 ; // Frame pointer x29
1940+ uint64_t __lr = 0 ; // Link register x30
1941+ uint64_t __sp = 0 ; // Stack pointer x31
1942+ uint64_t __pc = 0 ; // Program counter
1943+ uint64_t __ra_sign_state = 0 ; // RA sign state register
19181944 };
19191945
19201946 struct Misc {
1921- mutable uint64_t __vg = 0 ; // Vector Granule
1947+ mutable uint32_t __vg = 0 ; // Vector Granule
1948+ bool __has_sme = checkHasSME();
19221949 };
19231950
1924- GPRs _registers;
1951+ GPRs _registers = {} ;
19251952 // Currently only the lower double in 128-bit vectore registers
19261953 // is perserved during unwinding. We could define new register
19271954 // numbers (> 96) which mean whole vector registers, then this
19281955 // struct would need to change to contain whole vector registers.
1929- double _vectorHalfRegisters[32 ];
1956+ double _vectorHalfRegisters[32 ] = {} ;
19301957
19311958 // Miscellaneous/virtual registers. These are stored below the GPRs and FPRs
19321959 // as they do not correspond to physical registers, so do not need to be
@@ -1971,10 +1998,6 @@ Registers_arm64::operator=(const Registers_arm64 &other) {
19711998 return *this ;
19721999}
19732000
1974- inline Registers_arm64::Registers_arm64 () {
1975- memset (static_cast <void *>(this ), 0 , sizeof (*this ));
1976- }
1977-
19782001inline bool Registers_arm64::validRegister (int regNum) const {
19792002 if (regNum == UNW_REG_IP)
19802003 return true ;
0 commit comments