OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can be | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 #include <assert.h> | |
8 #include <errno.h> | |
9 #include <stdio.h> | |
10 #include <stdlib.h> | |
11 #include <string.h> | |
12 #include <sys/mman.h> | |
13 #include <unistd.h> | |
14 | |
15 #include "native_client/src/include/elf32.h" | |
16 #include "native_client/src/include/elf_auxv.h" | |
17 #include "native_client/src/include/nacl_macros.h" | |
18 #include "native_client/src/trusted/service_runtime/include/sys/unistd.h" | |
19 #include "native_client/src/untrusted/irt/irt.h" | |
20 | |
21 | |
eliben
2013/10/08 23:24:16
A comment in this file explaining what it contains
Mark Seaborn
2013/10/10 23:55:49
I've added a comment.
| |
22 void _user_start(void *info); | |
23 | |
24 static __thread void *g_tls_value; | |
25 | |
26 | |
27 static int irt_close(int fd) { | |
28 if (close(fd) != 0) | |
29 return errno; | |
30 return 0; | |
31 } | |
32 | |
33 static int irt_write(int fd, const void *buf, size_t count, size_t *nwrote) { | |
34 int result = write(fd, buf, count); | |
35 if (result < 0) | |
36 return errno; | |
37 *nwrote = result; | |
38 return 0; | |
39 } | |
40 | |
41 static int irt_fstat(int fd, struct stat *st) { | |
42 /* TODO(mseaborn): Implement this and convert "struct stat". */ | |
43 return ENOSYS; | |
44 } | |
45 | |
46 static void irt_exit(int status) { | |
47 _exit(status); | |
48 } | |
49 | |
50 static int irt_sysconf(int name, int *value) { | |
51 switch (name) { | |
52 case NACL_ABI__SC_PAGESIZE: | |
53 /* | |
54 * For now, return the host's page size (typically 4k) rather | |
55 * than 64k (NaCl's usual page size), which pexes will usually | |
56 * be tested with. We could change this to 64k, but then the | |
57 * mmap() we define here should round up requested sizes to | |
58 * multiples of 64k. | |
59 */ | |
60 *value = getpagesize(); | |
61 return 0; | |
62 default: | |
63 return EINVAL; | |
64 } | |
65 } | |
66 | |
67 static int irt_mmap(void **addr, size_t len, int prot, int flags, | |
68 int fd, off_t off) { | |
69 void *result = mmap(*addr, len, prot, flags, fd, off); | |
70 if (result == MAP_FAILED) | |
71 return errno; | |
72 *addr = result; | |
73 return 0; | |
74 } | |
75 | |
76 static int tls_init(void *ptr) { | |
77 g_tls_value = ptr; | |
78 return 0; | |
79 } | |
80 | |
81 static void *tls_get(void) { | |
82 return g_tls_value; | |
83 } | |
84 | |
85 void *__nacl_read_tp(void) { | |
86 return g_tls_value; | |
87 } | |
88 | |
89 static void irt_stub_func(const char *name) { | |
90 fprintf(stderr, "Error: Unimplemented IRT function: %s\n", name); | |
91 abort(); | |
92 } | |
93 | |
94 #define DEFINE_STUB(name) \ | |
95 static void irt_stub_##name() { irt_stub_func(#name); } | |
96 #define USE_STUB(s, name) (typeof(s.name)) irt_stub_##name | |
97 | |
98 DEFINE_STUB(gettod) | |
99 DEFINE_STUB(clock) | |
100 DEFINE_STUB(nanosleep) | |
101 DEFINE_STUB(sched_yield) | |
102 static struct nacl_irt_basic irt_basic = { | |
103 irt_exit, | |
104 USE_STUB(irt_basic, gettod), | |
105 USE_STUB(irt_basic, clock), | |
106 USE_STUB(irt_basic, nanosleep), | |
107 USE_STUB(irt_basic, sched_yield), | |
108 irt_sysconf, | |
109 }; | |
110 | |
111 DEFINE_STUB(dup) | |
112 DEFINE_STUB(dup2) | |
113 DEFINE_STUB(read) | |
114 DEFINE_STUB(seek) | |
115 DEFINE_STUB(getdents) | |
116 static struct nacl_irt_fdio irt_fdio = { | |
117 irt_close, | |
118 USE_STUB(irt_fdio, dup), | |
119 USE_STUB(irt_fdio, dup2), | |
120 USE_STUB(irt_fdio, read), | |
121 irt_write, | |
122 USE_STUB(irt_fdio, seek), | |
123 irt_fstat, | |
124 USE_STUB(irt_fdio, getdents), | |
125 }; | |
126 | |
127 DEFINE_STUB(munmap) | |
128 DEFINE_STUB(mprotect) | |
129 static struct nacl_irt_memory irt_memory = { | |
130 irt_mmap, | |
131 USE_STUB(irt_memory, munmap), | |
132 USE_STUB(irt_memory, mprotect), | |
133 }; | |
134 | |
135 static struct nacl_irt_tls irt_tls = { | |
136 tls_init, | |
137 tls_get, | |
138 }; | |
139 | |
140 struct nacl_interface_table { | |
141 const char *name; | |
142 const void *table; | |
143 size_t size; | |
144 }; | |
145 | |
146 static const struct nacl_interface_table irt_interfaces[] = { | |
147 { NACL_IRT_BASIC_v0_1, &irt_basic, sizeof(irt_basic) }, | |
148 { NACL_IRT_FDIO_v0_1, &irt_fdio, sizeof(irt_fdio) }, | |
149 { NACL_IRT_MEMORY_v0_3, &irt_memory, sizeof(irt_memory) }, | |
150 { NACL_IRT_TLS_v0_1, &irt_tls, sizeof(irt_tls) }, | |
151 }; | |
152 | |
153 static size_t irt_interface_query(const char *interface_ident, | |
154 void *table, size_t tablesize) { | |
155 unsigned i; | |
156 for (i = 0; i < NACL_ARRAY_SIZE(irt_interfaces); ++i) { | |
157 if (0 == strcmp(interface_ident, irt_interfaces[i].name)) { | |
158 const size_t size = irt_interfaces[i].size; | |
159 if (size <= tablesize) { | |
160 memcpy(table, irt_interfaces[i].table, size); | |
161 return size; | |
162 } | |
163 break; | |
164 } | |
165 } | |
166 fprintf(stderr, "Warning: unavailable IRT interface queried: %s\n", | |
167 interface_ident); | |
168 return 0; | |
169 } | |
170 | |
171 /* Layout for empty argv/env arrays. */ | |
172 struct startup_info { | |
173 void (*cleanup_func)(); | |
174 int envc; | |
175 int argc; | |
176 char *argv0; | |
177 char *envp0; | |
178 Elf32_auxv_t auxv[2]; | |
179 }; | |
180 | |
181 int main(int argc, char **argv) { | |
182 /* TODO(mseaborn): Copy across argv and environment arrays. */ | |
183 struct startup_info info; | |
184 info.cleanup_func = NULL; | |
185 info.envc = 0; | |
186 info.argc = 0; | |
187 info.argv0 = NULL; | |
188 info.envp0 = NULL; | |
189 info.auxv[0].a_type = AT_SYSINFO; | |
190 info.auxv[0].a_un.a_val = (uintptr_t) irt_interface_query; | |
191 info.auxv[1].a_type = 0; | |
192 info.auxv[1].a_un.a_val = 0; | |
193 | |
194 _user_start(&info); | |
195 return 1; | |
196 } | |
OLD | NEW |