Skip to content

Commit 6239227

Browse files
committed
[lldb][AArch64] Save/restore TLS registers around expressions
Previously lldb was storing them but not restoring them. Meaning that this function: ``` void expr(uint64_t value) { __asm__ volatile("msr tpidr_el0, %0" ::"r"(value)); } ``` When run from lldb: ``` (lldb) expression expr() ``` Would leave tpidr as `value` instead of the original value of the register. A check for this scenario has been added to TestAArch64LinuxTLSRegisters.py, which covers tpidr and the SME excluisve tpidr2 register when it's present. Reviewed By: omjavaid Differential Revision: https://reviews.llvm.org/D156512
1 parent f17601b commit 6239227

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,10 @@ Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
559559
dst += GetFPRSize();
560560
}
561561

562-
if (GetRegisterInfo().IsMTEEnabled())
562+
if (GetRegisterInfo().IsMTEEnabled()) {
563563
::memcpy(dst, GetMTEControl(), GetMTEControlSize());
564+
dst += GetMTEControlSize();
565+
}
564566

565567
::memcpy(dst, GetTLSBuffer(), GetTLSBufferSize());
566568

@@ -671,8 +673,17 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
671673
::memcpy(GetMTEControl(), src, GetMTEControlSize());
672674
m_mte_ctrl_is_valid = true;
673675
error = WriteMTEControl();
676+
if (error.Fail())
677+
return error;
678+
src += GetMTEControlSize();
674679
}
675680

681+
// There is always a TLS set. It changes size based on system properties, it's
682+
// not something an expression can change.
683+
::memcpy(GetTLSBuffer(), src, GetTLSBufferSize());
684+
m_tls_is_valid = true;
685+
error = WriteTLS();
686+
676687
return error;
677688
}
678689

lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,33 @@ def setup(self, registers):
4242
substrs=["stopped", "stop reason = breakpoint"],
4343
)
4444

45-
def check_tls_reg(self, registers):
46-
self.setup(registers)
47-
45+
def check_registers(self, registers, values):
4846
regs = self.thread().GetSelectedFrame().GetRegisters()
4947
tls_regs = regs.GetFirstValueByName("Thread Local Storage Registers")
5048
self.assertTrue(tls_regs.IsValid(), "No TLS registers found.")
5149

50+
for register in registers:
51+
tls_reg = tls_regs.GetChildMemberWithName(register)
52+
self.assertTrue(tls_reg.IsValid(), "{} register not found.".format(
53+
register))
54+
self.assertEqual(tls_reg.GetValueAsUnsigned(), values[register])
55+
56+
def check_tls_reg(self, registers):
57+
self.setup(registers)
58+
5259
# Since we can't predict what the value will be, the program has set
5360
# a target value for us to find.
5461
initial_values = {
5562
"tpidr": 0x1122334455667788,
5663
"tpidr2": 0x8877665544332211,
5764
}
5865

59-
for register in registers:
60-
tls_reg = tls_regs.GetChildMemberWithName(register)
61-
self.assertTrue(tls_reg.IsValid(), "{} register not found.".format(
62-
register))
63-
self.assertEqual(tls_reg.GetValueAsUnsigned(), initial_values[register])
66+
self.check_registers(registers, initial_values)
67+
68+
# Their values should be restored if an expression modifies them.
69+
self.runCmd("expression expr_func()")
70+
71+
self.check_registers(registers, initial_values)
6472

6573
set_values = {
6674
"tpidr": 0x1111222233334444,
@@ -95,7 +103,7 @@ def test_tls_no_sme(self):
95103
@skipUnlessPlatform(["linux"])
96104
def test_tls_sme(self):
97105
if not self.isAArch64SME():
98-
self.skipTest("SME must present.")
106+
self.skipTest("SME must be present.")
99107

100108
self.check_tls_reg(["tpidr", "tpidr2"])
101109

lldb/test/API/linux/aarch64/tls_registers/main.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,18 @@ void set_tpidr2(uint64_t value) {
2222
__asm__ volatile("msr S3_3_C13_C0_5, %0" ::"r"(value));
2323
}
2424

25+
bool use_tpidr2 = false;
26+
const uint64_t tpidr_pattern = 0x1122334455667788;
27+
const uint64_t tpidr2_pattern = 0x8877665544332211;
28+
29+
void expr_func() {
30+
set_tpidr(~tpidr_pattern);
31+
if (use_tpidr2)
32+
set_tpidr2(~tpidr2_pattern);
33+
}
34+
2535
int main(int argc, char *argv[]) {
26-
bool use_tpidr2 = argc > 1;
36+
use_tpidr2 = argc > 1;
2737

2838
uint64_t original_tpidr = get_tpidr();
2939
// Accessing this on a core without it produces SIGILL. Only do this if
@@ -32,10 +42,8 @@ int main(int argc, char *argv[]) {
3242
if (use_tpidr2)
3343
original_tpidr2 = get_tpidr2();
3444

35-
uint64_t tpidr_pattern = 0x1122334455667788;
3645
set_tpidr(tpidr_pattern);
3746

38-
uint64_t tpidr2_pattern = 0x8877665544332211;
3947
if (use_tpidr2)
4048
set_tpidr2(tpidr2_pattern);
4149

0 commit comments

Comments
 (0)