2018-01-20

1. 背景/引言

不同于x86, x86-64的前6个参数没有压栈, 而是通过寄存器传递. 这样, 似乎无法通过bt -f来获得参数. 本文给出一个例子, 说明x86-64在一些情况下, 依旧能够获得函数的参数.

前6个参数分别存放到rdi, rsi, rdx, rcx, r8d, r9d.

2. 例子

crash> bt
PID: 4392   TASK: ffff8801b7af0880  CPU: 0   COMMAND: "your_cmd"
 #0 [ffff8801836b3af0] schedule at ffffffff8157cc1d
 #1 [ffff8801836b3bc8] schedule_timeout at ffffffff8157dc75
 #2 [ffff8801836b3c98] structone_mod_free at ffffffffa0771156 [your_kmod]
 #3 [ffff8801836b3d08] free_structone at ffffffffa077146b [your_kmod]
 ...略...
 #9 [ffff8801836b3eb8] kthread at ffffffff810ac69e
#10 [ffff8801836b3f48] kernel_thread at ffffffff8100c38a

这里想知道传递给structone_mod_free的参数的具体值. 其原型是 void structone_mod_free(struct structone *structone)

crash> bt -f
...省略...
 #1 [ffff8801836b3bc8] schedule_timeout at ffffffff8157dc75
    ffff8801836b3bd0: ffffffff8302e658 ffffffff810ace2a 
    ffff8801836b3be0: ffffffff8302e640 ffff8801bb635810 
    ffff8801836b3bf0: ffff8801bb635828 0000000000000046 
    ffff8801836b3c00: ffff8801bb635810 0000000000000282 
    ffff8801836b3c10: 0000000000000282 ffff8801bb635810 
    ffff8801836b3c20: ffff8801836b3c30 ffffffff810c6cad 
    ffff8801836b3c30: ffff8801836b3c50 0000000000000282 
    ffff8801836b3c40: ffff8801bb635810 0000000000000000 
    ffff8801836b3c50: ffff8801836b3c90 00000000bc3fea60 
    ffff8801836b3c60: ffff8801836b3ce0 ffff8801bb635800 
    ffff8801836b3c70: ffff8801836b3ca0 ffff8801b6d5eb60 (r13)
    ffff8801836b3c80: ffff8801bb635810(r14) 7fffffffffffffff  (r15)
    ffff8801836b3c90: ffff8801836b3d00 (bp)    ffffffffa0771156(ra) 
 #2 [ffff8801836b3c98] structone_mod_free at ffffffffa0771156 [your_kmod]
    ffff8801836b3ca0: 0000000000000000 ffff8801b7af0880 
    ffff8801836b3cb0: ffffffff810acb20 ffff8801bb635850 
    ffff8801836b3cc0: ffff8801bb635850 0000000000000282 
    ffff8801836b3cd0: ffff8801836b3ce0 ffff8801b6d5eb60 
    ffff8801836b3ce0: ffff8801b5fe76b8 ffff8801bb1091e0 
    ffff8801836b3cf0: 0000000000000000 0000000000000000 
    ffff8801836b3d00: ffff8801836b3d30 ffffffffa077146b 
 #3 [ffff8801836b3d08] free_structone at ffffffffa077146b [your_kmod]
 ...省略...
crash> disass structone_mod_free
Dump of assembler code for function structone_mod_free:
   0xffffffffa07710b0 <+0>:     push   %rbp   #应该是 ffff8801836b3d30
   0xffffffffa07710b1 <+1>:     mov    %rsp,%rbp
   0xffffffffa07710b4 <+4>:     sub    $0x60,%rsp
   0xffffffffa07710b8 <+8>:     mov    %rbx,-0x28(%rbp)  #
   0xffffffffa07710bc <+12>:    mov    %r12,-0x20(%rbp)
   0xffffffffa07710c0 <+16>:    mov    %r13,-0x18(%rbp)
   0xffffffffa07710c4 <+20>:    mov    %r14,-0x10(%rbp)
   0xffffffffa07710c8 <+24>:    mov    %r15,-0x8(%rbp)



   0xffffffffa07710cc <+28>:    nopl   0x0(%rax,%rax,1)
   0xffffffffa07710d1 <+33>:    mov    0x88(%rdi),%rbx   #访问structone的成员
   0xffffffffa07710d8 <+40>:    mov    %rdi,%r13  #备份参数struct structone *structone
   0xffffffffa07710db <+43>:    test   %rbx,%rbx

   ...
   0xffffffffa077114e <+158>:   mov    %r15,%rdi
   0xffffffffa0771151 <+161>:   callq  0xffffffff8157da10 <schedule_timeout>  #这里
   0xffffffffa0771156 <+166>:   test   %rax,%rax    

上面省略了部分汇编, 省略的那部分没有修改到 %r13.

crash> disass schedule_timeout
Dump of assembler code for function schedule_timeout:
   0xffffffff8157da10 <+0>:     push   %rbp
   0xffffffff8157da11 <+1>:     mov    %rsp,%rbp
   0xffffffff8157da14 <+4>:     sub    $0xc0,%rsp
   0xffffffff8157da1b <+11>:    mov    %rbx,-0x28(%rbp)
   0xffffffff8157da1f <+15>:    mov    %r12,-0x20(%rbp)
   0xffffffff8157da23 <+19>:    mov    %r13,-0x18(%rbp)
   0xffffffff8157da27 <+23>:    mov    %r14,-0x10(%rbp)
   0xffffffff8157da2b <+27>:    mov    %r15,-0x8(%rbp)   

看到将r13第3个压栈.

结合bt -f, 可知参数存放的地址是 0xffff8801b6d5eb60.
crash> p *(struct structone *)0xffff8801b6d5eb60
或者 crash> structone 0xffff8801b6d5eb60
即可知 structone 的具体值了.

3. 参考资料

https://people.redhat.com/anderson/crash_whitepaper/help_pages/bt.html

http://www.x86-64.org/documentation/abi.pdf

本文地址: https://awakening-fong.github.io/posts/debug/crash_func_args_x86_64

转载请注明出处: https://awakening-fong.github.io


若无法评论, 请打开JavaScript, 并通过proxy.


blog comments powered by Disqus