简体   繁体   English

如何确定堆栈中保存的值?

[英]How to determine values saved on the stack?

I'm doing some experimenting and would like to be able to see what is saved on the stack during a system call (the saved state of the user land process). 我正在做一些实验,并希望能够在系统调用期间查看堆栈中保存的内容(用户登陆过程的已保存状态)。 According to http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S it shows that the various values of registers are saved at those particular offsets to the stack pointer. 根据http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S它表明寄存器的各种值都保存在堆栈指针的那些特定偏移处。 Here is the code I have been trying to use to examine what is saved on the stack (this is in a custom system call I have created): 这是我一直试图用来检查堆栈上保存的代码的代码(这是我创建的自定义系统调用):

asm("movl 0x1C(%esp), %ecx");
asm("movl %%ecx, %0" : "=r" (value));

where value is an unsigned long. 其中value是unsigned long。

As of right now, this value is not what is expected (it is showing a 0 is saved for the user value of ds). 截至目前,该值不是预期的值(它显示为ds的用户值保存0)。

Am I correctly accessing the offset of the stack pointer? 我是否正确访问堆栈指针的偏移量?

Another possibility might be could I use a debugger such as GDB to examine the stack contents while in the kernel? 另一种可能性是我可以在内核中使用调试器(如GDB)来检查堆栈内容吗? I don't have much extensive use with debugging and am not sure of how to debug code inside the kernel. 我没有广泛使用调试,也不知道如何在内核中调试代码。 Any help is much appreciated. 任何帮助深表感谢。

No need for inline assembly. 无需内联装配。 The saved state that entry_32.S pushes onto the stack for a syscall is laid out as a struct pt_regs , and you can get a pointer to it like this (you'll need to include <asm/ptrace.h> and/or <asm/processor.h> either directly or indirectly): entry_32.S推送到堆栈以进行系统调用的已保存状态被布置为struct pt_regs ,您可以像这样获得指向它的指针(您需要包含<asm/ptrace.h>和/或<asm/processor.h>直接或间接):

struct pt_regs *regs = task_pt_regs(current);

Inline assembly is trickier than it seems. 内联汇编比看起来更棘手。 Trying to shortly cover the concerns for GCC: 试图简要介绍海湾合作委员会的担忧:

  1. If it modifies processor registers, it's necessary to put these registers on the clobber list. 如果它修改了处理器寄存器,则必须将这些寄存器放在clobber列表中。 It's important to note that the clobber list must contain ALL registers that you changed directly (read explicitly ) or indirectly (read implicitly ); 重要的是要注意,clobber列表必须包含您直接更改( 显式读取)或间接更改( 隐式读取)的所有寄存器;
  2. To reinforce (1), conditional and mathematical operations also change registers, more known as status flags (zero, carry, overflow, etc), so you have to inform it by adding "cc" to the clobber list; 为了强化(1),条件和数学运算也会改变寄存器,更多地称为状态标志(零,进位,溢出等),因此你必须通过在clobber列表中添加“cc”来通知它;
  3. Add "memory" if it modifies different (read random) memory positions; 如果它修改了不同的(随机读取)内存位置,则添加“内存” ;
  4. Add the volatile keyword if it modifies memory that isn't mentioned on the input/output arguments; 如果它修改了输入/输出参数中未提及的内存,则添加volatile关键字;

Then, your code becomes: 然后,您的代码变为:

asm("movl 0x1C(%%esp), %0;"
    : "=r" (value)
    : /* no inputs :) */
    /* no modified registers */
);

The output argument isn't required to be on the clobber list because GCC already knows it will be changed. 输出参数不需要在clobber列表中,因为GCC已经知道它将被更改。

Alternatively, since all you want is the value of ESP register, you can avoid all the pain doing this: 或者,因为你想要的只是ESP寄存器的值,你可以避免这样做的所有痛苦:

register int esp asm("esp");
esp += 0x1C;

It might not solve your problem, but it's the way to go. 它可能无法解决您的问题,但这是要走的路。 For reference, check this , this and this . 作为参考,请检查这个这个这个

Keep in mind that x86_64 code will often pass values in registers (since it has so many) so nothing will be on the stack. 请记住,x86_64代码通常会传递寄存器中的值(因为它有很多),因此堆栈中不会有任何内容。 Check the gcc intermediate output ( -S IIRC) and look for push in the assembly. 检查gcc中间输出( -S IIRC)并查看装配中的push

I'm not familiar with debugging kernel code, but gdb is definitely nicer to examine the stack interactively. 我不熟悉调试内核代码,但gdb绝对能更好地交互式地检查堆栈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM