1 /*
2 * Stack-less Just-In-Time compiler
3 *
4 * Copyright Zoltan Herczeg ([email protected]). All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without modification, are
7 * permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice, this list of
10 * conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 * of conditions and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE COPYRIGHT HOLDER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #define SLJIT_HAS_CHUNK_HEADER
28 #define SLJIT_HAS_EXECUTABLE_OFFSET
29
30 struct sljit_chunk_header {
31 void *executable;
32 };
33
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <stdio.h>
37 #include <string.h>
38
39 #ifndef O_NOATIME
40 #define O_NOATIME 0
41 #endif
42
43 /* this is a linux extension available since kernel 3.11 */
44 #ifndef O_TMPFILE
45 #define O_TMPFILE 0x404000
46 #endif
47
48 #ifndef _GNU_SOURCE
49 char *secure_getenv(const char *name);
50 int mkostemp(char *template, int flags);
51 #endif
52
create_tempfile(void)53 static SLJIT_INLINE int create_tempfile(void)
54 {
55 int fd;
56 char tmp_name[256];
57 size_t tmp_name_len = 0;
58 char *dir;
59 struct stat st;
60 #if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
61 mode_t mode;
62 #endif
63
64 #ifdef HAVE_MEMFD_CREATE
65 /* this is a GNU extension, make sure to use -D_GNU_SOURCE */
66 fd = memfd_create("sljit", MFD_CLOEXEC);
67 if (fd != -1) {
68 fchmod(fd, 0);
69 return fd;
70 }
71 #endif
72
73 dir = secure_getenv("TMPDIR");
74
75 if (dir) {
76 size_t len = strlen(dir);
77 if (len > 0 && len < sizeof(tmp_name)) {
78 if ((stat(dir, &st) == 0) && S_ISDIR(st.st_mode)) {
79 memcpy(tmp_name, dir, len + 1);
80 tmp_name_len = len;
81 }
82 }
83 }
84
85 #ifdef P_tmpdir
86 if (!tmp_name_len) {
87 tmp_name_len = strlen(P_tmpdir);
88 if (tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name))
89 strcpy(tmp_name, P_tmpdir);
90 }
91 #endif
92 if (!tmp_name_len) {
93 strcpy(tmp_name, "/tmp");
94 tmp_name_len = 4;
95 }
96
97 SLJIT_ASSERT(tmp_name_len > 0 && tmp_name_len < sizeof(tmp_name));
98
99 if (tmp_name_len > 1 && tmp_name[tmp_name_len - 1] == '/')
100 tmp_name[--tmp_name_len] = '\0';
101
102 fd = open(tmp_name, O_TMPFILE | O_EXCL | O_RDWR | O_NOATIME | O_CLOEXEC, 0);
103 if (fd != -1)
104 return fd;
105
106 if (tmp_name_len >= sizeof(tmp_name) - 7)
107 return -1;
108
109 strcpy(tmp_name + tmp_name_len, "/XXXXXX");
110 #if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
111 mode = umask(0777);
112 #endif
113 fd = mkostemp(tmp_name, O_CLOEXEC | O_NOATIME);
114 #if defined(SLJIT_SINGLE_THREADED) && SLJIT_SINGLE_THREADED
115 umask(mode);
116 #else
117 fchmod(fd, 0);
118 #endif
119
120 if (fd == -1)
121 return -1;
122
123 if (unlink(tmp_name)) {
124 close(fd);
125 return -1;
126 }
127
128 return fd;
129 }
130
alloc_chunk(sljit_uw size)131 static SLJIT_INLINE struct sljit_chunk_header* alloc_chunk(sljit_uw size)
132 {
133 struct sljit_chunk_header *retval;
134 int fd;
135
136 fd = create_tempfile();
137 if (fd == -1)
138 return NULL;
139
140 if (ftruncate(fd, (off_t)size)) {
141 close(fd);
142 return NULL;
143 }
144
145 retval = (struct sljit_chunk_header *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
146
147 if (retval == MAP_FAILED) {
148 close(fd);
149 return NULL;
150 }
151
152 retval->executable = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
153
154 if (retval->executable == MAP_FAILED) {
155 munmap((void *)retval, size);
156 close(fd);
157 return NULL;
158 }
159
160 close(fd);
161 return retval;
162 }
163
free_chunk(void * chunk,sljit_uw size)164 static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
165 {
166 struct sljit_chunk_header *header = ((struct sljit_chunk_header *)chunk) - 1;
167
168 munmap(header->executable, size);
169 munmap((void *)header, size);
170 }
171
172 #include "sljitExecAllocatorCore.c"
173