转载

X86-64下的汇编代码调试解析

这篇文章对于一些经常用gdb的大牛来说应该是最基本的东西了,但是这里我只想分享一些基本的工具或者其他我找到的一些有用的东西。

如果你正在从gdb向lldb转换的话,这两者在命令上还是有些不同的。LLDB已经有 文档说明 了两者的不同点。本文中关于LLDB的调试信息都是源于那篇说明文档的。

基本的gdb和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)

原文  http://www.freebuf.com/articles/web/94291.html
正文到此结束
Loading...