Question

How can I print out the current value at the stack pointer in C in Linux (Debian and Ubuntu)?

I tried google but found no results.

Was it helpful?

Solution

One trick, which is not portable or really even guaranteed to work, is to simple print out the address of a local as a pointer.

void print_stack_pointer() {
  void* p = NULL;
  printf("%p", (void*)&p);
}

This will essentially print out the address of p which is a good approximation of the current stack pointer

OTHER TIPS

There is no portable way to do that.

In GNU C, this may work for target ISAs that have a register named SP, including x86 where gcc recognizes "SP" as short for ESP or RSP.

// broken with clang, but usually works with GCC
register void *sp asm ("sp");
printf("%p", sp);

This usage of local register variables is now deprecated by GCC:

The only supported use for this feature is to specify registers for input and output operands when calling Extended asm

Defining a register variable does not reserve the register. Other than when invoking the Extended asm, the contents of the specified register are not guaranteed. For this reason, the following uses are explicitly not supported. If they appear to work, it is only happenstance, and may stop working as intended due to (seemingly) unrelated changes in surrounding code, or even minor changes in the optimization of a future version of gcc. ...

It's also broken in practice with clang where sp is treated like any other uninitialized variable.

In addition to duedl0r's answer with specifically GCC you could use __builtin_frame_address(0) which is GCC specific (but not x86 specific).

This should also work on Clang (but there are some bugs about it).

Taking the address of a local (as JaredPar answered) is also a solution.

Notice that AFAIK the C standard does not require any call stack in theory.

Remember Appel's paper: garbage collection can be faster than stack allocation; A very weird C implementation could use such a technique! But AFAIK it has never been used for C.

One could dream of a other techniques. And you could have split stacks (at least on recent GCC), in which case the very notion of stack pointer has much less sense (because then the stack is not contiguous, and could be made of many segments of a few call frames each).

On Linuxyou can use the proc pseudo-filesystem to print the stack pointer.

Have a look here, at the /proc/your-pid/stat pseudo-file, at the fields 28, 29.

startstack %lu The address of the start (i.e., bottom) of the stack.

kstkesp %lu The current value of ESP (stack pointer), as found in the kernel stack page for the process.

You just have to parse these two values!

You can also use an extended assembler instruction, for example:

#include <stdint.h>

uint64_t getsp( void )
{
    uint64_t sp;
    asm( "mov %%rsp, %0" : "=rm" ( sp ));
    return sp;
}

For a 32 bit system, 64 has to be replaced with 32, and rsp with esp.

You have that info in the file /proc/<your-process-id>/maps, in the same line as the string [stack] appears(so it is independent of the compiler or machine). The only downside of this approach is that for that file to be read it is needed to be root.

Try lldb or gdb. For example we can set backtrace format in lldb.

settings set frame-format "frame #${frame.index}: ${ansi.fg.yellow}${frame.pc}: {pc:${frame.pc},fp:${frame.fp},sp:${frame.sp}}  ${ansi.normal}{ ${module.file.basename}{\`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\n"

So we can print the bp , sp in debug such as

frame #10: 0x208895c4: pc:0x208895c4,fp:0x01f7d458,sp:0x01f7d414   UIKit`-[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 376

Look more at https://lldb.llvm.org/use/formatting.html

You can use setjmp. The exact details are implementation dependent, look in the header file.

#include <setjmp.h>
jmp_buf jmp;
setjmp(jmp);
printf("%08x\n", jmp[0].j_esp);

This is also handy when executing unknown code. You can check the sp before and after and do a longjmp to clean up.

If you are using msvc you can use the provided function _AddressOfReturnAddress()

It'll return the address of the return address, which is guaranteed to be the value of RSP at a functions' entry. Once you return from that function, the RSP value will be increased by 8 since the return address is pop'ed off. Using that information, you can write a simple function that return the current address of the stack pointer like this:

uintptr_t GetStackPointer() {
    return (uintptr_t)_AddressOfReturnAddress() + 0x8;
}

int main(int argc, const char argv[]) {
    uintptr_t rsp = GetStackPointer();
    printf("Stack pointer: %p\n", rsp);
}

Showcase

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top