from __future__ import annotations
import logging

from angr.sim_type import (
    SimTypeFunction,
    SimTypePointer,
    SimTypeLong,
    SimStruct,
    SimTypeInt,
    SimTypeChar,
    SimTypeBottom,
    SimTypeFd,
    SimTypeLongLong,
)
from angr.procedures import SIM_PROCEDURES as P
from angr.calling_conventions import SYSCALL_CC
from . import SimSyscallLibrary

_l = logging.getLogger(__name__)


lib = SimSyscallLibrary()
lib.set_library_names("linux")
lib.add_all_from_dict(P["linux_kernel"])
for arch, os_name_to_cc in SYSCALL_CC.items():
    linux_syscall_cc = os_name_to_cc.get("Linux")
    if linux_syscall_cc:
        lib.set_default_cc(arch, linux_syscall_cc)

lib.add("open", P["posix"]["open"])
lib.add("read", P["posix"]["read"])
lib.add("write", P["posix"]["write"])
lib.add("close", P["posix"]["close"])
lib.add("exit", P["libc"]["exit"])
lib.add("sigaction", P["posix"]["sigaction"])
lib.add("dup", P["posix"]["dup"])
lib.add("pread64", P["posix"]["pread64"])
lib.add("pwrite64", P["posix"]["pwrite64"])
lib.add("socket", P["posix"]["socket"])
lib.add("recvfrom", P["posix"]["recvfrom"])
lib.add("select", P["posix"]["select"])
lib.add("chroot", P["posix"]["chroot"])

lib.add_alias("exit", "exit_group")
lib.add_alias("getuid", "geteuid")
lib.add_alias("getgid", "getegid")


# syscall prototypes

