148 lines
5 KiB
Plaintext
148 lines
5 KiB
Plaintext
# run this as: jq -r -f SELF syscalls.json
|
|
# download syscalls.json from https://syscalls.mebeim.net/db/x86/64/x64/v6.6/table.json
|
|
|
|
def asargs: join(", ");
|
|
def csig: "\(.name)(\(.signature | asargs))";
|
|
def indent(w): w + (split("\n") | join("\n" + w));
|
|
def getargs: .signature | map(capture("(?<type>.*[^a-zA-Z_0-9]+)(?<name>[a-zA-Z_0-9]*)"));
|
|
def strim: sub("^[[:space:]]+"; "") | sub("[[:space:]]+$"; "");
|
|
def rawtype: gsub("const"; "") | strim;
|
|
|
|
# returns false if the given type may contain or be a pointer
|
|
def isflat: [.] | inside([
|
|
"char",
|
|
"unsigned char",
|
|
"int",
|
|
"struct cachestat_range",
|
|
"struct stat",
|
|
"struct pollfd",
|
|
"sigset_t",
|
|
"fd_set",
|
|
"struct __kernel_old_timeval",
|
|
"struct __kernel_old_itimerval",
|
|
"struct __kernel_timespec",
|
|
"struct sockaddr",
|
|
"void",
|
|
"loff_t",
|
|
"struct rusage",
|
|
"struct new_utsname",
|
|
"struct sembuf",
|
|
"struct msqid_ds", # unused pointers
|
|
"struct linux_dirent",
|
|
"struct timezone",
|
|
"struct rlimit",
|
|
"struct sysinfo",
|
|
"struct tms",
|
|
"gid_t",
|
|
"uid_t",
|
|
"siginfo_t",
|
|
"struct utimbuf",
|
|
"struct ustat",
|
|
"struct statfs",
|
|
"struct sched_param",
|
|
"struct __kernel_timex",
|
|
"__kernel_old_time_t",
|
|
"u32",
|
|
"unsigned long",
|
|
"aio_context_t",
|
|
"struct io_event",
|
|
"struct iocb",
|
|
"struct linux_dirent64",
|
|
"timer_t",
|
|
"struct __kernel_itimerspec",
|
|
"struct epoll_event",
|
|
"struct mq_attr",
|
|
"unsigned int",
|
|
"struct siginfo",
|
|
"size_t",
|
|
"struct perf_event_attr",
|
|
"struct rlimit64",
|
|
"struct file_handle",
|
|
"struct getcpu_cache",
|
|
"struct sched_attr",
|
|
"union bpf_attr",
|
|
"struct statx",
|
|
"struct __aio_sigset",
|
|
"struct rseq",
|
|
"struct io_uring_params",
|
|
"struct clone_args",
|
|
"struct open_how",
|
|
"struct mount_attr",
|
|
"struct landlock_ruleset_attr",
|
|
"struct futex_waitv",
|
|
""
|
|
]);
|
|
|
|
# returns true if the given type definitely contains a pointer
|
|
def isntflat: [.] | inside([
|
|
"struct sigaction",
|
|
"struct iovec",
|
|
"struct shmid_ds",
|
|
"struct user_msghdr",
|
|
"struct msgbuf",
|
|
"stack_t",
|
|
"struct sigevent",
|
|
"struct kexec_segment",
|
|
"struct robust_list_head",
|
|
"struct mmsghdr",
|
|
""
|
|
]);
|
|
|
|
def nimtype: rawtype |
|
|
if . == "" then null
|
|
|
|
# pointers
|
|
elif endswith("*") then rtrimstr("*") | strim |
|
|
if isflat then "pointer"
|
|
elif isntflat then "pointer #[ TODO \(.) is not a flat type ]#"
|
|
elif endswith("*") then "pointer #[ TODO \(.) is a nested pointer ]#"
|
|
else error("\(.) is of dubious flatness!") end
|
|
|
|
# scalar types
|
|
elif startswith("enum") then "cint"
|
|
elif [.] | inside(["int", "key_t", "pid_t", "clockid_t", "timer_t", "mqd_t", "__s32", "rwf_t"]) then "cint"
|
|
elif [.] | inside(["size_t"]) then "csize_t"
|
|
elif [.] | inside(["umode_t"]) then "cushort"
|
|
elif [.] | inside(["unsigned int", "uid_t", "gid_t", "qid_t", "u32", "__u32"]) then "cuint"
|
|
elif [.] | inside(["unsigned long", "off_t"]) then "clong"
|
|
elif [.] | inside(["aio_context_t", "__u64"]) then "culong"
|
|
elif [.] | inside(["loff_t"]) then "clonglong"
|
|
elif [.] | inside(["key_serial_t"]) then "int32"
|
|
elif [.] | inside(["cap_user_header_t", "cap_user_data_t"]) then "pointer"
|
|
else error("\(.) is unknown as a nimtype") end;
|
|
|
|
def nimstack: rawtype |
|
|
if . == "" then null
|
|
|
|
# pointers
|
|
elif endswith("*") then rtrimstr("*") | strim |
|
|
if isflat then "state.memory.raw_address(state.stack.pop.p)"
|
|
elif isntflat then "nil # TODO \(.) is not a flat type"
|
|
elif endswith("*") then "nil # TODO \(.) is a nested pointer"
|
|
else error("\(.) is of dubious flatness!") end
|
|
|
|
# scalar types
|
|
elif startswith("enum") then "state.stack.pop.i.cint"
|
|
elif [.] | inside(["int", "key_t", "pid_t", "clockid_t", "timer_t", "mqd_t", "__s32", "rwf_t"]) then "state.stack.pop.i.cint"
|
|
elif [.] | inside(["size_t"]) then "state.stack.pop.u.csize_t"
|
|
elif [.] | inside(["umode_t"]) then "state.stack.pop.i.cushort"
|
|
elif [.] | inside(["unsigned int", "uid_t", "gid_t", "qid_t", "u32", "__u32"]) then "state.stack.pop.u.cuint"
|
|
elif [.] | inside(["unsigned long", "off_t"]) then "state.stack.pop.i.clong"
|
|
elif [.] | inside(["aio_context_t", "__u64"]) then "state.stack.pop.u.culong"
|
|
elif [.] | inside(["loff_t"]) then "state.stack.pop.i.clonglong"
|
|
elif [.] | inside(["key_serial_t"]) then "state.stack.pop.i.int32"
|
|
elif [.] | inside(["cap_user_header_t", "cap_user_data_t"]) then "state.memory.raw_address(state.stack.pop.p)"
|
|
else error("\(.) is unknown as a nimtype") end;
|
|
|
|
|
|
def letstr: getargs | map("let syscall_\(.name | gsub("_"; "")): \(.type | nimtype) = \(.type | nimstack)") | join("\n");
|
|
|
|
def argcomma: if ( getargs | length ) == 0 then "" else ", " end;
|
|
def argstr: getargs | map("syscall_" + (.name | gsub("_"; ""))) | join(", ");
|
|
|
|
.syscalls[] |
|
|
" of \(.number): # \(csig)\n" +
|
|
"\(letstr | indent(" "))\n" +
|
|
" let retval: clong = syscall(\(.number)\(argcomma)\(argstr))\n" +
|
|
" state.stack.add ArcticType(i: retval.int64)\n"
|