OLD | NEW |
| (Empty) |
1 //===- subzero/crosstest/stack_hack.x8664.c - X8664 stack hack ------------===// | |
2 // | |
3 // The Subzero Code Generator | |
4 // | |
5 // This file is distributed under the University of Illinois Open Source | |
6 // License. See LICENSE.TXT for details. | |
7 // | |
8 //===----------------------------------------------------------------------===// | |
9 // | |
10 // Implements main() for crosstests in x86-64. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 #include <assert.h> | |
14 #include <stdint.h> | |
15 | |
16 #include <sys/mman.h> | |
17 | |
18 // X8664_STACK_HACK needs to be defined before xdefs.h is included. | |
19 #define X8664_STACK_HACK | |
20 #include "xdefs.h" | |
21 | |
22 /// xSetStack is used to set %rsp to NewRsp. OldRsp is a pointer that will be | |
23 /// used to save the old %rsp value. | |
24 #define xSetStack(NewRsp, OldRsp) \ | |
25 do { \ | |
26 __asm__ volatile("xchgq %1, %%rsp\n\t" \ | |
27 "xchgq %1, %0" \ | |
28 : "=r"(*(OldRsp)) \ | |
29 : "r"(NewRsp)); \ | |
30 } while (0) | |
31 | |
32 extern int wrapped_main(int argc, char *argv[]); | |
33 | |
34 unsigned char *xStackStart(uint32 StackEnd, uint32 Size) { | |
35 const uint32 PageBoundary = 4 << 20; // 4 MB. | |
36 const uint64 StackStart = StackEnd - Size; | |
37 assert(StackStart + (PageBoundary - 1) & ~(PageBoundary - 1) && | |
38 "StackStart not aligned to page boundary."); | |
39 (void)PageBoundary; | |
40 assert((StackStart & 0xFFFFFFFF00000000ull) == 0 && "StackStart wraps."); | |
41 return (unsigned char *)StackStart; | |
42 } | |
43 | |
44 unsigned char *xAllocStack(uint64 StackEnd, uint32 Size) { | |
45 assert((StackEnd & 0xFFFFFFFF00000000ull) == 0 && "Invalid StackEnd."); | |
46 void *Stack = | |
47 mmap(xStackStart(StackEnd, Size), Size, PROT_READ | PROT_WRITE, | |
48 MAP_FIXED | MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS, -1, 0); | |
49 assert(Stack != MAP_FAILED && "mmap failed. no stack."); | |
50 return Stack; | |
51 } | |
52 | |
53 void xDeallocStack(uint64 StackEnd, uint32 Size) { | |
54 assert((StackEnd & 0xFFFFFFFF00000000ull) == 0 && "Invalid StackEnd."); | |
55 munmap(xStackStart(StackEnd, Size), Size); | |
56 } | |
57 | |
58 int main(int argc, char *argv[]) { | |
59 // These "locals" need to live **NOT** in the stack. | |
60 static int Argc; | |
61 static char **Argv; | |
62 static const uint32_t StackEnd = 0x80000000; | |
63 static const uint32_t StackSize = 40 * 1024 * 1024; | |
64 static unsigned char *new_rsp; | |
65 static unsigned char *old_rsp; | |
66 static unsigned char *dummy_rsp; | |
67 static int Failures; | |
68 Argc = argc; | |
69 Argv = argv; | |
70 new_rsp = xAllocStack(StackEnd, StackSize) + StackSize; | |
71 xSetStack(new_rsp, &old_rsp); | |
72 Failures = wrapped_main(Argc, Argv); | |
73 xSetStack(old_rsp, &new_rsp); | |
74 xDeallocStack(StackEnd, StackSize); | |
75 return Failures; | |
76 } | |
OLD | NEW |