# angr.utils.library.register_kernel_types()
# print(angr.utils.library.cprotos2py(angr.procedures.definitions.linux_kernel._amd64_c_decls, fd_spots=angr.procedures.definitions.linux_kernel._amd64_fd_spots, remove_sys_prefix=True))
_base_syscall_decls = {
    # long sys_time(time_t *tloc);
    "time": SimTypeFunction(
        [SimTypePointer(SimTypeLong(signed=True, label="time_t"), offset=0)],
        SimTypeLong(signed=True),
        arg_names=["tloc"],
    ),
    # long sys_stime(time_t *tptr);
    "stime": SimTypeFunction(
        [SimTypePointer(SimTypeLong(signed=True, label="time_t"), offset=0)],
        SimTypeLong(signed=True),
        arg_names=["tptr"],
    ),
    # long sys_gettimeofday(struct timeval *tv, struct timezone *tz);
    "gettimeofday": SimTypeFunction(
        [
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_usec": SimTypeLong(signed=True)},
                    name="timeval",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
            SimTypePointer(SimStruct({}, name="timezone", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["tv", "tz"],
    ),
    # long sys_settimeofday(struct timeval *tv, struct timezone *tz);
    "settimeofday": SimTypeFunction(
        [
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_usec": SimTypeLong(signed=True)},
                    name="timeval",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
            SimTypePointer(SimStruct({}, name="timezone", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["tv", "tz"],
    ),
    # long sys_adjtimex(struct timex *txc_p);
    "adjtimex": SimTypeFunction(
        [SimTypePointer(SimStruct({}, name="timex", pack=False, align=None), offset=0)],
        SimTypeLong(signed=True),
        arg_names=["txc_p"],
    ),
    # long sys_times(struct tms *tbuf);
    "times": SimTypeFunction(
        [SimTypePointer(SimStruct({}, name="tms", pack=False, align=None), offset=0)],
        SimTypeLong(signed=True),
        arg_names=["tbuf"],
    ),
    # long sys_gettid(void);
    "gettid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
    "nanosleep": SimTypeFunction(
        [
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
        ],
        SimTypeLong(signed=True),
        arg_names=["rqtp", "rmtp"],
    ),
    # long sys_alarm(unsigned int seconds);
    "alarm": SimTypeFunction([SimTypeInt(signed=False)], SimTypeLong(signed=True), arg_names=["seconds"]),
    # long sys_getpid(void);
    "getpid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_getppid(void);
    "getppid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_getuid(void);
    "getuid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_geteuid(void);
    "geteuid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_getgid(void);
    "getgid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_getegid(void);
    "getegid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
    "getresuid": SimTypeFunction(
        [
            SimTypePointer(SimTypeInt(signed=False, label="uid_t"), offset=0),
            SimTypePointer(SimTypeInt(signed=False, label="uid_t"), offset=0),
            SimTypePointer(SimTypeInt(signed=False, label="uid_t"), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["ruid", "euid", "suid"],
    ),
    # long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
    "getresgid": SimTypeFunction(
        [
            SimTypePointer(SimTypeInt(signed=False, label="gid_t"), offset=0),
            SimTypePointer(SimTypeInt(signed=False, label="gid_t"), offset=0),
            SimTypePointer(SimTypeInt(signed=False, label="gid_t"), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["rgid", "egid", "sgid"],
    ),
    # long sys_getpgid(pid_t pid);
    "getpgid": SimTypeFunction([SimTypeInt(signed=True, label="pid_t")], SimTypeLong(signed=True), arg_names=["pid"]),
    # long sys_getpgrp(void);
    "getpgrp": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_getsid(pid_t pid);
    "getsid": SimTypeFunction([SimTypeInt(signed=True, label="pid_t")], SimTypeLong(signed=True), arg_names=["pid"]),
    # long sys_getgroups(int gidsetsize, gid_t *grouplist);
    "getgroups": SimTypeFunction(
        [SimTypeInt(signed=True), SimTypePointer(SimTypeInt(signed=False, label="gid_t"), offset=0)],
        SimTypeLong(signed=True),
        arg_names=["gidsetsize", "grouplist"],
    ),
    # long sys_setregid(gid_t rgid, gid_t egid);
    "setregid": SimTypeFunction(
        [SimTypeInt(signed=False, label="gid_t"), SimTypeInt(signed=False, label="gid_t")],
        SimTypeLong(signed=True),
        arg_names=["rgid", "egid"],
    ),
    # long sys_setgid(gid_t gid);
    "setgid": SimTypeFunction([SimTypeInt(signed=False, label="gid_t")], SimTypeLong(signed=True), arg_names=["gid"]),
    # long sys_setreuid(uid_t ruid, uid_t euid);
    "setreuid": SimTypeFunction(
        [SimTypeInt(signed=False, label="uid_t"), SimTypeInt(signed=False, label="uid_t")],
        SimTypeLong(signed=True),
        arg_names=["ruid", "euid"],
    ),
    # long sys_setuid(uid_t uid);
    "setuid": SimTypeFunction([SimTypeInt(signed=False, label="uid_t")], SimTypeLong(signed=True), arg_names=["uid"]),
    # long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
    "setresuid": SimTypeFunction(
        [
            SimTypeInt(signed=False, label="uid_t"),
            SimTypeInt(signed=False, label="uid_t"),
            SimTypeInt(signed=False, label="uid_t"),
        ],
        SimTypeLong(signed=True),
        arg_names=["ruid", "euid", "suid"],
    ),
    # long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
    "setresgid": SimTypeFunction(
        [
            SimTypeInt(signed=False, label="gid_t"),
            SimTypeInt(signed=False, label="gid_t"),
            SimTypeInt(signed=False, label="gid_t"),
        ],
        SimTypeLong(signed=True),
        arg_names=["rgid", "egid", "sgid"],
    ),
    # long sys_setfsuid(uid_t uid);
    "setfsuid": SimTypeFunction([SimTypeInt(signed=False, label="uid_t")], SimTypeLong(signed=True), arg_names=["uid"]),
    # long sys_setfsgid(gid_t gid);
    "setfsgid": SimTypeFunction([SimTypeInt(signed=False, label="gid_t")], SimTypeLong(signed=True), arg_names=["gid"]),
    # long sys_setpgid(pid_t pid, pid_t pgid);
    "setpgid": SimTypeFunction(
        [SimTypeInt(signed=True, label="pid_t"), SimTypeInt(signed=True, label="pid_t")],
        SimTypeLong(signed=True),
        arg_names=["pid", "pgid"],
    ),
    # long sys_setsid(void);
    "setsid": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_setgroups(int gidsetsize, gid_t *grouplist);
    "setgroups": SimTypeFunction(
        [SimTypeInt(signed=True), SimTypePointer(SimTypeInt(signed=False, label="gid_t"), offset=0)],
        SimTypeLong(signed=True),
        arg_names=["gidsetsize", "grouplist"],
    ),
    # long sys_acct(const char *name);
    "acct": SimTypeFunction([SimTypePointer(SimTypeChar(), offset=0)], SimTypeLong(signed=True), arg_names=["name"]),
    # long sys_capget(cap_user_header_t header, cap_user_data_t dataptr);
    "capget": None,
    # long sys_capset(cap_user_header_t header, const cap_user_data_t data);
    "capset": None,
    # long sys_personality(unsigned int personality);
    "personality": SimTypeFunction([SimTypeInt(signed=False)], SimTypeLong(signed=True), arg_names=["personality"]),
    # long sys_sigpending(old_sigset_t *set);
    "sigpending": None,
    # long sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
    "sigprocmask": None,
    # long sys_sigaltstack(const struct sigaltstack *uss, struct sigaltstack *uoss);
    "sigaltstack": SimTypeFunction(
        [
            SimTypePointer(SimStruct({}, name="sigaltstack", pack=False, align=None), offset=0),
            SimTypePointer(SimStruct({}, name="sigaltstack", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["uss", "uoss"],
    ),
    # long sys_getitimer(int which, struct itimerval *value);
    "getitimer": SimTypeFunction(
        [SimTypeInt(signed=True), SimTypePointer(SimStruct({}, name="itimerval", pack=False, align=None), offset=0)],
        SimTypeLong(signed=True),
        arg_names=["which", "value"],
    ),
    # long sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
    "setitimer": SimTypeFunction(
        [
            SimTypeInt(signed=True),
            SimTypePointer(SimStruct({}, name="itimerval", pack=False, align=None), offset=0),
            SimTypePointer(SimStruct({}, name="itimerval", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["which", "value", "ovalue"],
    ),
    # long sys_timer_create(clockid_t which_clock, struct sigevent *timer_event_spec, timer_t * created_timer_id);
    "timer_create": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="clockid_t"),
            SimTypePointer(SimStruct({}, name="sigevent", pack=False, align=None), offset=0),
            SimTypePointer(SimTypePointer(SimTypeBottom(label="BOT"), label="timer_t", offset=0), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["which_clock", "timer_event_spec", "created_timer_id"],
    ),
    # long sys_timer_gettime(timer_t timer_id, struct itimerspec *setting);
    "timer_gettime": SimTypeFunction(
        [
            SimTypePointer(SimTypeBottom(label="BOT"), label="timer_t", offset=0),
            SimTypePointer(SimStruct({}, name="itimerspec", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["timer_id", "setting"],
    ),
    # long sys_timer_getoverrun(timer_t timer_id);
    "timer_getoverrun": SimTypeFunction(
        [SimTypePointer(SimTypeBottom(label="BOT"), label="timer_t", offset=0)],
        SimTypeLong(signed=True),
        arg_names=["timer_id"],
    ),
    # long sys_timer_settime(timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting);
    "timer_settime": SimTypeFunction(
        [
            SimTypePointer(SimTypeBottom(label="BOT"), label="timer_t", offset=0),
            SimTypeInt(signed=True),
            SimTypePointer(SimStruct({}, name="itimerspec", pack=False, align=None), offset=0),
            SimTypePointer(SimStruct({}, name="itimerspec", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["timer_id", "flags", "new_setting", "old_setting"],
    ),
    # long sys_timer_delete(timer_t timer_id);
    "timer_delete": SimTypeFunction(
        [SimTypePointer(SimTypeBottom(label="BOT"), label="timer_t", offset=0)],
        SimTypeLong(signed=True),
        arg_names=["timer_id"],
    ),
    # long sys_clock_settime(clockid_t which_clock, const struct timespec *tp);
    "clock_settime": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="clockid_t"),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
        ],
        SimTypeLong(signed=True),
        arg_names=["which_clock", "tp"],
    ),
    # long sys_clock_gettime(clockid_t which_clock, struct timespec *tp);
    "clock_gettime": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="clockid_t"),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
        ],
        SimTypeLong(signed=True),
        arg_names=["which_clock", "tp"],
    ),
    # long sys_clock_adjtime(clockid_t which_clock, struct timex *tx);
    "clock_adjtime": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="clockid_t"),
            SimTypePointer(SimStruct({}, name="timex", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["which_clock", "tx"],
    ),
    # long sys_clock_getres(clockid_t which_clock, struct timespec *tp);
    "clock_getres": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="clockid_t"),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
        ],
        SimTypeLong(signed=True),
        arg_names=["which_clock", "tp"],
    ),
    # long sys_clock_nanosleep(clockid_t which_clock, int flags, const struct timespec *rqtp, struct timespec *rmtp);
    "clock_nanosleep": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="clockid_t"),
            SimTypeInt(signed=True),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
        ],
        SimTypeLong(signed=True),
        arg_names=["which_clock", "flags", "rqtp", "rmtp"],
    ),
    # long sys_nice(int increment);
    "nice": SimTypeFunction([SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["increment"]),
    # long sys_sched_setscheduler(pid_t pid, int policy, struct sched_param *param);
    "sched_setscheduler": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypeInt(signed=True),
            SimTypePointer(SimStruct({}, name="sched_param", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "policy", "param"],
    ),
    # long sys_sched_setparam(pid_t pid, struct sched_param *param);
    "sched_setparam": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(SimStruct({}, name="sched_param", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "param"],
    ),
    # long sys_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags);
    "sched_setattr": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(SimStruct({}, name="sched_attr", pack=False, align=None), offset=0),
            SimTypeInt(signed=False),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "attr", "flags"],
    ),
    # long sys_sched_getscheduler(pid_t pid);
    "sched_getscheduler": SimTypeFunction(
        [SimTypeInt(signed=True, label="pid_t")], SimTypeLong(signed=True), arg_names=["pid"]
    ),
    # long sys_sched_getparam(pid_t pid, struct sched_param *param);
    "sched_getparam": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(SimStruct({}, name="sched_param", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "param"],
    ),
    # long sys_sched_getattr(pid_t pid, struct sched_attr *attr, unsigned int size, unsigned int flags);
    "sched_getattr": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(SimStruct({}, name="sched_attr", pack=False, align=None), offset=0),
            SimTypeInt(signed=False),
            SimTypeInt(signed=False),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "attr", "size", "flags"],
    ),
    # long sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr);
    "sched_setaffinity": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypeInt(signed=False),
            SimTypePointer(SimTypeLong(signed=False), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "len", "user_mask_ptr"],
    ),
    # long sys_sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr);
    "sched_getaffinity": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypeInt(signed=False),
            SimTypePointer(SimTypeLong(signed=False), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "len", "user_mask_ptr"],
    ),
    # long sys_sched_yield(void);
    "sched_yield": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_sched_get_priority_max(int policy);
    "sched_get_priority_max": SimTypeFunction(
        [SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["policy"]
    ),
    # long sys_sched_get_priority_min(int policy);
    "sched_get_priority_min": SimTypeFunction(
        [SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["policy"]
    ),
    # long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
    "sched_rr_get_interval": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "interval"],
    ),
    # long sys_setpriority(int which, int who, int niceval);
    "setpriority": SimTypeFunction(
        [SimTypeInt(signed=True), SimTypeInt(signed=True), SimTypeInt(signed=True)],
        SimTypeLong(signed=True),
        arg_names=["which", "who", "niceval"],
    ),
    # long sys_getpriority(int which, int who);
    "getpriority": SimTypeFunction(
        [SimTypeInt(signed=True), SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["which", "who"]
    ),
    # long sys_shutdown(int, int);
    "shutdown": SimTypeFunction(
        [SimTypeFd(), SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["None", "None"]
    ),
    # long sys_reboot(int magic1, int magic2, unsigned int cmd, void *arg);
    "reboot": SimTypeFunction(
        [
            SimTypeInt(signed=True),
            SimTypeInt(signed=True),
            SimTypeInt(signed=False),
            SimTypePointer(SimTypeBottom(label="void"), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["magic1", "magic2", "cmd", "arg"],
    ),
    # long sys_restart_syscall(void);
    "restart_syscall": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_kexec_load(unsigned long entry, unsigned long nr_segments, struct kexec_segment *segments, unsigned long flags);
    "kexec_load": SimTypeFunction(
        [
            SimTypeLong(signed=False),
            SimTypeLong(signed=False),
            SimTypePointer(SimStruct({}, name="kexec_segment", pack=False, align=None), offset=0),
            SimTypeLong(signed=False),
        ],
        SimTypeLong(signed=True),
        arg_names=["entry", "nr_segments", "segments", "flags"],
    ),
    # long sys_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline_ptr, unsigned long flags);
    "kexec_file_load": SimTypeFunction(
        [
            SimTypeInt(signed=True),
            SimTypeInt(signed=True),
            SimTypeLong(signed=False),
            SimTypePointer(SimTypeChar(), offset=0),
            SimTypeLong(signed=False),
        ],
        SimTypeLong(signed=True),
        arg_names=["kernel_fd", "initrd_fd", "cmdline_len", "cmdline_ptr", "flags"],
    ),
    # long sys_exit(int error_code);
    "exit": SimTypeFunction([SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["error_code"]),
    # long sys_exit_group(int error_code);
    "exit_group": SimTypeFunction([SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["error_code"]),
    # long sys_wait4(pid_t pid, int *stat_addr, int options, struct rusage *ru);
    "wait4": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(SimTypeInt(signed=True), offset=0),
            SimTypeInt(signed=True),
            SimTypePointer(SimStruct({}, name="rusage", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "stat_addr", "options", "ru"],
    ),
    # long sys_waitid(int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru);
    "waitid": SimTypeFunction(
        [
            SimTypeInt(signed=True),
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(SimStruct({}, name="siginfo", pack=False, align=None), offset=0),
            SimTypeInt(signed=True),
            SimTypePointer(SimStruct({}, name="rusage", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["which", "pid", "infop", "options", "ru"],
    ),
    # long sys_waitpid(pid_t pid, int *stat_addr, int options);
    "waitpid": SimTypeFunction(
        [
            SimTypeInt(signed=True, label="pid_t"),
            SimTypePointer(SimTypeInt(signed=True), offset=0),
            SimTypeInt(signed=True),
        ],
        SimTypeLong(signed=True),
        arg_names=["pid", "stat_addr", "options"],
    ),
    # long sys_set_tid_address(int *tidptr);
    "set_tid_address": SimTypeFunction(
        [SimTypePointer(SimTypeInt(signed=True), offset=0)], SimTypeLong(signed=True), arg_names=["tidptr"]
    ),
    # long sys_futex(u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3);
    "futex": SimTypeFunction(
        [
            SimTypePointer(SimTypeInt(signed=False, label="u32"), offset=0),
            SimTypeInt(signed=True),
            SimTypeInt(signed=False, label="u32"),
            SimTypePointer(
                SimStruct(
                    {"tv_sec": SimTypeLong(signed=True, label="time_t"), "tv_nsec": SimTypeLong(signed=True)},
                    name="timespec",
                    pack=False,
                    align=None,
                ),
                offset=0,
            ),
            SimTypePointer(SimTypeInt(signed=False, label="u32"), offset=0),
            SimTypeInt(signed=False, label="u32"),
        ],
        SimTypeLong(signed=True),
        arg_names=["uaddr", "op", "val", "utime", "uaddr2", "val3"],
    ),
    # long sys_init_module(void *umod, unsigned long len, const char *uargs);
    "init_module": SimTypeFunction(
        [
            SimTypePointer(SimTypeBottom(label="void"), offset=0),
            SimTypeLong(signed=False),
            SimTypePointer(SimTypeChar(), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["umod", "len", "uargs"],
    ),
    # long sys_delete_module(const char *name_user, unsigned int flags);
    "delete_module": SimTypeFunction(
        [SimTypePointer(SimTypeChar(), offset=0), SimTypeInt(signed=False)],
        SimTypeLong(signed=True),
        arg_names=["name_user", "flags"],
    ),
    # long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize);
    "rt_sigsuspend": SimTypeFunction(
        [
            SimTypePointer(SimTypeInt(signed=True, label="sigset_t"), offset=0),
            SimTypeLong(signed=False, label="size_t"),
        ],
        SimTypeLong(signed=True),
        arg_names=["unewset", "sigsetsize"],
    ),
    # long sys_sigaction(int, const struct old_sigaction *, struct old_sigaction *);
    "sigaction": SimTypeFunction(
        [
            SimTypeInt(signed=True),
            SimTypePointer(SimStruct({}, name="old_sigaction", pack=False, align=None), offset=0),
            SimTypePointer(SimStruct({}, name="old_sigaction", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["None", "None", "None"],
    ),
    # long sys_rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t);
    "rt_sigaction": SimTypeFunction(
        [
            SimTypeInt(signed=True),
            SimTypePointer(SimStruct({}, name="sigaction", pack=False, align=None), offset=0),
            SimTypePointer(SimStruct({}, name="sigaction", pack=False, align=None), offset=0),
            SimTypeLong(signed=False, label="size_t"),
        ],
        SimTypeLong(signed=True),
        arg_names=["None", "None", "None", "None"],
    ),
    # long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
    "rt_sigprocmask": SimTypeFunction(
        [
            SimTypeInt(signed=True),
            SimTypePointer(SimTypeInt(signed=True, label="sigset_t"), offset=0),
            SimTypePointer(SimTypeInt(signed=True, label="sigset_t"), offset=0),
            SimTypeLong(signed=False, label="size_t"),
        ],
        SimTypeLong(signed=True),
        arg_names=["how", "set", "oset", "sigsetsize"],
    ),
    # long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
    "rt_sigpending": SimTypeFunction(
        [
            SimTypePointer(SimTypeInt(signed=True, label="sigset_t"), offset=0),
            SimTypeLong(signed=False, label="size_t"),
        ],
        SimTypeLong(signed=True),
        arg_names=["set", "sigsetsize"],
    ),
    # long sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize);
    "rt_sigtimedwait": None,
    # long sys_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo);
    "rt_tgsigqueueinfo": None,
    # long sys_kill(pid_t pid, int sig);
    "kill": SimTypeFunction(
        [SimTypeInt(signed=True, label="pid_t"), SimTypeInt(signed=True)],
        SimTypeLong(signed=True),
        arg_names=["pid", "sig"],
    ),
    # long sys_tgkill(pid_t tgid, pid_t pid, int sig);
    "tgkill": SimTypeFunction(
        [SimTypeInt(signed=True, label="pid_t"), SimTypeInt(signed=True, label="pid_t"), SimTypeInt(signed=True)],
        SimTypeLong(signed=True),
        arg_names=["tgid", "pid", "sig"],
    ),
    # long sys_tkill(pid_t pid, int sig);
    "tkill": SimTypeFunction(
        [SimTypeInt(signed=True, label="pid_t"), SimTypeInt(signed=True)],
        SimTypeLong(signed=True),
        arg_names=["pid", "sig"],
    ),
    # long sys_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *uinfo);
    "rt_sigqueueinfo": None,
    # long sys_sgetmask(void);
    "sgetmask": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_ssetmask(int newmask);
    "ssetmask": SimTypeFunction([SimTypeInt(signed=True)], SimTypeLong(signed=True), arg_names=["newmask"]),
    # long sys_signal(int sig, __sighandler_t handler);
    "signal": None,
    # long sys_pause(void);
    "pause": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_sync(void);
    "sync": SimTypeFunction([], SimTypeLong(signed=True)),
    # long sys_fsync(unsigned int fd);
    "fsync": SimTypeFunction([SimTypeFd()], SimTypeLong(signed=True), arg_names=["fd"]),
    # long sys_fdatasync(unsigned int fd);
    "fdatasync": SimTypeFunction([SimTypeFd()], SimTypeLong(signed=True), arg_names=["fd"]),
    # long sys_bdflush(int func, long data);
    "bdflush": SimTypeFunction(
        [SimTypeInt(signed=True), SimTypeLong(signed=True)], SimTypeLong(signed=True), arg_names=["func", "data"]
    ),
    # long sys_mount(char *dev_name, char *dir_name, char *type, unsigned long flags, void *data);
    "mount": SimTypeFunction(
        [
            SimTypePointer(SimTypeChar(), offset=0),
            SimTypePointer(SimTypeChar(), offset=0),
            SimTypePointer(SimTypeChar(), offset=0),
            SimTypeLong(signed=False),
            SimTypePointer(SimTypeBottom(label="void"), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["dev_name", "dir_name", "type", "flags", "data"],
    ),
    # long sys_umount(char *name, int flags);
    "umount": SimTypeFunction(
        [SimTypePointer(SimTypeChar(), offset=0), SimTypeInt(signed=True)],
        SimTypeLong(signed=True),
        arg_names=["name", "flags"],
    ),
    # long sys_oldumount(char *name);
    "oldumount": SimTypeFunction(
        [SimTypePointer(SimTypeChar(), offset=0)], SimTypeLong(signed=True), arg_names=["name"]
    ),
    # long sys_truncate(const char *path, long length);
    "truncate": SimTypeFunction(
        [SimTypePointer(SimTypeChar(), offset=0), SimTypeLong(signed=True)],
        SimTypeLong(signed=True),
        arg_names=["path", "length"],
    ),
    # long sys_ftruncate(unsigned int fd, unsigned long length);
    "ftruncate": SimTypeFunction(
        [SimTypeFd(), SimTypeLong(signed=False)], SimTypeLong(signed=True), arg_names=["fd", "length"]
    ),
    # long sys_stat(const char *filename, struct __old_kernel_stat *statbuf);
    "stat": SimTypeFunction(
        [
            SimTypePointer(SimTypeChar(), offset=0),
            SimTypePointer(SimStruct({}, name="__old_kernel_stat", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["filename", "statbuf"],
    ),
    # long sys_statfs(const char * path, struct statfs *buf);
    "statfs": SimTypeFunction(
        [
            SimTypePointer(SimTypeChar(), offset=0),
            SimTypePointer(SimStruct({}, name="statfs", pack=False, align=None), offset=0),
        ],
        SimTypeLong(signed=True),
        arg_names=["path", "buf"],
    ),
    # long sys_statfs64(const char *path, size_t sz, struct statfs64 *buf);
    "statfs64": SimTypeFunction(
        [
