Lynxer

Documentation

Named syscalls

Lynxer exposes one named built-in per Linux syscall. They are raw ABI calls: argument layouts, flags, structures and pointer lifetimes are the caller's responsibility. Every wrapper is target-gated and reached through the architecture's namespace.

global setup(){ syscalls("Linux", "amd64"); }

global main(){
    println(amd64.syscallGetProcessId());
    println(amd64.syscallYieldProcessor());
}

Selecting an operating system and architecture

syscalls("<os>", "<arch>") must run before any syscall call; it declares which operating system and architecture the program targets.

KeywordKindSelects
Linuxoperating systemthe Linux syscall surface (amd64.syscallX)
winAPI, windows, win32operating systemthe Windows API surface (winAPI.getX)
macOS, darwinoperating systemrecognised, but not implemented
amd64, x86-64architecturex86-64
arm64, aarch64architectureAArch64

Calls then use the matching namespace — amd64.syscallRead(...) or arm64.syscallRead(...). A call through the wrong namespace is an error.

Windows API calls

Selecting the Windows target (winAPI, windows or win32) is only possible on a Windows host. It makes the winAPI.* namespace available — the Win32 calls a program needs, in the camelCase Win32 naming:

global setup(){ syscalls("winAPI", "amd64"); }

global main(){
    println(winAPI.getProcessId());
    println(winAPI.getCurrentDirectory());
    println(winAPI.getComputerName());
}
FunctionReturns
winAPI.getProcessId()the current process id
winAPI.getCurrentDirectory()the current directory
winAPI.getComputerName()the computer name
winAPI.getTempPath()the temporary directory
winAPI.getSystemDirectory()the system directory
winAPI.getWindowsDirectory()the Windows directory
winAPI.getModuleFileName()the running executable's path
winAPI.getTickCount()milliseconds since the system started
winAPI.getLastError()the last Win32 error code
winAPI.getEnvironmentVariable(name)the variable's value, or ""
winAPI.setEnvironmentVariable(name, value)whether it was set
winAPI.expandEnvironmentStrings(text)text with %VAR% expanded
winAPI.getDiskFreeBytes(path)free bytes on the volume, or -1
winAPI.getKnownFolderPath(name)a Known Folder path, or ""
winAPI.sleep(milliseconds)—
winAPI.outputDebugString(text)—
winAPI.beep(frequency, duration)whether it played

Files and handles. A handle is an integer (-1 on failure) and must be closed with closeHandle; the file calls use the same scalar-sentinel convention as the rest of the stdlib, with getLastError() for the reason:

FunctionReturns
winAPI.createFile(path, mode)a handle, or -1; mode is read, write, append or readwrite
winAPI.readFile(handle, length)up to length bytes, or ""
winAPI.writeFile(handle, text)bytes written, or -1
winAPI.closeHandle(handle)whether it closed
winAPI.fileSize(handle)size in bytes, or -1
winAPI.seekFile(handle, offset)the new position, or -1
winAPI.deleteFile(path)whether it was removed
winAPI.copyFile(source, destination, overwrite)whether it was copied
winAPI.moveFile(source, destination)whether it was moved
winAPI.createDirectory(path)whether it was created
winAPI.removeDirectory(path)whether it was removed

Beyond files, the surface also covers process control (getCurrentThreadId, openProcess, terminateProcess, getExitCodeProcess, createProcess, waitForSingleObject), the console session (getStdHandle, getConsoleMode, setConsoleMode, setConsoleTitle, getConsoleOutputCP, setConsoleOutputCP), file attributes and paths (getFileAttributes, setFileAttributes, getFullPathName, flushFileBuffers) and the high-resolution timer (queryPerformanceCounter, queryPerformanceFrequency). The full reference is windows-api.

