[Lldb-commits] [lldb] [lldb] [debugserver] Use "full" x86_64 GPR state when available. (PR #108663)
https://github.com/mrpippy created https://github.com/llvm/llvm-project/pull/108663 macOS 10.15 added a "full" x86_64 GPR thread state flavor, equivalent to the normal one but with DS, ES, SS, and GSbase added. This flavor can only be used with processes that install a custom LDT (functionality that was also added in 10.15 and is used by apps like Wine to execute 32-bit code). Along with allowing DS, ES, SS, and GSbase to be viewed/modified, using the full flavor is necessary when debugging a thread executing 32-bit code. If thread_set_state() is used with the regular thread state flavor, the kernel resets CS to the 64-bit code segment (see [set_thread_state64()](https://github.com/apple-oss-distributions/xnu/blob/94d3b452840153a99b38a3a9659680b2a006908e/osfmk/i386/pcb.c#L723), which makes debugging impossible. There's no way to detect whether the full flavor is available, try to use it and fall back to the regular one if it's not available. A downside is that this patch exposes the DS, ES, SS, and GSbase registers for all x86_64 processes, even though they are not populated unless the full thread state is available. I'm not sure if there's a way to tell LLDB that a register is unavailable. The classic GDB `g` command [allows returning `x`](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html#Packets) to denote unavailable registers, but it seems like the debug server uses newer commands like `jThreadsInfo` and I'm not sure if those have the same support. Fixes #57591 (also filed as Apple FB11464104) @jasonmolenda >From 4453801c7d8abf7a6adfb7fae57ad9fa9d52a0c4 Mon Sep 17 00:00:00 2001 From: Brendan Shanks Date: Thu, 12 Sep 2024 16:01:30 -0700 Subject: [PATCH] [lldb] [debugserver] Use "full" x86_64 GPR state when available. macOS 10.15 added a "full" x86_64 GPR thread state flavor, equivalent to the normal one but with DS, ES, SS, and GSbase added. This flavor can only be used with processes that install a custom LDT (functionality that was also added in 10.15 and is used by apps like Wine to execute 32-bit code). Along with allowing DS, ES, SS, and GSbase to be viewed/modified, using the full flavor is necessary when debugging a thread executing 32-bit code. If thread_set_state() is used with the regular thread state flavor, the kernel resets CS to the 64-bit code segment, which makes debugging impossible. There's no way to detect whether the full flavor is available, try to use it and fall back to the regular one if it's not available. A downside is that this patch exposes the DS, ES, SS, and GSbase registers for all x86_64 processes, even though they are not populated unless the full thread state is available. Fixes #57591 --- .../MacOSX/x86_64/DNBArchImplX86_64.cpp | 52 +++ .../source/MacOSX/x86_64/DNBArchImplX86_64.h | 4 +- .../MacOSX/x86_64/MachRegisterStatesX86_64.h | 5 ++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 5a62e2a8d12e2c..286fd72267b349 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -182,22 +182,39 @@ kern_return_t DNBArchImplX86_64::GetGPRState(bool force) { m_state.context.gpr.__gs = ('g' << 8) + 's'; m_state.SetError(e_regSetGPR, Read, 0); #else -mach_msg_type_number_t count = e_regSetWordSizeGPR; +mach_msg_type_number_t count = e_regSetWordSizeGPRFull; +int flavor = __x86_64_THREAD_FULL_STATE; m_state.SetError( e_regSetGPR, Read, -::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, +::thread_get_state(m_thread->MachPortNumber(), flavor, (thread_state_t)&m_state.context.gpr, &count)); + +if (!m_state.GetError(e_regSetGPR, Read)) { + m_state.hasFullGPRState = true; +} else { + m_state.hasFullGPRState = false; + count = e_regSetWordSizeGPR; + flavor = __x86_64_THREAD_STATE; + m_state.SetError( + e_regSetGPR, Read, + ::thread_get_state(m_thread->MachPortNumber(), flavor, + (thread_state_t)&m_state.context.gpr, &count)); +} DNBLogThreadedIf( LOG_THREAD, -"::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" +"::thread_get_state (0x%4.4x, %u (%s), &gpr, %u) => 0x%8.8x" "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" "\n\trip = %16.16llx" -"\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", -m_thread->MachPortNumber(), x86_THREAD_STATE64,
[Lldb-commits] [lldb] [lldb] [debugserver] Use "full" x86_64 GPR state when available. (PR #108663)
mrpippy wrote: Great, no I don't think I have permissions to merge. I pushed a new version that fixed a typo in the `GetGPRState` log call, and in `SetGPRState` adds the new fields to the log call. https://github.com/llvm/llvm-project/pull/108663 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] [lldb] [debugserver] Use "full" x86_64 GPR state when available. (PR #108663)
https://github.com/mrpippy updated https://github.com/llvm/llvm-project/pull/108663 >From a9b19cbd20083e2b1d6c8de342206cb0ec6183b7 Mon Sep 17 00:00:00 2001 From: Brendan Shanks Date: Thu, 12 Sep 2024 16:01:30 -0700 Subject: [PATCH] [lldb] [debugserver] Use "full" x86_64 GPR state when available. macOS 10.15 added a "full" x86_64 GPR thread state flavor, equivalent to the normal one but with DS, ES, SS, and GSbase added. This flavor can only be used with processes that install a custom LDT (functionality that was also added in 10.15 and is used by apps like Wine to execute 32-bit code). Along with allowing DS, ES, SS, and GSbase to be viewed/modified, using the full flavor is necessary when debugging a thread executing 32-bit code. If thread_set_state() is used with the regular thread state flavor, the kernel resets CS to the 64-bit code segment, which makes debugging impossible. There's no way to detect whether the full flavor is available, try to use it and fall back to the regular one if it's not available. A downside is that this patch exposes the DS, ES, SS, and GSbase registers for all x86_64 processes, even though they are not populated unless the full thread state is available. Fixes #57591 --- .../MacOSX/x86_64/DNBArchImplX86_64.cpp | 67 +++ .../source/MacOSX/x86_64/DNBArchImplX86_64.h | 4 +- .../MacOSX/x86_64/MachRegisterStatesX86_64.h | 5 ++ 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 5a62e2a8d12e2c..3b3f1f02a2851f 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -182,22 +182,39 @@ kern_return_t DNBArchImplX86_64::GetGPRState(bool force) { m_state.context.gpr.__gs = ('g' << 8) + 's'; m_state.SetError(e_regSetGPR, Read, 0); #else -mach_msg_type_number_t count = e_regSetWordSizeGPR; +mach_msg_type_number_t count = e_regSetWordSizeGPRFull; +int flavor = __x86_64_THREAD_FULL_STATE; m_state.SetError( e_regSetGPR, Read, -::thread_get_state(m_thread->MachPortNumber(), __x86_64_THREAD_STATE, +::thread_get_state(m_thread->MachPortNumber(), flavor, (thread_state_t)&m_state.context.gpr, &count)); + +if (!m_state.GetError(e_regSetGPR, Read)) { + m_state.hasFullGPRState = true; +} else { + m_state.hasFullGPRState = false; + count = e_regSetWordSizeGPR; + flavor = __x86_64_THREAD_STATE; + m_state.SetError( + e_regSetGPR, Read, + ::thread_get_state(m_thread->MachPortNumber(), flavor, + (thread_state_t)&m_state.context.gpr, &count)); +} DNBLogThreadedIf( LOG_THREAD, -"::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x" +"::thread_get_state (0x%4.4x, %u (%s), &gpr, %u) => 0x%8.8x" "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx" "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx" "\n\t r8 = %16.16llx r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx" "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx" "\n\trip = %16.16llx" -"\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx", -m_thread->MachPortNumber(), x86_THREAD_STATE64, -x86_THREAD_STATE64_COUNT, m_state.GetError(e_regSetGPR, Read), +"\n\tflg = %16.16llx cs = %16.16llx fs = %16.16llx gs = %16.16llx" +"\n\t ds = %16.16llx es = %16.16llx ss = %16.16llx gsB = %16.16llx", +m_thread->MachPortNumber(), flavor, +m_state.hasFullGPRState ? "full" : "non-full", +m_state.hasFullGPRState ? e_regSetWordSizeGPRFull +: e_regSetWordSizeGPR, +m_state.GetError(e_regSetGPR, Read), m_state.context.gpr.__rax, m_state.context.gpr.__rbx, m_state.context.gpr.__rcx, m_state.context.gpr.__rdx, m_state.context.gpr.__rdi, m_state.context.gpr.__rsi, @@ -208,7 +225,9 @@ kern_return_t DNBArchImplX86_64::GetGPRState(bool force) { m_state.context.gpr.__r14, m_state.context.gpr.__r15, m_state.context.gpr.__rip, m_state.context.gpr.__rflags, m_state.context.gpr.__cs, m_state.context.gpr.__fs, -m_state.context.gpr.__gs); +m_state.context.gpr.__gs, m_state.context.gpr.__ds, +m_state.context.gpr.__es, m_state.context.gpr.__ss, +m_state.context.gpr.__gsbase ); // DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) // => 0x%8.8x" @@ -459,21 +478,26 @@ kern_return_t DNBArchImplX86_64::SetGPRState() { "(SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount()); + mach_msg_type_number_t count