summaryrefslogtreecommitdiffstats
path: root/libc
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2013-10-07 23:53:13 -0700
committerElliott Hughes <enh@google.com>2013-10-07 23:53:13 -0700
commit0437f3ff296a4c66675c7386b0522e6062413e5a (patch)
tree5e7d056d8647f2ad0fcd79ab9291f920073f0a7c /libc
parentd2b6b5f2dbe56f19b6143f876e2677da1735bb5d (diff)
downloadbionic-0437f3ff296a4c66675c7386b0522e6062413e5a.zip
bionic-0437f3ff296a4c66675c7386b0522e6062413e5a.tar.gz
bionic-0437f3ff296a4c66675c7386b0522e6062413e5a.tar.bz2
Refactor the syscall generation script.
Primarily so that the new x86_64 alias functionality is now available for all architectures. Change-Id: I9fde59093a1d08de98923f121a6e3d05ec5801d2
Diffstat (limited to 'libc')
-rwxr-xr-xlibc/tools/gensyscalls.py308
1 files changed, 157 insertions, 151 deletions
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 386a8db..d31af9d 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -23,6 +23,7 @@ def make_dir(path):
make_dir(parent)
os.mkdir(path)
+
def create_file(relpath):
dir = os.path.dirname(bionic_temp + relpath)
make_dir(dir)
@@ -34,52 +35,15 @@ syscall_stub_header = """/* autogenerated by gensyscalls.py */
#include <linux/err.h>
#include <machine/asm.h>
-ENTRY(%(fname)s)
+ENTRY(%(func)s)
"""
+
function_alias = """
.globl _C_LABEL(%(alias)s)
- .equ _C_LABEL(%(alias)s), _C_LABEL(%(fname)s)
-"""
-
-#
-# x86 assembler templates for each syscall stub
-#
-
-x86_registers = [ "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp" ]
-
-x86_call = """ movl $%(idname)s, %%eax
- int $0x80
- cmpl $-MAX_ERRNO, %%eax
- jb 1f
- negl %%eax
- pushl %%eax
- call __set_errno
- addl $4, %%esp
- orl $-1, %%eax
-1:
+ .equ _C_LABEL(%(alias)s), _C_LABEL(%(func)s)
"""
-x86_return = """ ret
-END(%(fname)s)
-"""
-
-#
-# x86_64 assembler templates for each syscall stub
-#
-
-x86_64_call = """ movl $%(idname)s, %%eax
- syscall
- cmpq $-MAX_ERRNO, %%rax
- jb 1f
- negl %%eax
- movl %%eax, %%edi
- call __set_errno
- orq $-1, %%rax
-1:
- ret
-END(%(fname)s)
-"""
#
# ARM assembler templates for each syscall stub
@@ -87,14 +51,14 @@ END(%(fname)s)
arm_eabi_call_default = syscall_stub_header + """\
mov ip, r7
- ldr r7, =%(idname)s
+ ldr r7, =%(__NR_name)s
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
-END(%(fname)s)
+END(%(func)s)
"""
arm_eabi_call_long = syscall_stub_header + """\
@@ -102,31 +66,32 @@ arm_eabi_call_long = syscall_stub_header + """\
.save {r4, r5, r6, r7}
stmfd sp!, {r4, r5, r6, r7}
ldmfd ip, {r4, r5, r6}
- ldr r7, =%(idname)s
+ ldr r7, =%(__NR_name)s
swi #0
ldmfd sp!, {r4, r5, r6, r7}
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno
-END(%(fname)s)
+END(%(func)s)
"""
+
#
-# mips assembler templates for each syscall stub
+# MIPS assembler templates for each syscall stub
#
mips_call = """/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
.text
- .globl %(fname)s
+ .globl %(func)s
.align 4
- .ent %(fname)s
+ .ent %(func)s
-%(fname)s:
+%(func)s:
.set noreorder
.cpload $t9
- li $v0, %(idname)s
+ li $v0, %(__NR_name)s
syscall
bnez $a3, 1f
move $a0, $v0
@@ -137,9 +102,54 @@ mips_call = """/* autogenerated by gensyscalls.py */
j $t9
nop
.set reorder
- .end %(fname)s
+ .end %(func)s
+"""
+
+
+#
+# x86 assembler templates for each syscall stub
+#
+
+x86_registers = [ "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp" ]
+
+x86_call = """\
+ movl $%(__NR_name)s, %%eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %%eax
+ jb 1f
+ negl %%eax
+ pushl %%eax
+ call __set_errno
+ addl $4, %%esp
+ orl $-1, %%eax
+1:
+"""
+
+x86_return = """\
+ ret
+END(%(func)s)
+"""
+
+
+#
+# x86_64 assembler templates for each syscall stub
+#
+
+x86_64_call = """\
+ movl $%(__NR_name)s, %%eax
+ syscall
+ cmpq $-MAX_ERRNO, %%rax
+ jb 1f
+ negl %%eax
+ movl %%eax, %%edi
+ call __set_errno
+ orq $-1, %%rax
+1:
+ ret
+END(%(func)s)
"""
+
def param_uses_64bits(param):
"""Returns True iff a syscall parameter description corresponds
to a 64-bit type."""
@@ -160,6 +170,7 @@ def param_uses_64bits(param):
# Ok
return True
+
def count_arm_param_registers(params):
"""This function is used to count the number of register used
to pass parameters when invoking an ARM system call.
@@ -184,6 +195,7 @@ def count_arm_param_registers(params):
count += 1
return count
+
def count_generic_param_registers(params):
count = 0
for param in params:
@@ -193,12 +205,14 @@ def count_generic_param_registers(params):
count += 1
return count
+
def count_generic_param_registers64(params):
count = 0
for param in params:
count += 1
return count
+
# This lets us support regular system calls like __NR_write and also weird
# ones like __ARM_NR_cacheflush, where the NR doesn't come at the start.
def make__NR_name(name):
@@ -207,133 +221,125 @@ def make__NR_name(name):
else:
return "__NR_%s" % (name)
-class State:
- def __init__(self):
- self.old_stubs = []
- self.new_stubs = []
- self.other_files = []
- self.syscalls = []
- def x86_64_genstub(self, fname, numparams, idname, aliases):
- t = { "fname" : fname, "idname" : idname }
+def add_aliases(stub, syscall):
+ aliases = syscall["aliases"]
+ for alias in aliases:
+ stub += function_alias % { "func" : syscall["func"], "alias" : alias }
+ return stub
- result = syscall_stub_header % t
- # rcx is used as 4th argument. Kernel wants it at r10.
- if (numparams > 3):
- result += " movq %rcx, %r10\n"
- result += x86_64_call % t
- for alias in aliases:
- t = { "fname" : fname, "alias" : alias }
- result += function_alias % t
+def arm_eabi_genstub(syscall):
+ num_regs = count_arm_param_registers(syscall["params"])
+ if num_regs > 4:
+ return arm_eabi_call_long % syscall
+ return arm_eabi_call_default % syscall
- return result
- def x86_genstub(self, fname, numparams, idname):
- t = { "fname" : fname,
- "idname" : idname }
+def mips_genstub(syscall):
+ return mips_call % syscall
- result = syscall_stub_header % t
- stack_bias = 4
- for r in range(numparams):
- result += " pushl " + x86_registers[r] + "\n"
- stack_bias += 4
- for r in range(numparams):
- result += " mov %d(%%esp), %s" % (stack_bias+r*4, x86_registers[r]) + "\n"
+def x86_genstub(syscall):
+ result = syscall_stub_header % syscall
+ stack_bias = 4
- result += x86_call % t
+ numparams = count_generic_param_registers(syscall["params"])
+ for r in range(numparams):
+ result += " pushl " + x86_registers[r] + "\n"
+ stack_bias += 4
- for r in range(numparams):
- result += " popl " + x86_registers[numparams-r-1] + "\n"
+ for r in range(numparams):
+ result += " mov %d(%%esp), %s" % (stack_bias+r*4, x86_registers[r]) + "\n"
- result += x86_return % t
- return result
+ result += x86_call % syscall
- def x86_genstub_socketcall(self, fname, idname, socketcall_id):
- # %ebx <--- Argument 1 - The call id of the needed vectored
- # syscall (socket, bind, recv, etc)
- # %ecx <--- Argument 2 - Pointer to the rest of the arguments
- # from the original function called (socket())
- t = { "fname" : fname,
- "idname" : idname }
+ for r in range(numparams):
+ result += " popl " + x86_registers[numparams-r-1] + "\n"
- result = syscall_stub_header % t
- stack_bias = 4
+ result += x86_return % syscall
+ return result
- # save the regs we need
- result += " pushl %ebx" + "\n"
- stack_bias += 4
- result += " pushl %ecx" + "\n"
- stack_bias += 4
+def x86_genstub_socketcall(syscall):
+ # %ebx <--- Argument 1 - The call id of the needed vectored
+ # syscall (socket, bind, recv, etc)
+ # %ecx <--- Argument 2 - Pointer to the rest of the arguments
+ # from the original function called (socket())
+
+ result = syscall_stub_header % syscall
+ stack_bias = 4
- # set the call id (%ebx)
- result += " mov $%d, %%ebx" % (socketcall_id) + "\n"
+ # save the regs we need
+ result += " pushl %ebx" + "\n"
+ stack_bias += 4
+ result += " pushl %ecx" + "\n"
+ stack_bias += 4
- # set the pointer to the rest of the args into %ecx
- result += " mov %esp, %ecx" + "\n"
- result += " addl $%d, %%ecx" % (stack_bias) + "\n"
+ # set the call id (%ebx)
+ result += " mov $%d, %%ebx" % syscall["socketcall_id"] + "\n"
- # now do the syscall code itself
- result += x86_call % t
+ # set the pointer to the rest of the args into %ecx
+ result += " mov %esp, %ecx" + "\n"
+ result += " addl $%d, %%ecx" % (stack_bias) + "\n"
- # now restore the saved regs
- result += " popl %ecx" + "\n"
- result += " popl %ebx" + "\n"
+ # now do the syscall code itself
+ result += x86_call % syscall
- # epilog
- result += x86_return % t
- return result
+ # now restore the saved regs
+ result += " popl %ecx" + "\n"
+ result += " popl %ebx" + "\n"
+ # epilog
+ result += x86_return % syscall
+ return result
- def arm_eabi_genstub(self,fname, flags, idname):
- t = { "fname" : fname,
- "idname" : idname }
- if flags:
- numargs = int(flags)
- if numargs > 4:
- return arm_eabi_call_long % t
- return arm_eabi_call_default % t
+def x86_64_genstub(syscall):
+ result = syscall_stub_header % syscall
+ num_regs = count_generic_param_registers64(syscall["params"])
+ if (num_regs > 3):
+ # rcx is used as 4th argument. Kernel wants it at r10.
+ result += " movq %rcx, %r10\n"
- def mips_genstub(self,fname, idname):
- t = { "fname" : fname,
- "idname" : idname }
- return mips_call % t
+ result += x86_64_call % syscall
+ return result
- def process_file(self,input):
+
+class State:
+ def __init__(self):
+ self.old_stubs = []
+ self.new_stubs = []
+ self.other_files = []
+ self.syscalls = []
+
+
+ def process_file(self, input):
parser = SysCallsTxtParser()
parser.parse_file(input)
self.syscalls = parser.syscalls
parser = None
- for t in self.syscalls:
- syscall_func = t["func"]
- syscall_aliases = t["aliases"]
- syscall_params = t["params"]
- syscall_name = t["name"]
- __NR_name = make__NR_name(t["name"])
-
- if t.has_key("arm"):
- num_regs = count_arm_param_registers(syscall_params)
- t["asm-arm"] = self.arm_eabi_genstub(syscall_func, num_regs, __NR_name)
-
- if t.has_key("x86"):
- num_regs = count_generic_param_registers(syscall_params)
- if t["socketcall_id"] >= 0:
- t["asm-x86"] = self.x86_genstub_socketcall(syscall_func, __NR_name, t["socketcall_id"])
+ for syscall in self.syscalls:
+ syscall["__NR_name"] = make__NR_name(syscall["name"])
+
+ if syscall.has_key("arm"):
+ syscall["asm-arm"] = add_aliases(arm_eabi_genstub(syscall), syscall)
+
+ if syscall.has_key("x86"):
+ if syscall["socketcall_id"] >= 0:
+ syscall["asm-x86"] = add_aliases(x86_genstub_socketcall(syscall), syscall)
else:
- t["asm-x86"] = self.x86_genstub(syscall_func, num_regs, __NR_name)
- elif t["socketcall_id"] >= 0:
+ syscall["asm-x86"] = add_aliases(x86_genstub(syscall), syscall)
+ elif syscall["socketcall_id"] >= 0:
E("socketcall_id for dispatch syscalls is only supported for x86 in '%s'" % t)
return
- if t.has_key("mips"):
- t["asm-mips"] = self.mips_genstub(syscall_func, make__NR_name(syscall_name))
+ if syscall.has_key("mips"):
+ syscall["asm-mips"] = add_aliases(mips_genstub(syscall), syscall)
+
+ if syscall.has_key("x86_64"):
+ syscall["asm-x86_64"] = add_aliases(x86_64_genstub(syscall), syscall)
- if t.has_key("x86_64"):
- num_regs = count_generic_param_registers64(syscall_params)
- t["asm-x86_64"] = self.x86_64_genstub(syscall_func, num_regs, __NR_name, syscall_aliases)
# Scan a Linux kernel asm/unistd.h file containing __NR_* constants
# and write out equivalent SYS_* constants for glibc source compatibility.
@@ -379,22 +385,22 @@ class State:
fp = create_file(path)
fp.write("# Auto-generated by gensyscalls.py. Do not edit.\n")
fp.write("syscall_src :=\n")
- for sc in self.syscalls:
- if sc.has_key("asm-%s" % arch):
- fp.write("syscall_src += arch-%s/syscalls/%s.S\n" % (arch, sc["func"]))
+ for syscall in self.syscalls:
+ if syscall.has_key("asm-%s" % arch):
+ fp.write("syscall_src += arch-%s/syscalls/%s.S\n" % (arch, syscall["func"]))
fp.close()
self.other_files.append(path)
# Write each syscall stub.
def gen_syscall_stubs(self):
- for sc in self.syscalls:
+ for syscall in self.syscalls:
for arch in all_arches:
- if sc.has_key("asm-%s" % arch):
- filename = "arch-%s/syscalls/%s.S" % (arch, sc["func"])
+ if syscall.has_key("asm-%s" % arch):
+ filename = "arch-%s/syscalls/%s.S" % (arch, syscall["func"])
D2(">>> generating " + filename)
fp = create_file(filename)
- fp.write(sc["asm-%s" % arch])
+ fp.write(syscall["asm-%s" % arch])
fp.close()
self.new_stubs.append(filename)