blob: 929bec47ef6f6bbc6f92ead97a4a1d9102e99ef3 [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
Dan Albertbc9f9f22014-08-08 15:19:20 -070055 .hidden __set_errno
56
Elliott Hughes0437f3f2013-10-07 23:53:13 -070057ENTRY(%(func)s)
Pavel Chupinf12a18b2012-12-12 13:11:48 +040058"""
59
Elliott Hughes0437f3f2013-10-07 23:53:13 -070060
H.J. Lu6fe4e872013-10-04 10:03:17 -070061function_alias = """
Elliott Hughes986f9062014-02-18 16:42:36 -080062 .globl %(alias)s
63 .equ %(alias)s, %(func)s
H.J. Lu6fe4e872013-10-04 10:03:17 -070064"""
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070065
Elliott Hughes0437f3f2013-10-07 23:53:13 -070066
67#
68# ARM assembler templates for each syscall stub
69#
70
71arm_eabi_call_default = syscall_stub_header + """\
72 mov ip, r7
73 ldr r7, =%(__NR_name)s
74 swi #0
75 mov r7, ip
76 cmn r0, #(MAX_ERRNO + 1)
77 bxls lr
78 neg r0, r0
79 b __set_errno
80END(%(func)s)
81"""
82
83arm_eabi_call_long = syscall_stub_header + """\
84 mov ip, sp
Elliott Hughes0437f3f2013-10-07 23:53:13 -070085 stmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080086 .cfi_def_cfa_offset 16
87 .cfi_rel_offset r4, 0
88 .cfi_rel_offset r5, 4
89 .cfi_rel_offset r6, 8
90 .cfi_rel_offset r7, 12
Elliott Hughes0437f3f2013-10-07 23:53:13 -070091 ldmfd ip, {r4, r5, r6}
92 ldr r7, =%(__NR_name)s
93 swi #0
94 ldmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080095 .cfi_def_cfa_offset 0
Elliott Hughes0437f3f2013-10-07 23:53:13 -070096 cmn r0, #(MAX_ERRNO + 1)
97 bxls lr
98 neg r0, r0
99 b __set_errno
100END(%(func)s)
101"""
102
103
104#
Colin Crossd1973ca2014-01-21 19:50:58 -0800105# Arm64 assembler templates for each syscall stub
106#
107
108arm64_call = syscall_stub_header + """\
Colin Crossd1973ca2014-01-21 19:50:58 -0800109 mov x8, %(__NR_name)s
110 svc #0
111
Colin Crossd1973ca2014-01-21 19:50:58 -0800112 cmn x0, #(MAX_ERRNO + 1)
113 cneg x0, x0, hi
114 b.hi __set_errno
115
116 ret
117END(%(func)s)
118"""
119
120
121#
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700122# MIPS assembler templates for each syscall stub
123#
124
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800125mips_call = syscall_stub_header + """\
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700126 .set noreorder
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800127 .cpload t9
128 li v0, %(__NR_name)s
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700129 syscall
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800130 bnez a3, 1f
131 move a0, v0
132 j ra
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700133 nop
1341:
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800135 la t9,__set_errno
136 j t9
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700137 nop
138 .set reorder
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800139END(%(func)s)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700140"""
141
142
Elliott Hughescd6780b2013-02-07 14:07:00 -0800143#
Chris Dearman50432122014-02-05 16:59:23 -0800144# MIPS64 assembler templates for each syscall stub
145#
146
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800147mips64_call = syscall_stub_header + """\
Chris Dearman50432122014-02-05 16:59:23 -0800148 .set push
149 .set noreorder
150 li v0, %(__NR_name)s
151 syscall
152 bnez a3, 1f
153 move a0, v0
154 j ra
155 nop
1561:
157 move t0, ra
158 bal 2f
159 nop
1602:
161 .cpsetup ra, t1, 2b
162 LA t9,__set_errno
163 .cpreturn
164 j t9
165 move ra, t0
166 .set pop
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800167END(%(func)s)
Chris Dearman50432122014-02-05 16:59:23 -0800168"""
169
170
171#
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700172# x86 assembler templates for each syscall stub
173#
174
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800175x86_registers = [ "ebx", "ecx", "edx", "esi", "edi", "ebp" ]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700176
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700177x86_call = """\
178 movl $%(__NR_name)s, %%eax
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700179 int $0x80
Elliott Hughes9aceab52013-03-12 14:57:30 -0700180 cmpl $-MAX_ERRNO, %%eax
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700181 jb 1f
182 negl %%eax
183 pushl %%eax
Dan Albert3726f9c2014-08-08 15:15:29 -0700184 call __set_errno
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700185 addl $4, %%esp
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001861:
187"""
188
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700189x86_return = """\
190 ret
191END(%(func)s)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700192"""
193
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700194
Elliott Hughescd6780b2013-02-07 14:07:00 -0800195#
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400196# x86_64 assembler templates for each syscall stub
197#
198
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700199x86_64_call = """\
200 movl $%(__NR_name)s, %%eax
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400201 syscall
202 cmpq $-MAX_ERRNO, %%rax
203 jb 1f
204 negl %%eax
205 movl %%eax, %%edi
Dan Albert3726f9c2014-08-08 15:15:29 -0700206 call __set_errno
Pavel Chupinf12a18b2012-12-12 13:11:48 +04002071:
208 ret
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700209END(%(func)s)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400210"""
211
Raghu Gandham1fa0d842012-01-27 17:51:42 -0800212
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100213def param_uses_64bits(param):
214 """Returns True iff a syscall parameter description corresponds
215 to a 64-bit type."""
216 param = param.strip()
217 # First, check that the param type begins with one of the known
218 # 64-bit types.
219 if not ( \
220 param.startswith("int64_t") or param.startswith("uint64_t") or \
221 param.startswith("loff_t") or param.startswith("off64_t") or \
222 param.startswith("long long") or param.startswith("unsigned long long") or
223 param.startswith("signed long long") ):
224 return False
225
226 # Second, check that there is no pointer type here
227 if param.find("*") >= 0:
228 return False
229
230 # Ok
231 return True
232
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700233
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100234def count_arm_param_registers(params):
235 """This function is used to count the number of register used
Elliott Hughescd6780b2013-02-07 14:07:00 -0800236 to pass parameters when invoking an ARM system call.
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100237 This is because the ARM EABI mandates that 64-bit quantities
238 must be passed in an even+odd register pair. So, for example,
239 something like:
240
241 foo(int fd, off64_t pos)
242
243 would actually need 4 registers:
244 r0 -> int
245 r1 -> unused
246 r2-r3 -> pos
247 """
248 count = 0
249 for param in params:
250 if param_uses_64bits(param):
251 if (count & 1) != 0:
252 count += 1
253 count += 2
254 else:
255 count += 1
256 return count
257
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700258
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100259def count_generic_param_registers(params):
260 count = 0
261 for param in params:
262 if param_uses_64bits(param):
263 count += 2
264 else:
265 count += 1
266 return count
267
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700268
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400269def count_generic_param_registers64(params):
270 count = 0
271 for param in params:
272 count += 1
273 return count
274
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700275
Elliott Hughescda62092013-03-22 13:50:44 -0700276# This lets us support regular system calls like __NR_write and also weird
277# ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
278def make__NR_name(name):
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700279 if name.startswith("__ARM_NR_"):
Elliott Hughescda62092013-03-22 13:50:44 -0700280 return name
281 else:
282 return "__NR_%s" % (name)
283
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700284
Elliott Hughesfff6e272013-10-24 17:03:20 -0700285def add_footer(pointer_length, stub, syscall):
286 # Add any aliases for this syscall.
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700287 aliases = syscall["aliases"]
288 for alias in aliases:
289 stub += function_alias % { "func" : syscall["func"], "alias" : alias }
Elliott Hughesfff6e272013-10-24 17:03:20 -0700290
291 # Use hidden visibility for any functions beginning with underscores.
Elliott Hughesfff6e272013-10-24 17:03:20 -0700292 if pointer_length == 64 and syscall["func"].startswith("__"):
Elliott Hughesd465eb42014-02-19 18:59:19 -0800293 stub += '.hidden ' + syscall["func"] + '\n'
Elliott Hughesfff6e272013-10-24 17:03:20 -0700294
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700295 return stub
296
297
298def arm_eabi_genstub(syscall):
299 num_regs = count_arm_param_registers(syscall["params"])
300 if num_regs > 4:
301 return arm_eabi_call_long % syscall
302 return arm_eabi_call_default % syscall
303
304
Colin Crossd1973ca2014-01-21 19:50:58 -0800305def arm64_genstub(syscall):
306 return arm64_call % syscall
307
308
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700309def mips_genstub(syscall):
310 return mips_call % syscall
311
312
Chris Dearman50432122014-02-05 16:59:23 -0800313def mips64_genstub(syscall):
314 return mips64_call % syscall
315
316
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700317def x86_genstub(syscall):
318 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700319
320 numparams = count_generic_param_registers(syscall["params"])
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800321 stack_bias = numparams*4 + 4
322 offset = 0
323 mov_result = ""
Christopher Ferris15b91e92014-05-29 18:17:09 -0700324 first_push = True
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800325 for register in x86_registers[:numparams]:
326 result += " pushl %%%s\n" % register
Christopher Ferris15b91e92014-05-29 18:17:09 -0700327 if first_push:
328 result += " .cfi_def_cfa_offset 8\n"
329 result += " .cfi_rel_offset %s, 0\n" % register
330 first_push = False
331 else:
332 result += " .cfi_adjust_cfa_offset 4\n"
333 result += " .cfi_rel_offset %s, 0\n" % register
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800334 mov_result += " mov %d(%%esp), %%%s\n" % (stack_bias+offset, register)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800335 offset += 4
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700336
Christopher Ferris15b91e92014-05-29 18:17:09 -0700337 result += mov_result
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700338 result += x86_call % syscall
339
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800340 for register in reversed(x86_registers[:numparams]):
341 result += " popl %%%s\n" % register
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700342
343 result += x86_return % syscall
344 return result
345
Serban Constantinescufeaa89a2013-10-07 16:49:09 +0100346
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700347def x86_genstub_socketcall(syscall):
348 # %ebx <--- Argument 1 - The call id of the needed vectored
349 # syscall (socket, bind, recv, etc)
350 # %ecx <--- Argument 2 - Pointer to the rest of the arguments
351 # from the original function called (socket())
352
353 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700354
355 # save the regs we need
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800356 result += " pushl %ebx\n"
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800357 result += " .cfi_def_cfa_offset 8\n"
358 result += " .cfi_rel_offset ebx, 0\n"
Christopher Ferris15b91e92014-05-29 18:17:09 -0700359 result += " pushl %ecx\n"
360 result += " .cfi_adjust_cfa_offset 4\n"
361 result += " .cfi_rel_offset ecx, 0\n"
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800362 stack_bias = 12
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700363
364 # set the call id (%ebx)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800365 result += " mov $%d, %%ebx\n" % syscall["socketcall_id"]
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700366
367 # set the pointer to the rest of the args into %ecx
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800368 result += " mov %esp, %ecx\n"
369 result += " addl $%d, %%ecx\n" % (stack_bias)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700370
371 # now do the syscall code itself
372 result += x86_call % syscall
373
374 # now restore the saved regs
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800375 result += " popl %ecx\n"
376 result += " popl %ebx\n"
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700377
378 # epilog
379 result += x86_return % syscall
380 return result
381
382
383def x86_64_genstub(syscall):
384 result = syscall_stub_header % syscall
385 num_regs = count_generic_param_registers64(syscall["params"])
386 if (num_regs > 3):
387 # rcx is used as 4th argument. Kernel wants it at r10.
388 result += " movq %rcx, %r10\n"
389
390 result += x86_64_call % syscall
391 return result
392
393
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700394class SysCallsTxtParser:
395 def __init__(self):
396 self.syscalls = []
397 self.lineno = 0
398
399 def E(self, msg):
400 print "%d: %s" % (self.lineno, msg)
401
402 def parse_line(self, line):
403 """ parse a syscall spec line.
404
405 line processing, format is
406 return type func_name[|alias_list][:syscall_name[:socketcall_id]] ( [paramlist] ) architecture_list
407 """
408 pos_lparen = line.find('(')
409 E = self.E
410 if pos_lparen < 0:
411 E("missing left parenthesis in '%s'" % line)
412 return
413
414 pos_rparen = line.rfind(')')
415 if pos_rparen < 0 or pos_rparen <= pos_lparen:
416 E("missing or misplaced right parenthesis in '%s'" % line)
417 return
418
419 return_type = line[:pos_lparen].strip().split()
420 if len(return_type) < 2:
421 E("missing return type in '%s'" % line)
422 return
423
424 syscall_func = return_type[-1]
425 return_type = string.join(return_type[:-1],' ')
426 socketcall_id = -1
427
428 pos_colon = syscall_func.find(':')
429 if pos_colon < 0:
430 syscall_name = syscall_func
431 else:
432 if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
433 E("misplaced colon in '%s'" % line)
434 return
435
436 # now find if there is a socketcall_id for a dispatch-type syscall
437 # after the optional 2nd colon
438 pos_colon2 = syscall_func.find(':', pos_colon + 1)
439 if pos_colon2 < 0:
440 syscall_name = syscall_func[pos_colon+1:]
441 syscall_func = syscall_func[:pos_colon]
442 else:
443 if pos_colon2+1 >= len(syscall_func):
444 E("misplaced colon2 in '%s'" % line)
445 return
446 syscall_name = syscall_func[(pos_colon+1):pos_colon2]
447 socketcall_id = int(syscall_func[pos_colon2+1:])
448 syscall_func = syscall_func[:pos_colon]
449
450 alias_delim = syscall_func.find('|')
451 if alias_delim > 0:
452 alias_list = syscall_func[alias_delim+1:].strip()
453 syscall_func = syscall_func[:alias_delim]
454 alias_delim = syscall_name.find('|')
455 if alias_delim > 0:
456 syscall_name = syscall_name[:alias_delim]
457 syscall_aliases = string.split(alias_list, ',')
458 else:
459 syscall_aliases = []
460
461 if pos_rparen > pos_lparen+1:
462 syscall_params = line[pos_lparen+1:pos_rparen].split(',')
463 params = string.join(syscall_params,',')
464 else:
465 syscall_params = []
466 params = "void"
467
468 t = {
469 "name" : syscall_name,
470 "func" : syscall_func,
471 "aliases" : syscall_aliases,
472 "params" : syscall_params,
473 "decl" : "%-15s %s (%s);" % (return_type, syscall_func, params),
474 "socketcall_id" : socketcall_id
475 }
476
477 # Parse the architecture list.
478 arch_list = line[pos_rparen+1:].strip()
479 if arch_list == "all":
480 for arch in all_arches:
481 t[arch] = True
482 else:
483 for arch in string.split(arch_list, ','):
484 if arch in all_arches:
485 t[arch] = True
486 else:
487 E("invalid syscall architecture '%s' in '%s'" % (arch, line))
488 return
489
490 self.syscalls.append(t)
491
492 logging.debug(t)
493
494
495 def parse_file(self, file_path):
496 logging.debug("parse_file: %s" % file_path)
497 fp = open(file_path)
498 for line in fp.xreadlines():
499 self.lineno += 1
500 line = line.strip()
501 if not line: continue
502 if line[0] == '#': continue
503 self.parse_line(line)
504
505 fp.close()
506
507
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700508class State:
509 def __init__(self):
510 self.old_stubs = []
511 self.new_stubs = []
512 self.other_files = []
513 self.syscalls = []
514
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400515
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700516 def process_file(self, input):
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700517 parser = SysCallsTxtParser()
518 parser.parse_file(input)
519 self.syscalls = parser.syscalls
520 parser = None
521
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700522 for syscall in self.syscalls:
523 syscall["__NR_name"] = make__NR_name(syscall["name"])
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700524
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700525 if syscall.has_key("arm"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700526 syscall["asm-arm"] = add_footer(32, arm_eabi_genstub(syscall), syscall)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700527
Colin Crossd1973ca2014-01-21 19:50:58 -0800528 if syscall.has_key("arm64"):
529 syscall["asm-arm64"] = add_footer(64, arm64_genstub(syscall), syscall)
530
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700531 if syscall.has_key("x86"):
532 if syscall["socketcall_id"] >= 0:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700533 syscall["asm-x86"] = add_footer(32, x86_genstub_socketcall(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800534 else:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700535 syscall["asm-x86"] = add_footer(32, x86_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700536 elif syscall["socketcall_id"] >= 0:
Elliott Hughesd6121652013-09-25 22:43:36 -0700537 E("socketcall_id for dispatch syscalls is only supported for x86 in '%s'" % t)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800538 return
Elliott Hughescd6780b2013-02-07 14:07:00 -0800539
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700540 if syscall.has_key("mips"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700541 syscall["asm-mips"] = add_footer(32, mips_genstub(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800542
Chris Dearman50432122014-02-05 16:59:23 -0800543 if syscall.has_key("mips64"):
544 syscall["asm-mips64"] = add_footer(64, mips64_genstub(syscall), syscall)
545
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700546 if syscall.has_key("x86_64"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700547 syscall["asm-x86_64"] = add_footer(64, x86_64_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700548
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700549 # Scan a Linux kernel asm/unistd.h file containing __NR_* constants
550 # and write out equivalent SYS_* constants for glibc source compatibility.
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700551 def scan_linux_unistd_h(self, fp, path):
552 pattern = re.compile(r'^#define __NR_([a-z]\S+) .*')
553 syscalls = set() # MIPS defines everything three times; work around that.
554 for line in open(path):
555 m = re.search(pattern, line)
556 if m:
557 syscalls.add(m.group(1))
558 for syscall in sorted(syscalls):
Elliott Hughescda62092013-03-22 13:50:44 -0700559 fp.write("#define SYS_%s %s\n" % (syscall, make__NR_name(syscall)))
Elliott Hughes8ecf2252013-03-21 18:06:55 -0700560
561
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700562 def gen_glibc_syscalls_h(self):
Elliott Hughescda62092013-03-22 13:50:44 -0700563 # TODO: generate a separate file for each architecture, like glibc's bits/syscall.h.
Elliott Hughes9724ce32013-03-21 19:43:54 -0700564 glibc_syscalls_h_path = "include/sys/glibc-syscalls.h"
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700565 logging.info("generating " + glibc_syscalls_h_path)
Elliott Hughes9724ce32013-03-21 19:43:54 -0700566 glibc_fp = create_file(glibc_syscalls_h_path)
Elliott Hughes103ccde2013-10-16 14:27:59 -0700567 glibc_fp.write("/* %s */\n" % warning)
Elliott Hughes9724ce32013-03-21 19:43:54 -0700568 glibc_fp.write("#ifndef _BIONIC_GLIBC_SYSCALLS_H_\n")
569 glibc_fp.write("#define _BIONIC_GLIBC_SYSCALLS_H_\n")
570
Serban Constantinescufeaa89a2013-10-07 16:49:09 +0100571 glibc_fp.write("#if defined(__aarch64__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700572 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 +0100573 glibc_fp.write("#elif defined(__arm__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700574 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 -0700575 glibc_fp.write("#elif defined(__mips__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700576 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 -0700577 glibc_fp.write("#elif defined(__i386__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700578 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 +0400579 glibc_fp.write("#elif defined(__x86_64__)\n")
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700580 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 -0700581 glibc_fp.write("#endif\n")
582
583 glibc_fp.write("#endif /* _BIONIC_GLIBC_SYSCALLS_H_ */\n")
584 glibc_fp.close()
585 self.other_files.append(glibc_syscalls_h_path)
586
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700587
Elliott Hughesd6121652013-09-25 22:43:36 -0700588 # Write each syscall stub.
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700589 def gen_syscall_stubs(self):
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700590 for syscall in self.syscalls:
Elliott Hughesd6121652013-09-25 22:43:36 -0700591 for arch in all_arches:
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700592 if syscall.has_key("asm-%s" % arch):
593 filename = "arch-%s/syscalls/%s.S" % (arch, syscall["func"])
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700594 logging.info(">>> generating " + filename)
Elliott Hughesd6121652013-09-25 22:43:36 -0700595 fp = create_file(filename)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700596 fp.write(syscall["asm-%s" % arch])
Elliott Hughesd6121652013-09-25 22:43:36 -0700597 fp.close()
598 self.new_stubs.append(filename)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700599
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700600
Elliott Hughesd6121652013-09-25 22:43:36 -0700601 def regenerate(self):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700602 logging.info("scanning for existing architecture-specific stub files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700603
Elliott Hughesd6121652013-09-25 22:43:36 -0700604 for arch in all_arches:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700605 arch_dir = "arch-" + arch
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700606 logging.info("scanning " + os.path.join(bionic_libc_root, arch_dir))
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700607 rel_path = os.path.join(arch_dir, "syscalls")
608 for file in os.listdir(os.path.join(bionic_libc_root, rel_path)):
609 if file.endswith(".S"):
610 self.old_stubs.append(os.path.join(rel_path, file))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700611
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700612 logging.info("found %d stub files" % len(self.old_stubs))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700613
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400614 if not os.path.exists(bionic_temp):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700615 logging.info("creating %s..." % bionic_temp)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400616 make_dir(bionic_temp)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700617
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700618 logging.info("re-generating stubs and support files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700619
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700620 self.gen_glibc_syscalls_h()
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700621 self.gen_syscall_stubs()
622
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700623 logging.info("comparing files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700624 adds = []
625 edits = []
626
627 for stub in self.new_stubs + self.other_files:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700628 tmp_file = os.path.join(bionic_temp, stub)
629 libc_file = os.path.join(bionic_libc_root, stub)
630 if not os.path.exists(libc_file):
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200631 # new file, git add it
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700632 logging.info("new file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700633 adds.append(libc_file)
634 shutil.copyfile(tmp_file, libc_file)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700635
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700636 elif not filecmp.cmp(tmp_file, libc_file):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700637 logging.info("changed file: " + stub)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400638 edits.append(stub)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700639
640 deletes = []
641 for stub in self.old_stubs:
642 if not stub in self.new_stubs:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700643 logging.info("deleted file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700644 deletes.append(os.path.join(bionic_libc_root, stub))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700645
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400646 if not DRY_RUN:
647 if adds:
648 commands.getoutput("git add " + " ".join(adds))
649 if deletes:
650 commands.getoutput("git rm " + " ".join(deletes))
651 if edits:
652 for file in edits:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700653 shutil.copyfile(os.path.join(bionic_temp, file),
654 os.path.join(bionic_libc_root, file))
655 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 -0700656
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700657 commands.getoutput("git add %s" % (os.path.join(bionic_libc_root, "SYSCALLS.TXT")))
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200658
659 if (not adds) and (not deletes) and (not edits):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700660 logging.info("no changes detected!")
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200661 else:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700662 logging.info("ready to go!!")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700663
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700664logging.basicConfig(level=logging.INFO)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700665
666state = State()
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700667state.process_file(os.path.join(bionic_libc_root, "SYSCALLS.TXT"))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700668state.regenerate()