x86-64下, crash通过bt -f找出函数参数
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