blob: f7785d6a3be4d89a2abe9ea825beacbbc32f5da8 [file] [log] [blame]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001#!/usr/bin/python
Pavel Chupinf12a18b2012-12-12 13:11:48 +04002
3# This tool is used to generate the assembler system call stubs,
4# the header files listing all available system calls, and the
5# makefiles used to build all the stubs.
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07006
Christopher Ferris01bd32e2014-08-05 12:19:27 -07007import atexit
Elliott Hughes103ccde2013-10-16 14:27:59 -07008import commands
9import filecmp
10import glob
Elliott Hughesdc1fb702014-08-20 11:16:11 -070011import logging
Elliott Hughes103ccde2013-10-16 14:27:59 -070012import os.path
13import re
14import shutil
15import stat
Elliott Hughesdc1fb702014-08-20 11:16:11 -070016import string
Elliott Hughes103ccde2013-10-16 14:27:59 -070017import sys
Christopher Ferris01bd32e2014-08-05 12:19:27 -070018import tempfile
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070019
Elliott Hughesdc1fb702014-08-20 11:16:11 -070020
21all_arches = [ "arm", "arm64", "mips", "mips64", "x86", "x86_64" ]
22
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070023
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070024# temp directory where we store all intermediate files
Christopher Ferris01bd32e2014-08-05 12:19:27 -070025bionic_temp = tempfile.mkdtemp(prefix="bionic_gensyscalls");
26# Make sure the directory is deleted when the script exits.
27atexit.register(shutil.rmtree, bionic_temp)
28
29bionic_libc_root = os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libc")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070030
Elliott Hughes103ccde2013-10-16 14:27:59 -070031warning = "Generated by gensyscalls.py. Do not edit."
32
Pavel Chupinf12a18b2012-12-12 13:11:48 +040033DRY_RUN = False
34
35def make_dir(path):
Raghu Gandham1fa0d842012-01-27 17:51:42 -080036 path = os.path.abspath(path)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070037 if not os.path.exists(path):
38 parent = os.path.dirname(path)
39 if parent:
40 make_dir(parent)
41 os.mkdir(path)
42
Elliott Hughes0437f3f2013-10-07 23:53:13 -070043
Pavel Chupinf12a18b2012-12-12 13:11:48 +040044def create_file(relpath):
Christopher Ferris01bd32e2014-08-05 12:19:27 -070045 full_path = os.path.join(bionic_temp, relpath)
46 dir = os.path.dirname(full_path)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070047 make_dir(dir)
Christopher Ferris01bd32e2014-08-05 12:19:27 -070048 return open(full_path, "w")
Pavel Chupinf12a18b2012-12-12 13:11:48 +040049
50
Elliott Hughes103ccde2013-10-16 14:27:59 -070051syscall_stub_header = "/* " + warning + " */\n" + \
52"""
Elliott Hughesed744842013-11-07 10:31:05 -080053#include <private/bionic_asm.h>
Pavel Chupinf12a18b2012-12-12 13:11:48 +040054
Elliott Hughes0437f3f2013-10-07 23:53:13 -070055ENTRY(%(func)s)
Pavel Chupinf12a18b2012-12-12 13:11:48 +040056"""
57
Elliott Hughes0437f3f2013-10-07 23:53:13 -070058
Elliott Hughes0437f3f2013-10-07 23:53:13 -070059#
60# ARM assembler templates for each syscall stub
61#
62
63arm_eabi_call_default = syscall_stub_header + """\
64 mov ip, r7
65 ldr r7, =%(__NR_name)s
66 swi #0
67 mov r7, ip
68 cmn r0, #(MAX_ERRNO + 1)
69 bxls lr
70 neg r0, r0
Elliott Hughes011e1112014-09-08 15:25:01 -070071 b __set_errno_internal
Elliott Hughes0437f3f2013-10-07 23:53:13 -070072END(%(func)s)
73"""
74
75arm_eabi_call_long = syscall_stub_header + """\
76 mov ip, sp
Elliott Hughes0437f3f2013-10-07 23:53:13 -070077 stmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080078 .cfi_def_cfa_offset 16
79 .cfi_rel_offset r4, 0
80 .cfi_rel_offset r5, 4
81 .cfi_rel_offset r6, 8
82 .cfi_rel_offset r7, 12
Elliott Hughes0437f3f2013-10-07 23:53:13 -070083 ldmfd ip, {r4, r5, r6}
84 ldr r7, =%(__NR_name)s
85 swi #0
86 ldmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080087 .cfi_def_cfa_offset 0
Elliott Hughes0437f3f2013-10-07 23:53:13 -070088 cmn r0, #(MAX_ERRNO + 1)
89 bxls lr
90 neg r0, r0
Elliott Hughes011e1112014-09-08 15:25:01 -070091 b __set_errno_internal
Elliott Hughes0437f3f2013-10-07 23:53:13 -070092END(%(func)s)
93"""
94
95
96#
Colin Crossd1973ca2014-01-21 19:50:58 -080097# Arm64 assembler templates for each syscall stub
98#
99
100arm64_call = syscall_stub_header + """\
Colin Crossd1973ca2014-01-21 19:50:58 -0800101 mov x8, %(__NR_name)s
102 svc #0
103
Colin Crossd1973ca2014-01-21 19:50:58 -0800104 cmn x0, #(MAX_ERRNO + 1)
105 cneg x0, x0, hi
Elliott Hughes011e1112014-09-08 15:25:01 -0700106 b.hi __set_errno_internal
Colin Crossd1973ca2014-01-21 19:50:58 -0800107
108 ret
109END(%(func)s)
110"""
111
112
113#
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700114# MIPS assembler templates for each syscall stub
115#
116
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800117mips_call = syscall_stub_header + """\
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700118 .set noreorder
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800119 .cpload t9
120 li v0, %(__NR_name)s
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700121 syscall
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800122 bnez a3, 1f
123 move a0, v0
124 j ra
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700125 nop
1261:
Elliott Hughes011e1112014-09-08 15:25:01 -0700127 la t9,__set_errno_internal
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800128 j t9
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700129 nop
130 .set reorder
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800131END(%(func)s)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700132"""
133
134
Elliott Hughescd6780b2013-02-07 14:07:00 -0800135#
Chris Dearman50432122014-02-05 16:59:23 -0800136# MIPS64 assembler templates for each syscall stub
137#
138
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800139mips64_call = syscall_stub_header + """\
Chris Dearman50432122014-02-05 16:59:23 -0800140 .set push
141 .set noreorder
142 li v0, %(__NR_name)s
143 syscall
144 bnez a3, 1f
145 move a0, v0
146 j ra
147 nop
1481:
149 move t0, ra
150 bal 2f
151 nop
1522:
153 .cpsetup ra, t1, 2b
Elliott Hughes011e1112014-09-08 15:25:01 -0700154 LA t9,__set_errno_internal
Chris Dearman50432122014-02-05 16:59:23 -0800155 .cpreturn
156 j t9
157 move ra, t0
158 .set pop
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800159END(%(func)s)
Chris Dearman50432122014-02-05 16:59:23 -0800160"""
161
162
163#
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700164# x86 assembler templates for each syscall stub
165#
166
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800167x86_registers = [ "ebx", "ecx", "edx", "esi", "edi", "ebp" ]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700168
Mingwei Shibe910522015-11-12 07:02:14 +0000169x86_call_prepare = """\
170
171 call __kernel_syscall
172 pushl %eax
173 .cfi_adjust_cfa_offset 4
174 .cfi_rel_offset eax, 0
175
176"""
177
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700178x86_call = """\
179 movl $%(__NR_name)s, %%eax
Mingwei Shibe910522015-11-12 07:02:14 +0000180 call *(%%esp)
181 addl $4, %%esp
182
Elliott Hughes9aceab52013-03-12 14:57:30 -0700183 cmpl $-MAX_ERRNO, %%eax
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700184 jb 1f
185 negl %%eax
186 pushl %%eax
Elliott Hughes011e1112014-09-08 15:25:01 -0700187 call __set_errno_internal
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700188 addl $4, %%esp
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001891:
190"""
191
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700192x86_return = """\
193 ret
194END(%(func)s)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700195"""
196
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700197
Elliott Hughescd6780b2013-02-07 14:07:00 -0800198#
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400199# x86_64 assembler templates for each syscall stub
200#
201
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700202x86_64_call = """\
203 movl $%(__NR_name)s, %%eax
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400204 syscall
205 cmpq $-MAX_ERRNO, %%rax
206 jb 1f
207 negl %%eax
208 movl %%eax, %%edi
Elliott Hughes011e1112014-09-08 15:25:01 -0700209 call __set_errno_internal
Pavel Chupinf12a18b2012-12-12 13:11:48 +04002101:
211 ret
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700212END(%(func)s)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400213"""
214
Raghu Gandham1fa0d842012-01-27 17:51:42 -0800215
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100216def param_uses_64bits(param):
217 """Returns True iff a syscall parameter description corresponds
218 to a 64-bit type."""
219 param = param.strip()
220 # First, check that the param type begins with one of the known
221 # 64-bit types.
222 if not ( \
223 param.startswith("int64_t") or param.startswith("uint64_t") or \
224 param.startswith("loff_t") or param.startswith("off64_t") or \
225 param.startswith("long long") or param.startswith("unsigned long long") or
226 param.startswith("signed long long") ):
227 return False
228
229 # Second, check that there is no pointer type here
230 if param.find("*") >= 0:
231 return False
232
233 # Ok
234 return True
235
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700236
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100237def count_arm_param_registers(params):
238 """This function is used to count the number of register used
Elliott Hughescd6780b2013-02-07 14:07:00 -0800239 to pass parameters when invoking an ARM system call.
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100240 This is because the ARM EABI mandates that 64-bit quantities
241 must be passed in an even+odd register pair. So, for example,
242 something like:
243
244 foo(int fd, off64_t pos)
245
246 would actually need 4 registers:
247 r0 -> int
248 r1 -> unused
249 r2-r3 -> pos
250 """
251 count = 0
252 for param in params:
253 if param_uses_64bits(param):
254 if (count & 1) != 0:
255 count += 1
256 count += 2
257 else:
258 count += 1
259 return count
260
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700261
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100262def count_generic_param_registers(params):
263 count = 0
264 for param in params:
265 if param_uses_64bits(param):
266 count += 2
267 else:
268 count += 1
269 return count
270
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700271
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400272def count_generic_param_registers64(params):
273 count = 0
274 for param in params:
275 count += 1
276 return count
277
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700278
Elliott Hughescda62092013-03-22 13:50:44 -0700279# This lets us support regular system calls like __NR_write and also weird
280# ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
281def make__NR_name(name):
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700282 if name.startswith("__ARM_NR_"):
Elliott Hughescda62092013-03-22 13:50:44 -0700283 return name
284 else:
285 return "__NR_%s" % (name)
286
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700287
Elliott Hughesfff6e272013-10-24 17:03:20 -0700288def add_footer(pointer_length, stub, syscall):
289 # Add any aliases for this syscall.
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700290 aliases = syscall["aliases"]
291 for alias in aliases:
Christopher Ferrisfa5faa02015-03-24 16:50:46 -0700292 stub += "\nALIAS_SYMBOL(%s, %s)\n" % (alias, syscall["func"])
Elliott Hughesfff6e272013-10-24 17:03:20 -0700293
Nick Kralevich00490ae2015-02-03 11:27:25 -0800294 # Use hidden visibility on LP64 for any functions beginning with underscores.
295 # Force hidden visibility for any functions which begin with 3 underscores
296 if (pointer_length == 64 and syscall["func"].startswith("__")) or syscall["func"].startswith("___"):
Elliott Hughesd465eb42014-02-19 18:59:19 -0800297 stub += '.hidden ' + syscall["func"] + '\n'
Elliott Hughesfff6e272013-10-24 17:03:20 -0700298
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700299 return stub
300
301
302def arm_eabi_genstub(syscall):
303 num_regs = count_arm_param_registers(syscall["params"])
304 if num_regs > 4:
305 return arm_eabi_call_long % syscall
306 return arm_eabi_call_default % syscall
307
308
Colin Crossd1973ca2014-01-21 19:50:58 -0800309def arm64_genstub(syscall):
310 return arm64_call % syscall
311
312
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700313def mips_genstub(syscall):
314 return mips_call % syscall
315
316
Chris Dearman50432122014-02-05 16:59:23 -0800317def mips64_genstub(syscall):
318 return mips64_call % syscall
319
320
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700321def x86_genstub(syscall):
322 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700323
324 numparams = count_generic_param_registers(syscall["params"])
Mingwei Shibe910522015-11-12 07:02:14 +0000325 stack_bias = numparams*4 + 8
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800326 offset = 0
327 mov_result = ""
Christopher Ferris15b91e92014-05-29 18:17:09 -0700328 first_push = True
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800329 for register in x86_registers[:numparams]:
330 result += " pushl %%%s\n" % register
Christopher Ferris15b91e92014-05-29 18:17:09 -0700331 if first_push:
332 result += " .cfi_def_cfa_offset 8\n"
333 result += " .cfi_rel_offset %s, 0\n" % register
334 first_push = False
335 else:
336 result += " .cfi_adjust_cfa_offset 4\n"
337 result += " .cfi_rel_offset %s, 0\n" % register
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800338 mov_result += " mov %d(%%esp), %%%s\n" % (stack_bias+offset, register)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800339 offset += 4
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700340
Mingwei Shibe910522015-11-12 07:02:14 +0000341 result += x86_call_prepare
Christopher Ferris15b91e92014-05-29 18:17:09 -0700342 result += mov_result
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700343 result += x86_call % syscall
344
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800345 for register in reversed(x86_registers[:numparams]):
346 result += " popl %%%s\n" % register
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700347
348 result += x86_return % syscall
349 return result
350
Serban Constantinescufeaa89a2013-10-07 16:49:09 +0100351
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700352def x86_genstub_socketcall(syscall):
353 # %ebx <--- Argument 1 - The call id of the needed vectored
354 # syscall (socket, bind, recv, etc)
355 # %ecx <--- Argument 2 - Pointer to the rest of the arguments
356 # from the original function called (socket())
357
358 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700359
360 # save the regs we need
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800361 result += " pushl %ebx\n"
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800362 result += " .cfi_def_cfa_offset 8\n"
363 result += " .cfi_rel_offset ebx, 0\n"
Christopher Ferris15b91e92014-05-29 18:17:09 -0700364 result += " pushl %ecx\n"
365 result += " .cfi_adjust_cfa_offset 4\n"
366 result += " .cfi_rel_offset ecx, 0\n"
Mingwei Shibe910522015-11-12 07:02:14 +0000367 stack_bias = 16
368
369 result += x86_call_prepare
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700370
371 # set the call id (%ebx)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800372 result += " mov $%d, %%ebx\n" % syscall["socketcall_id"]
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700373
374 # set the pointer to the rest of the args into %ecx
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800375 result += " mov %esp, %ecx\n"
376 result += " addl $%d, %%ecx\n" % (stack_bias)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700377
378 # now do the syscall code itself
379 result += x86_call % syscall
380
381 # now restore the saved regs
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800382 result += " popl %ecx\n"
383 result += " popl %ebx\n"
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700384
385 # epilog
386 result += x86_return % syscall
387 return result
388
389
390def x86_64_genstub(syscall):
391 result = syscall_stub_header % syscall
392 num_regs = count_generic_param_registers64(syscall["params"])
393 if (num_regs > 3):
394 # rcx is used as 4th argument. Kernel wants it at r10.
395 result += " movq %rcx, %r10\n"
396
397 result += x86_64_call % syscall
398 return result
399
400
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700401class SysCallsTxtParser:
402 def __init__(self):
403 self.syscalls = []
404 self.lineno = 0
405
406 def E(self, msg):
407 print "%d: %s" % (self.lineno, msg)
408
409 def parse_line(self, line):
410 """ parse a syscall spec line.
411
412 line processing, format is
413 return type func_name[|alias_list][:syscall_name[:socketcall_id]] ( [paramlist] ) architecture_list
414 """
415 pos_lparen = line.find('(')
416 E = self.E
417 if pos_lparen < 0:
418 E("missing left parenthesis in '%s'" % line)
419 return
420
421 pos_rparen = line.rfind(')')
422 if pos_rparen < 0 or pos_rparen <= pos_lparen:
423 E("missing or misplaced right parenthesis in '%s'" % line)
424 return
425
426 return_type = line[:pos_lparen].strip().split()
427 if len(return_type) < 2:
428 E("missing return type in '%s'" % line)
429 return
430
431 syscall_func = return_type[-1]
432 return_type = string.join(return_type[:-1],' ')
433 socketcall_id = -1
434
435 pos_colon = syscall_func.find(':')
436 if pos_colon < 0:
437 syscall_name = syscall_func
438 else:
439 if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
440 E("misplaced colon in '%s'" % line)
441 return
442
443 # now find if there is a socketcall_id for a dispatch-type syscall
444 # after the optional 2nd colon
445 pos_colon2 = syscall_func.find(':', pos_colon + 1)
446 if pos_colon2 < 0:
447 syscall_name = syscall_func[pos_colon+1:]
448 syscall_func = syscall_func[:pos_colon]
449 else:
450 if pos_colon2+1 >= len(syscall_func):
451 E("misplaced colon2 in '%s'" % line)
452 return
453 syscall_name = syscall_func[(pos_colon+1):pos_colon2]
454 socketcall_id = int(syscall_func[pos_colon2+1:])
455 syscall_func = syscall_func[:pos_colon]
456
457 alias_delim = syscall_func.find('|')
458 if alias_delim > 0:
459 alias_list = syscall_func[alias_delim+1:].strip()
460 syscall_func = syscall_func[:alias_delim]
461 alias_delim = syscall_name.find('|')
462 if alias_delim > 0:
463 syscall_name = syscall_name[:alias_delim]
464 syscall_aliases = string.split(alias_list, ',')
465 else:
466 syscall_aliases = []
467
468 if pos_rparen > pos_lparen+1:
469 syscall_params = line[pos_lparen+1:pos_rparen].split(',')
470 params = string.join(syscall_params,',')
471 else:
472 syscall_params = []
473 params = "void"
474
475 t = {
476 "name" : syscall_name,
477 "func" : syscall_func,
478 "aliases" : syscall_aliases,
479 "params" : syscall_params,
480 "decl" : "%-15s %s (%s);" % (return_type, syscall_func, params),
481 "socketcall_id" : socketcall_id
482 }
483
484 # Parse the architecture list.
485 arch_list = line[pos_rparen+1:].strip()
486 if arch_list == "all":
487 for arch in all_arches:
488 t[arch] = True
489 else:
490 for arch in string.split(arch_list, ','):
491 if arch in all_arches:
492 t[arch] = True
493 else:
494 E("invalid syscall architecture '%s' in '%s'" % (arch, line))
495 return
496
497 self.syscalls.append(t)
498
499 logging.debug(t)
500
501
502 def parse_file(self, file_path):
503 logging.debug("parse_file: %s" % file_path)
504 fp = open(file_path)
505 for line in fp.xreadlines():
506 self.lineno += 1
507 line = line.strip()
508 if not line: continue
509 if line[0] == '#': continue
510 self.parse_line(line)
511
512 fp.close()
513
514
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700515class State:
516 def __init__(self):
517 self.old_stubs = []
518 self.new_stubs = []
519 self.other_files = []
520 self.syscalls = []
521
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400522
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700523 def process_file(self, input):
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700524 parser = SysCallsTxtParser()
525 parser.parse_file(input)
526 self.syscalls = parser.syscalls
527 parser = None
528
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700529 for syscall in self.syscalls:
530 syscall["__NR_name"] = make__NR_name(syscall["name"])
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700531
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700532 if syscall.has_key("arm"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700533 syscall["asm-arm"] = add_footer(32, arm_eabi_genstub(syscall), syscall)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700534
Colin Crossd1973ca2014-01-21 19:50:58 -0800535 if syscall.has_key("arm64"):
536 syscall["asm-arm64"] = add_footer(64, arm64_genstub(syscall), syscall)
537
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700538 if syscall.has_key("x86"):
539 if syscall["socketcall_id"] >= 0:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700540 syscall["asm-x86"] = add_footer(32, x86_genstub_socketcall(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800541 else:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700542 syscall["asm-x86"] = add_footer(32, x86_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700543 elif syscall["socketcall_id"] >= 0:
Elliott Hughesd6121652013-09-25 22:43:36 -0700544 E("socketcall_id for dispatch syscalls is only supported for x86 in '%s'" % t)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800545 return
Elliott Hughescd6780b2013-02-07 14:07:00 -0800546
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700547 if syscall.has_key("mips"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700548 syscall["asm-mips"] = add_footer(32, mips_genstub(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800549
Chris Dearman50432122014-02-05 16:59:23 -0800550 if syscall.has_key("mips64"):
551 syscall["asm-mips64"] = add_footer(64, mips64_genstub(syscall), syscall)
552
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700553 if syscall.has_key("x86_64"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700554 syscall["asm-x86_64"] = add_footer(64, x86_64_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700555
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700556 # Scan a Linux kernel asm/unistd.h file containing __NR_* constants
557 # and write out equivalent SYS_* constants for glibc source compatibility.
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700558 def scan_linux_unistd_h(self, fp, path):
559 pattern = re.compile(r'^#define __NR_([a-z]\S+) .*')
560 syscalls = set() # MIPS defines everything three times; work around that.
561 for line in open(path):
562 m = re.search(pattern, line)
563 if m:
564 syscalls.add(m.group(1))
565 for syscall in sorted(syscalls):
Elliott Hughescda62092013-03-22 13:50:44 -0700566 fp.write("#define SYS_%s %s\n" % (syscall, make__NR_name(syscall)))
Elliott Hughes8ecf2252013-03-21 18:06:55 -0700567
568
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700569 def gen_glibc_syscalls_h(self):
Elliott Hughescda62092013-03-22 13:50:44 -0700570 # TODO: generate a separate file for each architecture, like glibc's bits/syscall.h.
Elliott Hughes9724ce32013-03-21 19:43:54 -0700571 glibc_syscalls_h_path = "include/sys/glibc-syscalls.h"
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700572 logging.info("generating " + glibc_syscalls_h_path)
Elliott Hughes9724ce32013-03-21 19:43:54 -0700573 glibc_fp = create_file(glibc_syscalls_h_path)
Elliott Hughes103ccde2013-10-16 14:27:59 -0700574 glibc_fp.write("/* %s */\n" % warning)
Elliott Hughes9724ce32013-03-21 19:43:54 -0700575 glibc_fp.write("#ifndef _BIONIC_GLIBC_SYSCALLS_H_\n")
576 glibc_fp.write("#define _BIONIC_GLIBC_SYSCALLS_H_\n")
577
Serban Constantinescufeaa89a2013-10-07 16:49:09 +0100578 glibc_fp.write("#if defined(__aarch64__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700579 self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-generic/unistd.h"))
Serban Constantinescufeaa89a2013-10-07 16:49:09 +0100580 glibc_fp.write("#elif defined(__arm__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700581 self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-arm/asm/unistd.h"))
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700582 glibc_fp.write("#elif defined(__mips__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700583 self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-mips/asm/unistd.h"))
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700584 glibc_fp.write("#elif defined(__i386__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700585 self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-x86/asm/unistd_32.h"))
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400586 glibc_fp.write("#elif defined(__x86_64__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700587 self.scan_linux_unistd_h(glibc_fp, os.path.join(bionic_libc_root, "kernel/uapi/asm-x86/asm/unistd_64.h"))
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700588 glibc_fp.write("#endif\n")
589
590 glibc_fp.write("#endif /* _BIONIC_GLIBC_SYSCALLS_H_ */\n")
591 glibc_fp.close()
592 self.other_files.append(glibc_syscalls_h_path)
593
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700594
Elliott Hughesd6121652013-09-25 22:43:36 -0700595 # Write each syscall stub.
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700596 def gen_syscall_stubs(self):
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700597 for syscall in self.syscalls:
Elliott Hughesd6121652013-09-25 22:43:36 -0700598 for arch in all_arches:
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700599 if syscall.has_key("asm-%s" % arch):
600 filename = "arch-%s/syscalls/%s.S" % (arch, syscall["func"])
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700601 logging.info(">>> generating " + filename)
Elliott Hughesd6121652013-09-25 22:43:36 -0700602 fp = create_file(filename)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700603 fp.write(syscall["asm-%s" % arch])
Elliott Hughesd6121652013-09-25 22:43:36 -0700604 fp.close()
605 self.new_stubs.append(filename)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700606
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700607
Elliott Hughesd6121652013-09-25 22:43:36 -0700608 def regenerate(self):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700609 logging.info("scanning for existing architecture-specific stub files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700610
Elliott Hughesd6121652013-09-25 22:43:36 -0700611 for arch in all_arches:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700612 arch_dir = "arch-" + arch
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700613 logging.info("scanning " + os.path.join(bionic_libc_root, arch_dir))
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700614 rel_path = os.path.join(arch_dir, "syscalls")
615 for file in os.listdir(os.path.join(bionic_libc_root, rel_path)):
616 if file.endswith(".S"):
617 self.old_stubs.append(os.path.join(rel_path, file))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700618
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700619 logging.info("found %d stub files" % len(self.old_stubs))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700620
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400621 if not os.path.exists(bionic_temp):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700622 logging.info("creating %s..." % bionic_temp)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400623 make_dir(bionic_temp)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700624
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700625 logging.info("re-generating stubs and support files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700626
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700627 self.gen_glibc_syscalls_h()
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700628 self.gen_syscall_stubs()
629
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700630 logging.info("comparing files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700631 adds = []
632 edits = []
633
634 for stub in self.new_stubs + self.other_files:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700635 tmp_file = os.path.join(bionic_temp, stub)
636 libc_file = os.path.join(bionic_libc_root, stub)
637 if not os.path.exists(libc_file):
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200638 # new file, git add it
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700639 logging.info("new file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700640 adds.append(libc_file)
641 shutil.copyfile(tmp_file, libc_file)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700642
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700643 elif not filecmp.cmp(tmp_file, libc_file):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700644 logging.info("changed file: " + stub)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400645 edits.append(stub)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700646
647 deletes = []
648 for stub in self.old_stubs:
649 if not stub in self.new_stubs:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700650 logging.info("deleted file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700651 deletes.append(os.path.join(bionic_libc_root, stub))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700652
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400653 if not DRY_RUN:
654 if adds:
655 commands.getoutput("git add " + " ".join(adds))
656 if deletes:
657 commands.getoutput("git rm " + " ".join(deletes))
658 if edits:
659 for file in edits:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700660 shutil.copyfile(os.path.join(bionic_temp, file),
661 os.path.join(bionic_libc_root, file))
662 commands.getoutput("git add " + " ".join((os.path.join(bionic_libc_root, file)) for file in edits))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700663
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700664 commands.getoutput("git add %s" % (os.path.join(bionic_libc_root, "SYSCALLS.TXT")))
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200665
666 if (not adds) and (not deletes) and (not edits):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700667 logging.info("no changes detected!")
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200668 else:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700669 logging.info("ready to go!!")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700670
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700671logging.basicConfig(level=logging.INFO)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700672
673state = State()
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700674state.process_file(os.path.join(bionic_libc_root, "SYSCALLS.TXT"))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700675state.regenerate()