blob: 45b0bb7fee829fb10d7a33def1d9838c4c0ec0c0 [file] [log] [blame]
//===- subzero/crosstest/stack_hack.x8664.c - X8664 stack hack ------------===//
//
// 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.
const uint64 StackStart = StackEnd - Size;
assert(StackStart + (PageBoundary - 1) & ~(PageBoundary - 1) &&
"StackStart not aligned to page boundary.");
(void)PageBoundary;
assert((StackStart & 0xFFFFFFFF00000000ull) == 0 && "StackStart wraps.");
return (unsigned char *)StackStart;
}
unsigned char *xAllocStack(uint64 StackEnd, uint32 Size) {
assert((StackEnd & 0xFFFFFFFF00000000ull) == 0 && "Invalid StackEnd.");
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;
}