#!/usr/bin/env python3
# See LICENSE file for copyright and license details.
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)