Skip to content

Commit e94c609

Browse files
authored
[lldb][Mach-O] Fix several bugs in x86_64 Mach-O corefile (#146460)
reading, and one bug in the new RegisterContextUnifiedCore class. The PR I landed a few days ago to allow Mach-O corefiles to augment their registers with additional per-thread registers in metadata exposed a few bugs in the x86_64 corefile reader when running under different CI environments. It also showed a bug in my RegisterContextUnifiedCore class where I wasn't properly handling lookups of unknown registers (e.g. the LLDB_GENERIC_RA when debugging an intel target). The Mach-O x86_64 corefile support would say that it had fpu & exc registers available in every corefile, regardless of whether they were actually present. It would only read the bytes for the first register flavor in the LC_THREAD, the GPRs, but it read them incorrectly, so sometimes you got more register context than you'd expect. The LC_THREAD register context specifies a flavor and the number of uint32_t words; the ObjectFileMachO method would read that number of uint64_t's, exceeding the GPR register space, but it was followed by FPU and then EXC register space so it didn't crash. If you had a corefile with GPR and EXC register bytes, it would be written into the GPR and then FPU register areas, with zeroes filling out the rest of the context.
1 parent ce159d2 commit e94c609

File tree

2 files changed

+32
-42
lines changed

2 files changed

+32
-42
lines changed

lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp

Lines changed: 26 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -184,46 +184,32 @@ class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 {
184184
SetError(GPRRegSet, Read, -1);
185185
SetError(FPURegSet, Read, -1);
186186
SetError(EXCRegSet, Read, -1);
187-
bool done = false;
188187

189-
while (!done) {
188+
while (offset < data.GetByteSize()) {
190189
int flavor = data.GetU32(&offset);
191190
if (flavor == 0)
192-
done = true;
193-
else {
194-
uint32_t i;
195-
uint32_t count = data.GetU32(&offset);
196-
switch (flavor) {
197-
case GPRRegSet:
198-
for (i = 0; i < count; ++i)
199-
(&gpr.rax)[i] = data.GetU64(&offset);
200-
SetError(GPRRegSet, Read, 0);
201-
done = true;
202-
203-
break;
204-
case FPURegSet:
205-
// TODO: fill in FPU regs....
206-
// SetError (FPURegSet, Read, -1);
207-
done = true;
208-
209-
break;
210-
case EXCRegSet:
211-
exc.trapno = data.GetU32(&offset);
212-
exc.err = data.GetU32(&offset);
213-
exc.faultvaddr = data.GetU64(&offset);
214-
SetError(EXCRegSet, Read, 0);
215-
done = true;
216-
break;
217-
case 7:
218-
case 8:
219-
case 9:
220-
// fancy flavors that encapsulate of the above flavors...
221-
break;
222-
223-
default:
224-
done = true;
225-
break;
226-
}
191+
break;
192+
uint32_t count = data.GetU32(&offset);
193+
switch (flavor) {
194+
case GPRRegSet: {
195+
uint32_t *gpr_data = reinterpret_cast<uint32_t *>(&gpr.rax);
196+
for (uint32_t i = 0; i < count && offset < data.GetByteSize(); ++i)
197+
gpr_data[i] = data.GetU32(&offset);
198+
SetError(GPRRegSet, Read, 0);
199+
} break;
200+
case FPURegSet:
201+
// TODO: fill in FPU regs....
202+
SetError(FPURegSet, Read, -1);
203+
break;
204+
case EXCRegSet:
205+
exc.trapno = data.GetU32(&offset);
206+
exc.err = data.GetU32(&offset);
207+
exc.faultvaddr = data.GetU64(&offset);
208+
SetError(EXCRegSet, Read, 0);
209+
break;
210+
default:
211+
offset += count * 4;
212+
break;
227213
}
228214
}
229215
}
@@ -353,11 +339,11 @@ class RegisterContextDarwin_x86_64_Mach : public RegisterContextDarwin_x86_64 {
353339
}
354340

355341
protected:
356-
int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return 0; }
342+
int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; }
357343

358-
int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return 0; }
344+
int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; }
359345

360-
int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return 0; }
346+
int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; }
361347

362348
int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override {
363349
return 0;

lldb/source/Plugins/Process/mach-core/RegisterContextUnifiedCore.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,15 +262,19 @@ size_t RegisterContextUnifiedCore::GetRegisterCount() {
262262

263263
const RegisterInfo *
264264
RegisterContextUnifiedCore::GetRegisterInfoAtIndex(size_t reg) {
265-
return &m_register_infos[reg];
265+
if (reg < m_register_infos.size())
266+
return &m_register_infos[reg];
267+
return nullptr;
266268
}
267269

268270
size_t RegisterContextUnifiedCore::GetRegisterSetCount() {
269271
return m_register_sets.size();
270272
}
271273

272274
const RegisterSet *RegisterContextUnifiedCore::GetRegisterSet(size_t set) {
273-
return &m_register_sets[set];
275+
if (set < m_register_sets.size())
276+
return &m_register_sets[set];
277+
return nullptr;
274278
}
275279

276280
bool RegisterContextUnifiedCore::ReadRegister(

0 commit comments

Comments
 (0)