Skip to content

Commit 37cd595

Browse files
authored
[lldb][debugserver] Upstream to debugserver changes (llvm#155733)
Review of diffs from lldb's internal debugserver and llvm.org main found two orphaned changes that should be upstreamed. First is in MachTask::ExceptionThread where we want to confirm that a mach exception messages is from the correct process before we process it. Second is that we want to run the arm64 register context through thread_convert_thread_state() after thread_get_state, and before thread_set_state, to re-sign fp/sp/lr/pc appropriately for ptrauth (arm64e) processes.
1 parent 5dfc4f7 commit 37cd595

File tree

2 files changed

+72
-20
lines changed

2 files changed

+72
-20
lines changed

lldb/tools/debugserver/source/MacOSX/MachTask.mm

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,17 @@ static void get_threads_profile_data(DNBProfileDataScanType scanType,
877877
if (exception_message.CatchExceptionRaise(task)) {
878878
if (exception_message.state.task_port != task) {
879879
if (exception_message.state.IsValid()) {
880+
pid_t new_pid = -1;
881+
kern_return_t kr =
882+
pid_for_task(exception_message.state.task_port, &new_pid);
883+
pid_t old_pid = mach_proc->ProcessID();
884+
if (kr == KERN_SUCCESS && old_pid != new_pid) {
885+
DNBLogError("Got an exec mach message but the pid of "
886+
"the new task and the pid of the old task "
887+
"do not match, something is wrong.");
888+
// exit the thread.
889+
break;
890+
}
880891
// We exec'ed and our task port changed on us.
881892
DNBLogThreadedIf(LOG_EXCEPTIONS,
882893
"task port changed from 0x%4.4x to 0x%4.4x",

lldb/tools/debugserver/source/MacOSX/arm64/DNBArchImplARM64.cpp

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,24 @@ uint64_t DNBArchMachARM64::GetSP(uint64_t failValue) {
199199
return failValue;
200200
}
201201

202+
static void log_signed_registers(arm_thread_state64_t *gpr, const char *desc) {
203+
if (DNBLogEnabledForAny(LOG_THREAD)) {
204+
const char *log_str = "%s signed regs "
205+
"\n fp=%16.16llx"
206+
"\n lr=%16.16llx"
207+
"\n sp=%16.16llx"
208+
"\n pc=%16.16llx";
209+
#if defined(DEBUGSERVER_IS_ARM64E)
210+
DNBLogThreaded(log_str, desc, reinterpret_cast<uint64_t>(gpr->__opaque_fp),
211+
reinterpret_cast<uint64_t>(gpr->__opaque_lr),
212+
reinterpret_cast<uint64_t>(gpr->__opaque_sp),
213+
reinterpret_cast<uint64_t>(gpr->__opaque_pc));
214+
#else
215+
DNBLogThreaded(log_str, desc, gpr->__fp, gpr->__lr, gpr->__sp, gpr->__pc);
216+
#endif
217+
}
218+
}
219+
202220
kern_return_t DNBArchMachARM64::GetGPRState(bool force) {
203221
int set = e_regSetGPR;
204222
// Check if we have valid cached registers
@@ -210,25 +228,29 @@ kern_return_t DNBArchMachARM64::GetGPRState(bool force) {
210228
kern_return_t kret =
211229
::thread_get_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64,
212230
(thread_state_t)&m_state.context.gpr, &count);
213-
if (DNBLogEnabledForAny(LOG_THREAD)) {
214-
uint64_t *x = &m_state.context.gpr.__x[0];
231+
log_signed_registers(&m_state.context.gpr, "Values from thread_get_state");
215232

216-
const char *log_str = "thread_get_state signed regs "
217-
"\n fp=%16.16llx"
218-
"\n lr=%16.16llx"
219-
"\n sp=%16.16llx"
220-
"\n pc=%16.16llx";
221-
#if defined(DEBUGSERVER_IS_ARM64E)
222-
DNBLogThreaded(log_str,
223-
reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_fp),
224-
reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_lr),
225-
reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_sp),
226-
reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_pc));
227-
#else
228-
DNBLogThreaded(log_str, m_state.context.gpr.__fp, m_state.context.gpr.__lr,
229-
m_state.context.gpr.__sp, m_state.context.gpr.__pc);
230-
#endif
233+
#if defined(THREAD_CONVERT_THREAD_STATE_TO_SELF) && defined(__LP64__)
234+
if (kret == KERN_SUCCESS) {
235+
mach_msg_type_number_t newcount = ARM_THREAD_STATE64_COUNT;
236+
arm_thread_state64_t new_gpr;
237+
kern_return_t convert_kret = thread_convert_thread_state(
238+
m_thread->MachPortNumber(), THREAD_CONVERT_THREAD_STATE_TO_SELF,
239+
ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, count,
240+
(thread_state_t)&new_gpr, &newcount);
241+
DNBLogThreadedIf(
242+
LOG_THREAD,
243+
"converted register values "
244+
"to debugserver's keys, return value %d, old count %d new count %d",
245+
convert_kret, count, newcount);
246+
if (convert_kret == KERN_SUCCESS)
247+
memcpy(&m_state.context.gpr, &new_gpr, count * 4);
248+
log_signed_registers(&m_state.context.gpr,
249+
"Values after thread_convert_thread_state");
250+
}
251+
#endif // THREAD_CONVERT_THREAD_STATE_TO_SELF
231252

253+
if (DNBLogEnabledForAny(LOG_THREAD)) {
232254
#if defined(DEBUGSERVER_IS_ARM64E)
233255
uint64_t log_fp = clear_pac_bits(
234256
reinterpret_cast<uint64_t>(m_state.context.gpr.__opaque_fp));
@@ -244,6 +266,7 @@ kern_return_t DNBArchMachARM64::GetGPRState(bool force) {
244266
uint64_t log_sp = m_state.context.gpr.__sp;
245267
uint64_t log_pc = m_state.context.gpr.__pc;
246268
#endif
269+
uint64_t *x = &m_state.context.gpr.__x[0];
247270
DNBLogThreaded(
248271
"thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x (count = %u) regs"
249272
"\n x0=%16.16llx"
@@ -567,10 +590,28 @@ kern_return_t DNBArchMachARM64::GetSMEState(bool force) {
567590
}
568591

569592
kern_return_t DNBArchMachARM64::SetGPRState() {
593+
arm_thread_state64_t *state_to_set = &m_state.context.gpr;
594+
#if defined(THREAD_CONVERT_THREAD_STATE_FROM_SELF) && defined(__LP64__)
595+
mach_msg_type_number_t count = ARM_THREAD_STATE64_COUNT;
596+
mach_msg_type_number_t new_count = ARM_THREAD_STATE64_COUNT;
597+
arm_thread_state64_t new_gpr;
598+
memcpy(&new_gpr, &m_state.context.gpr, count * 4);
599+
kern_return_t convert_kret = thread_convert_thread_state(
600+
m_thread->MachPortNumber(), THREAD_CONVERT_THREAD_STATE_FROM_SELF,
601+
ARM_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, count,
602+
(thread_state_t)&new_gpr, &new_count);
603+
if (convert_kret == KERN_SUCCESS)
604+
state_to_set = &new_gpr;
605+
DNBLogThreadedIf(LOG_THREAD,
606+
"converted register values "
607+
"to inferior's keys, return value %d, count %d",
608+
convert_kret, new_count);
609+
#endif // THREAD_CONVERT_THREAD_STATE_TO_SELF
610+
570611
int set = e_regSetGPR;
571-
kern_return_t kret = ::thread_set_state(
572-
m_thread->MachPortNumber(), ARM_THREAD_STATE64,
573-
(thread_state_t)&m_state.context.gpr, e_regSetGPRCount);
612+
kern_return_t kret =
613+
::thread_set_state(m_thread->MachPortNumber(), ARM_THREAD_STATE64,
614+
(thread_state_t)state_to_set, e_regSetGPRCount);
574615
m_state.SetError(set, Write,
575616
kret); // Set the current write error for this register set
576617
m_state.InvalidateRegisterSetState(set); // Invalidate the current register

0 commit comments

Comments
 (0)