1818#include " cet_unwind.h"
1919#include " config.h"
2020#include " libunwind.h"
21+ #include " libunwind_ext.h"
22+
23+ #if __has_feature(ptrauth_calls)
24+ #include < ptrauth.h>
25+ #endif
2126
2227namespace libunwind {
2328
@@ -93,6 +98,10 @@ class _LIBUNWIND_HIDDEN Registers_x86 {
9398 uint32_t getEDI () const { return _registers.__edi ; }
9499 void setEDI (uint32_t value) { _registers.__edi = value; }
95100
101+ typedef uint32_t reg_t ;
102+ void normalizeNewLinkRegister (reg_t &, unw_word_t ) { }
103+ void normalizeExistingLinkRegister (reg_t &) { }
104+
96105private:
97106 struct GPRs {
98107 unsigned int __eax;
@@ -311,6 +320,10 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 {
311320 uint64_t getR15 () const { return _registers.__r15 ; }
312321 void setR15 (uint64_t value) { _registers.__r15 = value; }
313322
323+ typedef uint64_t reg_t ;
324+ void normalizeNewLinkRegister (reg_t &, unw_word_t ) { }
325+ void normalizeExistingLinkRegister (reg_t &) { }
326+
314327private:
315328 struct GPRs {
316329 uint64_t __rax;
@@ -620,6 +633,10 @@ class _LIBUNWIND_HIDDEN Registers_ppc {
620633 uint64_t getCR () const { return _registers.__cr ; }
621634 void setCR (uint32_t value) { _registers.__cr = value; }
622635
636+ typedef uint32_t reg_t ;
637+ void normalizeNewLinkRegister (reg_t &, unw_word_t ) { }
638+ void normalizeExistingLinkRegister (reg_t &) { }
639+
623640private:
624641 struct ppc_thread_state_t {
625642 unsigned int __srr0; /* Instruction address register (PC) */
@@ -1815,6 +1832,8 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
18151832public:
18161833 Registers_arm64 ();
18171834 Registers_arm64 (const void *registers);
1835+ Registers_arm64 (const Registers_arm64&);
1836+ Registers_arm64& operator =(const Registers_arm64&);
18181837
18191838 bool validRegister (int num) const ;
18201839 uint64_t getRegister (int num) const ;
@@ -1834,11 +1853,63 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
18341853
18351854 uint64_t getSP () const { return _registers.__sp ; }
18361855 void setSP (uint64_t value) { _registers.__sp = value; }
1837- uint64_t getIP () const { return _registers.__pc ; }
1838- void setIP (uint64_t value) { _registers.__pc = value; }
1856+ uint64_t getIP () const {
1857+ uint64_t value = _registers.__pc ;
1858+ #if __has_feature(ptrauth_calls)
1859+ // Note the value of the PC was signed to its address in the register state
1860+ // but everyone else expects it to be sign by the SP, so convert on return.
1861+ value = (uint64_t )ptrauth_auth_and_resign ((void *)_registers.__pc ,
1862+ ptrauth_key_return_address,
1863+ &_registers.__pc ,
1864+ ptrauth_key_return_address,
1865+ getSP ());
1866+ #endif
1867+ return value;
1868+ }
1869+ void setIP (uint64_t value) {
1870+ #if __has_feature(ptrauth_calls)
1871+ // Note the value which was set should have been signed with the SP.
1872+ // We then resign with the slot we are being stored in to so that both SP and LR
1873+ // can't be spoofed at the same time.
1874+ value = (uint64_t )ptrauth_auth_and_resign ((void *)value,
1875+ ptrauth_key_return_address,
1876+ getSP (),
1877+ ptrauth_key_return_address,
1878+ &_registers.__pc );
1879+ #endif
1880+ _registers.__pc = value;
1881+ }
18391882 uint64_t getFP () const { return _registers.__fp ; }
18401883 void setFP (uint64_t value) { _registers.__fp = value; }
18411884
1885+ typedef uint64_t reg_t ;
1886+ void normalizeNewLinkRegister (reg_t & linkRegister, unw_word_t procInfoFlags) {
1887+ (void )linkRegister;
1888+ (void )procInfoFlags;
1889+ #if __has_feature(ptrauth_calls)
1890+ if (procInfoFlags == ProcInfoFlags_IsARM64Image) {
1891+ // If the current frame is arm64e then the LR should have been signed by
1892+ // the SP. In this case, we'll just leave it as is. For other frames,
1893+ // we'll now sign the LR so that setIP below can assume all inputs are signed.
1894+ linkRegister = (uint64_t )ptrauth_sign_unauthenticated ((void *)linkRegister,
1895+ ptrauth_key_return_address,
1896+ _registers.__sp );
1897+ }
1898+ #endif
1899+ }
1900+
1901+ void normalizeExistingLinkRegister (reg_t & linkRegister) {
1902+ (void )linkRegister;
1903+ #if __has_feature(ptrauth_calls)
1904+ // If we are in an arm64/arm64e frame, then the PC should have been signed with the SP
1905+ linkRegister = (uint64_t )ptrauth_auth_data ((void *)linkRegister, ptrauth_key_return_address, _registers.__sp );
1906+ #endif
1907+ }
1908+
1909+ // arm64_32 and i386 simulator hack
1910+ void normalizeNewLinkRegister (uint32_t &, unw_word_t ) { }
1911+ void normalizeExistingLinkRegister (uint32_t &) { }
1912+
18421913private:
18431914 struct GPRs {
18441915 uint64_t __x[29 ]; // x0-x28
@@ -1866,6 +1937,25 @@ inline Registers_arm64::Registers_arm64(const void *registers) {
18661937 memcpy (_vectorHalfRegisters,
18671938 static_cast <const uint8_t *>(registers) + sizeof (GPRs),
18681939 sizeof (_vectorHalfRegisters));
1940+ #if __has_feature(ptrauth_calls)
1941+ uint64_t pcRegister = 0 ;
1942+ memcpy (&pcRegister, ((uint8_t *)&_registers) + offsetof (GPRs, __pc), sizeof (pcRegister));
1943+ setIP (pcRegister);
1944+ #endif
1945+ }
1946+
1947+ inline Registers_arm64::Registers_arm64 (const Registers_arm64& other) {
1948+ *this = other;
1949+ }
1950+
1951+ inline Registers_arm64& Registers_arm64::operator =(const Registers_arm64& other) {
1952+ memcpy (&_registers, &other._registers , sizeof (_registers));
1953+ memcpy (_vectorHalfRegisters, &other._vectorHalfRegisters ,
1954+ sizeof (_vectorHalfRegisters));
1955+ #if __has_feature(ptrauth_calls)
1956+ setIP (other.getIP ());
1957+ #endif
1958+ return *this ;
18691959}
18701960
18711961inline Registers_arm64::Registers_arm64 () {
@@ -1891,7 +1981,7 @@ inline bool Registers_arm64::validRegister(int regNum) const {
18911981
18921982inline uint64_t Registers_arm64::getRegister (int regNum) const {
18931983 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1894- return _registers. __pc ;
1984+ return getIP () ;
18951985 if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
18961986 return _registers.__sp ;
18971987 if (regNum == UNW_AARCH64_RA_SIGN_STATE)
@@ -1907,7 +1997,7 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const {
19071997
19081998inline void Registers_arm64::setRegister (int regNum, uint64_t value) {
19091999 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)
1910- _registers. __pc = value;
2000+ setIP ( value) ;
19112001 else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)
19122002 _registers.__sp = value;
19132003 else if (regNum == UNW_AARCH64_RA_SIGN_STATE)
@@ -2129,6 +2219,10 @@ class _LIBUNWIND_HIDDEN Registers_arm {
21292219 uint32_t getIP () const { return _registers.__pc ; }
21302220 void setIP (uint32_t value) { _registers.__pc = value; }
21312221
2222+ typedef uint32_t reg_t ;
2223+ void normalizeNewLinkRegister (reg_t &, unw_word_t ) { }
2224+ void normalizeExistingLinkRegister (reg_t &) { }
2225+
21322226 void saveVFPAsX () {
21332227 assert (_use_X_for_vfp_save || !_saved_vfp_d0_d15);
21342228 _use_X_for_vfp_save = true ;
0 commit comments