C++ Logo


Advanced search

[std-proposals] #include <call_stack>

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Wed, 31 May 2023 08:20:13 +0100
A month or two ago I suggested that we should have a standard library
function to get the value of the stack pointer, and also the frame pointer.

Another useful function for analysing and manipulating the stack would be
as follows:

      void set_stack_pointer_and_invoke( char *custom_stack, void
(*funcptr)(void) );

You would use this function to invoke another function with your own custom
stack, for example:

    char *const mystack = new char[4096u];
    set_stack_pointer_and_invoke( mystack + 4088u, SomeLibraryFunction );

Since the stack grows negatively on x86_64, I add 4088 to it to give it the
highest address for a 64-Bit value. Alternatively the function could take a
third parameter to indicate the size of the stack and let the compiler
decide how to calculate it. Here's one way of determining it:

bool stack_grows_positively_Detail(int *const p)
    return static_cast<uintptr_t>(p) < static_cast<uintptr_t>(&p);

bool stack_grows_positively(void)
    int i;
    return stack_grows_positively_Detail(&i);

This would serve two purposes:
(1) If you have a recursive function that will re-enter thousands of times,
then you can temporarily allocate a stack in the gigabytes.
(2) If the stack isn't executable, and you need to execute the stack. Or,
if the stack _is_executable, and you want to prevent execution of the stack
(for added security when calling 3rd party library functions).

The x86_64 assembler for changing and later restoring the stack pointer is
as follows:

    push r15 ; callee-saved
    mov r15,rsp ; save the original stack pointer
    mov rsp,rdi ; set the stack pointer
    call rsi ; invoke the function pointer
    mov rsp,r15 ; restore the original stack pointer
    pop r15 ; restore the original value of r15

I have this working for x86_64 up on GodBolt with support for exception


Received on 2023-05-31 07:20:16