Last active
February 6, 2017 21:23
-
-
Save abadams/89d7b64139d8faeb9cc0fa6d3a93f982 to your computer and use it in GitHub Desktop.
Demonstration of swapping out the stack pointer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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