You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

调试过程

  1. 启动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
  1. 执行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
  1. 继续执行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) 

解决方法

  1. 使用ni指令:
    ni(next instruction)指令会执行当前汇编指令,遇到callq这类函数调用时直接执行完整个函数,然后停在调用后的下一条指令,完美实现"单步一条指令即停"的需求。

  2. 设置跳过库函数的单步规则:
    如果需要严格在当前可执行文件模块内单步执行所有指令,不想进入任何库函数,可以通过LLDB设置跳过指定库的函数:

settings set target.process.thread.step-avoid-regexp "^libc.so.6`"

设置后再使用si,就只会在当前程序模块内单步执行汇编指令,不会跳进libc等库函数中。

内容的提问来源于stack exchange,提问作者John554

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 21:30:56