31

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Juicy
  • 11,840
  • 35
  • 123
  • 212

10 Answers10

53

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

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 1
    yeah I can't think of a better way in std C, The OP should be aware that the declaration of p probably happens as part of the function predicate after the last frame is pushed and before this is completely constructed... probably. – Grady Player Nov 18 '13 at 23:00
  • 11
    There's no need to initialize `p`, since its value is never used -- nor is there any particular reason to make `p` a `void*` (it might as well be an `int`). The correct format for a `void*` value is `%p`, not `%d` -- and you need to convert the pointer value to `void*`. So: `int dummy; printf("%p\n", (void*)&dummy);`. (You also misspelled `printf`.) But yes, that seems to give a reasonable approximation of the current stack pointer. – Keith Thompson Nov 18 '13 at 23:28
  • 7
    @KeithThompson i realize the `NULL` init is unnecessary but I also can't force myself to write code that uses an uninitialize variable. It feels dirtier than printing out the stack pointer :) – JaredPar Nov 18 '13 at 23:35
  • 5
    @JaredPar: There are plenty of things you can do with an uninitialized variable -- like assigning a value to it. Only using its *value* causes problems. – Keith Thompson Nov 18 '13 at 23:41
  • What if the compiler inlines this `print_stack_pointer` function into the caller function by the compiler, and then `p` somehow gets on top of other variables? – Daniel Chin Apr 12 '23 at 04:01
24

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.

Community
  • 1
  • 1
duedl0r
  • 9,289
  • 3
  • 30
  • 45
14

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

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
5

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!

Paschalis
  • 11,929
  • 9
  • 52
  • 82
  • You don't need your PID, you can always use `/proc/self/stat` – Peter Cordes Jul 15 '19 at 01:01
  • That is true, for the case you want to do it for your own process. This would be weird though, as this very action would probably shift the SP. I ended up using inline assembly arch-specific approach back then! – Paschalis Jul 15 '19 at 10:25
  • I assumed this question was asking about getting your own stack-pointer value. (So yes, inline asm is obviously much better.) If you want another process's current stack pointer, `ptrace(2)` can read registers. This answer is kind of for a related question, like the lowest address of your stack mapping, which is a reasonable thing to also want to know from inside a process. – Peter Cordes Jul 15 '19 at 10:31
2

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.

peterh
  • 11,875
  • 18
  • 85
  • 108
baz
  • 1,317
  • 15
  • 10
  • I'd recommend only using `"=r"`. clang unfortunately always picks memory when it's an option. Omitting `"=m"` works around this braindead optimization bug. Also, use `uintptr_t`. – Peter Cordes Jul 15 '19 at 00:59
  • I get **radically** different values from this than the accepted answer that takes the address of a local variable. E.g., 0x7FFEE0DA8190 from this, 0x1168bf020 from the other way. Furthermore, this way gives values that decrease as you go deeper into a call chain, and the other way gives values that increase. (Tested on Mac, 64 bits, Clang.) – JWWalker Feb 13 '21 at 00:39
  • Don't you have to use `movq`, to be able to move a 64 bit value? – vmemmap Aug 13 '22 at 10:39
1

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.

Garmekain
  • 664
  • 5
  • 18
  • 2
    `[stack]` only appears for the initial/main thread's stack. Thread stacks don't get that tag so this isn't useful in a multi-threaded process. You don't have to be root to read your own `/proc/self/maps`, though. – Peter Cordes Jul 15 '19 at 01:00
1

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

Victor Choy
  • 4,006
  • 28
  • 35
1

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.

Renate
  • 761
  • 4
  • 11
1

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

Zambu
  • 11
  • 2
0

You may use the following:

uint32_t msp_value = __get_MSP(); // Read Main Stack pointer

By the same way if you want to get the PSP value:

uint32_t psp_value = __get_PSP(); // Read Process Stack pointer

If you want to use assembly language, you can also use MSP and PSP process:

MRS R0, MSP // Read Main Stack pointer to R0
 
MRS R0, PSP // Read Process Stack pointer to R0
user16217248
  • 3,119
  • 19
  • 19
  • 37