Chromium Code Reviews| Index: crosstest/stack_hack.x8664.c |
| diff --git a/crosstest/stack_hack.x8664.c b/crosstest/stack_hack.x8664.c |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4f7715beda23e175c94f1511eed8b53dd0b76ce1 |
| --- /dev/null |
| +++ b/crosstest/stack_hack.x8664.c |
| @@ -0,0 +1,76 @@ |
| +//===- subzero/crosstest/stack_hack.x8664.c.h - X8664 stack hack ----------===// |
|
Jim Stichnoth
2015/08/10 16:08:04
no .h
John
2015/08/10 20:41:16
Done.
|
| +// |
| +// The Subzero Code Generator |
| +// |
| +// This file is distributed under the University of Illinois Open Source |
| +// License. See LICENSE.TXT for details. |
| +// |
| +//===----------------------------------------------------------------------===// |
| +// |
| +// Implements main() for crosstests in x86-64. |
| +// |
| +//===----------------------------------------------------------------------===// |
| +#include <assert.h> |
| +#include <stdint.h> |
| + |
| +#include <sys/mman.h> |
| + |
| +// X8664_STACK_HACK needs to be defined before xdefs.h is included. |
| +#define X8664_STACK_HACK |
| +#include "xdefs.h" |
| + |
| +/// xSetStack is used to set %rsp to NewRsp. OldRsp is a pointer that will be |
| +/// used to save the old %rsp value. |
| +#define xSetStack(NewRsp, OldRsp) \ |
| + do { \ |
| + __asm__ volatile("xchgq %1, %%rsp\n\t" \ |
| + "xchgq %1, %0" \ |
| + : "=r"(*(OldRsp)) \ |
| + : "r"(NewRsp)); \ |
| + } while (0) |
| + |
| +extern int wrapped_main(int argc, char *argv[]); |
| + |
| +unsigned char *xStackStart(uint32 StackEnd, uint32 Size) { |
| + const uint32 PageBoundary = 4 << 20; // 4 MB. |
|
Jim Stichnoth
2015/08/10 16:08:04
May want to "(void)PageBoundary;" in case we ever
John
2015/08/10 20:41:16
Done.
|
| + const uint64 StackStart = StackEnd - Size; |
| + assert(StackStart + (PageBoundary - 1) & ~(PageBoundary - 1) && |
| + "StackStart not aligned to page boundary."); |
| + assert((StackStart & 0xFFFFFFFF00000000ull) == 0 && "StackStart wraps."); |
| + return (unsigned char *)StackStart; |
| +} |
| + |
| +unsigned char *xAllocStack(uint64 StackEnd, uint32 Size) { |
| + assert((StackEnd & 0xFFFFFFFF00000000ull) == 0 && "Invalid StackEnd."); |
| + void *Foo = xStackStart(StackEnd, Size); |
|
Jim Stichnoth
2015/08/10 16:08:04
Foo?
John
2015/08/10 20:41:16
Bar instead?
Jim Stichnoth
2015/08/11 16:01:36
Made me look, well played sir.
|
| + void *Stack = |
| + mmap(xStackStart(StackEnd, Size), Size, PROT_READ | PROT_WRITE, |
| + MAP_FIXED | MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS, -1, 0); |
| + assert(Stack != MAP_FAILED && "mmap failed. no stack."); |
| + return Stack; |
| +} |
| + |
| +void xDeallocStack(uint64 StackEnd, uint32 Size) { |
| + assert((StackEnd & 0xFFFFFFFF00000000ull) == 0 && "Invalid StackEnd."); |
| + munmap(xStackStart(StackEnd, Size), Size); |
| +} |
| + |
| +int main(int argc, char *argv[]) { |
| + // These "locals" need to live **NOT** in the stack. |
| + static int Argc; |
| + static char **Argv; |
| + static const uint32_t StackEnd = 0x80000000; |
| + static const uint32_t StackSize = 40 * 1024 * 1024; |
| + static unsigned char *new_rsp; |
| + static unsigned char *old_rsp; |
| + static unsigned char *dummy_rsp; |
| + static int Failures; |
| + Argc = argc; |
| + Argv = argv; |
| + new_rsp = xAllocStack(StackEnd, StackSize) + StackSize; |
| + xSetStack(new_rsp, &old_rsp); |
| + Failures = wrapped_main(Argc, Argv); |
| + xSetStack(old_rsp, &new_rsp); |
| + xDeallocStack(StackEnd, StackSize); |
| + return Failures; |
| +} |