Print out value of stack pointer
Asked Answered
C

10

33

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.

Cerography answered 18/11, 2013 at 22:52 Comment(3)
it will depend on architecture but in x86 the Register SP points to top of stack, BP points to base of stack frame... you could use inline asm to copy that to a void * and print that.Lavallee
Why do you ask? What is the purpose of this?Muff
@BasileStarynkevitch In my case to play with buffer overflowsCerography
A
54

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

Abreu answered 18/11, 2013 at 22:54 Comment(5)
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.Lavallee
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.Hewart
@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 :)Abreu
@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.Hewart
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?Meletius
L
25

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.

Logorrhea answered 18/11, 2013 at 23:23 Comment(3)
That seems to work for gcc. I doubt that it's portable to most other compilers.Hewart
Of course on 64 bits you'll want to use an integer type that is able to hold a pointer, ideally intptr_t from stdint.hPalatalized
it's also looks specific to the processor architecture (x86, probably works on ARM too)Kev
M
15

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

Muff answered 19/11, 2013 at 6:40 Comment(0)
Y
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!

Yuu answered 18/3, 2015 at 13:9 Comment(3)
You don't need your PID, you can always use /proc/self/statIon
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!Yuu
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.Ion
U
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.

Unterwalden answered 4/4, 2017 at 2:44 Comment(3)
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.Ion
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.)Mastrianni
Don't you have to use movq, to be able to move a 64 bit value?Parceling
P
2

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.

Prophet answered 12/2, 2022 at 15:31 Comment(2)
If you're willing to use functions POSIX deprecated and removed from POSIX 7, you can just use getcontext() directly.Opsonize
and getcontext and its family is removed from POSIX 2008 specification :3Denisse
H
2

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

Heliograph answered 15/4, 2022 at 23:52 Comment(0)
P
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.

Ponceau answered 20/8, 2018 at 19:44 Comment(1)
[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.Ion
S
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

Sly answered 14/4, 2020 at 6:59 Comment(0)
B
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
Barbuto answered 9/10, 2022 at 18:15 Comment(1)
You can use ` around code to format it. Good readability is always appreciatedJordan

© 2022 - 2024 — McMap. All rights reserved.