diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index c9384a651e81b..206ee4ed4b8cb 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -532,8 +532,10 @@ Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( dst += GetFPRSize(); } - if (GetRegisterInfo().IsMTEEnabled()) + if (GetRegisterInfo().IsMTEEnabled()) { ::memcpy(dst, GetMTEControl(), GetMTEControlSize()); + dst += GetMTEControlSize(); + } ::memcpy(dst, GetTLSTPIDR(), GetTLSTPIDRSize()); @@ -640,8 +642,17 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( ::memcpy(GetMTEControl(), src, GetMTEControlSize()); m_mte_ctrl_is_valid = true; error = WriteMTEControl(); + if (error.Fail()) + return error; + src += GetMTEControlSize(); } + // There is always a TLS set. It changes size based on system properties, it's + // not something an expression can change. + ::memcpy(GetTLSTPIDR(), src, GetTLSTPIDRSize()); + m_tls_tpidr_is_valid = true; + error = WriteTLSTPIDR(); + return error; } diff --git a/lldb/test/API/linux/aarch64/tls_register/TestAArch64LinuxTLSRegister.py b/lldb/test/API/linux/aarch64/tls_register/TestAArch64LinuxTLSRegister.py index d4ab5d70cc764..235b0e8f79e03 100644 --- a/lldb/test/API/linux/aarch64/tls_register/TestAArch64LinuxTLSRegister.py +++ b/lldb/test/API/linux/aarch64/tls_register/TestAArch64LinuxTLSRegister.py @@ -11,6 +11,15 @@ class AArch64LinuxTLSRegister(TestBase): NO_DEBUG_INFO_TESTCASE = True + def check_tpidr(self): + regs = self.thread().GetSelectedFrame().GetRegisters() + tls_regs = regs.GetFirstValueByName("Thread Local Storage Registers") + self.assertTrue(tls_regs.IsValid(), "No TLS registers found.") + tpidr = tls_regs.GetChildMemberWithName("tpidr") + self.assertTrue(tpidr.IsValid(), "No tpidr register found.") + + self.assertEqual(tpidr.GetValueAsUnsigned(), 0x1122334455667788) + @skipUnlessArch("aarch64") @skipUnlessPlatform(["linux"]) def test_tls(self): @@ -44,14 +53,11 @@ def test_tls(self): # Since we can't predict what the value will be, the program has set # a target value for us to find. + self.check_tpidr() - regs = self.thread().GetSelectedFrame().GetRegisters() - tls_regs = regs.GetFirstValueByName("Thread Local Storage Registers") - self.assertTrue(tls_regs.IsValid(), "No TLS registers found.") - tpidr = tls_regs.GetChildMemberWithName("tpidr") - self.assertTrue(tpidr.IsValid(), "No tpidr register found.") - - self.assertEqual(tpidr.GetValueAsUnsigned(), 0x1122334455667788) + # It should be saved/restored before/after an expression. + self.runCmd("expression expr_func()") + self.check_tpidr() # Set our own value for the program to find. self.expect("register write tpidr 0x{:x}".format(0x8877665544332211)) diff --git a/lldb/test/API/linux/aarch64/tls_register/main.c b/lldb/test/API/linux/aarch64/tls_register/main.c index 7a5fd3f5fcbdf..12bc2ea479a39 100644 --- a/lldb/test/API/linux/aarch64/tls_register/main.c +++ b/lldb/test/API/linux/aarch64/tls_register/main.c @@ -1,6 +1,12 @@ #include #include +const uint64_t pattern = 0x1122334455667788; + +void expr_func() { + __asm__ volatile("msr tpidr_el0, %0" ::"r"(~pattern)); +} + int main() { // Save tpidr to restore later. uint64_t tpidr = 0;