diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -559,8 +559,10 @@ dst += GetFPRSize(); } - if (GetRegisterInfo().IsMTEEnabled()) + if (GetRegisterInfo().IsMTEEnabled()) { ::memcpy(dst, GetMTEControl(), GetMTEControlSize()); + dst += GetMTEControlSize(); + } ::memcpy(dst, GetTLSBuffer(), GetTLSBufferSize()); @@ -671,8 +673,17 @@ ::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(GetTLSBuffer(), src, GetTLSBufferSize()); + m_tls_is_valid = true; + error = WriteTLS(); + return error; } diff --git a/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py b/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py --- a/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py +++ b/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py @@ -42,13 +42,20 @@ substrs=["stopped", "stop reason = breakpoint"], ) - def check_tls_reg(self, registers): - self.setup(registers) - + def check_registers(self, registers, values): regs = self.thread().GetSelectedFrame().GetRegisters() tls_regs = regs.GetFirstValueByName("Thread Local Storage Registers") self.assertTrue(tls_regs.IsValid(), "No TLS registers found.") + for register in registers: + tls_reg = tls_regs.GetChildMemberWithName(register) + self.assertTrue(tls_reg.IsValid(), "{} register not found.".format( + register)) + self.assertEqual(tls_reg.GetValueAsUnsigned(), values[register]) + + def check_tls_reg(self, registers): + self.setup(registers) + # Since we can't predict what the value will be, the program has set # a target value for us to find. initial_values = { @@ -56,11 +63,12 @@ "tpidr2": 0x8877665544332211, } - for register in registers: - tls_reg = tls_regs.GetChildMemberWithName(register) - self.assertTrue(tls_reg.IsValid(), "{} register not found.".format( - register)) - self.assertEqual(tls_reg.GetValueAsUnsigned(), initial_values[register]) + self.check_registers(registers, initial_values) + + # Their values should be restored if an expression modifies them. + self.runCmd("expression expr_func()") + + self.check_registers(registers, initial_values) set_values = { "tpidr": 0x1111222233334444, @@ -95,7 +103,7 @@ @skipUnlessPlatform(["linux"]) def test_tls_sme(self): if not self.isAArch64SME(): - self.skipTest("SME must present.") + self.skipTest("SME must be present.") self.check_tls_reg(["tpidr", "tpidr2"]) diff --git a/lldb/test/API/linux/aarch64/tls_registers/main.c b/lldb/test/API/linux/aarch64/tls_registers/main.c --- a/lldb/test/API/linux/aarch64/tls_registers/main.c +++ b/lldb/test/API/linux/aarch64/tls_registers/main.c @@ -22,8 +22,18 @@ __asm__ volatile("msr S3_3_C13_C0_5, %0" ::"r"(value)); } +bool use_tpidr2 = false; +const uint64_t tpidr_pattern = 0x1122334455667788; +const uint64_t tpidr2_pattern = 0x8877665544332211; + +void expr_func() { + set_tpidr(~tpidr_pattern); + if (use_tpidr2) + set_tpidr2(~tpidr2_pattern); +} + int main(int argc, char *argv[]) { - bool use_tpidr2 = argc > 1; + use_tpidr2 = argc > 1; uint64_t original_tpidr = get_tpidr(); // Accessing this on a core without it produces SIGILL. Only do this if @@ -32,10 +42,8 @@ if (use_tpidr2) original_tpidr2 = get_tpidr2(); - uint64_t tpidr_pattern = 0x1122334455667788; set_tpidr(tpidr_pattern); - uint64_t tpidr2_pattern = 0x8877665544332211; if (use_tpidr2) set_tpidr2(tpidr2_pattern);