19ded074eSagge3#!/usr/libexec/flua 29ded074eSagge3-- 39ded074eSagge3-- SPDX-License-Identifier: BSD-2-Clause 49ded074eSagge3-- 59ded074eSagge3-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org> 69ded074eSagge3-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org> 79ded074eSagge3-- 89ded074eSagge3 99ded074eSagge3-- Setup to be a module, or ran as its own script. 109ded074eSagge3local sysproto_h = {} 119ded074eSagge3local script = not pcall(debug.getlocal, 4, 1) -- TRUE if script. 129ded074eSagge3if script then 139ded074eSagge3 -- Add library root to the package path. 149ded074eSagge3 local path = arg[0]:gsub("/[^/]+.lua$", "") 159ded074eSagge3 package.path = package.path .. ";" .. path .. "/../?.lua" 169ded074eSagge3end 179ded074eSagge3 189ded074eSagge3local FreeBSDSyscall = require("core.freebsd-syscall") 199ded074eSagge3local generator = require("tools.generator") 209ded074eSagge3 219ded074eSagge3-- File has not been decided yet; config will decide file. Default defined as 229ded074eSagge3-- /dev/null. 239ded074eSagge3sysproto_h.file = "/dev/null" 249ded074eSagge3 259ded074eSagge3function sysproto_h.generate(tbl, config, fh) 269ded074eSagge3 -- Grab the master system calls table. 279ded074eSagge3 local s = tbl.syscalls 289ded074eSagge3 299ded074eSagge3 -- Bind the generator to the parameter file. 309ded074eSagge3 local gen = generator:new({}, fh) 319ded074eSagge3 gen.storage_levels = {} -- make sure storage is clear 329ded074eSagge3 339ded074eSagge3 -- Write the generated preamble. 349ded074eSagge3 gen:preamble("System call prototypes.") 359ded074eSagge3 369ded074eSagge3 -- Write out all the preprocessor directives. 379ded074eSagge3 gen:write(string.format([[ 389ded074eSagge3#ifndef %s 399ded074eSagge3#define %s 409ded074eSagge3 419ded074eSagge3#include <sys/types.h> 429ded074eSagge3#include <sys/signal.h> 439ded074eSagge3#include <sys/cpuset.h> 449ded074eSagge3#include <sys/domainset.h> 459ded074eSagge3#include <sys/_ffcounter.h> 469ded074eSagge3#include <sys/_semaphore.h> 479ded074eSagge3#include <sys/ucontext.h> 489ded074eSagge3#include <sys/wait.h> 499ded074eSagge3 509ded074eSagge3#include <bsm/audit_kevents.h> 519ded074eSagge3 529ded074eSagge3struct proc; 539ded074eSagge3 549ded074eSagge3struct thread; 559ded074eSagge3 569ded074eSagge3#define PAD_(t) (sizeof(syscallarg_t) <= sizeof(t) ? \ 579ded074eSagge3 0 : sizeof(syscallarg_t) - sizeof(t)) 589ded074eSagge3 599ded074eSagge3#if BYTE_ORDER == LITTLE_ENDIAN 609ded074eSagge3#define PADL_(t) 0 619ded074eSagge3#define PADR_(t) PAD_(t) 629ded074eSagge3#else 639ded074eSagge3#define PADL_(t) PAD_(t) 649ded074eSagge3#define PADR_(t) 0 659ded074eSagge3#endif 669ded074eSagge3 679ded074eSagge3]], config.sysproto_h, config.sysproto_h)) 689ded074eSagge3 699ded074eSagge3 -- 64-bit padding preprocessor directive. 709ded074eSagge3 gen:pad64(config.abiChanges("pair_64bit")) 719ded074eSagge3 729ded074eSagge3 -- 739ded074eSagge3 -- Storing each compat entry requires storing multiple levels of file 749ded074eSagge3 -- generation; compat entries are given ranges of 10 instead to cope 759ded074eSagge3 -- with this. For example, 13 is indexed as 130; 131 is the second 769ded074eSagge3 -- storage level of 13. 779ded074eSagge3 -- 789ded074eSagge3 799ded074eSagge3 -- Store all the compat #ifdef from compat_options at their zero index. 809ded074eSagge3 for _, v in pairs(config.compat_options) do 819ded074eSagge3 -- Tag an extra newline to the end, so it doesn't have to be 829ded074eSagge3 -- worried about later. 839ded074eSagge3 gen:store(string.format("\n#ifdef %s\n\n", v.definition), 849ded074eSagge3 v.compatlevel * 10) 859ded074eSagge3 end 869ded074eSagge3 879ded074eSagge3 for _, v in pairs(s) do 889ded074eSagge3 local c = v:compatLevel() 899ded074eSagge3 909ded074eSagge3 -- Audit defines are stored at an arbitrarily large number so 919ded074eSagge3 -- that they're always at the last storage level, and compat 929ded074eSagge3 -- entries can be indexed by their compat level (more 939ded074eSagge3 -- intuitive). 949ded074eSagge3 local audit_idx = 10000 -- this should do 959ded074eSagge3 96*42d075f4SBrooks Davis gen:write(v.prolog) 97*42d075f4SBrooks Davis gen:store(v.prolog, 1) 98*42d075f4SBrooks Davis for _, w in pairs(config.compat_options) do 99*42d075f4SBrooks Davis gen:store(v.prolog, w.compatlevel * 10) 100*42d075f4SBrooks Davis end 101*42d075f4SBrooks Davis 1029ded074eSagge3 -- Handle non-compat: 1039ded074eSagge3 if v:native() then 1049ded074eSagge3 -- All these negation conditions are because (in 1059ded074eSagge3 -- general) these are cases where code for sysproto.h 1069ded074eSagge3 -- is not generated. 1079ded074eSagge3 if not v.type.NOARGS and not v.type.NOPROTO and 1089ded074eSagge3 not v.type.NODEF then 1099ded074eSagge3 if #v.args > 0 then 1109ded074eSagge3 gen:write(string.format( 1119ded074eSagge3 "struct %s {\n", v.arg_alias)) 1129ded074eSagge3 for _, arg in ipairs(v.args) do 1139ded074eSagge3 if arg.type == "int" and 1149ded074eSagge3 arg.name == "_pad" and 1159ded074eSagge3 config.abiChanges( 1169ded074eSagge3 "pair_64bit") then 1179ded074eSagge3 gen:write("#ifdef PAD64_REQUIRED\n") 1189ded074eSagge3 end 1199ded074eSagge3 1209ded074eSagge3 gen:write(string.format([[ 1219ded074eSagge3 char %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)]; 1229ded074eSagge3]], 1239ded074eSagge3 arg.name, arg.type, 1249ded074eSagge3 arg.type, arg.name, 1259ded074eSagge3 arg.name, arg.type)) 1269ded074eSagge3 1279ded074eSagge3 if arg.type == "int" and 1289ded074eSagge3 arg.name == "_pad" and 1299ded074eSagge3 config.abiChanges( 1309ded074eSagge3 "pair_64bit") then 1319ded074eSagge3 gen:write("#endif\n") 1329ded074eSagge3 end 1339ded074eSagge3 end 1349ded074eSagge3 gen:write("};\n") 1359ded074eSagge3 else 1369ded074eSagge3 gen:write(string.format( 1379ded074eSagge3 "struct %s {\n\tsyscallarg_t dummy;\n};\n", 1389ded074eSagge3 v.arg_alias)) 1399ded074eSagge3 end 1409ded074eSagge3 end 1419ded074eSagge3 if not v.type.NOPROTO and not v.type.NODEF then 1429ded074eSagge3 local sys_prefix = "sys_" 1439ded074eSagge3 if v.name == "nosys" or v.name == "lkmnosys" or 1449ded074eSagge3 v.name == "sysarch" or 1459ded074eSagge3 v.name:find("^freebsd") or 1469ded074eSagge3 v.name:find("^linux") then 1479ded074eSagge3 sys_prefix = "" 1489ded074eSagge3 end 1499ded074eSagge3 gen:store(string.format( 1509ded074eSagge3 "%s\t%s%s(struct thread *, struct %s *);\n", 1519ded074eSagge3 v.rettype, sys_prefix, v.name, v.arg_alias), 1529ded074eSagge3 1) 1539ded074eSagge3 gen:store(string.format( 1549ded074eSagge3 "#define\t%sAUE_%s\t%s\n", 1559ded074eSagge3 config.syscallprefix, v:symbol(), v.audit), 1569ded074eSagge3 audit_idx) 1579ded074eSagge3 end 1589ded074eSagge3 1599ded074eSagge3 -- Handle compat (everything >= FREEBSD3): 1609ded074eSagge3 elseif c >= 3 then 1619ded074eSagge3 local idx = c * 10 1629ded074eSagge3 if not v.type.NOARGS and not v.type.NOPROTO and 1639ded074eSagge3 not v.type.NODEF then 1649ded074eSagge3 if #v.args > 0 then 1659ded074eSagge3 gen:store(string.format( 1669ded074eSagge3 "struct %s {\n", v.arg_alias), idx) 1679ded074eSagge3 for _, arg in ipairs(v.args) do 1689ded074eSagge3 gen:store(string.format([[ 1699ded074eSagge3 char %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)]; 1709ded074eSagge3]], 1719ded074eSagge3 arg.name, arg.type, 1729ded074eSagge3 arg.type, arg.name, 1739ded074eSagge3 arg.name, arg.type), idx) 1749ded074eSagge3 end 1759ded074eSagge3 gen:store("};\n", idx) 1769ded074eSagge3 else 1779ded074eSagge3 -- Not stored, written on the first run. 1789ded074eSagge3 gen:write(string.format([[ 1799ded074eSagge3struct %s { 1809ded074eSagge3 syscallarg_t dummy; 1819ded074eSagge3}; 1829ded074eSagge3]], 1839ded074eSagge3 v.arg_alias)) 1849ded074eSagge3 end 1859ded074eSagge3 end 1869ded074eSagge3 if not v.type.NOPROTO and not v.type.NODEF then 1879ded074eSagge3 gen:store(string.format([[ 1889ded074eSagge3%s %s%s(struct thread *, struct %s *); 1899ded074eSagge3]], 1909ded074eSagge3 v.rettype, v:compatPrefix(), v.name, 1919ded074eSagge3 v.arg_alias), idx + 1) 1929ded074eSagge3 gen:store(string.format([[ 1939ded074eSagge3#define %sAUE_%s%s %s 1949ded074eSagge3]], 1959ded074eSagge3 config.syscallprefix, v:compatPrefix(), 1969ded074eSagge3 v.name, v.audit), audit_idx) 1979ded074eSagge3 end 1989ded074eSagge3 end 1999ded074eSagge3 -- Do nothing for obsolete, unimplemented, and reserved. 2009ded074eSagge3 end 2019ded074eSagge3 2029ded074eSagge3 -- Append #endif to the end of each compat option. 2039ded074eSagge3 for _, v in pairs(config.compat_options) do 2049ded074eSagge3 -- Based on how they're indexed, 9 is the last index. 2059ded074eSagge3 local end_idx = (v.compatlevel * 10) + 9 2069ded074eSagge3 -- Need an extra newline after #endif. 2079ded074eSagge3 gen:store(string.format("\n#endif /* %s */\n\n", v.definition), 2089ded074eSagge3 end_idx) 2099ded074eSagge3 end 2109ded074eSagge3 211*42d075f4SBrooks Davis gen:write(tbl.epilog) 212*42d075f4SBrooks Davis gen:store(tbl.epilog, 1) 213*42d075f4SBrooks Davis for _, w in pairs(config.compat_options) do 214*42d075f4SBrooks Davis gen:store(tbl.epilog, w.compatlevel * 10) 215*42d075f4SBrooks Davis end 216*42d075f4SBrooks Davis 2179ded074eSagge3 if gen.storage_levels ~= nil then 2189ded074eSagge3 gen:writeStorage() 2199ded074eSagge3 end 2209ded074eSagge3 2219ded074eSagge3 -- After storage has been unrolled, tag on the ending bits. 2229ded074eSagge3 gen:write(string.format([[ 2239ded074eSagge3 2249ded074eSagge3#undef PAD_ 2259ded074eSagge3#undef PADL_ 2269ded074eSagge3#undef PADR_ 2279ded074eSagge3 2289ded074eSagge3#endif /* !%s */ 2299ded074eSagge3]], config.sysproto_h)) 2309ded074eSagge3end 2319ded074eSagge3 2329ded074eSagge3-- Entry of script: 2339ded074eSagge3if script then 2349ded074eSagge3 local config = require("config") 2359ded074eSagge3 2369ded074eSagge3 if #arg < 1 or #arg > 2 then 2379ded074eSagge3 error("usage: " .. arg[0] .. " syscall.master") 2389ded074eSagge3 end 2399ded074eSagge3 2409ded074eSagge3 local sysfile, configfile = arg[1], arg[2] 2419ded074eSagge3 2429ded074eSagge3 config.merge(configfile) 2439ded074eSagge3 config.mergeCompat() 2449ded074eSagge3 2459ded074eSagge3 -- The parsed system call table. 2469ded074eSagge3 local tbl = FreeBSDSyscall:new{sysfile = sysfile, config = config} 2479ded074eSagge3 2489ded074eSagge3 sysproto_h.file = config.sysproto -- change file here 2499ded074eSagge3 sysproto_h.generate(tbl, config, sysproto_h.file) 2509ded074eSagge3end 2519ded074eSagge3 2529ded074eSagge3-- Return the module. 2539ded074eSagge3return sysproto_h 254