Skip to content

Instantly share code, notes, and snippets.

@abadams
Last active February 6, 2017 21:23
Show Gist options
  • Save abadams/89d7b64139d8faeb9cc0fa6d3a93f982 to your computer and use it in GitHub Desktop.
Save abadams/89d7b64139d8faeb9cc0fa6d3a93f982 to your computer and use it in GitHub Desktop.
Demonstration of swapping out the stack pointer
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int silly_factorial(int i) {
if (i == 0) {
int x;
printf("Hello from %p\n", &x);
return 1;
}
return silly_factorial(i - 1) * i;
}
template<typename Callable>
void launch_helper(Callable *arg) {
printf("Hi!\n");
(*arg)();
}
template<typename Callable>
void run_with_big_stack(Callable &callable, size_t sz) {
uintptr_t arg_bits = (uintptr_t)(&callable);
uintptr_t launcher = (uintptr_t)(&launch_helper<Callable>);
char *mem = (char *)malloc(sz);
char *stack_end = mem + sz;
printf("New stack will start at %p and grow to %p\n",
stack_end, mem);
asm volatile (
"movq %[arg_bits], %%rdi\n" // first argument to launcher goes in rdi
"movq %%rsp, %%r12\n" // stash the old stack pointer in r12. It's callee-saved
"movq %[stack_end], %%rsp\n" // set new stack pointer
"callq *%[launcher]\n" // call inner function
"movq %%r12, %%rsp\n" // restore old stack pointer
: // outputs
: [arg_bits]"r"(arg_bits),
[stack_end]"r"(stack_end),
[launcher]"r"(launcher) // inputs
: "r12", "rdi" // clobbers
);
free(mem);
}
int main(int argc, char **argv) {
auto task = []() {printf("%d\n", silly_factorial(1024 * 1024));};
// Would crash with a stack overflow:
// task();
run_with_big_stack(task, 64 * 1024 * 1024);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment