Skip to content

Commit 82ebd33

Browse files
authored
[LLDB][Minidumps] Read x64 registers as 64b and handle truncation in the file builder (llvm#106473)
This patch addresses a bug where `cs`/`fs` and other segmentation flags were being identified as having a type of `32b` and `64b` for `rflags`. In that case the register value was returning the fail value `0xF...` and this was corrupting some minidumps. Here we just read it as a 64b value and truncate it. In addition to that fix, I added comparing the registers from the live process to the loaded core for the generic minidump test. Prior only being ARM register tests. This explains why this was not detected before.
1 parent ee6961d commit 82ebd33

File tree

2 files changed

+42
-8
lines changed

2 files changed

+42
-8
lines changed

lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -491,12 +491,14 @@ GetThreadContext_x86_64(RegisterContext *reg_ctx) {
491491
thread_context.r14 = read_register_u64(reg_ctx, "r14");
492492
thread_context.r15 = read_register_u64(reg_ctx, "r15");
493493
thread_context.rip = read_register_u64(reg_ctx, "rip");
494-
thread_context.eflags = read_register_u32(reg_ctx, "rflags");
495-
thread_context.cs = read_register_u16(reg_ctx, "cs");
496-
thread_context.fs = read_register_u16(reg_ctx, "fs");
497-
thread_context.gs = read_register_u16(reg_ctx, "gs");
498-
thread_context.ss = read_register_u16(reg_ctx, "ss");
499-
thread_context.ds = read_register_u16(reg_ctx, "ds");
494+
// To make our code agnostic to whatever type the register value identifies
495+
// itself as, we read as a u64 and truncate to u32/u16 ourselves.
496+
thread_context.eflags = read_register_u64(reg_ctx, "rflags");
497+
thread_context.cs = read_register_u64(reg_ctx, "cs");
498+
thread_context.fs = read_register_u64(reg_ctx, "fs");
499+
thread_context.gs = read_register_u64(reg_ctx, "gs");
500+
thread_context.ss = read_register_u64(reg_ctx, "ss");
501+
thread_context.ds = read_register_u64(reg_ctx, "ds");
500502
return thread_context;
501503
}
502504

lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def verify_core_file(
1717
expected_modules,
1818
expected_threads,
1919
stacks_to_sps_map,
20+
stacks_to_registers_map,
2021
):
2122
# To verify, we'll launch with the mini dump
2223
target = self.dbg.CreateTarget(None)
@@ -62,6 +63,17 @@ def verify_core_file(
6263
# Try to read just past the red zone and fail
6364
process.ReadMemory(sp - red_zone - 1, 1, error)
6465
self.assertTrue(error.Fail(), "No failure when reading past the red zone")
66+
# Verify the registers are the same
67+
self.assertIn(thread_id, stacks_to_registers_map)
68+
register_val_list = stacks_to_registers_map[thread_id]
69+
frame_register_list = frame.GetRegisters()
70+
for x in register_val_list:
71+
self.assertEqual(
72+
x.GetValueAsUnsigned(),
73+
frame_register_list.GetFirstValueByName(
74+
x.GetName()
75+
).GetValueAsUnsigned(),
76+
)
6577

6678
self.dbg.DeleteTarget(target)
6779

@@ -93,12 +105,16 @@ def test_save_linux_mini_dump(self):
93105
expected_number_of_threads = process.GetNumThreads()
94106
expected_threads = []
95107
stacks_to_sp_map = {}
108+
stakcs_to_registers_map = {}
96109

97110
for thread_idx in range(process.GetNumThreads()):
98111
thread = process.GetThreadAtIndex(thread_idx)
99112
thread_id = thread.GetThreadID()
100113
expected_threads.append(thread_id)
101114
stacks_to_sp_map[thread_id] = thread.GetFrameAtIndex(0).GetSP()
115+
stakcs_to_registers_map[thread_id] = thread.GetFrameAtIndex(
116+
0
117+
).GetRegisters()
102118

103119
# save core and, kill process and verify corefile existence
104120
base_command = "process save-core --plugin-name=minidump "
@@ -110,6 +126,7 @@ def test_save_linux_mini_dump(self):
110126
expected_modules,
111127
expected_threads,
112128
stacks_to_sp_map,
129+
stakcs_to_registers_map,
113130
)
114131

115132
self.runCmd(base_command + " --style=modified-memory '%s'" % (core_dirty))
@@ -120,6 +137,7 @@ def test_save_linux_mini_dump(self):
120137
expected_modules,
121138
expected_threads,
122139
stacks_to_sp_map,
140+
stakcs_to_registers_map,
123141
)
124142

125143
self.runCmd(base_command + " --style=full '%s'" % (core_full))
@@ -130,6 +148,7 @@ def test_save_linux_mini_dump(self):
130148
expected_modules,
131149
expected_threads,
132150
stacks_to_sp_map,
151+
stakcs_to_registers_map,
133152
)
134153

135154
options = lldb.SBSaveCoreOptions()
@@ -147,6 +166,7 @@ def test_save_linux_mini_dump(self):
147166
expected_modules,
148167
expected_threads,
149168
stacks_to_sp_map,
169+
stakcs_to_registers_map,
150170
)
151171

152172
options = lldb.SBSaveCoreOptions()
@@ -163,6 +183,7 @@ def test_save_linux_mini_dump(self):
163183
expected_modules,
164184
expected_threads,
165185
stacks_to_sp_map,
186+
stakcs_to_registers_map,
166187
)
167188

168189
# Minidump can now save full core files, but they will be huge and
@@ -181,6 +202,7 @@ def test_save_linux_mini_dump(self):
181202
expected_modules,
182203
expected_threads,
183204
stacks_to_sp_map,
205+
stakcs_to_registers_map,
184206
)
185207

186208
self.assertSuccess(process.Kill())
@@ -276,13 +298,16 @@ def test_save_linux_mini_dump_default_options(self):
276298
expected_threads = []
277299
stacks_to_sp_map = {}
278300
expected_pid = process.GetProcessInfo().GetProcessID()
301+
stacks_to_registers_map = {}
279302

280303
for thread_idx in range(process.GetNumThreads()):
281304
thread = process.GetThreadAtIndex(thread_idx)
282305
thread_id = thread.GetThreadID()
283306
expected_threads.append(thread_id)
284307
stacks_to_sp_map[thread_id] = thread.GetFrameAtIndex(0).GetSP()
285-
308+
stacks_to_registers_map[thread_id] = thread.GetFrameAtIndex(
309+
0
310+
).GetRegisters()
286311

287312
# This is almost identical to the single thread test case because
288313
# minidump defaults to stacks only, so we want to see if the
@@ -294,7 +319,14 @@ def test_save_linux_mini_dump_default_options(self):
294319
error = process.SaveCore(options)
295320
self.assertTrue(error.Success())
296321

297-
self.verify_core_file(default_value_file, expected_pid, expected_modules, expected_threads, stacks_to_sp_map)
322+
self.verify_core_file(
323+
default_value_file,
324+
expected_pid,
325+
expected_modules,
326+
expected_threads,
327+
stacks_to_sp_map,
328+
stacks_to_registers_map,
329+
)
298330

299331
finally:
300332
self.assertTrue(self.dbg.DeleteTarget(target))

0 commit comments

Comments
 (0)