# This tool is used to generate the assembler system call stubs, # the header files listing all available system calls, and the # makefiles used to build all the stubs.
def param_uses_64bits_on_ilp32(param): """Returns True iff a syscall parameter description corresponds
to a 64-bit type.""" # Canonicalize whitespace so there's no leading/trailing spaces, # and there's never more than one contiguous space.
param = ' '.join(param.split())
# On ilp32 pointers are always 32 bits. if param.find("*") >= 0: returnFalse
# Since this script can't resolve typedefs to their underlying types, # we have to list all the names used for 64-bit types. return ( \
param.startswith("int64_t") or param.startswith("uint64_t") or \
param.startswith("loff_t") or param.startswith("off64_t") or \
param.startswith("long long") or param.startswith("unsigned long long") or \
param.startswith("signed long long"))
def count_param_registers_arm32(params): """This function is used to count the number of register used
to pass parameters when invoking an ARM system call.
This is because the ARM EABI mandates that 64-bit quantities
must be passed in an even+odd register pair. So, for example,
something like:
foo(int fd, off64_t pos)
would actually need 4 registers:
r0 -> int
r1 -> unused
r2-r3 -> pos """
count = 0 for param in params: if param_uses_64bits_on_ilp32(param): if (count & 1) != 0:
count += 1
count += 2 else:
count += 1 return count
def count_param_registers_x86(params):
count = 0 for param in params: if param_uses_64bits_on_ilp32(param):
count += 2 else:
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): if name.startswith("__ARM_NR_"): return name else: return"__NR_%s" % (name)
def aliases(syscall):
result = '' for alias in syscall["aliases"]:
result += "ALIAS_SYMBOL(%s, %s)\n" % (alias, syscall["func"]) return result
def x86_genstub(syscall):
result = syscall_stub_header % syscall
numparams = count_param_registers_x86(syscall["params"])
stack_bias = numparams*4 + 8
offset = 0
mov_result = ""
first_push = True for register in x86_registers[:numparams]:
result += " pushl %%%s\n" % register if first_push:
result += " .cfi_def_cfa_offset 8\n"
result += " .cfi_rel_offset %s, 0\n" % register
first_push = False else:
result += " .cfi_adjust_cfa_offset 4\n"
result += " .cfi_rel_offset %s, 0\n" % register
mov_result += " mov %d(%%esp), %%%s\n" % (stack_bias+offset, register)
offset += 4
result += x86_call_prepare
result += mov_result
result += x86_call % syscall
for register in reversed(x86_registers[:numparams]):
result += " popl %%%s\n" % register
result += x86_return % syscall return result
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
# save the regs we need
result += " pushl %ebx\n"
result += " .cfi_def_cfa_offset 8\n"
result += " .cfi_rel_offset ebx, 0\n"
result += " pushl %ecx\n"
result += " .cfi_adjust_cfa_offset 4\n"
result += " .cfi_rel_offset ecx, 0\n"
stack_bias = 16
result += x86_call_prepare
# set the call id (%ebx)
result += " mov $%d, %%ebx\n" % syscall["socketcall_id"]
# set the pointer to the rest of the args into %ecx
result += " mov %esp, %ecx\n"
result += " addl $%d, %%ecx\n" % (stack_bias)
# now do the syscall code itself
result += x86_call % syscall
# now restore the saved regs
result += " popl %ecx\n"
result += " popl %ebx\n"
# epilog
result += x86_return % syscall return result
def x86_64_genstub(syscall):
result = syscall_stub_header % syscall
num_regs = len(syscall["params"]) if (num_regs > 3): # rcx is used as 4th argument. Kernel wants it at r10.
result += " movq %rcx, %r10\n"
with no line breaking/continuation allowed. """
pos_lparen = line.find('(')
E = self.E if pos_lparen < 0:
E("missing left parenthesis in '%s'" % line) return
pos_rparen = line.rfind(')') if pos_rparen < 0or pos_rparen <= pos_lparen:
E("missing or misplaced right parenthesis in '%s'" % line) return
pos_colon = syscall_func.find(':') if pos_colon < 0:
syscall_name = syscall_func else: if pos_colon == 0or pos_colon+1 >= len(syscall_func):
E("misplaced colon in '%s'" % line) return
# now find if there is a socketcall_id for a dispatch-type syscall # after the optional 2nd colon
pos_colon2 = syscall_func.find(':', pos_colon + 1) if pos_colon2 < 0:
syscall_name = syscall_func[pos_colon+1:]
syscall_func = syscall_func[:pos_colon] else: if pos_colon2+1 >= len(syscall_func):
E("misplaced colon2 in '%s'" % line) return
syscall_name = syscall_func[(pos_colon+1):pos_colon2]
socketcall_id = int(syscall_func[pos_colon2+1:])
syscall_func = syscall_func[:pos_colon]
# Parse the architecture list.
arch_list = line[pos_rparen+1:].strip() if arch_list == "all": for arch in SupportedArchitectures:
t[arch] = True else: for arch in arch_list.split(','): if arch == "lp32": for arch in SupportedArchitectures: if"64"notin arch:
t[arch] = True elif arch == "lp64": for arch in SupportedArchitectures: if"64"in arch:
t[arch] = True elif arch in SupportedArchitectures:
t[arch] = True else:
E("invalid syscall architecture '%s' in '%s'" % (arch, line)) return
if socketcall_id >= 0: for arch in SupportedArchitectures: if arch != 'x86'and arch in t:
E("socketcall is x86-only") return
self.syscalls.append(t)
def parse_open_file(self, fp): for line in fp:
self.lineno += 1
line = line.strip() ifnot line: continue if line[0] == '#': continue
self.parse_line(line) if self.errors:
sys.exit(1)
def parse_file(self, file_path): with open(file_path) as fp:
self.parse_open_file(fp)
print("/* Generated by gensyscalls.py. Do not edit. */\n")
print("#include <private/bionic_asm.h>\n") for syscall in parser.syscalls: if ("asm-%s" % arch) in syscall:
print(syscall["asm-%s" % arch])
if arch == 'arm64':
print('\nNOTE_GNU_PROPERTY()\n')
if __name__ == "__main__": if len(sys.argv) < 2:
print("Usage: gensyscalls.py ARCH SOURCE_FILE")
sys.exit(1)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.