From c131f122778c62f920a99bbf854ced4a37ee8b03 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 3 Dec 2023 19:23:35 +0100 Subject: First commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- devtools/create-linux-syscall | 332 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100755 devtools/create-linux-syscall (limited to 'devtools/create-linux-syscall') diff --git a/devtools/create-linux-syscall b/devtools/create-linux-syscall new file mode 100755 index 0000000..0b8e800 --- /dev/null +++ b/devtools/create-linux-syscall @@ -0,0 +1,332 @@ +#!/usr/bin/env python3 + +import sys + +lines = [] +try: + while True: + lines.append(input()) +except EOFError: + pass + +def remove_comments(text): + return ' '.join(t.split('/*')[0] for t in text.split('*/')) + +functions = frozenset(sys.argv[1:]) if len(sys.argv) > 1 else None + +lines = remove_comments(' '.join(lines)).replace('\t', ' ') +lines = [line.strip() for line in lines.split(';') if line] +lines = [' '.join(word for word in line.split(' ')[1:] if word) for line in lines + if line.replace('//', '').strip().startswith('asmlinkage ')] +lines = sorted(lines) + +def map_type(typ): + orig_typ = typ + if typ.startswith('signed ') and typ != 'signed char': + typ = typ[len('signed '):] + typemap = { + 'void' : 'LIBSYSCALLS_TYPE_VOID', + 'char' : 'LIBSYSCALLS_TYPE_CHAR', + 'signed char' : 'LIBSYSCALLS_TYPE_SCHAR', + 'unsigned char' : 'LIBSYSCALLS_TYPE_UCHAR', + 'short int' : 'LIBSYSCALLS_TYPE_SHORT', + 'unsigned short int' : 'LIBSYSCALLS_TYPE_USHORT', + 'int' : 'LIBSYSCALLS_TYPE_INT', + 'unsigned int' : 'LIBSYSCALLS_TYPE_UINT', + 'long int' : 'LIBSYSCALLS_TYPE_LONG', + 'unsigned long int' : 'LIBSYSCALLS_TYPE_ULONG', + 'long long int' : 'LIBSYSCALLS_TYPE_LLONG', + 'unsigned long long int' : 'LIBSYSCALLS_TYPE_ULLONG', + 'size_t' : 'LIBSYSCALLS_TYPE_SIZE', + 'ssize_t' : 'LIBSYSCALLS_TYPE_SSIZE', + 'ptrdiff_t' : 'LIBSYSCALLS_TYPE_PTRDIFF', + 'float' : 'LIBSYSCALLS_TYPE_FLOAT', + 'double' : 'LIBSYSCALLS_TYPE_DOUBLE', + 'long double' : 'LIBSYSCALLS_TYPE_LDOUBLE', + 'int8_t' : 'LIBSYSCALLS_TYPE_INT8', + 'uint8_t' : 'LIBSYSCALLS_TYPE_UINT8', + 'int16_t' : 'LIBSYSCALLS_TYPE_INT16', + 'uint16_t' : 'LIBSYSCALLS_TYPE_UINT16', + 'int32_t' : 'LIBSYSCALLS_TYPE_INT32', + 'uint32_t' : 'LIBSYSCALLS_TYPE_UINT32', + 'int64_t' : 'LIBSYSCALLS_TYPE_INT64', + 'uint64_t' : 'LIBSYSCALLS_TYPE_UINT64', + 'struct sockaddr' : 'LIBSYSCALLS_TYPE_STRUCT_SOCKADDR', + 'struct timex' : 'LIBSYSCALLS_TYPE_STRUCT_TIMEX', + 'struct old_timex32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEX32', + 'struct iovec' : 'LIBSYSCALLS_TYPE_STRUCT_IOVEC_ARRAY', + 'struct statfs' : 'LIBSYSCALLS_TYPE_STRUCT_STATFS', + 'struct statfs64' : 'LIBSYSCALLS_TYPE_STRUCT_STATFS64', + 'struct stat' : 'LIBSYSCALLS_TYPE_STRUCT_STAT', + 'struct stat64' : 'LIBSYSCALLS_TYPE_STRUCT_STAT64', + 'struct old_stat' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_STAT', + 'struct mount_attr' : 'LIBSYSCALLS_TYPE_STRUCT_MOUNT_ATTR', + 'struct ustat' : 'LIBSYSCALLS_TYPE_STRUCT_USTAT', + 'struct statx' : 'LIBSYSCALLS_TYPE_STRUCT_STATX', + 'struct linux_dirent' : 'LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT', + 'struct linux_dirent64' : 'LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT64', + 'struct old_linux_dirent' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_LINUX_DIRENT', + 'struct open_how' : 'LIBSYSCALLS_TYPE_STRUCT_OPEN_HOW', + 'struct iob' : 'LIBSYSCALLS_TYPE_STRUCT_IOB', + 'struct io_event' : 'LIBSYSCALLS_TYPE_STRUCT_IO_EVENT', + 'struct timespec' : 'LIBSYSCALLS_TYPE_STRUCT_TIMESPEC', + 'struct old_timespec32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMESPEC32', + 'struct aio_sigset' : 'LIBSYSCALLS_TYPE_STRUCT_AIO_SIGSET', + 'struct io_uring_params' : 'LIBSYSCALLS_TYPE_STRUCT_IO_URING_PARAMS', + 'struct epoll_event' : 'LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT', + 'struct pollfd' : 'LIBSYSCALLS_TYPE_STRUCT_POLLFD', + 'struct utimbuf' : 'LIBSYSCALLS_TYPE_STRUCT_UTIMBUF', + 'struct old_utimbuf32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_UTIMBUF32', + 'struct old_timeval' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL', + 'struct old_timeval32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_TIMEVAL32', + 'struct sel_arg_struct' : 'LIBSYSCALLS_TYPE_STRUCT_SEL_ARG_STRUCT', + 'struct tms' : 'LIBSYSCALLS_TYPE_STRUCT_TMS', + 'struct itimerspec' : 'LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC', + 'struct old_itimerspec32' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERSPEC32', + 'struct siginfo' : 'LIBSYSCALLS_TYPE_STRUCT_SIGINFO', + 'struct rusage' : 'LIBSYSCALLS_TYPE_STRUCT_RUSAGE', + 'struct robust_list_head' : 'LIBSYSCALLS_TYPE_STRUCT_ROBUST_LIST_HEAD', + 'struct futex_waitv' : 'LIBSYSCALLS_TYPE_STRUCT_FUTEX_WAITV', + 'struct old_itimerval' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_ITIMERVAL', + 'struct kexec_segment' : 'LIBSYSCALLS_TYPE_STRUCT_KEXEC_SEGMENT', + 'struct sigevent' : 'LIBSYSCALLS_TYPE_STRUCT_SIGEVENT', + 'struct sched_param' : 'LIBSYSCALLS_TYPE_STRUCT_SCHED_PARAM', + 'struct sigaltstack' : 'LIBSYSCALLS_TYPE_STRUCT_SIGALTSTACK', + 'struct sigaction' : 'LIBSYSCALLS_TYPE_STRUCT_SIGACTION', + 'struct old_sigaction' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_SIGACTION', + 'struct new_utsname' : 'LIBSYSCALLS_TYPE_STRUCT_NEW_UTSNAME', + 'struct old_utsname' : 'LIBSYSCALLS_TYPE_STRUCT_OLD_UTSNAME', + 'struct oldold_utsname' : 'LIBSYSCALLS_TYPE_STRUCT_OLDOLD_UTSNAME', + 'struct rlimit' : 'LIBSYSCALLS_TYPE_STRUCT_RLIMIT', + 'struct rlimit64' : 'LIBSYSCALLS_TYPE_STRUCT_RLIMIT64', + 'struct file_handle' : 'LIBSYSCALLS_TYPE_STRUCT_FILE_HANDLE', + 'struct timezone' : 'LIBSYSCALLS_TYPE_STRUCT_TIMEZONE', + 'struct sysinfo' : 'LIBSYSCALLS_TYPE_STRUCT_SYSINFO', + 'struct mq_attr' : 'LIBSYSCALLS_TYPE_STRUCT_MQ_ATTR', + 'struct msqid_ds' : 'LIBSYSCALLS_TYPE_STRUCT_MSQID_DS', + 'struct msgbuf' : 'LIBSYSCALLS_TYPE_STRUCT_MSGBUF', + 'struct semid_ds' : 'LIBSYSCALLS_TYPE_STRUCT_SEMID_DS', + 'struct sembuf' : 'LIBSYSCALLS_TYPE_STRUCT_SEMBUF', + 'struct shmid_ds' : 'LIBSYSCALLS_TYPE_STRUCT_SHMID_DS', + 'struct user_msghdr' : 'LIBSYSCALLS_TYPE_STRUCT_MSGHDR', + 'struct mmsghdr' : 'LIBSYSCALLS_TYPE_STRUCT_MMSGHDR', + 'struct clone_args' : 'LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS', + 'struct perf_event_attr' : 'LIBSYSCALLS_TYPE_STRUCT_PERF_EVENT_ATTR', + 'struct sched_attr' : 'LIBSYSCALLS_TYPE_STRUCT_SCHED_ATTR', + 'struct rseq' : 'LIBSYSCALLS_TYPE_STRUCT_RSEQ', + 'struct landlock_ruleset_attr' : 'LIBSYSCALLS_TYPE_STRUCT_LANDLOCK_RULESET_ATTR', + 'struct cachestat_range' : 'LIBSYSCALLS_TYPE_STRUCT_CACHESTAT_RANGE', + 'struct cachestat' : 'LIBSYSCALLS_TYPE_STRUCT_CACHESTAT', + 'struct mmap_arg_struct' : 'LIBSYSCALLS_TYPE_STRUCT_MMAP_ARG_STRUCT', + 'union bpf_attr' : 'LIBSYSCALLS_TYPE_UNION_BPF_ATTR', + 'u8' : 'uint8_t', + 'u16' : 'uint16_t', + 'u32' : 'uint32_t', + 'u64' : 'uint64_t', + 's8' : 'int8_t', + 's16' : 'int16_t', + 's32' : 'int32_t', + 's64' : 'int64_t', + 'gid_t' : 'gid32_t', + 'compat_gid_t' : 'gid32_t', + 'gid32_t' : 'u32', + 'old_gid_t' : 'unsigned short int', + 'uid_t' : 'uid32_t', + 'compat_uid_t' : 'uid32_t', + 'uid32_t' : 'u32', + 'old_uid_t' : 'unsigned short int', + 'gid16_t' : 'u16', + 'uid16_t' : 'u16', + 'pid_t' : 'int', + 'umode_t' : 'unsigned short int', + 'aio_context_t' : 'unsigned long int', + 'sigset_t' : 'unsigned long int', + 'loff_t' : 'long long int', + 'off_t' : 'long int', + 'qid_t' : 'uid32_t', + 'clockid_t' : 'int', + 'timer_t' : 'int', + 'mqd_t' : 'int', + 'key_t' : 'int', + 'rwf_t' : 'int', + 'time_t' : 'long int', + 'old_time_t' : 'long int', + 'old_time32_t' : 's32', + 'time64_t' : 's64', # also defined as `long long int` + 'key_serial_t' : 'int32_t', + 'old_sigset_t' : 'unsigned long int', + 'intptr_t' : 'long int', + 'uintptr_t' : 'unsigned long int', + 'compat_ulong_t' : 'u32', + 'fd_set' : 'LIBSYSCALLS_TYPE_FD_SET' + } + while not typ.startswith('LIBSYSCALLS'): + if typ == '???': + typ = typemap.get(typ, 'LIBSYSCALLS_TYPE_UNKNOWN /* TO'+'DO */') + else: + typ = typemap.get(typ, 'LIBSYSCALLS_TYPE_UNKNOWN /* TO'+'DO (%s) */' % typ) + if typ.startswith('LIBSYSCALLS_TYPE_UNKNOWN') and (orig_typ.split(' ')[0] in ('struct', 'union')): + typ = 'LIBSYSCALLS_TYPE_STRUCT /* TO'+'DO */' + return typ + +def get_type(param): + old_param = [p for p in param.replace('*', ' * ').split(' ') if p and p != '__user'] + param = [] + width = '' + sign = '' + constness = '' + require = None + have_type = False + for p in old_param: + if p == 'volatile': + pass + elif p == 'restrict': + pass + elif p == 'long': + width += 'long ' + require = 'int' + elif p == 'short': + width += 'short ' + require = 'int' + elif p == 'signed': + sign += 'signed ' + require = 'int' + elif p == 'unsigned': + sign += 'unsigned ' + require = 'int' + elif p == 'struct': + sign += 'struct ' + elif p == 'union': + sign += 'union ' + elif p == 'enum': + sign += 'enum ' + elif p == 'const': + constness = 'const' + else: + if require and p != require: + param.append(sign + width + require) + have_type = True + if p == '*': + param.append(constness + p) + constness = '' + elif not have_type: + p = sign + width + p + if p.startswith('struct __kernel_'): + p = 'struct ' + p[len('struct __kernel_'):] + elif p.startswith('struct __old_kernel_'): + p = 'struct old_' + p[len('struct __old_kernel_'):] + elif p.startswith('__kernel_'): + p = p[len('__kernel_'):] + elif p.startswith('__old_kernel_'): + p = 'old_' + p[len('__old_kernel_'):] + elif p.startswith('__'): + p = p[len('__'):] + param.append(p) + have_type = True + sign = '' + width = '' + require = None + if require: + param.append(sign + width.strip() + require) + if len(param) == 1: + return (map_type(param[0]), False, False) + if param == ['char', 'const*']: + return ('LIBSYSCALLS_TYPE_STRING', False, False) + if param == ['void', '*']: + return ('LIBSYSCALLS_TYPE_MEMORY_ADDRESS', False, False) + if len(param) == 2 and param[1] == '*': + return (map_type(param[0]), False, True) + if len(param) == 2 and param[1] == 'const*': + return (map_type(param[0]), True, False) + return ('LIBSYSCALLS_TYPE_UNKNOWN /* TO'+'DO */', False, False) + +def format_mask(args): + if len(args) == 0: + return '0' + if len(args) == 1: + return '_' + str(args[0] + 1) + return '(%s)' % ' | ' .join('_' + str(arg + 1) for arg in sorted(args)) + +queued = {} +for line in lines: + line = line.split(')')[0] + [name, params] = line.split('(') + name = name.split(' ') + return_type, name = ' '.join(name[:-1]), name[-1] + while name[0] == '*': + return_type += '*' + name = name[1:] + if functions is not None and name not in functions: + continue + if return_type == 'long': + return_type = '???' + params = [param.strip() for param in params.split(',')] + if params == ['void']: + params = [] + param_types = [] + in_pointer_mask = [] + out_pointer_mask = [] + for i, param in enumerate(params): + (typ, is_in, is_out) = get_type(param) + param_types.append(typ) + if is_in: + in_pointer_mask.append(i) + if is_out: + out_pointer_mask.append(i) + code = [] + (return_type, return_type_ptr_in, return_type_ptr_out) = get_type(return_type) + if return_type_ptr_in or return_type_ptr_out: + return_type += ' *' + return_type = return_type.replace('* *', '**') + if False: + code.append('\nstatic struct libsyscalls_syscall_abi libsyscalls_linux_syscall_%s = {' % name) + code.append('\t.category = LIBSYSCALLS_CAT_SUPPORT_PENDING /* TO'+'DO */,') + code.append('\t/* TO'+'DO .subcategory = , */') + code.append('\t.min_argument_count = %i,%s' % (len(params), (' /* TO'+'DO */' if len(params) > 1 else ''))) + code.append('\t.max_argument_count = %i,' % len(params)) + code.append('\t.in_pointer_mask = %s,' % format_mask(in_pointer_mask)) + code.append('\t.out_pointer_mask = %s,' % format_mask(out_pointer_mask)) + code.append('\t.symbolic_mask = 0, /* TO'+'DO */') + code.append('\t.symbolic_return = 0,') + code.append('\t.expect_zero = 1, /* TO'+'DO */') + code.append('\t.symbol_printer = ~0, /* TO'+'DO */') + code.append('\t.return_type = %s%s' % (return_type, (',' if len(params) else ''))) + if len(params): + code.append('\t.parameters_types = {') + for i, param_type in enumerate(param_types): + code.append('\t\t' + param_type + ('' if i + 1 == len(param_types) else ',')) + code.append('\t}') + code.append('};') + else: + paramstr = '' + for i, param_type in enumerate(param_types): + if i: + paramstr += ', ' + paramstr += {(False, False) : '_', + (True, False) : 'IN', + (False, True) : 'OUT', + (True, True) : 'BI'}[(i in in_pointer_mask), (i in out_pointer_mask)] + paramstr += ',' + param_type.replace('LIBSYSCALLS_TYPE_', '') + code.append('\nSYS(%s, /*CATEGORY*/, /*SUBCATEGORY*/, %i, ZERO(%s),' % + (name, len(params), return_type.replace('LIBSYSCALLS_TYPE_', ''))) + code.append('\tPARAMS(%s),' % paramstr) + code.append('\t.symbolic_return = 0,') + code.append('\t.symbol_printer = ~0') + code.append(');') + code = '\n'.join(code) + if functions is None: + print(code) + else: + queued[name] = code + +not_found = [] +for name in sys.argv[1:]: + if name in queued: + print(queued[name]) + else: + not_found.append(name) + +if not_found: + for name in not_found: + print('Could not find ' + name, file = sys.stderr) + sys.exit(1) -- cgit v1.2.3-70-g09d2