如何知道崩溃转储中的函数的哪个参数属于哪个地址

时间:2021-11-22 18:49:16

I am new to crash dump analysis. Here is the output of bt -f of my vmcore and I want to see the value of the argument of the function foo that it was holding at that time. I have a 64-bit machine and browsing the code I found out that foo only accepts one argument. Anyways, is there a way to know which address belongs to which argument.

我对崩溃转储分析很陌生。这是vmcore的bt -f的输出我想看看函数foo的参数值。我有一个64位的机器,浏览了我发现foo只接受一个参数的代码。无论如何,是否有办法知道哪个地址属于哪个参数。

#4 [ffff8807adfaf8c0] foobar at ffffffffa11c7c15 [foo]
   ffff8807adfaf8c8: ffff881033e1d800 ffff8807adfaf8e8 
   ffff8807adfaf8d8: ffff8807adfaf938 ffffffffa11c7ce1

This is the register values at the end

这是末尾的寄存器值

RIP: 00007fa64fdfb907  RSP: 00007fff2a187ca0  RFLAGS: 00010246
RAX: 00000000000000a6  RBX: ffffffff8100b072  RCX: 00007fa6506f7390
RDX: 0000000000000000  RSI: 0000000000000000  RDI: 00007fa6508fe910
RBP: 00007fa6508fe8f0   R8: 00007fa6508fe930   R9: 0000000000000000
R10: 00007fff2a1884b0  R11: 0000000000000246  R12: 0000000000000000
R13: 0000000000000000  R14: 0000000000000000  R15: 00007fa6508fe990
ORIG_RAX: 00000000000000a6  CS: 0033  SS: 002b

1 个解决方案

#1


3  

The argument to foobar() was likely passed in a register, so it may not exist at any memory address at all. The type of the argument will dictate whether it was passed in a register, or in memory.

foobar()的参数可能是在寄存器中传递的,因此它可能根本不存在于任何内存地址。参数的类型将决定它是在寄存器中传递的,还是在内存中传递的。

You mentioned in your comment that the prototype of the function is:

你在评论中提到,这个函数的原型是:

static void foobar(struct bar *b)

So, the first argument is regular INTEGER type (as defined by the x86_64 ABI; this includes pointers). To find the value of that pointer argument, you'll need to look at the disassembly of your foo function from the entry point up until the current instruction (ie, that at RIP). The value would have been passed to the function in %rdi.

因此,第一个参数是正则整数类型(由x86_64 ABI定义);这包括指针)。要找到指针参数的值,您需要查看从入口点到当前指令(例如,位于RIP)的foo函数的分解。该值将被传递给%rdi中的函数。

However, the value in %rdi may have been overwritten, or modified, between function entry and the instruction that your dump happened. In that case, you may need to do a little detective-work to work backwards and find the argument that was originally passed.

但是,在函数条目和转储发生的指令之间,%rdi中的值可能被重写或修改。在这种情况下,您可能需要做一些检查工作,以便向后工作并找到最初传递的参数。

As a general approach, I'd suggest:

总的来说,我建议:

  • Get a disassembly of the function, from the entry point until the RIP shown.

    获取函数的分解,从入口点到显示的RIP。

  • Look at how %rdi is used in that disassembly. Is there anything that modified %rdi? Were there any function calls (which may themselves overwrite the %rdi value). If not, your argument was 00007fa6508fe910

    看看在拆卸过程中如何使用%rdi。有修改%rdi的东西吗?是否有任何函数调用(它们本身可能覆盖%rdi值)。如果不是,你的论点是00007fa6508fe910

  • If %rdi was modified, see if has been copied to another register, or saved on the stack. If not, see how the caller generated that pointer, by looking at its disassembly.

    如果修改了%rdi,请查看是否已复制到另一个寄存器,或保存到堆栈中。如果不是,请查看它的分解,看看调用者是如何生成该指针的。

#1


3  

The argument to foobar() was likely passed in a register, so it may not exist at any memory address at all. The type of the argument will dictate whether it was passed in a register, or in memory.

foobar()的参数可能是在寄存器中传递的,因此它可能根本不存在于任何内存地址。参数的类型将决定它是在寄存器中传递的,还是在内存中传递的。

You mentioned in your comment that the prototype of the function is:

你在评论中提到,这个函数的原型是:

static void foobar(struct bar *b)

So, the first argument is regular INTEGER type (as defined by the x86_64 ABI; this includes pointers). To find the value of that pointer argument, you'll need to look at the disassembly of your foo function from the entry point up until the current instruction (ie, that at RIP). The value would have been passed to the function in %rdi.

因此,第一个参数是正则整数类型(由x86_64 ABI定义);这包括指针)。要找到指针参数的值,您需要查看从入口点到当前指令(例如,位于RIP)的foo函数的分解。该值将被传递给%rdi中的函数。

However, the value in %rdi may have been overwritten, or modified, between function entry and the instruction that your dump happened. In that case, you may need to do a little detective-work to work backwards and find the argument that was originally passed.

但是,在函数条目和转储发生的指令之间,%rdi中的值可能被重写或修改。在这种情况下,您可能需要做一些检查工作,以便向后工作并找到最初传递的参数。

As a general approach, I'd suggest:

总的来说,我建议:

  • Get a disassembly of the function, from the entry point until the RIP shown.

    获取函数的分解,从入口点到显示的RIP。

  • Look at how %rdi is used in that disassembly. Is there anything that modified %rdi? Were there any function calls (which may themselves overwrite the %rdi value). If not, your argument was 00007fa6508fe910

    看看在拆卸过程中如何使用%rdi。有修改%rdi的东西吗?是否有任何函数调用(它们本身可能覆盖%rdi值)。如果不是,你的论点是00007fa6508fe910

  • If %rdi was modified, see if has been copied to another register, or saved on the stack. If not, see how the caller generated that pointer, by looking at its disassembly.

    如果修改了%rdi,请查看是否已复制到另一个寄存器,或保存到堆栈中。如果不是,请查看它的分解,看看调用者是如何生成该指针的。