diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map index b79c512834e0..eeb75dc28a2c 100644 --- a/lib/libsys/syscalls.map +++ b/lib/libsys/syscalls.map @@ -1,806 +1,804 @@ /* * FreeBSD system call symbols. * DO NOT EDIT-- this file is automatically @generated. */ FBSDprivate_1.0 { _syscall; __sys_syscall; __sys_exit; _fork; __sys_fork; _read; __sys_read; _write; __sys_write; _open; __sys_open; _close; __sys_close; _wait4; __sys_wait4; _link; __sys_link; _unlink; __sys_unlink; _chdir; __sys_chdir; _fchdir; __sys_fchdir; _chmod; __sys_chmod; _chown; __sys_chown; _break; __sys_break; _getpid; __sys_getpid; _mount; __sys_mount; _unmount; __sys_unmount; _setuid; __sys_setuid; _getuid; __sys_getuid; _geteuid; __sys_geteuid; _ptrace; __sys_ptrace; _recvmsg; __sys_recvmsg; _sendmsg; __sys_sendmsg; _recvfrom; __sys_recvfrom; _accept; __sys_accept; _getpeername; __sys_getpeername; _getsockname; __sys_getsockname; _access; __sys_access; _chflags; __sys_chflags; _fchflags; __sys_fchflags; _sync; __sys_sync; _kill; __sys_kill; _getppid; __sys_getppid; _dup; __sys_dup; _getegid; __sys_getegid; _profil; __sys_profil; _ktrace; __sys_ktrace; _getgid; __sys_getgid; _getlogin; __sys_getlogin; _setlogin; __sys_setlogin; _acct; __sys_acct; _sigaltstack; __sys_sigaltstack; _ioctl; __sys_ioctl; _reboot; __sys_reboot; _revoke; __sys_revoke; _symlink; __sys_symlink; _readlink; __sys_readlink; _execve; __sys_execve; _umask; __sys_umask; _chroot; __sys_chroot; _msync; __sys_msync; __sys_vfork; _munmap; __sys_munmap; _mprotect; __sys_mprotect; _madvise; __sys_madvise; _mincore; __sys_mincore; _getgroups; __sys_getgroups; _setgroups; __sys_setgroups; _getpgrp; __sys_getpgrp; _setpgid; __sys_setpgid; _setitimer; __sys_setitimer; _swapon; __sys_swapon; _getitimer; __sys_getitimer; _getdtablesize; __sys_getdtablesize; _dup2; __sys_dup2; _fcntl; __sys_fcntl; _select; __sys_select; _fsync; __sys_fsync; _setpriority; __sys_setpriority; _socket; __sys_socket; _connect; __sys_connect; _getpriority; __sys_getpriority; _bind; __sys_bind; _setsockopt; __sys_setsockopt; _listen; __sys_listen; _gettimeofday; __sys_gettimeofday; _getrusage; __sys_getrusage; _getsockopt; __sys_getsockopt; _readv; __sys_readv; _writev; __sys_writev; _settimeofday; __sys_settimeofday; _fchown; __sys_fchown; _fchmod; __sys_fchmod; _setreuid; __sys_setreuid; _setregid; __sys_setregid; _rename; __sys_rename; _flock; __sys_flock; _mkfifo; __sys_mkfifo; _sendto; __sys_sendto; _shutdown; __sys_shutdown; _socketpair; __sys_socketpair; _mkdir; __sys_mkdir; _rmdir; __sys_rmdir; _utimes; __sys_utimes; _adjtime; __sys_adjtime; _setsid; __sys_setsid; _quotactl; __sys_quotactl; _nlm_syscall; __sys_nlm_syscall; _nfssvc; __sys_nfssvc; _lgetfh; __sys_lgetfh; _getfh; __sys_getfh; _sysarch; __sys_sysarch; _rtprio; __sys_rtprio; _semsys; __sys_semsys; _msgsys; __sys_msgsys; _shmsys; __sys_shmsys; _setfib; __sys_setfib; _ntp_adjtime; __sys_ntp_adjtime; _setgid; __sys_setgid; _setegid; __sys_setegid; _seteuid; __sys_seteuid; _pathconf; __sys_pathconf; _fpathconf; __sys_fpathconf; _getrlimit; __sys_getrlimit; _setrlimit; __sys_setrlimit; ___syscall; __sys___syscall; ___sysctl; __sys___sysctl; _mlock; __sys_mlock; _munlock; __sys_munlock; _undelete; __sys_undelete; _futimes; __sys_futimes; _getpgid; __sys_getpgid; _poll; __sys_poll; _semget; __sys_semget; _semop; __sys_semop; _msgget; __sys_msgget; _msgsnd; __sys_msgsnd; _msgrcv; __sys_msgrcv; _shmat; __sys_shmat; _shmdt; __sys_shmdt; _shmget; __sys_shmget; _clock_gettime; __sys_clock_gettime; _clock_settime; __sys_clock_settime; _clock_getres; __sys_clock_getres; _ktimer_create; __sys_ktimer_create; _ktimer_delete; __sys_ktimer_delete; _ktimer_settime; __sys_ktimer_settime; _ktimer_gettime; __sys_ktimer_gettime; _ktimer_getoverrun; __sys_ktimer_getoverrun; _nanosleep; __sys_nanosleep; _ffclock_getcounter; __sys_ffclock_getcounter; _ffclock_setestimate; __sys_ffclock_setestimate; _ffclock_getestimate; __sys_ffclock_getestimate; _clock_nanosleep; __sys_clock_nanosleep; _clock_getcpuclockid2; __sys_clock_getcpuclockid2; _ntp_gettime; __sys_ntp_gettime; _minherit; __sys_minherit; _rfork; __sys_rfork; _issetugid; __sys_issetugid; _lchown; __sys_lchown; _aio_read; __sys_aio_read; _aio_write; __sys_aio_write; _lio_listio; __sys_lio_listio; _lchmod; __sys_lchmod; _lutimes; __sys_lutimes; _preadv; __sys_preadv; _pwritev; __sys_pwritev; _fhopen; __sys_fhopen; _modnext; __sys_modnext; _modstat; __sys_modstat; _modfnext; __sys_modfnext; _modfind; __sys_modfind; _kldload; __sys_kldload; _kldunload; __sys_kldunload; _kldfind; __sys_kldfind; _kldnext; __sys_kldnext; _kldstat; __sys_kldstat; _kldfirstmod; __sys_kldfirstmod; _getsid; __sys_getsid; _setresuid; __sys_setresuid; _setresgid; __sys_setresgid; _aio_return; __sys_aio_return; _aio_suspend; __sys_aio_suspend; _aio_cancel; __sys_aio_cancel; _aio_error; __sys_aio_error; - _yield; - __sys_yield; _mlockall; __sys_mlockall; _munlockall; __sys_munlockall; ___getcwd; __sys___getcwd; _sched_setparam; __sys_sched_setparam; _sched_getparam; __sys_sched_getparam; _sched_setscheduler; __sys_sched_setscheduler; _sched_getscheduler; __sys_sched_getscheduler; _sched_yield; __sys_sched_yield; _sched_get_priority_max; __sys_sched_get_priority_max; _sched_get_priority_min; __sys_sched_get_priority_min; _sched_rr_get_interval; __sys_sched_rr_get_interval; _utrace; __sys_utrace; _kldsym; __sys_kldsym; _jail; __sys_jail; _nnpfs_syscall; __sys_nnpfs_syscall; _sigprocmask; __sys_sigprocmask; _sigsuspend; __sys_sigsuspend; _sigpending; __sys_sigpending; _sigtimedwait; __sys_sigtimedwait; _sigwaitinfo; __sys_sigwaitinfo; ___acl_get_file; __sys___acl_get_file; ___acl_set_file; __sys___acl_set_file; ___acl_get_fd; __sys___acl_get_fd; ___acl_set_fd; __sys___acl_set_fd; ___acl_delete_file; __sys___acl_delete_file; ___acl_delete_fd; __sys___acl_delete_fd; ___acl_aclcheck_file; __sys___acl_aclcheck_file; ___acl_aclcheck_fd; __sys___acl_aclcheck_fd; _extattrctl; __sys_extattrctl; _extattr_set_file; __sys_extattr_set_file; _extattr_get_file; __sys_extattr_get_file; _extattr_delete_file; __sys_extattr_delete_file; _aio_waitcomplete; __sys_aio_waitcomplete; _getresuid; __sys_getresuid; _getresgid; __sys_getresgid; _kqueue; __sys_kqueue; _extattr_set_fd; __sys_extattr_set_fd; _extattr_get_fd; __sys_extattr_get_fd; _extattr_delete_fd; __sys_extattr_delete_fd; ___setugid; __sys___setugid; _eaccess; __sys_eaccess; _afs3_syscall; __sys_afs3_syscall; _nmount; __sys_nmount; ___mac_get_proc; __sys___mac_get_proc; ___mac_set_proc; __sys___mac_set_proc; ___mac_get_fd; __sys___mac_get_fd; ___mac_get_file; __sys___mac_get_file; ___mac_set_fd; __sys___mac_set_fd; ___mac_set_file; __sys___mac_set_file; _kenv; __sys_kenv; _lchflags; __sys_lchflags; _uuidgen; __sys_uuidgen; _sendfile; __sys_sendfile; _mac_syscall; __sys_mac_syscall; _ksem_close; __sys_ksem_close; _ksem_post; __sys_ksem_post; _ksem_wait; __sys_ksem_wait; _ksem_trywait; __sys_ksem_trywait; _ksem_init; __sys_ksem_init; _ksem_open; __sys_ksem_open; _ksem_unlink; __sys_ksem_unlink; _ksem_getvalue; __sys_ksem_getvalue; _ksem_destroy; __sys_ksem_destroy; ___mac_get_pid; __sys___mac_get_pid; ___mac_get_link; __sys___mac_get_link; ___mac_set_link; __sys___mac_set_link; _extattr_set_link; __sys_extattr_set_link; _extattr_get_link; __sys_extattr_get_link; _extattr_delete_link; __sys_extattr_delete_link; ___mac_execve; __sys___mac_execve; _sigaction; __sys_sigaction; _sigreturn; __sys_sigreturn; _getcontext; __sys_getcontext; _setcontext; __sys_setcontext; _swapcontext; __sys_swapcontext; ___acl_get_link; __sys___acl_get_link; ___acl_set_link; __sys___acl_set_link; ___acl_delete_link; __sys___acl_delete_link; ___acl_aclcheck_link; __sys___acl_aclcheck_link; _sigwait; __sys_sigwait; _thr_create; __sys_thr_create; _thr_exit; __sys_thr_exit; _thr_self; __sys_thr_self; _thr_kill; __sys_thr_kill; _jail_attach; __sys_jail_attach; _extattr_list_fd; __sys_extattr_list_fd; _extattr_list_file; __sys_extattr_list_file; _extattr_list_link; __sys_extattr_list_link; _ksem_timedwait; __sys_ksem_timedwait; _thr_suspend; __sys_thr_suspend; _thr_wake; __sys_thr_wake; _kldunloadf; __sys_kldunloadf; _audit; __sys_audit; _auditon; __sys_auditon; _getauid; __sys_getauid; _setauid; __sys_setauid; _getaudit; __sys_getaudit; _setaudit; __sys_setaudit; _getaudit_addr; __sys_getaudit_addr; _setaudit_addr; __sys_setaudit_addr; _auditctl; __sys_auditctl; __umtx_op; __sys__umtx_op; _thr_new; __sys_thr_new; _sigqueue; __sys_sigqueue; _kmq_open; __sys_kmq_open; _kmq_setattr; __sys_kmq_setattr; _kmq_timedreceive; __sys_kmq_timedreceive; _kmq_timedsend; __sys_kmq_timedsend; _kmq_notify; __sys_kmq_notify; _kmq_unlink; __sys_kmq_unlink; _abort2; __sys_abort2; _thr_set_name; __sys_thr_set_name; _aio_fsync; __sys_aio_fsync; _rtprio_thread; __sys_rtprio_thread; _sctp_peeloff; __sys_sctp_peeloff; _sctp_generic_sendmsg; __sys_sctp_generic_sendmsg; _sctp_generic_sendmsg_iov; __sys_sctp_generic_sendmsg_iov; _sctp_generic_recvmsg; __sys_sctp_generic_recvmsg; _pread; __sys_pread; _pwrite; __sys_pwrite; _mmap; __sys_mmap; _lseek; __sys_lseek; _truncate; __sys_truncate; _ftruncate; __sys_ftruncate; _thr_kill2; __sys_thr_kill2; _shm_unlink; __sys_shm_unlink; _cpuset; __sys_cpuset; _cpuset_setid; __sys_cpuset_setid; _cpuset_getid; __sys_cpuset_getid; _cpuset_getaffinity; __sys_cpuset_getaffinity; _cpuset_setaffinity; __sys_cpuset_setaffinity; _faccessat; __sys_faccessat; _fchmodat; __sys_fchmodat; _fchownat; __sys_fchownat; _fexecve; __sys_fexecve; _futimesat; __sys_futimesat; _linkat; __sys_linkat; _mkdirat; __sys_mkdirat; _mkfifoat; __sys_mkfifoat; _openat; __sys_openat; _readlinkat; __sys_readlinkat; _renameat; __sys_renameat; _symlinkat; __sys_symlinkat; _unlinkat; __sys_unlinkat; _posix_openpt; __sys_posix_openpt; _gssd_syscall; __sys_gssd_syscall; _jail_get; __sys_jail_get; _jail_set; __sys_jail_set; _jail_remove; __sys_jail_remove; ___semctl; __sys___semctl; _msgctl; __sys_msgctl; _shmctl; __sys_shmctl; _lpathconf; __sys_lpathconf; ___cap_rights_get; __sys___cap_rights_get; _cap_enter; __sys_cap_enter; _cap_getmode; __sys_cap_getmode; _pdfork; __sys_pdfork; _pdkill; __sys_pdkill; _pdgetpid; __sys_pdgetpid; _pselect; __sys_pselect; _getloginclass; __sys_getloginclass; _setloginclass; __sys_setloginclass; _rctl_get_racct; __sys_rctl_get_racct; _rctl_get_rules; __sys_rctl_get_rules; _rctl_get_limits; __sys_rctl_get_limits; _rctl_add_rule; __sys_rctl_add_rule; _rctl_remove_rule; __sys_rctl_remove_rule; _posix_fallocate; __sys_posix_fallocate; _posix_fadvise; __sys_posix_fadvise; _wait6; __sys_wait6; _cap_rights_limit; __sys_cap_rights_limit; _cap_ioctls_limit; __sys_cap_ioctls_limit; _cap_ioctls_get; __sys_cap_ioctls_get; _cap_fcntls_limit; __sys_cap_fcntls_limit; _cap_fcntls_get; __sys_cap_fcntls_get; _bindat; __sys_bindat; _connectat; __sys_connectat; _chflagsat; __sys_chflagsat; _accept4; __sys_accept4; _pipe2; __sys_pipe2; _aio_mlock; __sys_aio_mlock; _procctl; __sys_procctl; _ppoll; __sys_ppoll; _futimens; __sys_futimens; _utimensat; __sys_utimensat; _fdatasync; __sys_fdatasync; _fstat; __sys_fstat; _fstatat; __sys_fstatat; _fhstat; __sys_fhstat; _getdirentries; __sys_getdirentries; _statfs; __sys_statfs; _fstatfs; __sys_fstatfs; _getfsstat; __sys_getfsstat; _fhstatfs; __sys_fhstatfs; _mknodat; __sys_mknodat; _kevent; __sys_kevent; _cpuset_getdomain; __sys_cpuset_getdomain; _cpuset_setdomain; __sys_cpuset_setdomain; _getrandom; __sys_getrandom; _getfhat; __sys_getfhat; _fhlink; __sys_fhlink; _fhlinkat; __sys_fhlinkat; _fhreadlink; __sys_fhreadlink; _funlinkat; __sys_funlinkat; _copy_file_range; __sys_copy_file_range; ___sysctlbyname; __sys___sysctlbyname; _shm_open2; __sys_shm_open2; _shm_rename; __sys_shm_rename; _sigfastblock; __sys_sigfastblock; ___realpathat; __sys___realpathat; _close_range; __sys_close_range; _rpctls_syscall; __sys_rpctls_syscall; ___specialfd; __sys___specialfd; _aio_writev; __sys_aio_writev; _aio_readv; __sys_aio_readv; _fspacectl; __sys_fspacectl; _sched_getcpu; __sys_sched_getcpu; _swapoff; __sys_swapoff; _kqueuex; __sys_kqueuex; _membarrier; __sys_membarrier; _timerfd_create; __sys_timerfd_create; _timerfd_gettime; __sys_timerfd_gettime; _timerfd_settime; __sys_timerfd_settime; _kcmp; __sys_kcmp; }; diff --git a/sys/tools/makesyscalls.lua b/sys/tools/makesyscalls.lua index 8784ff603e81..6f21079d0ebc 100644 --- a/sys/tools/makesyscalls.lua +++ b/sys/tools/makesyscalls.lua @@ -1,1626 +1,1630 @@ -- -- SPDX-License-Identifier: BSD-2-Clause -- -- Copyright (c) 2019 Kyle Evans -- -- Redistribution and use in source and binary forms, with or without -- modification, are permitted provided that the following conditions -- are met: -- 1. Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- 2. Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in the -- documentation and/or other materials provided with the distribution. -- -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -- SUCH DAMAGE. -- -- We generally assume that this script will be run by flua, however we've -- carefully crafted modules for it that mimic interfaces provided by modules -- available in ports. Currently, this script is compatible with lua from ports -- along with the compatible luafilesystem and lua-posix modules. local lfs = require("lfs") local unistd = require("posix.unistd") local savesyscall = -1 local maxsyscall = -1 local generated_tag = "@" .. "generated" -- Default configuration; any of these may get replaced by a configuration file -- optionally specified. local config = { os_id_keyword = "FreeBSD", -- obsolete, ignored on input, not generated abi_func_prefix = "", libsysmap = "/dev/null", sysnames = "syscalls.c", sysproto = "../sys/sysproto.h", sysproto_h = "_SYS_SYSPROTO_H_", syshdr = "../sys/syscall.h", sysmk = "/dev/null", syssw = "init_sysent.c", syscallprefix = "SYS_", switchname = "sysent", namesname = "syscallnames", systrace = "systrace_args.c", capabilities_conf = "capabilities.conf", capenabled = {}, compat_set = "native", mincompat = 0, abi_type_suffix = "", abi_flags = "", abi_flags_mask = 0, abi_headers = "", abi_intptr_t = "intptr_t", abi_size_t = "size_t", abi_u_long = "u_long", abi_long = "long", abi_semid_t = "semid_t", abi_ptr_array_t = "", ptr_intptr_t_cast = "intptr_t", syscall_abi_change = "", sys_abi_change = {}, syscall_no_abi_change = "", sys_no_abi_change = {}, obsol = "", obsol_dict = {}, unimpl = "", unimpl_dict = {}, } local config_modified = {} local cleantmp = true local tmpspace = "/tmp/sysent." .. unistd.getpid() .. "/" local output_files = { "sysnames", "syshdr", "sysmk", "libsysmap", "syssw", "systrace", "sysproto", } -- These ones we'll create temporary files for; generation purposes. local temp_files = { "sysaue", "sysdcl", "syscompat", "syscompatdcl", "sysent", "sysinc", "sysarg", "sysprotoend", "systracetmp", "systraceret", } -- Opened files local files = {} local function cleanup() for _, v in pairs(files) do assert(v:close()) end if cleantmp then if lfs.dir(tmpspace) then for fname in lfs.dir(tmpspace) do if fname ~= "." and fname ~= ".." then assert(os.remove(tmpspace .. "/" .. fname)) end end end if lfs.attributes(tmpspace) and not lfs.rmdir(tmpspace) then assert(io.stderr:write("Failed to clean up tmpdir: " .. tmpspace .. "\n")) end else assert(io.stderr:write("Temp files left in " .. tmpspace .. "\n")) end end local function abort(status, msg) assert(io.stderr:write(msg .. "\n")) cleanup() os.exit(status) end -- Each entry should have a value so we can represent abi flags as a bitmask -- for convenience. One may also optionally provide an expr; this gets applied -- to each argument type to indicate whether this argument is subject to ABI -- change given the configured flags. local known_abi_flags = { long_size = { value = 0x00000001, exprs = { "_Contains[a-z_]*_long_", "^long [a-z0-9_]+$", "long [*]", "size_t [*]", -- semid_t is not included because it is only used -- as an argument or written out individually and -- said writes are handled by the ksem framework. -- Technically a sign-extension issue exists for -- arguments, but because semid_t is actually a file -- descriptor negative 32-bit values are invalid -- regardless of sign-extension. }, }, time_t_size = { value = 0x00000002, exprs = { "_Contains[a-z_]*_timet_", }, }, pointer_args = { value = 0x00000004, }, pointer_size = { value = 0x00000008, exprs = { "_Contains[a-z_]*_ptr_", "[*][*]", }, }, pair_64bit = { value = 0x00000010, exprs = { "^dev_t[ ]*$", "^id_t[ ]*$", "^off_t[ ]*$", }, }, } local known_flags = { STD = 0x00000001, OBSOL = 0x00000002, RESERVED = 0x00000004, UNIMPL = 0x00000008, NODEF = 0x00000010, NOARGS = 0x00000020, NOPROTO = 0x00000040, NOSTD = 0x00000080, NOTSTATIC = 0x00000100, CAPENABLED = 0x00000200, SYSMUX = 0x00000400, -- Compat flags start from here. We have plenty of space. } -- All compat option entries should have five entries: -- definition: The preprocessor macro that will be set for this -- compatlevel: The level this compatibility should be included at. This -- generally represents the version of FreeBSD that it is compatible -- with, but ultimately it's just the level of mincompat in which it's -- included. -- flag: The name of the flag in syscalls.master. -- prefix: The prefix to use for _args and syscall prototype. This will be -- used as-is, without "_" or any other character appended. -- descr: The description of this compat option in init_sysent.c comments. -- The special "stdcompat" entry will cause the other five to be autogenerated. local compat_option_sets = { native = { { definition = "COMPAT_43", compatlevel = 3, flag = "COMPAT", prefix = "o", descr = "old", }, { stdcompat = "FREEBSD4" }, { stdcompat = "FREEBSD6" }, { stdcompat = "FREEBSD7" }, { stdcompat = "FREEBSD10" }, { stdcompat = "FREEBSD11" }, { stdcompat = "FREEBSD12" }, { stdcompat = "FREEBSD13" }, { stdcompat = "FREEBSD14" }, }, } -- compat_options will be resolved to a set from the configuration. local compat_options local function trim(s, char) if s == nil then return nil end if char == nil then char = "%s" end return s:gsub("^" .. char .. "+", ""):gsub(char .. "+$", "") end -- config looks like a shell script; in fact, the previous makesyscalls.sh -- script actually sourced it in. It had a pretty common format, so we should -- be fine to make various assumptions local function process_config(file) local cfg = {} local comment_line_expr = "^%s*#.*" -- We capture any whitespace padding here so we can easily advance to -- the end of the line as needed to check for any trailing bogus bits. -- Alternatively, we could drop the whitespace and instead try to -- use a pattern to strip out the meaty part of the line, but then we -- would need to sanitize the line for potentially special characters. local line_expr = "^([%w%p]+%s*)=(%s*[`\"]?[^\"`]*[`\"]?)" if not file then return nil, "No file given" end local fh = assert(io.open(file)) for nextline in fh:lines() do -- Strip any whole-line comments nextline = nextline:gsub(comment_line_expr, "") -- Parse it into key, value pairs local key, value = nextline:match(line_expr) if key ~= nil and value ~= nil then local kvp = key .. "=" .. value key = trim(key) value = trim(value) local delim = value:sub(1,1) if delim == '"' then local trailing_context -- Strip off the key/value part trailing_context = nextline:sub(kvp:len() + 1) -- Strip off any trailing comment trailing_context = trailing_context:gsub("#.*$", "") -- Strip off leading/trailing whitespace trailing_context = trim(trailing_context) if trailing_context ~= "" then print(trailing_context) abort(1, "Malformed line: " .. nextline) end value = trim(value, delim) else -- Strip off potential comments value = value:gsub("#.*$", "") -- Strip off any padding whitespace value = trim(value) if value:match("%s") then abort(1, "Malformed config line: " .. nextline) end end cfg[key] = value elseif not nextline:match("^%s*$") then -- Make sure format violations don't get overlooked -- here, but ignore blank lines. Comments are already -- stripped above. abort(1, "Malformed config line: " .. nextline) end end assert(io.close(fh)) return cfg end local function grab_capenabled(file, open_fail_ok) local capentries = {} local commentExpr = "#.*" if file == nil then print "No file" return {} end local fh = io.open(file) if fh == nil then if not open_fail_ok then abort(1, "Failed to open " .. file) end return {} end for nextline in fh:lines() do -- Strip any comments nextline = nextline:gsub(commentExpr, "") if nextline ~= "" then capentries[nextline] = true end end assert(io.close(fh)) return capentries end local function process_compat() local nval = 0 for _, v in pairs(known_flags) do if v > nval then nval = v end end nval = nval << 1 for _, v in pairs(compat_options) do if v.stdcompat ~= nil then local stdcompat = v.stdcompat v.definition = "COMPAT_" .. stdcompat:upper() v.compatlevel = tonumber(stdcompat:match("([0-9]+)$")) v.flag = stdcompat:gsub("FREEBSD", "COMPAT") v.prefix = stdcompat:lower() .. "_" v.descr = stdcompat:lower() end local tmpname = "sys" .. v.flag:lower() local dcltmpname = tmpname .. "dcl" files[tmpname] = io.tmpfile() files[dcltmpname] = io.tmpfile() v.tmp = tmpname v.dcltmp = dcltmpname known_flags[v.flag] = nval v.mask = nval nval = nval << 1 v.count = 0 end end local function process_abi_flags() local flags, mask = config.abi_flags, 0 for txtflag in flags:gmatch("([^|]+)") do if known_abi_flags[txtflag] == nil then abort(1, "Unknown abi_flag: " .. txtflag) end mask = mask | known_abi_flags[txtflag].value end config.abi_flags_mask = mask end local function process_obsol() local obsol = config.obsol for syscall in obsol:gmatch("([^ ]+)") do config.obsol_dict[syscall] = true end end local function process_unimpl() local unimpl = config.unimpl for syscall in unimpl:gmatch("([^ ]+)") do config.unimpl_dict[syscall] = true end end local function process_syscall_abi_change() local changes_abi = config.syscall_abi_change for syscall in changes_abi:gmatch("([^ ]+)") do config.sys_abi_change[syscall] = true end local no_changes = config.syscall_no_abi_change for syscall in no_changes:gmatch("([^ ]+)") do config.sys_no_abi_change[syscall] = true end end local function abi_changes(name) if known_abi_flags[name] == nil then abort(1, "abi_changes: unknown flag: " .. name) end return config.abi_flags_mask & known_abi_flags[name].value ~= 0 end local function strip_abi_prefix(funcname) local abiprefix = config.abi_func_prefix local stripped_name if funcname == nil then return nil end if abiprefix ~= "" and funcname:find("^" .. abiprefix) then stripped_name = funcname:gsub("^" .. abiprefix, "") else stripped_name = funcname end return stripped_name end local function read_file(tmpfile) if files[tmpfile] == nil then print("Not found: " .. tmpfile) return end local fh = files[tmpfile] assert(fh:seek("set")) return assert(fh:read("a")) end local function write_line(tmpfile, line) if files[tmpfile] == nil then print("Not found: " .. tmpfile) return end assert(files[tmpfile]:write(line)) end local function write_line_pfile(tmppat, line) for k in pairs(files) do if k:match(tmppat) ~= nil then assert(files[k]:write(line)) end end end -- Check both literal intptr_t and the abi version because this needs -- to work both before and after the substitution local function isptrtype(type) return type:find("*") or type:find("caddr_t") or type:find("intptr_t") or type:find(config.abi_intptr_t) end local function isptrarraytype(type) return type:find("[*][*]") or type:find("[*][ ]*const[ ]*[*]") end -- Find types that are always 64-bits wide local function is64bittype(type) return type:find("^dev_t[ ]*$") or type:find("^id_t[ ]*$") or type:find("^off_t[ ]*$") end local process_syscall_def -- These patterns are processed in order on any line that isn't empty. local pattern_table = { { -- To be removed soon pattern = "%s*$" .. config.os_id_keyword, process = function(_, _) -- Ignore... ID tag end, }, { dump_prevline = true, pattern = "^#%s*include", process = function(line) line = line .. "\n" write_line("sysinc", line) end, }, { dump_prevline = true, pattern = "^#", process = function(line) if line:find("^#%s*if") then savesyscall = maxsyscall elseif line:find("^#%s*else") then maxsyscall = savesyscall end line = line .. "\n" write_line("sysent", line) write_line("sysdcl", line) write_line("sysarg", line) write_line_pfile("syscompat[0-9]*$", line) write_line("sysnames", line) write_line_pfile("systrace.*", line) end, }, { dump_prevline = true, pattern = "%%ABI_HEADERS%%", process = function() if config.abi_headers ~= "" then local line = config.abi_headers .. "\n" write_line("sysinc", line) end end, }, { -- Buffer anything else pattern = ".+", process = function(line, prevline) local incomplete = line:find("\\$") ~= nil -- Lines that end in \ get the \ stripped -- Lines that start with a syscall number, prepend \n line = trim(line):gsub("\\$", "") if line:find("^[0-9]") and prevline then process_syscall_def(prevline) prevline = nil end prevline = (prevline or '') .. line incomplete = incomplete or prevline:find(",$") ~= nil incomplete = incomplete or prevline:find("{") ~= nil and prevline:find("}") == nil if prevline:find("^[0-9]") and not incomplete then process_syscall_def(prevline) prevline = nil end return prevline end, }, } local function process_sysfile(file) local capentries = {} local commentExpr = "^%s*;.*" if file == nil then print "No file" return {} end local fh = io.open(file) if fh == nil then print("Failed to open " .. file) return {} end local function do_match(nextline, prevline) local pattern, handler, dump for _, v in pairs(pattern_table) do pattern = v.pattern handler = v.process dump = v.dump_prevline if nextline:match(pattern) then if dump and prevline then process_syscall_def(prevline) prevline = nil end return handler(nextline, prevline) end end abort(1, "Failed to handle: " .. nextline) end local prevline for nextline in fh:lines() do -- Strip any comments nextline = nextline:gsub(commentExpr, "") if nextline ~= "" then prevline = do_match(nextline, prevline) end end -- Dump any remainder if prevline ~= nil and prevline:find("^[0-9]") then process_syscall_def(prevline) end assert(io.close(fh)) return capentries end local function get_mask(flags) local mask = 0 for _, v in ipairs(flags) do if known_flags[v] == nil then abort(1, "Checking for unknown flag " .. v) end mask = mask | known_flags[v] end return mask end local function get_mask_pat(pflags) local mask = 0 for k, v in pairs(known_flags) do if k:find(pflags) then mask = mask | v end end return mask end local function align_sysent_comment(col) write_line("sysent", "\t") col = col + 8 - col % 8 while col < 56 do write_line("sysent", "\t") col = col + 8 end end local function strip_arg_annotations(arg) arg = arg:gsub("_Contains_[^ ]*[_)] ?", "") arg = arg:gsub("_In[^ ]*[_)] ?", "") arg = arg:gsub("_Out[^ ]*[_)] ?", "") return trim(arg) end local function check_abi_changes(arg) for k, v in pairs(known_abi_flags) do local exprs = v.exprs if abi_changes(k) and exprs ~= nil then for _, e in pairs(exprs) do if arg:find(e) then return true end end end end return false end local function process_args(args) local funcargs = {} local changes_abi = false for arg in args:gmatch("([^,]+)") do local arg_abi_change = check_abi_changes(arg) changes_abi = changes_abi or arg_abi_change arg = strip_arg_annotations(arg) local argname = arg:match("([^* ]+)$") -- argtype is... everything else. local argtype = trim(arg:gsub(argname .. "$", ""), nil) if argtype == "" and argname == "void" then goto out end -- is64bittype() needs a bare type so check it after argname -- is removed changes_abi = changes_abi or (abi_changes("pair_64bit") and is64bittype(argtype)) argtype = argtype:gsub("intptr_t", config.abi_intptr_t) argtype = argtype:gsub("semid_t", config.abi_semid_t) if isptrtype(argtype) then argtype = argtype:gsub("size_t", config.abi_size_t) argtype = argtype:gsub("^long", config.abi_long); argtype = argtype:gsub("^u_long", config.abi_u_long); argtype = argtype:gsub("^const u_long", "const " .. config.abi_u_long); elseif argtype:find("^long$") then argtype = config.abi_long end if isptrarraytype(argtype) and config.abi_ptr_array_t ~= "" then -- `* const *` -> `**` argtype = argtype:gsub("[*][ ]*const[ ]*[*]", "**") -- e.g., `struct aiocb **` -> `uint32_t *` argtype = argtype:gsub("[^*]*[*]", config.abi_ptr_array_t .. " ", 1) end -- XX TODO: Forward declarations? See: sysstubfwd in CheriBSD if arg_abi_change then local abi_type_suffix = config.abi_type_suffix argtype = argtype:gsub("(struct [^ ]*)", "%1" .. abi_type_suffix) argtype = argtype:gsub("(union [^ ]*)", "%1" .. abi_type_suffix) end if abi_changes("pair_64bit") and is64bittype(argtype) then if #funcargs % 2 == 1 then funcargs[#funcargs + 1] = { type = "int", name = "_pad", } end funcargs[#funcargs + 1] = { type = "uint32_t", name = argname .. "1", } funcargs[#funcargs + 1] = { type = "uint32_t", name = argname .. "2", } else funcargs[#funcargs + 1] = { type = argtype, name = argname, } end end ::out:: return funcargs, changes_abi end local function handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype, auditev, syscallret, funcname, funcalias, funcargs, argalias) local argssize if flags & known_flags.SYSMUX ~= 0 then argssize = "0" elseif #funcargs > 0 or flags & known_flags.NODEF ~= 0 then argssize = "AS(" .. argalias .. ")" else argssize = "0" end write_line("systrace", string.format([[ /* %s */ case %d: { ]], funcname, sysnum)) write_line("systracetmp", string.format([[ /* %s */ case %d: ]], funcname, sysnum)) write_line("systraceret", string.format([[ /* %s */ case %d: ]], funcname, sysnum)) if #funcargs > 0 and flags & known_flags.SYSMUX == 0 then write_line("systracetmp", "\t\tswitch (ndx) {\n") write_line("systrace", string.format( "\t\tstruct %s *p = params;\n", argalias)) local argtype, argname, desc, padding padding = "" for idx, arg in ipairs(funcargs) do argtype = arg.type argname = arg.name argtype = trim(argtype:gsub("__restrict$", ""), nil) if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then write_line("systracetmp", "#ifdef PAD64_REQUIRED\n") end -- Pointer arg? if argtype:find("*") then desc = "userland " .. argtype else desc = argtype; end write_line("systracetmp", string.format( "\t\tcase %d%s:\n\t\t\tp = \"%s\";\n\t\t\tbreak;\n", idx - 1, padding, desc)) if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then padding = " - _P_" write_line("systracetmp", "#define _P_ 0\n#else\n#define _P_ 1\n#endif\n") end if isptrtype(argtype) then write_line("systrace", string.format( "\t\tuarg[a++] = (%s)p->%s; /* %s */\n", config.ptr_intptr_t_cast, argname, argtype)) elseif argtype == "union l_semun" then write_line("systrace", string.format( "\t\tuarg[a++] = p->%s.buf; /* %s */\n", argname, argtype)) elseif argtype:sub(1,1) == "u" or argtype == "size_t" then write_line("systrace", string.format( "\t\tuarg[a++] = p->%s; /* %s */\n", argname, argtype)) else if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then write_line("systrace", "#ifdef PAD64_REQUIRED\n") end write_line("systrace", string.format( "\t\tiarg[a++] = p->%s; /* %s */\n", argname, argtype)) if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then write_line("systrace", "#endif\n") end end end write_line("systracetmp", "\t\tdefault:\n\t\t\tbreak;\n\t\t};\n") if padding ~= "" then write_line("systracetmp", "#undef _P_\n\n") end write_line("systraceret", string.format([[ if (ndx == 0 || ndx == 1) p = "%s"; break; ]], syscallret)) end local n_args = #funcargs if flags & known_flags.SYSMUX ~= 0 then n_args = 0 end write_line("systrace", string.format( "\t\t*n_args = %d;\n\t\tbreak;\n\t}\n", n_args)) write_line("systracetmp", "\t\tbreak;\n") local nargflags = get_mask({"NOARGS", "NOPROTO", "NODEF"}) if flags & nargflags == 0 then if #funcargs > 0 then write_line("sysarg", string.format("struct %s {\n", argalias)) for _, v in ipairs(funcargs) do local argname, argtype = v.name, v.type if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then write_line("sysarg", "#ifdef PAD64_REQUIRED\n") end write_line("sysarg", string.format( "\tchar %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];\n", argname, argtype, argtype, argname, argname, argtype)) if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then write_line("sysarg", "#endif\n") end end write_line("sysarg", "};\n") else write_line("sysarg", string.format( "struct %s {\n\tsyscallarg_t dummy;\n};\n", argalias)) end end local protoflags = get_mask({"NOPROTO", "NODEF"}) if flags & protoflags == 0 then local sys_prefix = "sys_" if funcname == "nosys" or funcname == "lkmnosys" or funcname == "sysarch" or funcname:find("^freebsd") or funcname:find("^linux") then sys_prefix = "" end write_line("sysdcl", string.format( "%s\t%s%s(struct thread *, struct %s *);\n", rettype, sys_prefix, funcname, argalias)) write_line("sysaue", string.format("#define\t%sAUE_%s\t%s\n", config.syscallprefix, funcalias, auditev)) end write_line("sysent", string.format("\t{ .sy_narg = %s, .sy_call = (sy_call_t *)", argssize)) local column = 8 + 2 + #argssize + 15 if flags & known_flags.SYSMUX ~= 0 then write_line("sysent", string.format( "nosys, .sy_auevent = AUE_NULL, " .. ".sy_flags = %s, .sy_thrcnt = SY_THR_STATIC },", sysflags)) column = column + #"nosys" + #"AUE_NULL" + 3 elseif flags & known_flags.NOSTD ~= 0 then write_line("sysent", string.format( "lkmressys, .sy_auevent = AUE_NULL, " .. ".sy_flags = %s, .sy_thrcnt = SY_THR_ABSENT },", sysflags)) column = column + #"lkmressys" + #"AUE_NULL" + 3 else if funcname == "nosys" or funcname == "lkmnosys" or funcname == "sysarch" or funcname:find("^freebsd") or funcname:find("^linux") then write_line("sysent", string.format( "%s, .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },", funcname, auditev, sysflags, thr_flag)) column = column + #funcname + #auditev + #sysflags + 3 else write_line("sysent", string.format( "sys_%s, .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },", funcname, auditev, sysflags, thr_flag)) column = column + #funcname + #auditev + #sysflags + 7 end end align_sysent_comment(column) write_line("sysent", string.format("/* %d = %s */\n", sysnum, funcalias)) write_line("sysnames", string.format("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, sysnum, funcalias)) if flags & known_flags.NODEF == 0 then write_line("syshdr", string.format("#define\t%s%s\t%d\n", config.syscallprefix, funcalias, sysnum)) write_line("sysmk", string.format(" \\\n\t%s.o", funcalias)) + -- yield has never been exposed as a syscall + if funcalias == "yield" then + return + end if funcalias ~= "exit" and funcalias ~= "vfork" then write_line("libsysmap", string.format("\t_%s;\n", funcalias)) end write_line("libsysmap", string.format("\t__sys_%s;\n", funcalias)) end end local function handle_obsol(sysnum, funcname, comment) write_line("sysent", "\t{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, " .. ".sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT },") align_sysent_comment(34) write_line("sysent", string.format("/* %d = obsolete %s */\n", sysnum, comment)) write_line("sysnames", string.format( "\t\"obs_%s\",\t\t\t/* %d = obsolete %s */\n", funcname, sysnum, comment)) write_line("syshdr", string.format("\t\t\t\t/* %d is obsolete %s */\n", sysnum, comment)) end local function handle_compat(sysnum, thr_flag, flags, sysflags, rettype, auditev, funcname, funcalias, funcargs, argalias) local argssize, out, outdcl, wrap, prefix, descr if #funcargs > 0 or flags & known_flags.NODEF ~= 0 then argssize = "AS(" .. argalias .. ")" else argssize = "0" end for _, v in pairs(compat_options) do if flags & v.mask ~= 0 then if config.mincompat > v.compatlevel then funcname = strip_abi_prefix(funcname) funcname = v.prefix .. funcname return handle_obsol(sysnum, funcname, funcname) end v.count = v.count + 1 out = v.tmp outdcl = v.dcltmp wrap = v.flag:lower() prefix = v.prefix descr = v.descr goto compatdone end end ::compatdone:: local dprotoflags = get_mask({"NOPROTO", "NODEF"}) local nargflags = dprotoflags | known_flags.NOARGS if #funcargs > 0 and flags & nargflags == 0 then write_line(out, string.format("struct %s {\n", argalias)) for _, v in ipairs(funcargs) do local argname, argtype = v.name, v.type write_line(out, string.format( "\tchar %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];\n", argname, argtype, argtype, argname, argname, argtype)) end write_line(out, "};\n") elseif flags & nargflags == 0 then write_line("sysarg", string.format( "struct %s {\n\tsyscallarg_t dummy;\n};\n", argalias)) end if flags & dprotoflags == 0 then write_line(outdcl, string.format( "%s\t%s%s(struct thread *, struct %s *);\n", rettype, prefix, funcname, argalias)) write_line("sysaue", string.format( "#define\t%sAUE_%s%s\t%s\n", config.syscallprefix, prefix, funcname, auditev)) end if flags & known_flags.NOSTD ~= 0 then write_line("sysent", string.format( "\t{ .sy_narg = %s, .sy_call = (sy_call_t *)%s, " .. ".sy_auevent = %s, .sy_flags = 0, " .. ".sy_thrcnt = SY_THR_ABSENT },", "0", "lkmressys", "AUE_NULL")) align_sysent_comment(8 + 2 + #"0" + 15 + #"lkmressys" + #"AUE_NULL" + 3) else write_line("sysent", string.format( "\t{ %s(%s,%s), .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },", wrap, argssize, funcname, auditev, sysflags, thr_flag)) align_sysent_comment(8 + 9 + #argssize + 1 + #funcname + #auditev + #sysflags + 4) end write_line("sysent", string.format("/* %d = %s %s */\n", sysnum, descr, funcalias)) write_line("sysnames", string.format( "\t\"%s.%s\",\t\t/* %d = %s %s */\n", wrap, funcalias, sysnum, descr, funcalias)) -- Do not provide freebsdN_* symbols in libc for < FreeBSD 7 local nosymflags = get_mask({"COMPAT", "COMPAT4", "COMPAT6"}) if flags & nosymflags ~= 0 then write_line("syshdr", string.format( "\t\t\t\t/* %d is %s %s */\n", sysnum, descr, funcalias)) elseif flags & known_flags.NODEF == 0 then write_line("syshdr", string.format("#define\t%s%s%s\t%d\n", config.syscallprefix, prefix, funcalias, sysnum)) write_line("sysmk", string.format(" \\\n\t%s%s.o", prefix, funcalias)) end end local function handle_unimpl(sysnum, sysstart, sysend, comment) if sysstart == nil and sysend == nil then sysstart = tonumber(sysnum) sysend = tonumber(sysnum) end sysnum = sysstart while sysnum <= sysend do write_line("sysent", string.format( "\t{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, " .. ".sy_auevent = AUE_NULL, .sy_flags = 0, " .. ".sy_thrcnt = SY_THR_ABSENT },\t\t\t/* %d = %s */\n", sysnum, comment)) write_line("sysnames", string.format( "\t\"#%d\",\t\t\t/* %d = %s */\n", sysnum, sysnum, comment)) sysnum = sysnum + 1 end end local function handle_reserved(sysnum, sysstart, sysend) handle_unimpl(sysnum, sysstart, sysend, "reserved for local use") end process_syscall_def = function(line) local sysstart, sysend, flags, funcname, sysflags local thr_flag, syscallret local orig = line flags = 0 thr_flag = "SY_THR_STATIC" -- Parse out the interesting information first local initialExpr = "^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s*" local sysnum, auditev, allflags = line:match(initialExpr) if sysnum == nil or auditev == nil or allflags == nil then -- XXX TODO: Better? abort(1, "Completely malformed: " .. line) end if sysnum:find("-") then sysstart, sysend = sysnum:match("^([%d]+)-([%d]+)$") if sysstart == nil or sysend == nil then abort(1, "Malformed range: " .. sysnum) end sysnum = nil sysstart = tonumber(sysstart) sysend = tonumber(sysend) if sysstart ~= maxsyscall + 1 then abort(1, "syscall number out of sync, missing " .. maxsyscall + 1) end else sysnum = tonumber(sysnum) if sysnum ~= maxsyscall + 1 then abort(1, "syscall number out of sync, missing " .. maxsyscall + 1) end end -- Split flags for flag in allflags:gmatch("([^|]+)") do if known_flags[flag] == nil then abort(1, "Unknown flag " .. flag .. " for " .. sysnum) end flags = flags | known_flags[flag] end if (flags & get_mask({"RESERVED", "UNIMPL"})) == 0 and sysnum == nil then abort(1, "Range only allowed with RESERVED and UNIMPL: " .. line) end if (flags & known_flags.NOTSTATIC) ~= 0 then thr_flag = "SY_THR_ABSENT" end -- Strip earlier bits out, leave declaration + alt line = line:gsub("^.+" .. allflags .. "%s*", "") local decl_fnd = line:find("^{") ~= nil if decl_fnd and line:find("}") == nil then abort(1, "Malformed, no closing brace: " .. line) end local decl, alt if decl_fnd then line = line:gsub("^{", "") decl, alt = line:match("([^}]*)}[%s]*(.*)$") else alt = line end if decl == nil and alt == nil then abort(1, "Malformed bits: " .. line) end local funcalias, funcomment, argalias, rettype, args if not decl_fnd and alt ~= nil and alt ~= "" then -- Peel off one entry for name funcname = trim(alt:match("^([^%s]+)"), nil) alt = alt:gsub("^([^%s]+)[%s]*", "") end -- Do we even need it? if flags & get_mask({"OBSOL", "UNIMPL"}) ~= 0 then local NF = 0 for _ in orig:gmatch("[^%s]+") do NF = NF + 1 end funcomment = funcname or '' if NF < 6 then funcomment = funcomment .. " " .. alt end funcomment = trim(funcomment) -- if funcname ~= nil then -- else -- funcomment = trim(alt) -- end goto skipalt end if alt ~= nil and alt ~= "" then local altExpr = "^([^%s]+)%s+([^%s]+)%s+([^%s]+)" funcalias, argalias, rettype = alt:match(altExpr) funcalias = trim(funcalias) if funcalias == nil or argalias == nil or rettype == nil then abort(1, "Malformed alt: " .. line) end end if decl_fnd then -- Don't clobber rettype set in the alt information if rettype == nil then rettype = "int" end -- Peel off the return type syscallret = line:match("([^%s]+)%s") line = line:match("[^%s]+%s(.+)") -- Pointer incoming if line:sub(1,1) == "*" then syscallret = syscallret .. " " end while line:sub(1,1) == "*" do line = line:sub(2) syscallret = syscallret .. "*" end funcname = line:match("^([^(]+)%(") if funcname == nil then abort(1, "Not a signature? " .. line) end args = line:match("^[^(]+%((.+)%)[^)]*$") args = trim(args, '[,%s]') end ::skipalt:: if funcname == nil then funcname = funcalias end funcname = trim(funcname) if config.obsol_dict[funcname] then local compat_prefix = "" for _, v in pairs(compat_options) do if flags & v.mask ~= 0 then compat_prefix = v.prefix goto obsol_compat_done end end ::obsol_compat_done:: args = nil flags = known_flags.OBSOL funcomment = compat_prefix .. funcname end if config.unimpl_dict[funcname] then flags = known_flags.UNIMPL funcomment = funcname end sysflags = "0" -- NODEF events do not get audited if flags & known_flags.NODEF ~= 0 then auditev = 'AUE_NULL' end -- If applicable; strip the ABI prefix from the name local stripped_name = strip_abi_prefix(funcname) if flags & known_flags.CAPENABLED ~= 0 or config.capenabled[funcname] ~= nil or config.capenabled[stripped_name] ~= nil then sysflags = "SYF_CAPENABLED" end local funcargs = {} local changes_abi = false if args ~= nil then funcargs, changes_abi = process_args(args) end if config.sys_no_abi_change[funcname] then changes_abi = false end local noproto = config.abi_flags ~= "" and not changes_abi local argprefix = '' local funcprefix = '' if abi_changes("pointer_args") then for _, v in ipairs(funcargs) do if isptrtype(v.type) then if config.sys_no_abi_change[funcname] then print("WARNING: " .. funcname .. " in syscall_no_abi_change, but pointers args are present") end changes_abi = true goto ptrfound end end ::ptrfound:: end if config.sys_abi_change[funcname] then changes_abi = true end if changes_abi then -- argalias should be: -- COMPAT_PREFIX + ABI Prefix + funcname argprefix = config.abi_func_prefix funcprefix = config.abi_func_prefix funcalias = funcprefix .. funcname noproto = false end if funcname ~= nil then funcname = funcprefix .. funcname end if funcalias == nil or funcalias == "" then funcalias = funcname end if argalias == nil and funcname ~= nil then argalias = funcname .. "_args" for _, v in pairs(compat_options) do local mask = v.mask if (flags & mask) ~= 0 then -- Multiple aliases doesn't seem to make -- sense. argalias = v.prefix .. argalias goto out end end ::out:: elseif argalias ~= nil then argalias = argprefix .. argalias end local ncompatflags = get_mask({"STD", "NODEF", "NOARGS", "NOPROTO", "NOSTD"}) local compatflags = get_mask_pat("COMPAT.*") if noproto or flags & known_flags.SYSMUX ~= 0 then flags = flags | known_flags.NOPROTO; end if flags & known_flags.OBSOL ~= 0 then handle_obsol(sysnum, funcname, funcomment) elseif flags & known_flags.RESERVED ~= 0 then handle_reserved(sysnum, sysstart, sysend) elseif flags & known_flags.UNIMPL ~= 0 then handle_unimpl(sysnum, sysstart, sysend, funcomment) elseif flags & compatflags ~= 0 then if flags & known_flags.STD ~= 0 then abort(1, "Incompatible COMPAT/STD: " .. line) end handle_compat(sysnum, thr_flag, flags, sysflags, rettype, auditev, funcname, funcalias, funcargs, argalias) elseif flags & ncompatflags ~= 0 then handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype, auditev, syscallret, funcname, funcalias, funcargs, argalias) else abort(1, "Bad flags? " .. line) end if sysend ~= nil then maxsyscall = sysend elseif sysnum ~= nil then maxsyscall = sysnum end end -- Entry point if #arg < 1 or #arg > 2 then error("usage: " .. arg[0] .. " input-file ") end local sysfile, configfile = arg[1], arg[2] -- process_config either returns nil and a message, or a -- table that we should merge into the global config if configfile ~= nil then local res = assert(process_config(configfile)) for k, v in pairs(res) do if v ~= config[k] then config[k] = v config_modified[k] = true end end end local compat_set = config.compat_set if compat_set ~= "" then if not compat_option_sets[compat_set] then abort(1, "Undefined compat set: " .. compat_set) end compat_options = compat_option_sets[compat_set] else compat_options = {} end -- We ignore errors here if we're relying on the default configuration. if not config_modified.capenabled then config.capenabled = grab_capenabled(config.capabilities_conf, config_modified.capabilities_conf == nil) elseif config.capenabled ~= "" then -- Due to limitations in the config format mostly, we'll have a comma -- separated list. Parse it into lines local capenabled = {} -- print("here: " .. config.capenabled) for sysc in config.capenabled:gmatch("([^,]+)") do capenabled[sysc] = true end config.capenabled = capenabled end process_compat() process_abi_flags() process_syscall_abi_change() process_obsol() process_unimpl() if not lfs.mkdir(tmpspace) then error("Failed to create tempdir " .. tmpspace) end -- XXX Revisit the error handling here, we should probably move the rest of this -- into a function that we pcall() so we can catch the errors and clean up -- gracefully. for _, v in ipairs(temp_files) do local tmpname = tmpspace .. v files[v] = io.open(tmpname, "w+") -- XXX Revisit these with a pcall() + error handler if not files[v] then abort(1, "Failed to open temp file: " .. tmpname) end end for _, v in ipairs(output_files) do local tmpname = tmpspace .. v files[v] = io.open(tmpname, "w+") -- XXX Revisit these with a pcall() + error handler if not files[v] then abort(1, "Failed to open temp output file: " .. tmpname) end end -- Write out all of the preamble bits write_line("sysent", string.format([[ /* The casts are bogus but will do for now. */ struct sysent %s[] = { ]], config.switchname)) write_line("syssw", string.format([[/* * System call switch table. * * DO NOT EDIT-- this file is automatically %s. */ ]], generated_tag)) write_line("sysarg", string.format([[/* * System call prototypes. * * DO NOT EDIT-- this file is automatically %s. */ #ifndef %s #define %s #include #include #include #include #include #include #include #include #include struct proc; struct thread; #define PAD_(t) (sizeof(syscallarg_t) <= sizeof(t) ? \ 0 : sizeof(syscallarg_t) - sizeof(t)) #if BYTE_ORDER == LITTLE_ENDIAN #define PADL_(t) 0 #define PADR_(t) PAD_(t) #else #define PADL_(t) PAD_(t) #define PADR_(t) 0 #endif ]], generated_tag, config.sysproto_h, config.sysproto_h)) if abi_changes("pair_64bit") then write_line("sysarg", string.format([[ #if !defined(PAD64_REQUIRED) && !defined(__amd64__) #define PAD64_REQUIRED #endif ]])) end if abi_changes("pair_64bit") then write_line("systrace", string.format([[ #if !defined(PAD64_REQUIRED) && !defined(__amd64__) #define PAD64_REQUIRED #endif ]])) end for _, v in pairs(compat_options) do write_line(v.tmp, string.format("\n#ifdef %s\n\n", v.definition)) end write_line("sysnames", string.format([[/* * System call names. * * DO NOT EDIT-- this file is automatically %s. */ const char *%s[] = { ]], generated_tag, config.namesname)) write_line("syshdr", string.format([[/* * System call numbers. * * DO NOT EDIT-- this file is automatically %s. */ ]], generated_tag)) write_line("sysmk", string.format([[# FreeBSD system call object files. # DO NOT EDIT-- this file is automatically %s. MIASM = ]], generated_tag)) write_line("libsysmap", string.format([[/* * FreeBSD system call symbols. * DO NOT EDIT-- this file is automatically %s. */ FBSDprivate_1.0 { ]], generated_tag)) write_line("systrace", string.format([[/* * System call argument to DTrace register array converstion. * * DO NOT EDIT-- this file is automatically %s. * This file is part of the DTrace syscall provider. */ static void systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) { int64_t *iarg = (int64_t *)uarg; int a = 0; switch (sysnum) { ]], generated_tag)) write_line("systracetmp", [[static void systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) { const char *p = NULL; switch (sysnum) { ]]) write_line("systraceret", [[static void systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) { const char *p = NULL; switch (sysnum) { ]]) -- Processing the sysfile will parse out the preprocessor bits and put them into -- the appropriate place. Any syscall-looking lines get thrown into the sysfile -- buffer, one per line, for later processing once they're all glued together. process_sysfile(sysfile) write_line("sysinc", "\n#define AS(name) (sizeof(struct name) / sizeof(syscallarg_t))\n") for _, v in pairs(compat_options) do if v.count > 0 then write_line("sysinc", string.format([[ #ifdef %s #define %s(n, name) .sy_narg = n, .sy_call = (sy_call_t *)__CONCAT(%s, name) #else #define %s(n, name) .sy_narg = 0, .sy_call = (sy_call_t *)nosys #endif ]], v.definition, v.flag:lower(), v.prefix, v.flag:lower())) end write_line(v.dcltmp, string.format("\n#endif /* %s */\n\n", v.definition)) end write_line("sysprotoend", string.format([[ #undef PAD_ #undef PADL_ #undef PADR_ #endif /* !%s */ ]], config.sysproto_h)) write_line("sysmk", "\n") write_line("libsysmap", "};\n") write_line("sysent", "};\n") write_line("sysnames", "};\n") -- maxsyscall is the highest seen; MAXSYSCALL should be one higher write_line("syshdr", string.format("#define\t%sMAXSYSCALL\t%d\n", config.syscallprefix, maxsyscall + 1)) write_line("systrace", [[ default: *n_args = 0; break; }; } ]]) write_line("systracetmp", [[ default: break; }; if (p != NULL) strlcpy(desc, p, descsz); } ]]) write_line("systraceret", [[ default: break; }; if (p != NULL) strlcpy(desc, p, descsz); } ]]) -- Finish up; output write_line("syssw", read_file("sysinc")) write_line("syssw", read_file("sysent")) write_line("sysproto", read_file("sysarg")) write_line("sysproto", read_file("sysdcl")) for _, v in pairs(compat_options) do write_line("sysproto", read_file(v.tmp)) write_line("sysproto", read_file(v.dcltmp)) end write_line("sysproto", read_file("sysaue")) write_line("sysproto", read_file("sysprotoend")) write_line("systrace", read_file("systracetmp")) write_line("systrace", read_file("systraceret")) for _, v in ipairs(output_files) do local target = config[v] if target ~= "/dev/null" then local fh = assert(io.open(target, "w+")) if fh == nil then abort(1, "Failed to open '" .. target .. "'") end assert(fh:write(read_file(v))) assert(fh:close()) end end cleanup()