Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / nacl_syscall_handlers_gen.py
1 #!/usr/bin/python
2 # Copyright (c) 2012 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 #  This script produces wrapped versions of syscall implementation
7 #  functions.  The wrappers extract syscall arguments from where the
8 #  syscall trampoline saves them.
9 #
10 #  Note that NaCl modules are always ILP32 and compiled with a
11 #  compiler that passes all arguments on the stack, but the service
12 #  runtime may be ILP32, LP64, or P64.  So we cannot use just char *
13 #  in the structure that we overlay on top of the stack memory to
14 #  extract system call arguments.  All syscall arguments are extracted
15 #  as uint32_t first, then cast to the desired type -- pointers are
16 #  not valid until they have been translated from user addresses to
17 #  system addresses, and this is the responsibility of the actual
18 #  system call handlers.
19 #
20 import getopt
21 import re
22 import sys
23
24 AUTOGEN_HEADER = """\
25 /*
26  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
27  *
28  * Automatically generated code.  See nacl_syscall_handlers_gen.py
29  *
30  * NaCl Server Runtime Service Call abstractions
31  */
32
33 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
34 #include "native_client/src/trusted/service_runtime/sys_exception.h"
35 #include "native_client/src/trusted/service_runtime/sys_fdio.h"
36 #include "native_client/src/trusted/service_runtime/sys_filename.h"
37 #include "native_client/src/trusted/service_runtime/sys_imc.h"
38 #include "native_client/src/trusted/service_runtime/sys_list_mappings.h"
39 #include "native_client/src/trusted/service_runtime/sys_memory.h"
40 #include "native_client/src/trusted/service_runtime/sys_parallel_io.h"
41
42 """
43
44
45 TABLE_INITIALIZER = """\
46
47 /* auto generated */
48
49 void NaClSyscallTableInit() {
50   int i;
51   for (i = 0; i < NACL_MAX_SYSCALLS; ++i) {
52     nacl_syscall[i].handler = &NaClSysNotImplementedDecoder;
53   }
54
55 %s
56 }
57 """
58
59
60 IMPLEMENTATION_SKELETON = """\
61 /* this function was automagically generated */
62 static int32_t %(name)sDecoder(struct NaClAppThread *natp) {
63 %(members)s\
64   return %(name)s(natp%(arglist)s);
65 }
66
67 /*
68  * Check that the function being wrapped has the same type as the type
69  * declared in SYSCALL_LIST.
70  */
71 static INLINE void AssertSameType_%(name)s(void) {
72   /* This assignment will give an error if the argument types don't match. */
73   int32_t (*dummy)(%(arg_type_list)s) = %(name)s;
74   /* 'dummy' is not actually a parameter but this suppresses the warning. */
75   UNREFERENCED_PARAMETER(dummy);
76 }
77 """
78
79 # Our syscall handling code, in nacl_syscall.S, always pushes the
80 # syscall arguments onto the untrusted user stack.  The syscall
81 # arguments get snapshotted from there into a per-syscall structure,
82 # to eliminate time-of-check vs time-of-use issues -- we always only
83 # refer to syscall arguments from this snapshot, rather than from the
84 # untrusted memory locations.
85
86
87 SYSCALL_LIST = [
88     ('NACL_sys_null', 'NaClSysNull', []),
89     ('NACL_sys_nameservice', 'NaClSysNameService', ['int *desc_in_out']),
90     ('NACL_sys_dup', 'NaClSysDup', ['int oldfd']),
91     ('NACL_sys_dup2', 'NaClSysDup2', ['int oldfd', 'int newfd']),
92     ('NACL_sys_open', 'NaClSysOpen',
93      ['char *pathname', 'int flags', 'int mode']),
94     ('NACL_sys_close', 'NaClSysClose', ['int d']),
95     ('NACL_sys_read', 'NaClSysRead',
96      ['int d', 'void *buf', 'size_t count']),
97     ('NACL_sys_write', 'NaClSysWrite',
98      ['int d', 'void *buf', 'size_t count']),
99     ('NACL_sys_lseek', 'NaClSysLseek',
100      ['int d', 'nacl_abi_off_t *offp', 'int whence']),
101     ('NACL_sys_ioctl', 'NaClSysIoctl',
102      ['int d', 'int request', 'void *arg']),
103     ('NACL_sys_fstat', 'NaClSysFstat',
104      ['int d', 'struct nacl_abi_stat *nasp']),
105     ('NACL_sys_stat', 'NaClSysStat',
106      ['const char *path', 'struct nacl_abi_stat *nasp']),
107     ('NACL_sys_getdents', 'NaClSysGetdents',
108      ['int d', 'void *buf', 'size_t count']),
109     ('NACL_sys_brk', 'NaClSysBrk', ['uintptr_t new_break']),
110     ('NACL_sys_mmap', 'NaClSysMmap',
111      ['void *start', 'size_t length', 'int prot',
112       'int flags', 'int d', 'nacl_abi_off_t *offp']),
113     ('NACL_sys_mprotect', 'NaClSysMprotect',
114      ['uint32_t start', 'size_t length', 'int prot']),
115     ('NACL_sys_list_mappings', 'NaClSysListMappings',
116      ['uint32_t regions', 'uint32_t count']),
117     ('NACL_sys_munmap', 'NaClSysMunmap', ['void *start', 'size_t length']),
118     ('NACL_sys_exit', 'NaClSysExit', ['int status']),
119     ('NACL_sys_getpid', 'NaClSysGetpid', []),
120     ('NACL_sys_thread_exit', 'NaClSysThreadExit',
121      ['int32_t *stack_flag']),
122     ('NACL_sys_gettimeofday', 'NaClSysGetTimeOfDay',
123      ['struct nacl_abi_timeval *tv', 'struct nacl_abi_timezone *tz']),
124     ('NACL_sys_clock', 'NaClSysClock', []),
125     ('NACL_sys_nanosleep', 'NaClSysNanosleep',
126      ['struct nacl_abi_timespec *req', 'struct nacl_abi_timespec *rem']),
127     ('NACL_sys_clock_getres', 'NaClSysClockGetRes',
128      ['int clk_id', 'uint32_t tsp']),
129     ('NACL_sys_clock_gettime', 'NaClSysClockGetTime',
130      ['int clk_id', 'uint32_t tsp']),
131     ('NACL_sys_mkdir', 'NaClSysMkdir', ['uint32_t path', 'int mode']),
132     ('NACL_sys_rmdir', 'NaClSysRmdir', ['uint32_t path']),
133     ('NACL_sys_chdir', 'NaClSysChdir', ['uint32_t path']),
134     ('NACL_sys_getcwd', 'NaClSysGetcwd', ['uint32_t buffer', 'int len']),
135     ('NACL_sys_unlink', 'NaClSysUnlink', ['uint32_t path']),
136     ('NACL_sys_pread', 'NaClSysPRead',
137      ['int32_t d', 'uint32_t usr_addr', 'uint32_t buffer_bytes',
138       'uint32_t offset_addr']),
139     ('NACL_sys_pwrite', 'NaClSysPWrite',
140      ['int32_t d', 'uint32_t usr_addr', 'uint32_t buffer_bytes',
141       'uint32_t offset_addr']),
142     ('NACL_sys_imc_makeboundsock', 'NaClSysImcMakeBoundSock',
143      ['int32_t *sap']),
144     ('NACL_sys_imc_accept', 'NaClSysImcAccept', ['int d']),
145     ('NACL_sys_imc_connect', 'NaClSysImcConnect', ['int d']),
146     ('NACL_sys_imc_sendmsg', 'NaClSysImcSendmsg',
147      ['int d', 'struct NaClAbiNaClImcMsgHdr *nanimhp', 'int flags']),
148     ('NACL_sys_imc_recvmsg', 'NaClSysImcRecvmsg',
149      ['int d', 'struct NaClAbiNaClImcMsgHdr *nanimhp', 'int flags']),
150     ('NACL_sys_imc_mem_obj_create', 'NaClSysImcMemObjCreate',
151      ['size_t size']),
152     ('NACL_sys_tls_init', 'NaClSysTlsInit', ['uint32_t thread_ptr']),
153     ('NACL_sys_thread_create', 'NaClSysThreadCreate',
154      ['void *prog_ctr', 'uint32_t stack_ptr',
155       'uint32_t thread_ptr', 'uint32_t second_thread_ptr']),
156     ('NACL_sys_tls_get', 'NaClSysTlsGet', []),
157     ('NACL_sys_thread_nice', 'NaClSysThreadNice', ['const int nice']),
158     ('NACL_sys_mutex_create', 'NaClSysMutexCreate', []),
159     ('NACL_sys_mutex_lock', 'NaClSysMutexLock',
160      ['int32_t mutex_handle']),
161     ('NACL_sys_mutex_unlock', 'NaClSysMutexUnlock',
162      ['int32_t mutex_handle']),
163     ('NACL_sys_mutex_trylock', 'NaClSysMutexTrylock',
164      ['int32_t mutex_handle']),
165     ('NACL_sys_cond_create', 'NaClSysCondCreate', []),
166     ('NACL_sys_cond_wait', 'NaClSysCondWait',
167      ['int32_t cond_handle', 'int32_t mutex_handle']),
168     ('NACL_sys_cond_signal', 'NaClSysCondSignal',
169      ['int32_t cond_handle']),
170     ('NACL_sys_cond_broadcast', 'NaClSysCondBroadcast',
171      ['int32_t cond_handle']),
172     ('NACL_sys_cond_timed_wait_abs', 'NaClSysCondTimedWaitAbs',
173      ['int32_t cond_handle', 'int32_t mutex_handle',
174       'struct nacl_abi_timespec *ts']),
175     ('NACL_sys_imc_socketpair', 'NaClSysImcSocketPair',
176      ['uint32_t descs_out']),
177     ('NACL_sys_sem_create', 'NaClSysSemCreate', ['int32_t init_value']),
178     ('NACL_sys_sem_wait', 'NaClSysSemWait', ['int32_t sem_handle']),
179     ('NACL_sys_sem_post', 'NaClSysSemPost', ['int32_t sem_handle']),
180     ('NACL_sys_sem_get_value', 'NaClSysSemGetValue',
181      ['int32_t sem_handle']),
182     ('NACL_sys_sched_yield', 'NaClSysSchedYield', []),
183     ('NACL_sys_sysconf', 'NaClSysSysconf', ['int32_t name', 'int32_t *result']),
184     ('NACL_sys_dyncode_create', 'NaClSysDyncodeCreate',
185      ['uint32_t dest', 'uint32_t src', 'uint32_t size']),
186     ('NACL_sys_dyncode_modify', 'NaClSysDyncodeModify',
187      ['uint32_t dest', 'uint32_t src', 'uint32_t size']),
188     ('NACL_sys_dyncode_delete', 'NaClSysDyncodeDelete',
189      ['uint32_t dest', 'uint32_t size']),
190     ('NACL_sys_second_tls_set', 'NaClSysSecondTlsSet',
191      ['uint32_t new_value']),
192     ('NACL_sys_second_tls_get', 'NaClSysSecondTlsGet', []),
193     ('NACL_sys_exception_handler', 'NaClSysExceptionHandler',
194      ['uint32_t handler_addr', 'uint32_t old_handler']),
195     ('NACL_sys_exception_stack', 'NaClSysExceptionStack',
196      ['uint32_t stack_addr', 'uint32_t stack_size']),
197     ('NACL_sys_exception_clear_flag', 'NaClSysExceptionClearFlag', []),
198     ('NACL_sys_test_infoleak', 'NaClSysTestInfoLeak', []),
199     ('NACL_sys_test_crash', 'NaClSysTestCrash', ['int crash_type']),
200     ('NACL_sys_futex_wait_abs', 'NaClSysFutexWaitAbs',
201      ['uint32_t addr', 'uint32_t value', 'uint32_t abstime_ptr']),
202     ('NACL_sys_futex_wake', 'NaClSysFutexWake',
203      ['uint32_t addr', 'uint32_t nwake']),
204     ]
205
206
207 # Syscall arguments MUST be declared in a simple-to-parse manner!
208 # They must match the following regexp:
209
210 ARG_RE = r'\s*((\w+\s+)+\**)\s*(\w+)'
211
212 # where matchobj.group(1) is the type, and matchobj.group(3) is the
213 # identifer.
214
215
216 def CollapseWhitespaces(s):
217   return re.sub(r'\s+', ' ', s)
218
219
220 def ExtractVariable(decl):
221   type_or_idents = re.match(ARG_RE, decl)
222   return type_or_idents.group(3)
223
224
225 def ExtractType(decl):
226   type_or_idents = re.match(ARG_RE, decl)
227   return CollapseWhitespaces(type_or_idents.group(1)).strip()
228
229
230 def TypeIsPointer(typestr):
231   return '*' in typestr
232
233
234 def ArgList(architecture, alist):
235   if not alist:
236     return ''
237
238   extractedargs = []
239   for arg in alist:
240     t = ExtractType(arg)
241     extra_cast = ''
242     # avoid cast to pointer from integer of different size
243     if TypeIsPointer(t):
244       extra_cast = '(uintptr_t)'
245     extractedargs += ['(' + t + ') ' + extra_cast
246                       + ' p.' + ExtractVariable(arg)]
247
248   return ', ' + ', '.join(extractedargs)
249
250
251 def MemoryArgStruct(architecture, name, alist):
252   if not alist:
253     return '  NaClCopyDropLock(natp->nap);'
254
255   margs = ['    uint32_t %s' % ExtractVariable(arg)
256            for arg in alist]
257   values = {
258       'name': name,
259       'members' : ';\n'.join(margs) + ';'
260       }
261
262   if len(margs) == 0:
263     return ''
264
265   return """\
266   struct %(name)sArgs {
267 %(members)s
268   } p;
269   if (!NaClCopyInFromUserAndDropLock(natp->nap, &p, natp->usr_syscall_args,
270                                      sizeof p)) {
271     return -NACL_ABI_EFAULT;
272   }
273
274 """ % values
275
276
277 def PrintSyscallTableInitializer(protos, ostr):
278   assign = []
279   for syscall_number, func_name, alist in protos:
280     assign.append("  NaClAddSyscall(%s, &%sDecoder);" %
281                   (syscall_number, func_name))
282     # These inlines are no-ops that should be optimized away.
283     # Emit the call just so that they are not reported as unused.
284     assign.append("  AssertSameType_%s();" % func_name)
285   print >>ostr, TABLE_INITIALIZER % "\n".join(assign)
286
287
288 def PrintImplSkel(architecture, protos, ostr):
289   print >>ostr, AUTOGEN_HEADER
290   for syscall_number, func_name, alist in protos:
291     values = { 'name' : func_name,
292                'arglist' : ArgList(architecture, alist),
293                'arg_type_list' :
294                    ', '.join(['struct NaClAppThread *natp'] + alist),
295                'members' : MemoryArgStruct(architecture, func_name, alist),
296                }
297     print >>ostr, IMPLEMENTATION_SKELETON % values
298
299
300 def main(argv):
301   usage = 'Usage: nacl_syscall_handlers_gen.py [-f regex] [-a arch]'
302   input_src = sys.stdin
303   output_dst = sys.stdout
304   arch = 'x86'
305   subarch = '32'
306   try:
307     opts, pargs = getopt.getopt(argv[1:], 'a:i:o:s:')
308   except getopt.error, e:
309     print >>sys.stderr, 'Illegal option:', str(e)
310     print >>sys.stderr, usage
311     return 1
312
313   for opt, val in opts:
314     if opt == '-a':
315       arch = val
316     elif opt == '-i':
317       input_src = open(val, 'r')
318     elif opt == '-o':
319       output_dst = open(val, 'w')
320     elif opt == '-s':
321       subarch = val
322     else:
323       raise Exception('Unknown option: %s' % opt)
324
325   if subarch != '':
326     arch = arch + '-' + subarch
327
328   # Check naming consistency.
329   for syscall_number, func_name, alist in SYSCALL_LIST:
330     assert syscall_number.startswith('NACL_sys_'), syscall_number
331     name1 = syscall_number[len('NACL_sys_'):].replace('_', '')
332     assert func_name.startswith('NaClSys'), func_name
333     name2 = func_name[len('NaClSys'):].lower()
334     assert name1 == name2, '%r != %r' % (name1, name2)
335
336   data = input_src.read()
337   protos = SYSCALL_LIST
338   print >>output_dst, data
339   PrintImplSkel(arch, protos, output_dst)
340   PrintSyscallTableInitializer(protos, output_dst)
341
342   return 0
343
344
345 if __name__ == '__main__':
346   sys.exit(main(sys.argv))