From: Yuichiro NAITO Subject: lldb: Show consistent stack pointer value with GDB To: tech@openbsd.org Date: Fri, 30 Aug 2024 18:21:14 +0900 While I see the top of the backtrace frame in the kernel core file, the stack register value is differs from what GDB shows. For example, the kernel core file that is written by ddb, the stack pointer of the crashed thread is saved by the 'savectx' function. GDB rollbacks the pointer to the position when the beginning of the 'savectx' function is called. The lldb in my code won't. The lldb shows as follows. ``` (lldb) register read General Purpose Registers: rbp = 0xffff80001c9e2460 rsp = 0xffff80001c9e2208 rip = 0xffffffff81adbc0c bsd.0`db_fncall + 1052 21 registers were unavailable. ``` Gdb shows as follows. ``` (gdb) info registers rax 0x0 0 rbx 0x0 0 rcx 0x0 0 rdx 0x0 0 rsi 0x0 0 rdi 0x0 0 rbp 0xffff80001c9e2460 0xffff80001c9e2460 rsp 0xffff80001c9e2210 0xffff80001c9e2210 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 r13 0x0 0 r14 0x0 0 r15 0x0 0 rip 0xffffffff819f8723 0xffffffff819f8723 eflags 0x0 0 cs 0x0 0 ss 0x0 0 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 ``` In this case, the lldb `rsp` value is 8 bytes smaller than what of gdb. These 8 bytes are the return address from the 'savectx' function. And `rip` is also different. It is my fault way to read it from `struct pcb`. The 'savectx' function is called from the 'dumpsys' function so the GDB shows the right pointer. In the other case, `struct pcb` is written by the 'cpu_switchto' function and the same thing happens. I fixed these cases to be consistent with GDB on amd64, i386, and arm64 architectures. OK? diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp index 1ebfc6a799f..34fc8067203 100644 --- a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_arm64.cpp @@ -91,7 +91,7 @@ bool RegisterContextOpenBSDKernel_arm64::ReadRegister( value = (u_int64_t)sf.sf_x29; return true; case gpr_sp_arm64: - value = (u_int64_t)pcb.pcb_sp; + value = (u_int64_t)(pcb.pcb_sp + sizeof(sf)); return true; case gpr_pc_arm64: value = (u_int64_t)sf.sf_lr; diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp index 9a909a4e07d..fcbe6d9000a 100644 --- a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp @@ -62,12 +62,13 @@ bool RegisterContextOpenBSDKernel_i386::ReadRegister( if ((pcb.pcb_flags & PCB_SAVECTX) != 0) { uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; switch (reg) { -#define PCBREG(x) \ - case lldb_##x##_i386: \ - value = pcb.pcb_##x; \ + case lldb_esp_i386: + value = (u_int32_t)pcb.pcb_ebp; + return true; + case lldb_ebp_i386: + value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_ebp, + error); return true; - PCBREG(ebp); - PCBREG(esp); case lldb_eip_i386: value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_ebp + 4, error); @@ -88,17 +89,21 @@ bool RegisterContextOpenBSDKernel_i386::ReadRegister( uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; switch (reg) { +#define PCBREG(x, offset) \ + case lldb_##x##_i386: \ + value = (u_int32_t)(pcb.pcb_##x + (offset)); \ + return true; #define SFREG(x) \ case lldb_##x##_i386: \ - value = sf.sf_##x; \ + value = (u_int32_t)sf.sf_##x; \ return true; SFREG(edi); SFREG(esi); SFREG(ebx); SFREG(eip); - PCBREG(ebp); - PCBREG(esp); + PCBREG(ebp, 0); + PCBREG(esp, sizeof(sf)); } #endif return false; diff --git a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp index 501fa858a92..a5eff4f42cf 100644 --- a/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp +++ b/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_x86_64.cpp @@ -77,9 +77,9 @@ bool RegisterContextOpenBSDKernel_x86_64::ReadRegister( case lldb_##x##_x86_64: \ value = (u_int64_t)sf.sf_##x; \ return true; -#define PCBREG(x) \ +#define PCBREG(x, offset) \ case lldb_##x##_x86_64: \ - value = pcb.pcb_##x; \ + value = pcb.pcb_##x + (offset); \ return true; switch (reg) { SFREG(r15); @@ -89,14 +89,14 @@ bool RegisterContextOpenBSDKernel_x86_64::ReadRegister( SFREG(rbp); SFREG(rbx); SFREG(rip); - PCBREG(rsp); + PCBREG(rsp, sizeof(sf)); } } else { switch (reg) { - PCBREG(rbp); - PCBREG(rsp); + PCBREG(rbp, 0); + PCBREG(rsp, 8); case lldb_rip_x86_64: - value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_rbp + 8, + value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_rsp, error); return true; } -- Yuichiro NAITO (naito.yuichiro@gmail.com)