6

我正在做一些实验,并希望能够在系统调用期间查看堆栈中保存的内容(用户登陆进程的保存状态)。根据http://lxr.linux.no/#linux+v2.6.30.1/arch/x86/kernel/entry_32.S它表明寄存器的各种值保存在堆栈指针的那些特定偏移量处。这是我一直试图用来检查堆栈中保存的内容的代码(这是在我创建的自定义系统调用中):

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

其中 value 是一个无符号长整数。

截至目前,该值不是预期的(它显示为 ds 的用户值保存了 0)。

我是否正确访问堆栈指针的偏移量?

另一种可能性可能是我可以在内核中使用诸如 GDB 之类的调试器来检查堆栈内容吗?我在调试方面没有太多广泛的用途,并且不确定如何调试内核中的代码。任何帮助深表感谢。

4

3 回答 3

4

无需内联汇编。为系统调用推入堆栈的已保存状态entry_32.S被布置为struct pt_regs,您可以像这样获得指向它的指针(您需要直接或间接包含<asm/ptrace.h>和/或):<asm/processor.h>

struct pt_regs *regs = task_pt_regs(current);

于 2010-04-09T20:18:10.003 回答
3

内联汇编比看起来更棘手。试图尽快解决对 GCC 的担忧:

  1. 如果它修改了处理器寄存器,则必须将这些寄存器放在 clobber 列表中。请务必注意,clobber 列表必须包含您直接(显式读取)或间接(隐式读取)更改的所有寄存器;
  2. 为了强化(1),条件和数学运算也会改变寄存器,更多地称为状态标志(零,进位,溢出等),所以你必须通过在clobber列表中添加“cc”来通知它;
  3. 如果修改不同的(读取随机)内存位置,则添加“内存” ;
  4. 如果它修改了输入/输出参数中未提及的内存,则添加volatile关键字;

然后,您的代码变为:

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

输出参数不需要在clobber 列表中,因为GCC 已经知道它将被更改。

或者,由于您想要的只是 ESP 寄存器的值,因此您可以避免这样做的所有痛苦:

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

它可能无法解决您的问题,但这是要走的路。作为参考,请检查thisthisthis

于 2010-04-06T05:48:58.920 回答
0

请记住,x86_64 代码通常会在寄存器中传递值(因为它有很多)所以堆栈上不会有任何内容。检查 gcc 中间输出 ( -SIIRC) 并push在程序集中查找。

我不熟悉调试内核代码,但 gdb 肯定更好地以交互方式检查堆栈。

于 2010-04-06T05:33:33.697 回答