blob: d78a5e7be01433dd33ee648d9c7c72b0fce0de36 [file] [log] [blame]
Stephen Crane77bb5642017-08-31 15:08:26 -07001#!/usr/bin/env 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
Luis Hector Chavezfa09b3c2018-08-03 20:53:28 -070029bionic_libc_root = os.path.join(os.path.dirname(os.path.abspath(__file__)),
30 "..")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070031
Elliott Hughes103ccde2013-10-16 14:27:59 -070032warning = "Generated by gensyscalls.py. Do not edit."
33
Pavel Chupinf12a18b2012-12-12 13:11:48 +040034DRY_RUN = False
35
36def make_dir(path):
Raghu Gandham1fa0d842012-01-27 17:51:42 -080037 path = os.path.abspath(path)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070038 if not os.path.exists(path):
39 parent = os.path.dirname(path)
40 if parent:
41 make_dir(parent)
42 os.mkdir(path)
43
Elliott Hughes0437f3f2013-10-07 23:53:13 -070044
Pavel Chupinf12a18b2012-12-12 13:11:48 +040045def create_file(relpath):
Christopher Ferris01bd32e2014-08-05 12:19:27 -070046 full_path = os.path.join(bionic_temp, relpath)
47 dir = os.path.dirname(full_path)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -070048 make_dir(dir)
Christopher Ferris01bd32e2014-08-05 12:19:27 -070049 return open(full_path, "w")
Pavel Chupinf12a18b2012-12-12 13:11:48 +040050
51
Elliott Hughes103ccde2013-10-16 14:27:59 -070052syscall_stub_header = "/* " + warning + " */\n" + \
53"""
Elliott Hughesed744842013-11-07 10:31:05 -080054#include <private/bionic_asm.h>
Pavel Chupinf12a18b2012-12-12 13:11:48 +040055
Elliott Hughes0437f3f2013-10-07 23:53:13 -070056ENTRY(%(func)s)
Pavel Chupinf12a18b2012-12-12 13:11:48 +040057"""
58
Elliott Hughes0437f3f2013-10-07 23:53:13 -070059
Elliott Hughes0437f3f2013-10-07 23:53:13 -070060#
61# ARM assembler templates for each syscall stub
62#
63
64arm_eabi_call_default = syscall_stub_header + """\
65 mov ip, r7
Christopher Ferrisf5a91232016-04-27 18:31:02 -070066 .cfi_register r7, ip
Elliott Hughes0437f3f2013-10-07 23:53:13 -070067 ldr r7, =%(__NR_name)s
68 swi #0
69 mov r7, ip
Christopher Ferrisf5a91232016-04-27 18:31:02 -070070 .cfi_restore r7
Elliott Hughes0437f3f2013-10-07 23:53:13 -070071 cmn r0, #(MAX_ERRNO + 1)
72 bxls lr
73 neg r0, r0
Elliott Hughes011e1112014-09-08 15:25:01 -070074 b __set_errno_internal
Elliott Hughes0437f3f2013-10-07 23:53:13 -070075END(%(func)s)
76"""
77
78arm_eabi_call_long = syscall_stub_header + """\
79 mov ip, sp
Elliott Hughes0437f3f2013-10-07 23:53:13 -070080 stmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080081 .cfi_def_cfa_offset 16
82 .cfi_rel_offset r4, 0
83 .cfi_rel_offset r5, 4
84 .cfi_rel_offset r6, 8
85 .cfi_rel_offset r7, 12
Elliott Hughes0437f3f2013-10-07 23:53:13 -070086 ldmfd ip, {r4, r5, r6}
87 ldr r7, =%(__NR_name)s
88 swi #0
89 ldmfd sp!, {r4, r5, r6, r7}
Christopher Ferrised459702013-12-02 17:44:53 -080090 .cfi_def_cfa_offset 0
Elliott Hughes0437f3f2013-10-07 23:53:13 -070091 cmn r0, #(MAX_ERRNO + 1)
92 bxls lr
93 neg r0, r0
Elliott Hughes011e1112014-09-08 15:25:01 -070094 b __set_errno_internal
Elliott Hughes0437f3f2013-10-07 23:53:13 -070095END(%(func)s)
96"""
97
98
99#
Colin Crossd1973ca2014-01-21 19:50:58 -0800100# Arm64 assembler templates for each syscall stub
101#
102
103arm64_call = syscall_stub_header + """\
Colin Crossd1973ca2014-01-21 19:50:58 -0800104 mov x8, %(__NR_name)s
105 svc #0
106
Colin Crossd1973ca2014-01-21 19:50:58 -0800107 cmn x0, #(MAX_ERRNO + 1)
108 cneg x0, x0, hi
Elliott Hughes011e1112014-09-08 15:25:01 -0700109 b.hi __set_errno_internal
Colin Crossd1973ca2014-01-21 19:50:58 -0800110
111 ret
112END(%(func)s)
113"""
114
115
116#
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700117# MIPS assembler templates for each syscall stub
118#
119
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800120mips_call = syscall_stub_header + """\
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700121 .set noreorder
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700122 .cpload $t9
123 li $v0, %(__NR_name)s
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700124 syscall
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700125 bnez $a3, 1f
126 move $a0, $v0
127 j $ra
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700128 nop
1291:
Elliott Hughesd4ca2312017-10-11 22:27:45 -0700130 la $t9,__set_errno_internal
131 j $t9
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700132 nop
133 .set reorder
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800134END(%(func)s)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700135"""
136
137
Elliott Hughescd6780b2013-02-07 14:07:00 -0800138#
Chris Dearman50432122014-02-05 16:59:23 -0800139# MIPS64 assembler templates for each syscall stub
140#
141
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800142mips64_call = syscall_stub_header + """\
Chris Dearman50432122014-02-05 16:59:23 -0800143 .set push
144 .set noreorder
Elliott Hughesab413c52017-10-13 13:22:24 -0700145 li $v0, %(__NR_name)s
Chris Dearman50432122014-02-05 16:59:23 -0800146 syscall
Elliott Hughesab413c52017-10-13 13:22:24 -0700147 bnez $a3, 1f
148 move $a0, $v0
149 j $ra
Chris Dearman50432122014-02-05 16:59:23 -0800150 nop
1511:
Elliott Hughesab413c52017-10-13 13:22:24 -0700152 move $t0, $ra
153 bal 2f
Chris Dearman50432122014-02-05 16:59:23 -0800154 nop
1552:
Elliott Hughesab413c52017-10-13 13:22:24 -0700156 .cpsetup $ra, $t1, 2b
157 LA $t9, __set_errno_internal
Chris Dearman50432122014-02-05 16:59:23 -0800158 .cpreturn
Elliott Hughesab413c52017-10-13 13:22:24 -0700159 j $t9
160 move $ra, $t0
Chris Dearman50432122014-02-05 16:59:23 -0800161 .set pop
Elliott Hughes9abbbdc2014-02-19 14:54:31 -0800162END(%(func)s)
Chris Dearman50432122014-02-05 16:59:23 -0800163"""
164
165
166#
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700167# x86 assembler templates for each syscall stub
168#
169
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800170x86_registers = [ "ebx", "ecx", "edx", "esi", "edi", "ebp" ]
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700171
Mingwei Shibe910522015-11-12 07:02:14 +0000172x86_call_prepare = """\
173
174 call __kernel_syscall
175 pushl %eax
176 .cfi_adjust_cfa_offset 4
177 .cfi_rel_offset eax, 0
178
179"""
180
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700181x86_call = """\
182 movl $%(__NR_name)s, %%eax
Mingwei Shibe910522015-11-12 07:02:14 +0000183 call *(%%esp)
184 addl $4, %%esp
185
Elliott Hughes9aceab52013-03-12 14:57:30 -0700186 cmpl $-MAX_ERRNO, %%eax
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700187 jb 1f
188 negl %%eax
189 pushl %%eax
Elliott Hughes011e1112014-09-08 15:25:01 -0700190 call __set_errno_internal
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700191 addl $4, %%esp
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -07001921:
193"""
194
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700195x86_return = """\
196 ret
197END(%(func)s)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700198"""
199
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700200
Elliott Hughescd6780b2013-02-07 14:07:00 -0800201#
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400202# x86_64 assembler templates for each syscall stub
203#
204
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700205x86_64_call = """\
206 movl $%(__NR_name)s, %%eax
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400207 syscall
208 cmpq $-MAX_ERRNO, %%rax
209 jb 1f
210 negl %%eax
211 movl %%eax, %%edi
Elliott Hughes011e1112014-09-08 15:25:01 -0700212 call __set_errno_internal
Pavel Chupinf12a18b2012-12-12 13:11:48 +04002131:
214 ret
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700215END(%(func)s)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400216"""
217
Raghu Gandham1fa0d842012-01-27 17:51:42 -0800218
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100219def param_uses_64bits(param):
220 """Returns True iff a syscall parameter description corresponds
221 to a 64-bit type."""
222 param = param.strip()
223 # First, check that the param type begins with one of the known
224 # 64-bit types.
225 if not ( \
226 param.startswith("int64_t") or param.startswith("uint64_t") or \
227 param.startswith("loff_t") or param.startswith("off64_t") or \
228 param.startswith("long long") or param.startswith("unsigned long long") or
229 param.startswith("signed long long") ):
230 return False
231
232 # Second, check that there is no pointer type here
233 if param.find("*") >= 0:
234 return False
235
236 # Ok
237 return True
238
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700239
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100240def count_arm_param_registers(params):
241 """This function is used to count the number of register used
Elliott Hughescd6780b2013-02-07 14:07:00 -0800242 to pass parameters when invoking an ARM system call.
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100243 This is because the ARM EABI mandates that 64-bit quantities
244 must be passed in an even+odd register pair. So, for example,
245 something like:
246
247 foo(int fd, off64_t pos)
248
249 would actually need 4 registers:
250 r0 -> int
251 r1 -> unused
252 r2-r3 -> pos
253 """
254 count = 0
255 for param in params:
256 if param_uses_64bits(param):
257 if (count & 1) != 0:
258 count += 1
259 count += 2
260 else:
261 count += 1
262 return count
263
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700264
David 'Digit' Turner95d751f2010-12-16 16:47:14 +0100265def count_generic_param_registers(params):
266 count = 0
267 for param in params:
268 if param_uses_64bits(param):
269 count += 2
270 else:
271 count += 1
272 return count
273
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700274
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400275def count_generic_param_registers64(params):
276 count = 0
277 for param in params:
278 count += 1
279 return count
280
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700281
Elliott Hughescda62092013-03-22 13:50:44 -0700282# This lets us support regular system calls like __NR_write and also weird
283# ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
284def make__NR_name(name):
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700285 if name.startswith("__ARM_NR_"):
Elliott Hughescda62092013-03-22 13:50:44 -0700286 return name
287 else:
288 return "__NR_%s" % (name)
289
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700290
Elliott Hughesfff6e272013-10-24 17:03:20 -0700291def add_footer(pointer_length, stub, syscall):
292 # Add any aliases for this syscall.
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700293 aliases = syscall["aliases"]
294 for alias in aliases:
Christopher Ferrisfa5faa02015-03-24 16:50:46 -0700295 stub += "\nALIAS_SYMBOL(%s, %s)\n" % (alias, syscall["func"])
Elliott Hughesfff6e272013-10-24 17:03:20 -0700296
Nick Kralevich00490ae2015-02-03 11:27:25 -0800297 # Use hidden visibility on LP64 for any functions beginning with underscores.
298 # Force hidden visibility for any functions which begin with 3 underscores
299 if (pointer_length == 64 and syscall["func"].startswith("__")) or syscall["func"].startswith("___"):
Elliott Hughesd465eb42014-02-19 18:59:19 -0800300 stub += '.hidden ' + syscall["func"] + '\n'
Elliott Hughesfff6e272013-10-24 17:03:20 -0700301
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700302 return stub
303
304
305def arm_eabi_genstub(syscall):
306 num_regs = count_arm_param_registers(syscall["params"])
307 if num_regs > 4:
308 return arm_eabi_call_long % syscall
309 return arm_eabi_call_default % syscall
310
311
Colin Crossd1973ca2014-01-21 19:50:58 -0800312def arm64_genstub(syscall):
313 return arm64_call % syscall
314
315
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700316def mips_genstub(syscall):
317 return mips_call % syscall
318
319
Chris Dearman50432122014-02-05 16:59:23 -0800320def mips64_genstub(syscall):
321 return mips64_call % syscall
322
323
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700324def x86_genstub(syscall):
325 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700326
327 numparams = count_generic_param_registers(syscall["params"])
Mingwei Shibe910522015-11-12 07:02:14 +0000328 stack_bias = numparams*4 + 8
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800329 offset = 0
330 mov_result = ""
Christopher Ferris15b91e92014-05-29 18:17:09 -0700331 first_push = True
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800332 for register in x86_registers[:numparams]:
333 result += " pushl %%%s\n" % register
Christopher Ferris15b91e92014-05-29 18:17:09 -0700334 if first_push:
335 result += " .cfi_def_cfa_offset 8\n"
336 result += " .cfi_rel_offset %s, 0\n" % register
337 first_push = False
338 else:
339 result += " .cfi_adjust_cfa_offset 4\n"
340 result += " .cfi_rel_offset %s, 0\n" % register
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800341 mov_result += " mov %d(%%esp), %%%s\n" % (stack_bias+offset, register)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800342 offset += 4
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700343
Mingwei Shibe910522015-11-12 07:02:14 +0000344 result += x86_call_prepare
Christopher Ferris15b91e92014-05-29 18:17:09 -0700345 result += mov_result
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700346 result += x86_call % syscall
347
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800348 for register in reversed(x86_registers[:numparams]):
349 result += " popl %%%s\n" % register
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700350
351 result += x86_return % syscall
352 return result
353
Serban Constantinescufeaa89a2013-10-07 16:49:09 +0100354
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700355def x86_genstub_socketcall(syscall):
356 # %ebx <--- Argument 1 - The call id of the needed vectored
357 # syscall (socket, bind, recv, etc)
358 # %ecx <--- Argument 2 - Pointer to the rest of the arguments
359 # from the original function called (socket())
360
361 result = syscall_stub_header % syscall
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700362
363 # save the regs we need
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800364 result += " pushl %ebx\n"
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800365 result += " .cfi_def_cfa_offset 8\n"
366 result += " .cfi_rel_offset ebx, 0\n"
Christopher Ferris15b91e92014-05-29 18:17:09 -0700367 result += " pushl %ecx\n"
368 result += " .cfi_adjust_cfa_offset 4\n"
369 result += " .cfi_rel_offset ecx, 0\n"
Mingwei Shibe910522015-11-12 07:02:14 +0000370 stack_bias = 16
371
372 result += x86_call_prepare
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700373
374 # set the call id (%ebx)
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800375 result += " mov $%d, %%ebx\n" % syscall["socketcall_id"]
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700376
377 # set the pointer to the rest of the args into %ecx
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800378 result += " mov %esp, %ecx\n"
379 result += " addl $%d, %%ecx\n" % (stack_bias)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700380
381 # now do the syscall code itself
382 result += x86_call % syscall
383
384 # now restore the saved regs
Christopher Ferrise4bc7562014-01-06 16:39:10 -0800385 result += " popl %ecx\n"
386 result += " popl %ebx\n"
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700387
388 # epilog
389 result += x86_return % syscall
390 return result
391
392
393def x86_64_genstub(syscall):
394 result = syscall_stub_header % syscall
395 num_regs = count_generic_param_registers64(syscall["params"])
396 if (num_regs > 3):
397 # rcx is used as 4th argument. Kernel wants it at r10.
398 result += " movq %rcx, %r10\n"
399
400 result += x86_64_call % syscall
401 return result
402
403
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700404class SysCallsTxtParser:
405 def __init__(self):
406 self.syscalls = []
407 self.lineno = 0
408
409 def E(self, msg):
410 print "%d: %s" % (self.lineno, msg)
411
412 def parse_line(self, line):
413 """ parse a syscall spec line.
414
415 line processing, format is
416 return type func_name[|alias_list][:syscall_name[:socketcall_id]] ( [paramlist] ) architecture_list
417 """
418 pos_lparen = line.find('(')
419 E = self.E
420 if pos_lparen < 0:
421 E("missing left parenthesis in '%s'" % line)
422 return
423
424 pos_rparen = line.rfind(')')
425 if pos_rparen < 0 or pos_rparen <= pos_lparen:
426 E("missing or misplaced right parenthesis in '%s'" % line)
427 return
428
429 return_type = line[:pos_lparen].strip().split()
430 if len(return_type) < 2:
431 E("missing return type in '%s'" % line)
432 return
433
434 syscall_func = return_type[-1]
435 return_type = string.join(return_type[:-1],' ')
436 socketcall_id = -1
437
438 pos_colon = syscall_func.find(':')
439 if pos_colon < 0:
440 syscall_name = syscall_func
441 else:
442 if pos_colon == 0 or pos_colon+1 >= len(syscall_func):
443 E("misplaced colon in '%s'" % line)
444 return
445
446 # now find if there is a socketcall_id for a dispatch-type syscall
447 # after the optional 2nd colon
448 pos_colon2 = syscall_func.find(':', pos_colon + 1)
449 if pos_colon2 < 0:
450 syscall_name = syscall_func[pos_colon+1:]
451 syscall_func = syscall_func[:pos_colon]
452 else:
453 if pos_colon2+1 >= len(syscall_func):
454 E("misplaced colon2 in '%s'" % line)
455 return
456 syscall_name = syscall_func[(pos_colon+1):pos_colon2]
457 socketcall_id = int(syscall_func[pos_colon2+1:])
458 syscall_func = syscall_func[:pos_colon]
459
460 alias_delim = syscall_func.find('|')
461 if alias_delim > 0:
462 alias_list = syscall_func[alias_delim+1:].strip()
463 syscall_func = syscall_func[:alias_delim]
464 alias_delim = syscall_name.find('|')
465 if alias_delim > 0:
466 syscall_name = syscall_name[:alias_delim]
467 syscall_aliases = string.split(alias_list, ',')
468 else:
469 syscall_aliases = []
470
471 if pos_rparen > pos_lparen+1:
472 syscall_params = line[pos_lparen+1:pos_rparen].split(',')
473 params = string.join(syscall_params,',')
474 else:
475 syscall_params = []
476 params = "void"
477
478 t = {
479 "name" : syscall_name,
480 "func" : syscall_func,
481 "aliases" : syscall_aliases,
482 "params" : syscall_params,
483 "decl" : "%-15s %s (%s);" % (return_type, syscall_func, params),
484 "socketcall_id" : socketcall_id
485 }
486
487 # Parse the architecture list.
488 arch_list = line[pos_rparen+1:].strip()
489 if arch_list == "all":
490 for arch in all_arches:
491 t[arch] = True
Elliott Hughes8251d442018-11-09 13:55:21 -0800492 elif arch_list == "lp32":
493 for arch in all_arches:
494 if "64" not in arch:
495 t[arch] = True
496 elif arch_list == "lp64":
497 for arch in all_arches:
498 if "64" in arch:
499 t[arch] = True
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700500 else:
501 for arch in string.split(arch_list, ','):
502 if arch in all_arches:
503 t[arch] = True
504 else:
505 E("invalid syscall architecture '%s' in '%s'" % (arch, line))
506 return
507
508 self.syscalls.append(t)
509
510 logging.debug(t)
511
Paul Lawrence7ea40902017-02-14 13:32:23 -0800512 def parse_open_file(self, fp):
513 for line in fp:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700514 self.lineno += 1
515 line = line.strip()
516 if not line: continue
517 if line[0] == '#': continue
518 self.parse_line(line)
519
Paul Lawrence7ea40902017-02-14 13:32:23 -0800520 def parse_file(self, file_path):
521 logging.debug("parse_file: %s" % file_path)
522 with open(file_path) as fp:
Alessio Balsini93d4f8b2017-04-11 18:27:29 +0200523 self.parse_open_file(fp)
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700524
525
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700526class State:
527 def __init__(self):
528 self.old_stubs = []
529 self.new_stubs = []
530 self.other_files = []
531 self.syscalls = []
532
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400533
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700534 def process_file(self, input):
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700535 parser = SysCallsTxtParser()
536 parser.parse_file(input)
537 self.syscalls = parser.syscalls
538 parser = None
539
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700540 for syscall in self.syscalls:
541 syscall["__NR_name"] = make__NR_name(syscall["name"])
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700542
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700543 if syscall.has_key("arm"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700544 syscall["asm-arm"] = add_footer(32, arm_eabi_genstub(syscall), syscall)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700545
Colin Crossd1973ca2014-01-21 19:50:58 -0800546 if syscall.has_key("arm64"):
547 syscall["asm-arm64"] = add_footer(64, arm64_genstub(syscall), syscall)
548
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700549 if syscall.has_key("x86"):
550 if syscall["socketcall_id"] >= 0:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700551 syscall["asm-x86"] = add_footer(32, x86_genstub_socketcall(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800552 else:
Elliott Hughesfff6e272013-10-24 17:03:20 -0700553 syscall["asm-x86"] = add_footer(32, x86_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700554 elif syscall["socketcall_id"] >= 0:
Elliott Hughesd6121652013-09-25 22:43:36 -0700555 E("socketcall_id for dispatch syscalls is only supported for x86 in '%s'" % t)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800556 return
Elliott Hughescd6780b2013-02-07 14:07:00 -0800557
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700558 if syscall.has_key("mips"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700559 syscall["asm-mips"] = add_footer(32, mips_genstub(syscall), syscall)
The Android Open Source Project4e468ed2008-12-17 18:03:48 -0800560
Chris Dearman50432122014-02-05 16:59:23 -0800561 if syscall.has_key("mips64"):
562 syscall["asm-mips64"] = add_footer(64, mips64_genstub(syscall), syscall)
563
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700564 if syscall.has_key("x86_64"):
Elliott Hughesfff6e272013-10-24 17:03:20 -0700565 syscall["asm-x86_64"] = add_footer(64, x86_64_genstub(syscall), syscall)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700566
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700567
568 # Scan Linux kernel asm/unistd.h files containing __NR_* constants
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700569 # and write out equivalent SYS_* constants for glibc source compatibility.
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700570 def gen_glibc_syscalls_h(self):
Elliott Hughes8aabbd72016-05-02 12:47:58 -0700571 glibc_syscalls_h_path = "include/bits/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 Hughesd2f725e2016-07-15 15:47:47 -0700575 glibc_fp.write("#ifndef _BIONIC_BITS_GLIBC_SYSCALLS_H_\n")
576 glibc_fp.write("#define _BIONIC_BITS_GLIBC_SYSCALLS_H_\n")
Elliott Hughes9724ce32013-03-21 19:43:54 -0700577
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700578 # Collect the set of all syscalls for all architectures.
579 syscalls = set()
dimitrydaebd052017-08-10 11:06:39 +0200580 pattern = re.compile(r'^\s*#\s*define\s*__NR_([a-z_]\S+)')
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700581 for unistd_h in ["kernel/uapi/asm-generic/unistd.h",
582 "kernel/uapi/asm-arm/asm/unistd.h",
Christopher Ferris48af7cb2017-02-21 12:35:09 -0800583 "kernel/uapi/asm-arm/asm/unistd-common.h",
584 "kernel/uapi/asm-arm/asm/unistd-eabi.h",
585 "kernel/uapi/asm-arm/asm/unistd-oabi.h",
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700586 "kernel/uapi/asm-mips/asm/unistd.h",
587 "kernel/uapi/asm-x86/asm/unistd_32.h",
588 "kernel/uapi/asm-x86/asm/unistd_64.h"]:
589 for line in open(os.path.join(bionic_libc_root, unistd_h)):
590 m = re.search(pattern, line)
591 if m:
592 nr_name = m.group(1)
593 if 'reserved' not in nr_name and 'unused' not in nr_name:
594 syscalls.add(nr_name)
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700595
Elliott Hughesd2f725e2016-07-15 15:47:47 -0700596 # Write out a single file listing them all. Note that the input
597 # files include #if trickery, so even for a single architecture
598 # we don't know exactly which ones are available.
599 # https://code.google.com/p/android/issues/detail?id=215853
600 for syscall in sorted(syscalls):
601 nr_name = make__NR_name(syscall)
602 glibc_fp.write("#if defined(%s)\n" % nr_name)
603 glibc_fp.write(" #define SYS_%s %s\n" % (syscall, nr_name))
604 glibc_fp.write("#endif\n")
605
606 glibc_fp.write("#endif /* _BIONIC_BITS_GLIBC_SYSCALLS_H_ */\n")
Elliott Hughes5c2772f2013-03-21 22:15:06 -0700607 glibc_fp.close()
608 self.other_files.append(glibc_syscalls_h_path)
609
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700610
Elliott Hughesd6121652013-09-25 22:43:36 -0700611 # Write each syscall stub.
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700612 def gen_syscall_stubs(self):
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700613 for syscall in self.syscalls:
Elliott Hughesd6121652013-09-25 22:43:36 -0700614 for arch in all_arches:
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700615 if syscall.has_key("asm-%s" % arch):
616 filename = "arch-%s/syscalls/%s.S" % (arch, syscall["func"])
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700617 logging.info(">>> generating " + filename)
Elliott Hughesd6121652013-09-25 22:43:36 -0700618 fp = create_file(filename)
Elliott Hughes0437f3f2013-10-07 23:53:13 -0700619 fp.write(syscall["asm-%s" % arch])
Elliott Hughesd6121652013-09-25 22:43:36 -0700620 fp.close()
621 self.new_stubs.append(filename)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700622
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700623
Elliott Hughesd6121652013-09-25 22:43:36 -0700624 def regenerate(self):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700625 logging.info("scanning for existing architecture-specific stub files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700626
Elliott Hughesd6121652013-09-25 22:43:36 -0700627 for arch in all_arches:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700628 arch_dir = "arch-" + arch
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700629 logging.info("scanning " + os.path.join(bionic_libc_root, arch_dir))
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700630 rel_path = os.path.join(arch_dir, "syscalls")
631 for file in os.listdir(os.path.join(bionic_libc_root, rel_path)):
632 if file.endswith(".S"):
633 self.old_stubs.append(os.path.join(rel_path, file))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700634
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700635 logging.info("found %d stub files" % len(self.old_stubs))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700636
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400637 if not os.path.exists(bionic_temp):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700638 logging.info("creating %s..." % bionic_temp)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400639 make_dir(bionic_temp)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700640
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700641 logging.info("re-generating stubs and support files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700642
Elliott Hughes1b91c6c2013-03-22 18:56:24 -0700643 self.gen_glibc_syscalls_h()
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700644 self.gen_syscall_stubs()
645
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700646 logging.info("comparing files...")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700647 adds = []
648 edits = []
649
650 for stub in self.new_stubs + self.other_files:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700651 tmp_file = os.path.join(bionic_temp, stub)
652 libc_file = os.path.join(bionic_libc_root, stub)
653 if not os.path.exists(libc_file):
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200654 # new file, git add it
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700655 logging.info("new file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700656 adds.append(libc_file)
657 shutil.copyfile(tmp_file, libc_file)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700658
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700659 elif not filecmp.cmp(tmp_file, libc_file):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700660 logging.info("changed file: " + stub)
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400661 edits.append(stub)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700662
663 deletes = []
664 for stub in self.old_stubs:
665 if not stub in self.new_stubs:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700666 logging.info("deleted file: " + stub)
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700667 deletes.append(os.path.join(bionic_libc_root, stub))
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700668
Pavel Chupinf12a18b2012-12-12 13:11:48 +0400669 if not DRY_RUN:
670 if adds:
671 commands.getoutput("git add " + " ".join(adds))
672 if deletes:
673 commands.getoutput("git rm " + " ".join(deletes))
674 if edits:
675 for file in edits:
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700676 shutil.copyfile(os.path.join(bionic_temp, file),
677 os.path.join(bionic_libc_root, file))
678 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 -0700679
Christopher Ferris01bd32e2014-08-05 12:19:27 -0700680 commands.getoutput("git add %s" % (os.path.join(bionic_libc_root, "SYSCALLS.TXT")))
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200681
682 if (not adds) and (not deletes) and (not edits):
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700683 logging.info("no changes detected!")
David 'Digit' Turnerfc269312010-10-11 22:11:06 +0200684 else:
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700685 logging.info("ready to go!!")
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700686
Elliott Hughesdc1fb702014-08-20 11:16:11 -0700687logging.basicConfig(level=logging.INFO)
The Android Open Source Projecta27d2ba2008-10-21 07:00:00 -0700688
Paul Lawrenceeabc3522016-11-11 11:33:42 -0800689if __name__ == "__main__":
690 state = State()
691 state.process_file(os.path.join(bionic_libc_root, "SYSCALLS.TXT"))
692 state.regenerate()