这篇文章对于一些经常用gdb的大牛来说应该是最基本的东西了,但是这里我只想分享一些基本的工具或者其他我找到的一些有用的东西。
如果你正在从gdb向lldb转换的话,这两者在命令上还是有些不同的。LLDB已经有 文档说明 了两者的不同点。本文中关于LLDB的调试信息都是源于那篇说明文档的。
l r (run the program) l s (step in) l n (step over) l finish (step out) l c (continue) l q (quit the program)
可以使用enter键运行最后一条指令,这个比较有用,你可以一直步过一些重复的调用。
我一直在OSX上用LLDB。我可以调试一个我自己创建的但是crash或者出现其他意外的程序:
$ sudo lldb ./asmttpd web_root
设置断点,跳转至指定label:
(lldb) b sys_write Breakpoint 3: where = asmttpd`sys_write, address = 0x00000000000029a
运行程序直到断点断下:
(lldb) r Process 32236 launched: './asmttpd' (x86_64) Process 32236 stopped * thread #1: tid = 0xe69b9, 0x00000000000029ae asmttpd`sys_write, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1 frame #0: 0x00000000000029ae asmttpd`sys_writeasmttpd`sys_write: -> 0x29ae <+0>: pushq %rdi 0x29af <+1>: pushq %rsi 0x29b0 <+2>: pushq %rdx 0x29b1 <+3>: pushq %r10
查看当前栈帧更多的信息:
(lldb) d asmttpd`sys_write: -> 0x29ae <+0>: pushq %rdi 0x29af <+1>: pushq %rsi 0x29b0 <+2>: pushq %rdx 0x29b1 <+3>: pushq %r10 0x29b3 <+5>: pushq %r8 0x29b5 <+7>: pushq %r9 0x29b7 <+9>: pushq %rbx 0x29b8 <+10>: pushq %rcx 0x29b9 <+11>: movq %rsi, %rdx 0x29bc <+14>: movq %rdi, %rsi 0x29bf <+17>: movq $0x1, %rdi 0x29c6 <+24>: movq $0x2000004, %rax 0x29cd <+31>: syscall 0x29cf <+33>: popq %rcx 0x29d0 <+34>: popq %rbx 0x29d1 <+35>: popq %r9 0x29d3 <+37>: popq %r8 0x29 <+39>: popq %r10 0x29d7 <+41>: popq %rdx 0x29d8 <+42>: popq %rsi 0x29d9 <+43>: popq %rdi 0x29da <+44>: retq
回溯查看:
(lldb) bt * thread #1: tid = 0xe69b9, 0x00000000000029ae asmttpd`sys_write, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1 * frame #0: 0x00000000000029ae asmttpd`sys_write frame #1: 0x00000000000021b6 asmttpd`print_line + 16 frame #2: 0x0000000000002ab3 asmttpd`start + 35 frame #3: 0x00007fff9900c5ad libdyld.dylib`start + 1 frame #4: 0x00007fff9900c5ad libdyld.dylib`start + 1
查看当前栈帧的前栈帧:
(lldb) up frame #1: 0x00000000000021b6 asmttpd`print_line + 16 asmttpd`print_line: 0x21b6 <+16>: movabsq $0x30cb, %rdi 0x21c0 <+26>: movq $0x1, %rsi 0x21c7 <+33>: callq 0x29ae ; sys_write 0x21cc <+38>: popq %rcx
返回至断点处的栈帧:
(lldb) down frame #0: 0x00000000000029ae asmttpd`sys_write asmttpd`sys_write: -> 0x29ae <+0>: pushq %rdi 0x29af <+1>: pushq %rsi 0x29b0 <+2>: pushq %rdx 0x29b1 <+3>: pushq %r10
dump寄存器的值:
(lldb) register read General Purpose Registers: rax = 0x0000000000002a90 asmttpd`start rbx = 0x0000000000000000 rcx = 0x00007fff5fbffaf8 rdx = 0x00007fff5fbffa40 rdi = 0x00000000000030cc start_text rsi = 0x000000000000000f rbp = 0x00007fff5fbffa18 rsp = 0x00007fff5fbff9b8 r8 = 0x0000000000000000 r9 = 0x00007fff7b1670c8 atexit_mutex + 24 r10 = 0x00000000ffffffff r11 = 0xffffffff00000000 r12 = 0x0000000000000000 r13 = 0x0000000000000000 r14 = 0x0000000000000000 r15 = 0x0000000000000000 rip = 0x00000000000029ae asmttpd`sys_write rflags = 0x0000000000000246 cs = 0x000000000000002b fs = 0x0000000000000000 gs = 0x0000000000000000
读某一个寄存器的值:
(lldb) register read rdi rdi = 0x00000000000030cc start_text
当你想找出一段由C代码编译的系统调用时,使用dtruss非常有用。dtruss在OSX上可以直接获得。这个命令似乎是Dtrace的一个变种。
$ cat sleep.c #include <time.h> int main () { struct timespec rqtp = { 2, 0 }; nanosleep(&rqtp, NULL); } $ clang sleep.c $ sudo dtruss ./a.out ...all kinds of fun stuff __semwait_signal(0xB03, 0x0, 0x1) = -1 Err#60
如果你用-g命令编译代码从而获得调试符号,你可以使用lldb的反编译命令来获得相同的汇编代码:
$ clang sleep.c -g $ lldb a.out (lldb) target create "a.out" Current executable set to 'a.out' (x86_64). (lldb) b main Breakpoint 1: where = a.out`main + 16 at sleep.c:3, address = 0x0000000100000f40 (lldb) r Process 33213 launched: '/Users/Nicholas/code/assembly/asmttpd/a.out' (x86_64) Process 33213 stopped * thread #1: tid = 0xeca04, 0x0000000100000f40 a.out`main + 16 at sleep.c:3, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x0000000100000f40 a.out`main + 16 at sleep.c:3 1 #include <time.h> 2 int main () { -> 3 struct timespec rqtp = { 4 2, 5 0 6 }; 7 (lldb) disassemble a.out`main: 0x100000f30 <+0>: pushq %rbp 0x100000f31 <+1>: movq %rsp, %rbp 0x100000f34 <+4>: subq $0x20, %rsp 0x100000f38 <+8>: leaq -0x10(%rbp), %rdi 0x100000f3c <+12>: xorl %eax, %eax 0x100000f3e <+14>: movl %eax, %esi -> 0x100000f40 <+16>: movq 0x49(%rip), %rcx 0x100000f47 <+23>: movq %rcx, -0x10(%rbp) 0x100000f4b <+27>: movq 0x46(%rip), %rcx 0x100000f52 <+34>: movq %rcx, -0x8(%rbp) 0x100000f56 <+38>: callq 0x100000f68 ; symbol stub for: nanosleep 0x100000f5b <+43>: xorl %edx, %edx 0x100000f5d <+45>: movl %eax, -0x14(%rbp) 0x100000f60 <+48>: movl %edx, %eax 0x100000f62 <+50>: addq $0x20, %rsp 0x100000f66 <+54>: popq %rbp 0x100000f67 <+55>: retq
如果你想学习更多关于X86-64的汇编代码编程的话,可以读下 writing X86-64 这篇博客。
*原文地址: nickdesaulniers ,FB小编老王隔壁的白帽子编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)