summaryrefslogtreecommitdiffstats
path: root/devtools/create-linux-syscall
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2023-12-03 19:23:35 +0100
committerMattias Andrée <maandree@kth.se>2023-12-03 19:23:35 +0100
commitc131f122778c62f920a99bbf854ced4a37ee8b03 (patch)
tree14c933f98f4d64dffb0a594bc40dd5121c6c5a8e /devtools/create-linux-syscall
downloadlibsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.gz
libsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.bz2
libsyscalls-c131f122778c62f920a99bbf854ced4a37ee8b03.tar.xz
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rwxr-xr-xdevtools/create-linux-syscall332
1 files changed, 332 insertions, 0 deletions
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)