summaryrefslogtreecommitdiff
path: root/lang/ghc/files/extra-patch-rts-Linker.c
blob: 9aee62ebab8b9404a867b65efb9f9b2c078a179f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
--- rts/Linker.c.orig	2007-12-10 19:11:32.000000000 +0100
+++ rts/Linker.c	2008-01-09 22:17:46.459941137 +0100
@@ -59,12 +59,12 @@
 #include <sys/wait.h>
 #endif
 
-#if defined(ia64_HOST_ARCH) || defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS)
+#if defined(ia64_HOST_ARCH) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
 #define USE_MMAP
 #include <fcntl.h>
 #include <sys/mman.h>
 
-#if defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS)
+#if defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -1199,8 +1199,10 @@
    struct stat st;
    int r, n;
 #ifdef USE_MMAP
+   /* In the absence of a MAP_32BIT flag to mmap() we map objects one
+    * after the other starting from a fixed location in memory. */
    int fd, pagesize;
-   void *map_addr = NULL;
+   static void *map_addr = (void *)0x40000000L;
 #else
    FILE *f;
 #endif
@@ -1262,6 +1264,7 @@
 
 #ifdef USE_MMAP
 #define ROUND_UP(x,size) ((x + size - 1) & ~(size - 1))
+#define ROUND_DOWN(x,size) (x & ~(size - 1))
 
    /* On many architectures malloc'd memory isn't executable, so we need to use mmap. */
 
@@ -1278,7 +1281,7 @@
 #ifdef ia64_HOST_ARCH
    /* The PLT needs to be right before the object */
    n = ROUND_UP(PLTSize(), pagesize);
-   oc->plt = mmap(NULL, n, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+   oc->plt = mmap(map_addr, n, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
    if (oc->plt == MAP_FAILED)
       barf("loadObj: can't allocate PLT");
 
@@ -1297,7 +1300,7 @@
 #if defined(x86_64_HOST_ARCH) && defined(MAP_32BIT)
 #define EXTRA_MAP_FLAGS MAP_32BIT
 #else
-#define EXTRA_MAP_FLAGS 0
+#define EXTRA_MAP_FLAGS MAP_FIXED
 #endif
 
    /* MAP_ANONYMOUS is MAP_ANON on some systems, e.g. OpenBSD */
@@ -1309,6 +1312,7 @@
 		    MAP_PRIVATE|EXTRA_MAP_FLAGS, fd, 0);
    if (oc->image == MAP_FAILED)
       barf("loadObj: can't map `%s'", path);
+   map_addr += n;
 
    close(fd);
 
@@ -2596,10 +2600,12 @@
 #define Elf_Sym     Elf64_Sym
 #define Elf_Rel     Elf64_Rel
 #define Elf_Rela    Elf64_Rela
+#if !defined(freebsd_HOST_OS)
 #define ELF_ST_TYPE ELF64_ST_TYPE
 #define ELF_ST_BIND ELF64_ST_BIND
 #define ELF_R_TYPE  ELF64_R_TYPE
 #define ELF_R_SYM   ELF64_R_SYM
+#endif
 #else
 #define ELFCLASS    ELFCLASS32
 #define Elf_Addr    Elf32_Addr
@@ -2772,15 +2778,35 @@
 x86_64_high_symbol( char *lbl, void *addr )
 {
     x86_64_bounce *bounce;
+    int pagesize;
+
+    pagesize = getpagesize();
 
-    if ( x86_64_bounce_buffer == NULL || 
+    if ( x86_64_bounce_buffer == NULL ||
 	 x86_64_bb_next_off >= X86_64_BB_SIZE ) {
-	x86_64_bounce_buffer = 
-	    mmap(NULL, X86_64_BB_SIZE * sizeof(x86_64_bounce), 
-		 PROT_EXEC|PROT_READ|PROT_WRITE, 
-		 MAP_PRIVATE|EXTRA_MAP_FLAGS|MAP_ANONYMOUS, -1, 0);
+#ifdef MAP_32BIT
+	    x86_64_bounce_buffer =
+		mmap(NULL, X86_64_BB_SIZE * sizeof(x86_64_bounce),
+		     PROT_EXEC|PROT_READ|PROT_WRITE,
+		     MAP_PRIVATE|EXTRA_MAP_FLAGS|MAP_ANONYMOUS, -1, 0);
+#else
+#define X86_64_BOUNCE_BUFFER_TOP 0x80000000L;
+	    x86_64_bounce *map_addr;
+
+	    x86_64_bounce_buffer = x86_64_bounce_buffer ?
+		    x86_64_bounce_buffer : (x86_64_bounce *)X86_64_BOUNCE_BUFFER_TOP;
+	    map_addr = x86_64_bounce_buffer - X86_64_BB_SIZE;
+	    map_addr = ROUND_DOWN((int)map_addr, pagesize);
+	    /* In the absence of MAP_32BIT we allocate the bounce
+	     * buffers at a fixed address, one after the other,
+	     * starting from the top and growing downwards. */
+	    x86_64_bounce_buffer =
+		mmap(map_addr, X86_64_BB_SIZE * sizeof(x86_64_bounce),
+		     PROT_EXEC|PROT_READ|PROT_WRITE,
+		     MAP_PRIVATE|EXTRA_MAP_FLAGS|MAP_ANONYMOUS, -1, 0);
+#endif
 	if (x86_64_bounce_buffer == MAP_FAILED) {
-	    barf("x86_64_high_symbol: mmap failed");
+	    barf("x86_64_high_symbol: mmap failed at %p", x86_64_bounce_buffer);
 	}
 	x86_64_bb_next_off = 0;
     }