Most calls are kernel32; getKnownFolderPath uses shell32/ole32. The long tail — other DLLs, user32, advapi32, *A/*W pairs, structs — is reachable today through ffiLoadLibrary/ffiLookup/ffiCall with a cdecl: signature (see native-modules); a curated wrapper for it may come later.

The namespace prefix is matched case-insensitively, an unknown function reports the closest match, and a winAPI.* call made before the selection (or after selecting another target) is a source-located error. Win32 handles, *W/*A pairs and struct layouts are not exposed yet; see windows and the tracker in ../todo.

For a complete reference, see windows-api.

Calling convention

Portable poll/epoll

poll(2) and epoll_wait(2) do not exist on AArch64, so the two portable wrappers dispatch to whichever the host has, while the explicit ppoll / epoll_pwait forms are available on both architectures:

Built-inamd64aarch64
syscallPollFileDescriptorspollppoll
syscallPpollFileDescriptorsppollppoll
syscallWaitForEventsepoll_waitepoll_pwait
syscallWaitForEventsWithSignalMaskepoll_pwaitepoll_pwait

Working directories

Built-inLinux syscallArguments
syscallGetCurrentDirectory(buffer, size)getcwdoutput buffer address, buffer capacity
syscallChangeDirectory(path)chdirNUL-terminated path address

File descriptors and files

Built-inLinux syscallArguments
syscallRead(fd, buffer, count)readdescriptor, buffer address, byte count
syscallWrite(fd, buffer, count)writedescriptor, buffer address, byte count
syscallPositionedRead64(fd, buffer, count, offset)pread64descriptor, buffer address, byte count, byte offset
syscallPositionedWrite64(fd, buffer, count, offset)pwrite64descriptor, buffer address, byte count, byte offset
syscallOpenAt(dirfd, path, flags, mode)openatdirectory descriptor, path address, flags, mode
syscallOpenAt2(dirfd, path, resolve, size)openat2directory descriptor, path, open_how address, size
syscallClose(fd)closedescriptor
syscallReadVector(fd, iov, count)readvdescriptor, iovec array address, element count
syscallWriteVector(fd, iov, count)writevdescriptor, iovec array address, element count
syscallSeekFile(fd, offset, whence)lseekdescriptor, offset, SEEK_* value
syscallGetFileStatus(fd, status)fstatdescriptor, stat structure address
syscallGetFileStatusAt(dirfd, path, status, flags)newfstatatdirectory descriptor, path, stat address, flags
syscallGetExtendedFileStatus(dirfd, path, flags, mask, status)statxdirectory descriptor, path, flags, mask, statx address
syscallTruncateFile(fd, length)ftruncatedescriptor, length
syscallFallocateFile(fd, mode, offset, length)fallocatedescriptor, mode, byte range
syscallCheckFileAccessAt(dirfd, path, mode, flags)faccessatdirectory descriptor, path address, access mode, flags
syscallCheckFileAccessAt2(dirfd, path, mode, flags)faccessat2as faccessat, with flags honoured
syscallCopyFileRange(fdin, offin, fdout, offout, length, flags)copy_file_rangeinput/output descriptors, offsets, length, flags
syscallSynchronizeFile(fd)fsyncdescriptor
syscallSynchronizeFileData(fd)fdatasyncdescriptor
syscallSynchronizeFilesystem(fd)syncfsany descriptor on the target filesystem
syscallDuplicateFileDescriptor(fd)dupdescriptor
syscallDuplicateFileDescriptorAt(fd, newfd, flags)dup3descriptor, new descriptor, flags
syscallCreatePipe(pipefd, flags)pipe2two-int output array address, flags
syscallControlFileDescriptor(fd, command, argument)fcntldescriptor, F_* command, command argument
syscallGetDirectoryEntries(fd, buffer, count)getdents64descriptor, buffer address, byte count
syscallReadSymbolicLink(dirfd, path, buffer, size)readlinkatdirectory descriptor, path, buffer, byte count
syscallControlInputOutput(fd, request, argument)ioctldescriptor, request code, request-specific argument
Built-inLinux syscallArguments
syscallCreateDirectoryAt(dirfd, path, mode)mkdiratdirectory descriptor, path address, mode
syscallRemoveFileAt(dirfd, path, flags)unlinkatdirectory descriptor, path address, flags
syscallRenameFileAt(oldfd, oldpath, newfd, newpath)renameatdirectory descriptors and path addresses
syscallCreateHardLinkAt(olddirfd, oldpath, newdirfd, newpath, flags)linkatdirectory descriptors, path addresses, flags
syscallCreateSymbolicLinkAt(target, newdirfd, linkpath)symlinkattarget address, directory descriptor, link path address
syscallChangeFilePermissions(dirfd, path, mode)fchmodatdirectory descriptor, path, mode
syscallChangeFileDescriptorPermissions(fd, mode)fchmoddescriptor, mode
syscallChangeFileOwner(dirfd, path, owner, group, flags)fchownatdirectory descriptor, path, owner, group, flags
syscallChangeFileDescriptorOwner(fd, owner, group)fchowndescriptor, owner, group

Memory and program execution

Built-inLinux syscallArguments
syscallMemoryMap(address, length, protection, flags, fd, offset)mmapaddress, length, PROT_*, MAP_*, descriptor, offset
syscallMemoryUnmap(address, length)munmapaddress, length
syscallMemoryProtect(address, length, protection)mprotectaddress, length, PROT_*
syscallMemoryAdvise(address, length, advice)madviseaddress, length, MADV_*
syscallMemoryRemap(oldaddress, oldsize, newsize, flags, newaddress)mremapold address, old size, new size, flags, new address
syscallSynchronizeMemory(address, length, flags)msyncmapped address, length, MS_* flags
syscallAdjustProgramBreak(address)brkrequested program-break address
syscallExecuteProgram(path, argv, envp)execvepath, argv-array, envp-array addresses
syscallExecuteProgramAt(fd, path, argv, envp, flags)execveatdescriptor, path, argv, envp, flags
syscallLockMemory(address, length)mlockaddress, length
syscallUnlockMemory(address, length)munlockaddress, length
syscallCreateMemoryFileDescriptor(name, flags)memfd_createname address, flags
syscallSetMemoryPolicy(address, length, mode, nodemask, maxnode, flags)mbindNUMA placement; both arches

Processes and threads

Built-inLinux syscallArguments
syscallExitProcess(status)exitexit status; does not return
syscallExitAllThreads(status)exit_groupexit status; does not return
syscallWaitForProcess(pid, status, options, rusage)wait4process ID, status address, options, rusage address
syscallWaitForProcessId(idtype, id, info, options, rusage)waitidid type, id, siginfo address, options, rusage
syscallGetProcessId()getpidnone
syscallGetParentProcessId()getppidnone
syscallSendSignal(pid, signal)killprocess ID, signal
syscallOpenProcessFileDescriptor(pid, flags)pidfd_openprocess ID, flags
syscallSendSignalToProcessFileDescriptor(pidfd, signal, info, flags)pidfd_send_signalpidfd, signal, siginfo address, flags
syscallCreateThread(flags, stack, parent_tid, child_tid, tls)cloneclone flags and native addresses
syscallCreateThread3(args, size)clone3clone_args address, size
syscallGetThreadId()gettidnone
syscallWaitOnMemory(address, operation, value, timeout, address2, value3)futexfutex address and futex ABI arguments
syscallSetThreadIdAddress(address)set_tid_addressaddress
syscallSetRobustThreadList(head, length)set_robust_listlist address, byte length
syscallGetRobustThreadList(pid, head, length)get_robust_listprocess ID, output addresses
syscallGetThreadAffinity(pid, size, mask)sched_getaffinityprocess ID, mask size, output mask
syscallSetThreadAffinity(pid, size, mask)sched_setaffinityprocess ID, mask size, mask address
syscallGetThreadPriority(which, who)getpriorityPRIO_* selector, id
syscallSetThreadPriority(which, who, priority)setpriorityPRIO_* selector, id, priority
syscallYieldProcessor()sched_yieldnone

Clocks, sleep, and randomness

Built-inLinux syscallArguments
syscallGetClockTime(clock, timespec)clock_gettimeclock ID, timespec address
syscallGetClockResolution(clock, resolution)clock_getresclock ID, timespec address
syscallGetTimeOfDay(timeval, timezone)gettimeofdaytimeval address, timezone address
syscallSleep(request, remainder)nanosleeptimespec addresses
syscallSleepClock(clock, flags, request, remainder)clock_nanosleepclock ID, flags, timespec addresses
syscallCreateTimerFileDescriptor(clock, flags)timerfd_createclock ID, flags
syscallControlTimerFileDescriptor(fd, flags, newvalue, oldvalue)timerfd_settimedescriptor, flags, itimerspec addresses
syscallGetRandomBytes(buffer, count, flags)getrandombuffer address, byte count, flags

Signals

Built-inLinux syscallArguments
syscallControlSignal(signal, action, oldaction, size)rt_sigactionsignal, sigaction addresses, signal-set size
syscallControlSignalMask(how, set, oldset, size)rt_sigprocmaskSIG_* how, signal-set addresses, size
syscallCreateSignalFileDescriptor(fd, mask, size, flags)signalfd4descriptor, mask, signal-set size, flags

Sockets

Built-inLinux syscallArguments
syscallCreateSocket(domain, type, protocol)socketsocket domain, type, protocol
syscallCreateSocketPair(domain, type, protocol, sockets)socketpairdomain, type, protocol, output array address
syscallBindSocket(socket, address, length)binddescriptor, socket address, length
syscallListenSocket(socket, backlog)listendescriptor, backlog
syscallAcceptConnection(socket, address, length)acceptdescriptor, address and length pointers
syscallAcceptConnection4(socket, address, length, flags)accept4as accept, with flags
syscallConnectSocket(socket, address, length)connectdescriptor, socket address, length
syscallSendData(socket, buffer, length, flags, address, addressLength)sendtodescriptor, buffer, length, flags, destination, address length
syscallReceiveData(socket, buffer, length, flags, address, addressLength)recvfromdescriptor, buffer, length, flags, source, address length
syscallSendMessage(socket, message, flags)sendmsgdescriptor, msghdr address, flags
syscallReceiveMessage(socket, message, flags)recvmsgdescriptor, msghdr address, flags
syscallSendMessages(socket, messages, count, flags)sendmmsgdescriptor, mmsghdr array, count, flags
syscallReceiveMessages(socket, messages, count, flags)recvmmsgdescriptor, mmsghdr array, count, flags
syscallShutdownSocket(socket, how)shutdowndescriptor, SHUT_* value
syscallGetSocketAddress(socket, address, length)getsocknamedescriptor, address and length pointers
syscallGetPeerAddress(socket, address, length)getpeernamedescriptor, address and length pointers
syscallSetSocketOption(socket, level, option, value, length)setsockoptdescriptor, level, option, value address, length
syscallGetSocketOption(socket, level, option, value, length)getsockoptdescriptor, level, option, output value, length pointer

Polling and event loops

Built-inLinux syscallArguments
syscallPollFileDescriptors(fds, count, timeout_ms)poll / ppollpollfd array address, count, timeout in milliseconds
syscallPpollFileDescriptors(fds, count, timespec, sigmask, sigsetsize)ppollpollfd array, count, timespec address, signal-mask address, signal-set size
syscallCreateEventPoll(flags)epoll_create1flags
syscallControlEventPoll(epoll, operation, fd, event)epoll_ctlepoll descriptor, EPOLL_CTL_*, descriptor, event address
syscallWaitForEvents(epoll, events, maxevents, timeout, sigmask)epoll_wait / epoll_pwaitepoll descriptor, event array, capacity, timeout, signal-mask address
syscallWaitForEventsWithSignalMask(epoll, events, maxevents, timeout, sigmask)epoll_pwaitas above; Lynxer supplies the signal-set size
syscallWaitForEvents2(epoll, events, maxevents, timeout, sigmask, size)epoll_pwait2nanosecond timeout
syscallCreateEventFileDescriptor(initval, flags)eventfd2initial counter, flags
syscallInitializeInodeNotifications(flags)inotify_init1IN_NONBLOCK/IN_CLOEXEC flags
syscallAddInodeNotificationWatch(inotify, path, mask)inotify_add_watchinotify descriptor, path address, event mask
syscallRemoveInodeNotificationWatch(inotify, watch)inotify_rm_watchinotify descriptor, watch descriptor

System information and resources

Built-inLinux syscallArguments
syscallGetSystemInformation(info)sysinfosysinfo structure address
syscallGetUnixSystemName(name)unameutsname structure address
syscallGetSystemTimes(buffer)timestms structure address (or 0)
syscallGetResourceUsage(who, usage)getrusageRUSAGE_* selector, usage structure address
syscallGetResourceLimit(resource, limit)getrlimitRLIMIT_* selector, rlimit structure address
syscallSetResourceLimit(resource, limit)setrlimitRLIMIT_* selector, rlimit structure address
syscallGetCapabilities(header, data)capgetcapability header and data addresses
syscallSetCapabilities(header, data)capsetcapability header and data addresses
syscallControlProcess(option, arg2, arg3, arg4, arg5)prctlPR_* option and option-specific arguments

Async I/O (io_uring)

Raw passthrough; build the io_uring_params and submission structures in native memory and pass their addresses. Available on both architectures.

Built-inLinux syscallArguments
syscallSetupIoUring(entries, params)io_uring_setupring entries, io_uring_params address
syscallEnterIoUring(fd, to_submit, min_complete, flags, sig, sigsz)io_uring_enterring descriptor and submission arguments
syscallRegisterIoUring(fd, opcode, arg, nr_args)io_uring_registerring descriptor, opcode, argument, count

Sandboxing (Landlock and seccomp)

Raw passthrough. The seccomp syscall is unguarded: operation 0 installs SECCOMP_MODE_STRICT, which terminates a process that issues anything outside its tiny allowlist.

Built-inLinux syscallArguments
syscallCreateLandlockRuleset(attr, size, flags)landlock_create_rulesetruleset attribute address, size, flags
syscallAddLandlockRule(ruleset, type, attr, flags)landlock_add_ruleruleset descriptor, rule type, rule attribute address, flags
syscallRestrictLandlockSelf(ruleset, flags)landlock_restrict_selfruleset descriptor, flags
syscallControlSeccomp(operation, flags, args)seccompoperation, flags, filter address

Fixtures

See also