blob: 329184f9bbd36a4707f5bafeef91330af716c4f5 [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
Christopher Ferrisf5a91232016-04-27 18:31:02 -070065 .cfi_register r7, ip
Elliott Hughes0437f3f2013-10-07 23:53:13 -070066 ldr r7, =%(__NR_name)s
67 swi #0
68 mov r7, ip
Christopher Ferrisf5a91232016-04-27 18:31:02 -070069 .cfi_restore r7
Elliott Hughes0437f3f2013-10-07 23:53:13 -070070 cmn r0, #(MAX_ERRNO + 1)
71 bxls lr
72 neg r0, r0
Elliott Hughes011e1112014-09-08 15:25:01 -070073 b __set_errno_internal
Elliott Hughes0437f3f2013-10-07 23:53:13 -070074END(%(func)s)
75"""
76
77arm_eabi_call_long = syscall_stub_header + """\
78 mov ip, sp
Elliott Hughes0437f3f2013-10-07 23:53:13 -070079 stmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080080 .cfi_def_cfa_offset 16
81 .cfi_rel_offset r4, 0
82 .cfi_rel_offset r5, 4
83 .cfi_rel_offset r6, 8
84 .cfi_rel_offset r7, 12
Elliott Hughes0437f3f2013-10-07 23:53:13 -070085 ldmfd ip, {r4, r5, r6}
86 ldr r7, =%(__NR_name)s
87 swi #0
88 ldmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080089 .cfi_def_cfa_offset 0
Elliott Hughes0437f3f2013-10-07 23:53:13 -070090 cmn r0, #(MAX_ERRNO + 1)
91 bxls lr
92 neg r0, r0
Elliott Hughes011e1112014-09-08 15:25:01 -070093 b __set_errno_internal
Elliott Hughes0437f3f2013-10-07 23:53:13 -070094END(%(func)s)
95"""
96
97
98#
Colin Crossd1973ca2014-01-21 19:50:58 -080099# Arm64 assembler templates for each syscall stub
100#
101
102arm64_call = syscall_stub_header + """\
Colin Crossd1973ca2014-01-21 19:50:58 -0800103 mov x8, %(__NR_name)s
104 svc #0
105
Colin Crossd1973ca2014-01-21 19:50:58 -0800106 cmn x0, #(MAX_ERRNO + 1)
107 cneg x0, x0, hi
Elliott Hughes011e1112014-09-08 15:25:01 -0700108 b.hi __set_errno_internal
Colin Crossd1973ca2014-01-21 19:50:58 -0800109
110 ret
111END(%(func)s)
112"""
113
114
115#
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700116# MIPS assembler templates for each syscall stub
117#
118
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800119mips_call = syscall_stub_header + """\
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700120 .set noreorder
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800121 .cpload t9
122 li v0, %(__NR_name)s
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700123 syscall
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800124 bnez a3, 1f
125 move a0, v0
126 j ra
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700127 nop
1281:
Elliott Hughes011e1112014-09-08 15:25:01 -0700129 la t9,__set_errno_internal
Elliott Hugheseae27dc2014-02-19 12:20:00 -0800130 j t9
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700131 nop
132 .set reorder
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800133END(%(func)s)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700134"""
135
136
Elliott Hughescd6780b2013-02-07 14:07:00 -0800137#
Chris Dearman50432122014-02-05 16:59:23 -0800138# MIPS64 assembler templates for each syscall stub
139#
140
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800141mips64_call = syscall_stub_header + """\
Chris Dearman50432122014-02-05 16:59:23 -0800142 .set push
143 .set noreorder
144 li v0, %(__NR_name)s
145 syscall
146 bnez a3, 1f
147 move a0, v0
148 j ra
149 nop
1501:
151 move t0, ra
152 bal 2f
153 nop
1542:
155 .cpsetup ra, t1, 2b
Elliott Hughes011e1112014-09-08 15:25:01 -0700156 LA t9,__set_errno_internal
Chris Dearman50432122014-02-05 16:59:23 -0800157 .cpreturn
158 j t9
159 move ra, t0
160 .set pop
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800161END(%(func)s)
Chris Dearman50432122014-02-05 16:59:23 -0800162"""
163
164
165#
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700166# x86 assembler templates for each syscall stub
167#
168
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800169x86_registers = [ "ebx", "ecx", "edx", "esi", "edi", "ebp" ]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700170
Mingwei Shibe910522015-11-12 07:02:14 +0000171x86_call_prepare = """\
172
173 call __kernel_syscall
174 pushl %eax
175 .cfi_adjust_cfa_offset 4
176 .cfi_rel_offset eax, 0
177
178"""
179
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700180x86_call = """\
181 movl $%(__NR_name)s, %%eax
Mingwei Shibe910522015-11-12 07:02:14 +0000182 call *(%%esp)
183 addl $4, %%esp
184
Elliott Hughes9aceab52013-03-12 14:57:30 -0700185 cmpl $-MAX_ERRNO, %%eax
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700186 jb 1f
187 negl %%eax
188 pushl %%eax
Elliott Hughes011e1112014-09-08 15:25:01 -0700189 call __set_errno_internal
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700190 addl $4, %%esp
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001911:
192"""
193
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700194x86_return = """\
195 ret
196END(%(func)s)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700197"""
198
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700199
Elliott Hughescd6780b2013-02-07 14:07:00 -0800200#
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400201# x86_64 assembler templates for each syscall stub
202#
203
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700204x86_64_call = """\
205 movl $%(__NR_name)s, %%eax
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400206 syscall
207 cmpq $-MAX_ERRNO, %%rax
208 jb 1f
209 negl %%eax
210 movl %%eax, %%edi
Elliott Hughes011e1112014-09-08 15:25:01 -0700211 call __set_errno_internal
Pavel Chupinf12a18b2012-12-12 13:11:48 +04002121:
213 ret
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700214END(%(func)s)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400215"""
216
Raghu Gandham1fa0d842012-01-27 17:51:42 -0800217
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100218def param_uses_64bits(param):
219 """Returns True iff a syscall parameter description corresponds
220 to a 64-bit type."""
221 param = param.strip()
222 # First, check that the param type begins with one of the known
223 # 64-bit types.
224 if not ( \
225 param.startswith("int64_t") or param.startswith("uint64_t") or \
226 param.startswith("loff_t") or param.startswith("off64_t") or \
227 param.startswith("long long") or param.startswith("unsigned long long") or
228 param.startswith("signed long long") ):
229 return False
230
231 # Second, check that there is no pointer type here
232 if param.find("*") >= 0:
233 return False
234
235 # Ok
236 return True
237
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700238
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100239def count_arm_param_registers(params):
240 """This function is used to count the number of register used
Elliott Hughescd6780b2013-02-07 14:07:00 -0800241 to pass parameters when invoking an ARM system call.
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100242 This is because the ARM EABI mandates that 64-bit quantities
243 must be passed in an even+odd register pair. So, for example,
244 something like:
245
246 foo(int fd, off64_t pos)
247
248 would actually need 4 registers:
249 r0 -> int
250 r1 -> unused
251 r2-r3 -> pos
252 """
253 count = 0
254 for param in params:
255 if param_uses_64bits(param):
256 if (count & 1) != 0:
257 count += 1
258 count += 2
259 else:
260 count += 1
261 return count
262
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700263
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100264def count_generic_param_registers(params):
265 count = 0
266 for param in params:
267 if param_uses_64bits(param):
268 count += 2
269 else:
270 count += 1
271 return count
272
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700273
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400274def count_generic_param_registers64(params):
275 count = 0
276 for param in params:
277 count += 1
278 return count
279
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700280
Elliott Hughescda62092013-03-22 13:50:44 -0700281# This lets us support regular system calls like __NR_write and also weird
282# ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
283def make__NR_name(name):
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700284 if name.startswith("__ARM_NR_"):
Elliott Hughescda62092013-03-22 13:50:44 -0700285 return name
286 else:
287 return "__NR_%s" % (name)
288
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700289
Elliott Hughesfff6e272013-10-24 17:03:20 -0700290def add_footer(pointer_length, stub, syscall):
291 # Add any aliases for this syscall.
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700292 aliases = syscall["aliases"]
293 for alias in aliases:
Christopher Ferrisfa5faa02015-03-24 16:50:46 -0700294 stub += "\nALIAS_SYMBOL(%s, %s)\n" % (alias, syscall["func"])
Elliott Hughesfff6e272013-10-24 17:03:20 -0700295
Nick Kralevich00490ae2015-02-03 11:27:25 -0800296 # Use hidden visibility on LP64 for any functions beginning with underscores.
297 # Force hidden visibility for any functions which begin with 3 underscores
298 if (pointer_length == 64 and syscall["func"].startswith("__")) or syscall["func"].startswith("___"):
Elliott Hughesd465eb42014-02-19 18:59:19 -0800299 stub += '.hidden ' + syscall["func"] + '\n'
Elliott Hughesfff6e272013-10-24 17:03:20 -0700300
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700301 return stub
302
303
304def arm_eabi_genstub(syscall):
305 num_regs = count_arm_param_registers(syscall["params"])
306 if num_regs > 4:
307 return arm_eabi_call_long % syscall
308 return arm_eabi_call_default % syscall
309
310
Colin Crossd1973ca2014-01-21 19:50:58 -0800311def arm64_genstub(syscall):
312 return arm64_call % syscall
313
314
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700315def mips_genstub(syscall):
316 return mips_call % syscall
317
318
Chris Dearman50432122014-02-05 16:59:23 -0800319def mips64_genstub(syscall):
320 return mips64_call % syscall
321
322
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700323def x86_genstub(syscall):
324 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700325
326 numparams = count_generic_param_registers(syscall["params"])
Mingwei Shibe910522015-11-12 07:02:14 +0000327 stack_bias = numparams*4 + 8
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800328 offset = 0
329 mov_result = ""
Christopher Ferris15b91e92014-05-29 18:17:09 -0700330 first_push = True
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800331 for register in x86_registers[:numparams]:
332 result += " pushl %%%s\n" % register
Christopher Ferris15b91e92014-05-29 18:17:09 -0700333 if first_push:
334 result += " .cfi_def_cfa_offset 8\n"
335 result += " .cfi_rel_offset %s, 0\n" % register
336 first_push = False
337 else:
338 result += " .cfi_adjust_cfa_offset 4\n"
339 result += " .cfi_rel_offset %s, 0\n" % register
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800340 mov_result += " mov %d(%%esp), %%%s\n" % (stack_bias+offset, register)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800341 offset += 4
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700342
Mingwei Shibe910522015-11-12 07:02:14 +0000343 result += x86_call_prepare
Christopher Ferris15b91e92014-05-29 18:17:09 -0700344 result += mov_result
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700345 result += x86_call % syscall
346
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800347 for register in reversed(x86_registers[:numparams]):
348 result += " popl %%%s\n" % register
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700349
350 result += x86_return % syscall
351 return result
352
Serban Constantinescufeaa89a2013-10-07 16:49:09 +0100353
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700354def x86_genstub_socketcall(syscall):
355 # %ebx <--- Argument 1 - The call id of the needed vectored
356 # syscall (socket, bind, recv, etc)
357 # %ecx <--- Argument 2 - Pointer to the rest of the arguments
358 # from the original function called (socket())
359
360 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700361
362 # save the regs we need
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800363 result += " pushl %ebx\n"
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800364 result += " .cfi_def_cfa_offset 8\n"
365 result += " .cfi_rel_offset ebx, 0\n"
Christopher Ferris15b91e92014-05-29 18:17:09 -0700366 result += " pushl %ecx\n"
367 result += " .cfi_adjust_cfa_offset 4\n"
368 result += " .cfi_rel_offset ecx, 0\n"
Mingwei Shibe910522015-11-12 07:02:14 +0000369 stack_bias = 16
370
371 result += x86_call_prepare
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700372
373 # set the call id (%ebx)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800374 result += " mov $%d, %%ebx\n" % syscall["socketcall_id"]
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700375
376 # set the pointer to the rest of the args into %ecx
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800377 result += " mov %esp, %ecx\n"
378 result += " addl $%d, %%ecx\n" % (stack_bias)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700379
380 # now do the syscall code itself
381 result += x86_call % syscall
382
383 # now restore the saved regs
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800384 result += " popl %ecx\n"
385 result += " popl %ebx\n"
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700386
387 # epilog
388 result += x86_return % syscall
389 return result
390
391
392def x86_64_genstub(syscall):
393 result = syscall_stub_header % syscall
394 num_regs = count_generic_param_registers64(syscall["params"])
395 if (num_regs > 3):
396 # rcx is used as 4th argument. Kernel wants it at r10.
397 result += " movq %rcx, %r10\n"
398
399 result += x86_64_call % syscall
400 return result
401
402
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700403class SysCallsTxtParser:
404 def __init__(self):
405 self.syscalls = []
406 self.lineno = 0
407
408 def E(self, msg):
409 print "%d: %s" % (self.lineno, msg)
410
411 def parse_line(self, line):
412 """ parse a syscall spec line.
413
414 line processing, format is
415 return type func_name[|alias_list][:syscall_name[:socketcall_id]] ( [paramlist] ) architecture_list
416 """
417 pos_lparen = line.find('(')
418 E = self.E
419 if pos_lparen < 0:
420 E("missing left parenthesis in '%s'" % line)
421 return
422
423 pos_rparen = line.rfind(')')
424 if pos_rparen < 0 or pos_rparen <= pos_lparen:
425 E("missing or misplaced right parenthesis in '%s'" % line)
426 return
427
428 return_type = line[:pos_lparen].strip().split()
429 if len(return_type) < 2:
430 E("missing return type in '%s'" % line)
431 return
432
433 syscall_func = return_type[-1]
434 return_type = string.join(return_type[:-1],' ')
435 socketcall_id = -1
436
437 pos_colon = syscall_func.find(':')
438 if pos_colon < 0:
439 syscall_name = syscall_func
440 else:
441 if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
442 E("misplaced colon in '%s'" % line)
443 return
444
445 # now find if there is a socketcall_id for a dispatch-type syscall
446 # after the optional 2nd colon
447 pos_colon2 = syscall_func.find(':', pos_colon + 1)
448 if pos_colon2 < 0:
449 syscall_name = syscall_func[pos_colon+1:]
450 syscall_func = syscall_func[:pos_colon]
451 else:
452 if pos_colon2+1 >= len(syscall_func):
453 E("misplaced colon2 in '%s'" % line)
454 return
455 syscall_name = syscall_func[(pos_colon+1):pos_colon2]
456 socketcall_id = int(syscall_func[pos_colon2+1:])
457 syscall_func = syscall_func[:pos_colon]
458
459 alias_delim = syscall_func.find('|')
460 if alias_delim > 0:
461 alias_list = syscall_func[alias_delim+1:].strip()
462 syscall_func = syscall_func[:alias_delim]
463 alias_delim = syscall_name.find('|')
464 if alias_delim > 0:
465 syscall_name = syscall_name[:alias_delim]
466 syscall_aliases = string.split(alias_list, ',')
467 else:
468 syscall_aliases = []
469
470 if pos_rparen > pos_lparen+1:
471 syscall_params = line[pos_lparen+1:pos_rparen].split(',')
472 params = string.join(syscall_params,',')
473 else:
474 syscall_params = []
475 params = "void"
476
477 t = {
478 "name" : syscall_name,
479 "func" : syscall_func,
480 "aliases" : syscall_aliases,
481 "params" : syscall_params,
482 "decl" : "%-15s %s (%s);" % (return_type, syscall_func, params),
483 "socketcall_id" : socketcall_id
484 }
485
486 # Parse the architecture list.
487 arch_list = line[pos_rparen+1:].strip()
488 if arch_list == "all":
489 for arch in all_arches:
490 t[arch] = True
491 else:
492 for arch in string.split(arch_list, ','):
493 if arch in all_arches:
494 t[arch] = True
495 else:
496 E("invalid syscall architecture '%s' in '%s'" % (arch, line))
497 return
498
499 self.syscalls.append(t)
500
501 logging.debug(t)
502
503
504 def parse_file(self, file_path):
505 logging.debug("parse_file: %s" % file_path)
506 fp = open(file_path)
507 for line in fp.xreadlines():
508 self.lineno += 1
509 line = line.strip()
510 if not line: continue
511 if line[0] == '#': continue
512 self.parse_line(line)
513
514 fp.close()
515
516
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700517class State:
518 def __init__(self):
519 self.old_stubs = []
520 self.new_stubs = []
521 self.other_files = []
522 self.syscalls = []
523
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400524
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700525 def process_file(self, input):
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700526 parser = SysCallsTxtParser()
527 parser.parse_file(input)
528 self.syscalls = parser.syscalls
529 parser = None
530
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700531 for syscall in self.syscalls:
532 syscall["__NR_name"] = make__NR_name(syscall["name"])
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700533
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700534 if syscall.has_key("arm"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700535 syscall["asm-arm"] = add_footer(32, arm_eabi_genstub(syscall), syscall)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700536
Colin Crossd1973ca2014-01-21 19:50:58 -0800537 if syscall.has_key("arm64"):
538 syscall["asm-arm64"] = add_footer(64, arm64_genstub(syscall), syscall)
539
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700540 if syscall.has_key("x86"):
541 if syscall["socketcall_id"] >= 0:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700542 syscall["asm-x86"] = add_footer(32, x86_genstub_socketcall(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800543 else:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700544 syscall["asm-x86"] = add_footer(32, x86_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700545 elif syscall["socketcall_id"] >= 0:
Elliott Hughesd6121652013-09-25 22:43:36 -0700546 E("socketcall_id for dispatch syscalls is only supported for x86 in '%s'" % t)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800547 return
Elliott Hughescd6780b2013-02-07 14:07:00 -0800548
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700549 if syscall.has_key("mips"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700550 syscall["asm-mips"] = add_footer(32, mips_genstub(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800551
Chris Dearman50432122014-02-05 16:59:23 -0800552 if syscall.has_key("mips64"):
553 syscall["asm-mips64"] = add_footer(64, mips64_genstub(syscall), syscall)
554
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700555 if syscall.has_key("x86_64"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700556 syscall["asm-x86_64"] = add_footer(64, x86_64_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700557
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700558
559 # Scan Linux kernel asm/unistd.h files containing __NR_* constants
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700560 # and write out equivalent SYS_* constants for glibc source compatibility.
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700561 def gen_glibc_syscalls_h(self):
Elliott Hughes8aabbd72016-05-02 12:47:58 -0700562 glibc_syscalls_h_path = "include/bits/glibc-syscalls.h"
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700563 logging.info("generating " + glibc_syscalls_h_path)
Elliott Hughes9724ce32013-03-21 19:43:54 -0700564 glibc_fp = create_file(glibc_syscalls_h_path)
Elliott Hughes103ccde2013-10-16 14:27:59 -0700565 glibc_fp.write("/* %s */\n" % warning)
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700566 glibc_fp.write("#ifndef _BIONIC_BITS_GLIBC_SYSCALLS_H_\n")
567 glibc_fp.write("#define _BIONIC_BITS_GLIBC_SYSCALLS_H_\n")
Elliott Hughes9724ce32013-03-21 19:43:54 -0700568
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700569 # Collect the set of all syscalls for all architectures.
570 syscalls = set()
571 pattern = re.compile(r'^\s*#\s*define\s*__NR_([a-z]\S+)')
572 for unistd_h in ["kernel/uapi/asm-generic/unistd.h",
573 "kernel/uapi/asm-arm/asm/unistd.h",
574 "kernel/uapi/asm-mips/asm/unistd.h",
575 "kernel/uapi/asm-x86/asm/unistd_32.h",
576 "kernel/uapi/asm-x86/asm/unistd_64.h"]:
577 for line in open(os.path.join(bionic_libc_root, unistd_h)):
578 m = re.search(pattern, line)
579 if m:
580 nr_name = m.group(1)
581 if 'reserved' not in nr_name and 'unused' not in nr_name:
582 syscalls.add(nr_name)
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700583
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700584 # Write out a single file listing them all. Note that the input
585 # files include #if trickery, so even for a single architecture
586 # we don't know exactly which ones are available.
587 # https://code.google.com/p/android/issues/detail?id=215853
588 for syscall in sorted(syscalls):
589 nr_name = make__NR_name(syscall)
590 glibc_fp.write("#if defined(%s)\n" % nr_name)
591 glibc_fp.write(" #define SYS_%s %s\n" % (syscall, nr_name))
592 glibc_fp.write("#endif\n")
593
594 glibc_fp.write("#endif /* _BIONIC_BITS_GLIBC_SYSCALLS_H_ */\n")
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700595 glibc_fp.close()
596 self.other_files.append(glibc_syscalls_h_path)
597
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700598
Elliott Hughesd6121652013-09-25 22:43:36 -0700599 # Write each syscall stub.
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700600 def gen_syscall_stubs(self):
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700601 for syscall in self.syscalls:
Elliott Hughesd6121652013-09-25 22:43:36 -0700602 for arch in all_arches:
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700603 if syscall.has_key("asm-%s" % arch):
604 filename = "arch-%s/syscalls/%s.S" % (arch, syscall["func"])
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700605 logging.info(">>> generating " + filename)
Elliott Hughesd6121652013-09-25 22:43:36 -0700606 fp = create_file(filename)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700607 fp.write(syscall["asm-%s" % arch])
Elliott Hughesd6121652013-09-25 22:43:36 -0700608 fp.close()
609 self.new_stubs.append(filename)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700610
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700611
Elliott Hughesd6121652013-09-25 22:43:36 -0700612 def regenerate(self):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700613 logging.info("scanning for existing architecture-specific stub files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700614
Elliott Hughesd6121652013-09-25 22:43:36 -0700615 for arch in all_arches:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700616 arch_dir = "arch-" + arch
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700617 logging.info("scanning " + os.path.join(bionic_libc_root, arch_dir))
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700618 rel_path = os.path.join(arch_dir, "syscalls")
619 for file in os.listdir(os.path.join(bionic_libc_root, rel_path)):
620 if file.endswith(".S"):
621 self.old_stubs.append(os.path.join(rel_path, file))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700622
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700623 logging.info("found %d stub files" % len(self.old_stubs))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700624
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400625 if not os.path.exists(bionic_temp):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700626 logging.info("creating %s..." % bionic_temp)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400627 make_dir(bionic_temp)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700628
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700629 logging.info("re-generating stubs and support files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700630
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700631 self.gen_glibc_syscalls_h()
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700632 self.gen_syscall_stubs()
633
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700634 logging.info("comparing files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700635 adds = []
636 edits = []
637
638 for stub in self.new_stubs + self.other_files:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700639 tmp_file = os.path.join(bionic_temp, stub)
640 libc_file = os.path.join(bionic_libc_root, stub)
641 if not os.path.exists(libc_file):
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200642 # new file, git add it
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700643 logging.info("new file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700644 adds.append(libc_file)
645 shutil.copyfile(tmp_file, libc_file)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700646
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700647 elif not filecmp.cmp(tmp_file, libc_file):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700648 logging.info("changed file: " + stub)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400649 edits.append(stub)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700650
651 deletes = []
652 for stub in self.old_stubs:
653 if not stub in self.new_stubs:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700654 logging.info("deleted file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700655 deletes.append(os.path.join(bionic_libc_root, stub))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700656
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400657 if not DRY_RUN:
658 if adds:
659 commands.getoutput("git add " + " ".join(adds))
660 if deletes:
661 commands.getoutput("git rm " + " ".join(deletes))
662 if edits:
663 for file in edits:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700664 shutil.copyfile(os.path.join(bionic_temp, file),
665 os.path.join(bionic_libc_root, file))
666 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 -0700667
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700668 commands.getoutput("git add %s" % (os.path.join(bionic_libc_root, "SYSCALLS.TXT")))
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200669
670 if (not adds) and (not deletes) and (not edits):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700671 logging.info("no changes detected!")
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200672 else:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700673 logging.info("ready to go!!")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700674
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700675logging.basicConfig(level=logging.INFO)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700676
Paul Lawrenceeabc3522016-11-11 11:33:42 -0800677if __name__ == "__main__":
678 state = State()
679 state.process_file(os.path.join(bionic_libc_root, "SYSCALLS.TXT"))
680 state.regenerate()