views:

231

answers:

3

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. 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.

As of right now, this value is not what is expected (it is showing a 0 is saved for the user value of ds).

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? 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.

A: 

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. Check the gcc intermediate output (-S IIRC) and look for push in the assembly.

I'm not familiar with debugging kernel code, but gdb is definitely nicer to examine the stack interactively.

Nathan Kidd
+1  A: 

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. It's important to note that the clobber list must contain ALL registers that you changed directly (read explicitly) or indirectly (read implicitly);
  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 adding by "cc" to the clobber list;
  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;

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.

Alternatively, since all you want is the value of ESP register, you can avoid all the pain doing this:

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.

jweyrich
+2  A: 

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):

struct pt_regs *regs = task_pt_regs(current);

Matthew Slattery