diff options
author | Elliott Hughes <enh@google.com> | 2013-10-07 23:53:13 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2013-10-07 23:53:13 -0700 |
commit | 0437f3ff296a4c66675c7386b0522e6062413e5a (patch) | |
tree | 5e7d056d8647f2ad0fcd79ab9291f920073f0a7c /libc | |
parent | d2b6b5f2dbe56f19b6143f876e2677da1735bb5d (diff) | |
download | bionic-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-x | libc/tools/gensyscalls.py | 308 |
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) |