LLDB中si指令无法按预期单步执行的问题求助
LLDB单步指令调试问题解决
问题现象
使用LLDB的si指令尝试单步执行汇编指令时,未按预期停在当前函数的下一条指令,反而直接跳进了libc库函数中,导致无法逐行调试main函数内的汇编代码。s指令与si表现一致,n指令可正常按源码行单步执行,需要找到真正单步执行一条指令即停的方法。
测试环境
- Linux Mint(运行于VirtualBox 7.0.10)
- 主机系统:MacOS Ventura 13.6
- LLDB版本:17.0.2
- 架构:x86-64
测试代码
#include <stdio.h> #include <stdlib.h> int main(){ printf("Hello \n"); printf("world\n"); printf("!\n"); exit(0); }
编译命令:clang test.c -o printf_test -g
调试过程
- 启动LLDB并在main函数设断点,查看汇编代码:
Process 2051 resuming Process 2051 stopped * thread #1, name = 'vuln-0', stop reason = breakpoint 1.1 frame #0: 0x000000000040114f vuln-0`main at task_5_vuln-0.c:5:2 2 #include <stdlib.h> 3 4 int main(){ -> 5 printf("Hello "); 6 printf("world"); 7 printf("\n"); 8 exit(0); (lldb) dis vuln-0`main: 0x401140 <+0>: pushq %rbp 0x401141 <+1>: movq %rsp, %rbp 0x401144 <+4>: subq $0x10, %rsp 0x401148 <+8>: movl $0x0, -0x4(%rbp) -> 0x40114f <+15>: leaq 0xeae(%rip), %rdi 0x401156 <+22>: movb $0x0, %al 0x401158 <+24>: callq 0x401030 ; symbol stub for: printf 0x40115d <+29>: leaq 0xea7(%rip), %rdi 0x401164 <+36>: movb $0x0, %al 0x401166 <+38>: callq 0x401030 ; symbol stub for: printf 0x40116b <+43>: leaq 0xe9f(%rip), %rdi 0x401172 <+50>: movb $0x0, %al 0x401174 <+52>: callq 0x401030 ; symbol stub for: printf 0x401179 <+57>: xorl %edi, %edi 0x40117b <+59>: callq 0x401040 ; symbol stub for: exit
- 执行
si后,未跳转到预期的0x401156 <+22>: movb $0x0, %al,而是进入libc的__fstatat64函数:
(lldb) si Process 2051 stopped * thread #1, name = 'vuln-0', stop reason = instruction step into frame #0: 0x00007ffff7e92eee libc.so.6`__GI___fstatat64(fd=1, file="", buf=0x00007fffffffd7e0, flag=4096) at fstatat64.c:168:3 (lldb) dis libc.so.6`__GI___fstatat64: 0x7ffff7e92ee0 <+0>: endbr64 0x7ffff7e92ee4 <+4>: movl %ecx, %r10d 0x7ffff7e92ee7 <+7>: movl $0x106, %eax ; imm = 0x106 0x7ffff7e92eec <+12>: syscall -> 0x7ffff7e92eee <+14>: cmpl $0xfffff000, %eax ; imm = 0xFFFFF000 0x7ffff7e92ef3 <+19>: ja 0x7ffff7e92f00 ; <+32> at fstatat64.c:167:5 0x7ffff7e92ef5 <+21>: xorl %eax, %eax 0x7ffff7e92ef7 <+23>: retq 0x7ffff7e92ef8 <+24>: nopl (%rax,%rax) 0x7ffff7e92f00 <+32>: movq 0x104f09(%rip), %rdx 0x7ffff7e92f07 <+39>: negl %eax 0x7ffff7e92f09 <+41>: movl %eax, %fs:(%rdx) 0x7ffff7e92f0c <+44>: movl $0xffffffff, %eax ; imm = 0xFFFFFFFF 0x7ffff7e92f11 <+49>: retq
- 继续执行
si多次后,程序直接结束,期间未返回main函数执行后续printf,但输出正常:
(lldb) si Process 2692 stopped * thread #1, name = 'vuln-0', stop reason = instruction step into frame #0: 0x00007ffff7dc5c87 libc.so.6`__GI___getrandom(buffer=0x00007ffff7f9f4d8, length=8, flags=1) at getrandom.c:29:10 (lldb) si Process 2692 stopped * thread #1, name = 'vuln-0', stop reason = instruction step into frame #0: 0x00007ffff7e999db libc.so.6`__brk(addr=0x0000000000000000) at brk.c:36:12 (lldb) si Hello Process 2692 stopped * thread #1, name = 'vuln-0', stop reason = instruction step into frame #0: 0x00007ffff7e93a37 libc.so.6`__GI___libc_write(fd=1, buf=0x00000000004052a0, nbytes=7) at write.c:26:10 (lldb) si world ! Process 2692 exited with status = 0 (0x00000000)
解决方法
使用
ni指令:ni(next instruction)指令会执行当前汇编指令,遇到callq这类函数调用时直接执行完整个函数,然后停在调用后的下一条指令,完美实现"单步一条指令即停"的需求。设置跳过库函数的单步规则:
如果需要严格在当前可执行文件模块内单步执行所有指令,不想进入任何库函数,可以通过LLDB设置跳过指定库的函数:
settings set target.process.thread.step-avoid-regexp "^libc.so.6`"
设置后再使用si,就只会在当前程序模块内单步执行汇编指令,不会跳进libc等库函数中。
内容的提问来源于stack exchange,提问作者John554
相关产品推荐
相关产品推荐

