Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Docker/Dockerfile.e2e
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ RUN rustup component add rust-src --toolchain nightly-2026-02-11-x86_64-unknown-
# Build lind-boot
FROM base as build-lind-boot
# NOTE: Using 'make' risks cache invalidation on unrelated Makefile changes
COPY --parents src/lind-boot src/wasmtime src/rawposix src/cage src/threei src/typemap src/fdtables src/sysdefs Makefile rust-toolchain.toml .
COPY --parents src/lind-boot src/wasmtime src/rawposix src/cage src/threei src/typemap src/fdtables src/sysdefs src/glibc scripts Makefile rust-toolchain.toml .
RUN rm -f src/wasmtime/crates/cage \
src/wasmtime/crates/threei \
src/wasmtime/crates/fdtables \
Expand All @@ -126,7 +126,7 @@ FROM base AS build-glibc
# NOTE: Using 'make' risks cache invalidation on unrelated Makefile changes
COPY scripts ./scripts
COPY tools ./tools
COPY --parents src/glibc Makefile .
COPY --parents src/glibc src/sysdefs Makefile .
COPY --from=build-lind-boot --parents build/lind-boot .
RUN make sysroot \
&& test -f lindfs/lib/libc.cwasm \
Expand Down
15 changes: 10 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ LINDFS_DIRS := \
WITH_FPCAST ?=

.PHONY: build
build: lindfs lind-boot sysroot
build: generate-syscall-mappings lindfs lind-boot sysroot
@echo "Build complete"

.PHONY: all
all: build

.PHONY: sysroot
sysroot: build-dir
sysroot: build-dir generate-syscall-mappings
./scripts/make_glibc_and_sysroot.sh $(if $(WITH_FPCAST),--with-fpcast)
$(MAKE) sync-sysroot

.PHONY: lind-boot
lind-boot: build-dir
lind-boot: build-dir generate-syscall-mappings
# Build lind-boot with `--release` flag for faster runtime (e.g. for tests)
cargo build --manifest-path src/lind-boot/Cargo.toml --release
cp src/lind-boot/target/release/lind-boot $(LINDBOOT_BIN)
Expand All @@ -50,14 +50,15 @@ lindfs:
cp -rT scripts/lindfs-conf/usr/share/zoneinfo $(LINDFS_ROOT)/usr/share/zoneinfo

.PHONY: lind-debug
lind-debug: lindfs build-dir
lind-debug: lindfs build-dir generate-syscall-mappings
# Build lind-boot with the lind_debug feature enabled
cargo build --manifest-path src/lind-boot/Cargo.toml --features lind_debug
cp src/lind-boot/target/debug/lind-boot $(LINDBOOT_BIN)

# Build glibc with LIND_DEBUG enabled (by setting the LIND_DEBUG variable)
$(MAKE) build_glibc LIND_DEBUG=1
build_glibc:

build_glibc: generate-syscall-mappings
# build sysroot passing -DLIND_DEBUG if LIND_DEBUG is set
if [ "$(LIND_DEBUG)" = "1" ]; then \
echo "Building glibc with LIND_DEBUG enabled"; \
Expand All @@ -69,6 +70,10 @@ build_glibc:
build-dir:
mkdir -p $(BUILD_DIR)

.PHONY: generate-syscall-mappings
generate-syscall-mappings: build-dir
python3 scripts/generate_syscall_mappings.py

.PHONY: sync-sysroot
sync-sysroot:
$(RM) -r $(SYSROOT_DIR)
Expand Down
1 change: 1 addition & 0 deletions docs/contribute/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ docker run --platform=linux/amd64 -v $(PWD):/lind -w /lind -it dev /bin/bash
5. Build toolchain (glibc and wasmtime)
```
# this may take a while ...
make generate-syscall-mappings
make lind-boot sysroot
```
6. Run the test suite
Expand Down
19 changes: 15 additions & 4 deletions docs/contribute/toolchain.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,18 @@ options.
Matching builtins are available in the *lind-wasm* repo under
[`src/glibc/wasi`](https://github.com/Lind-Project/lind-wasm/tree/main/src/glibc/wasi).

3. __Build *glibc* and generate sysroot__ (see [`make sysroot`](https://github.com/Lind-Project/lind-wasm/blob/main/Makefile))
3. __Generate syscall mappings__ (see [`make generate-syscall-mappings`](https://github.com/Lind-Project/lind-wasm/blob/main/Makefile))

Auto-generates syscall mapping constants from `src/glibc/lind_syscall/lind_syscall_num.h`
and produces `src/sysdefs/src/constants/syscall_const.rs`. This must run before building *lind-boot*, *glibc* and *wasmtime* to ensure Rust code has the correct syscall definitions.

```bash
python3 scripts/generate_syscall_mappings.py
```

The source of truth is the Linux x86_64 syscall table as defined in the *glibc* header file.

4. __Build *glibc* and generate sysroot__ (see [`make sysroot`](https://github.com/Lind-Project/lind-wasm/blob/main/Makefile))
1. Configure and compile *glibc* for the *WASI* target with *Clang*

2. Compile extra files:
Expand All @@ -51,10 +62,10 @@ options.
along with headers and a pre-built C runtime into a
sysroot directory structure as required by *Clang*.

4. __Build custom wasmtime__ (see [`make wasmtime`](https://github.com/Lind-Project/lind-wasm/blob/main/Makefile))
5. __Build lind-boot__ (see [`make lind-boot`](https://github.com/Lind-Project/lind-wasm/blob/main/Makefile))

Builds `src/wasmtime` workspace. Custom dependencies `fdtables`, `RawPOSIX`
and `sysdefs` are included in the build automatically.
Builds `src/lind-boot` workspace, which provides the *WebAssembly* runtime (`wasmtime`).
Custom dependencies `fdtables`, `RawPOSIX` and `sysdefs` are included in the build automatically.


A customized `wasm-opt` binary is included in the *lind-wasm* repo under
Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ EOF

Lind-wasm runtime must be compiled before running the program. To compile the lind-wasm runtime, you will first go to the `lind-wasm/` directory. At there, you can choose:

3.a. use `make all` to compile both lind-glibc and rust code at once.
3.a. use `make all` to compile both lind-glibc and rust code at once. (this automatically generates syscall mappings)

3.b. use `make lind-boot` to compile runtime(lind-boot/wasmtime/rawposix/3i/etc.), and `make sysroot` to compile lind-glibc.
3.b. use `make generate-syscall-mappings` to auto-generate system call constants. Then use `make lind-boot` to compile runtime(lind-boot/wasmtime/rawposix/3i/etc.), and `make sysroot` to compile lind-glibc.

**NOTES: More options can be found in lind-wasm/Makefile**

Expand Down
103 changes: 103 additions & 0 deletions scripts/generate_syscall_mappings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python3
# Auto-generates syscall mapping constants for lind-wasm.
#
# Reads syscall definitions from glibc's lind_syscall_num.h and generates:
# - src/sysdefs/src/constants/syscall_const.rs (full set of syscalls)
#
# This script should be run before building lind-boot and glibc.
#
# Source of truth: src/glibc/lind_syscall/lind_syscall_num.h

from __future__ import annotations

import re
import sys
from pathlib import Path


def parse_c_header(header_path: str) -> dict[str, int]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems not including lind specific syscall num?

"""Parse syscall constants from glibc's lind_syscall_num.h header file."""
syscalls = {}

try:
with open(header_path) as f:
content = f.read()
except FileNotFoundError:
print(f"Error: Could not find {header_path}", file=sys.stderr)
sys.exit(1)

# Match #define SYSCALL_NAME number
pattern = r'#define\s+(\w+)\s+(\d+)'

for match in re.finditer(pattern, content):
name, number = match.groups()
syscalls[name] = int(number)

if not syscalls:
print(f"Error: Could not parse any syscalls from {header_path}", file=sys.stderr)
sys.exit(1)

return syscalls


def generate_rust_constants(syscalls: dict[str, int]) -> str:
"""Generate Rust constants for sysdefs/constants/syscall_const.rs."""
lines = [
"//! Syscall number constants for the Lind platform.",
"//!",
"//! Includes both standard Linux x86_64 syscalls and Lind-specific extensions:",
"//! - REGISTER_HANDLER_SYSCALL (1001)",
"//! - COPY_DATA_BETWEEN_CAGES_SYSCALL (1002)",
"//! - COPY_HANDLER_TABLE_TO_CAGE_SYSCALL (1003)",
"//!",
"//! Source of truth: Linux x86_64 syscall table",
"//! https://github.com/torvalds/linux/blob/v6.16-rc1/arch/x86/entry/syscalls/syscall_64.tbl",
"//! (Historical overview: https://filippo.io/linux-syscall-table/)",
"//!",
"//! Keep these in sync with glibc's lind_syscall_num.h and RawPOSIX dispatcher.",
"",
]

# Sort by syscall number for readability
sorted_syscalls = sorted(syscalls.items(), key=lambda x: x[1])

for name, number in sorted_syscalls:
lines.append(f"pub const {name}: i32 = {number};")

lines.append("")
return "\n".join(lines)





def write_file(path: str, content: str) -> None:
"""Write content to file, creating directories if needed."""
Path(path).parent.mkdir(parents=True, exist_ok=True)
with open(path, 'w') as f:
f.write(content)
print(f"Generated: {path}")


def main() -> None:
"""Generate syscall mapping constants from glibc header."""
# Find workspace root (should be run from lind-wasm directory)
workspace_root = Path(__file__).parent.parent

c_header = workspace_root / "src/glibc/lind_syscall/lind_syscall_num.h"
rust_sysdefs_out = workspace_root / "src/sysdefs/src/constants/syscall_const.rs"

print("Parsing syscall definitions...")
syscalls = parse_c_header(str(c_header))
print(f"Found {len(syscalls)} syscall definitions")

# Generate Rust constants for sysdefs
print("\nGenerating sysdefs constants...")
rust_content = generate_rust_constants(syscalls)
write_file(str(rust_sysdefs_out), rust_content)

print("Done!")


if __name__ == "__main__":
main()
9 changes: 4 additions & 5 deletions src/glibc/lind_syscall/lind_syscall_num.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
#define WRITE_SYSCALL 1
#define OPEN_SYSCALL 2
#define CLOSE_SYSCALL 3
#define XSTAT_SYSCALL 4
#define FXSTAT_SYSCALL 5
#define STAT_SYSCALL 4
#define FSTAT_SYSCALL 5
#define LSTAT_SYSCALL 6

#define POLL_SYSCALL 7
Expand Down Expand Up @@ -46,7 +46,7 @@
#define DUP_SYSCALL 32
#define DUP2_SYSCALL 33

#define NANOSLEEP_TIME64_SYSCALL 35
#define NANOSLEEP_SYSCALL 35

#define SETITIMER_SYSCALL 38
#define GETPID_SYSCALL 39
Expand All @@ -69,7 +69,6 @@
#define CLONE_SYSCALL 56
#define FORK_SYSCALL 57
#define EXEC_SYSCALL 59
#define EXECVE_SYSCALL 59
#define EXIT_SYSCALL 60
#define EXIT_GROUP_SYSCALL 231
#define WAITPID_SYSCALL 61
Expand Down Expand Up @@ -119,7 +118,7 @@
#define SYMLINKAT_SYSCALL 266
#define READLINKAT_SYSCALL 267
#define PPOLL_SYSCALL 271
#define SYNC_FILE_RANGE 277
#define SYNC_FILE_RANGE_SYSCALL 277
#define ACCEPT4_SYSCALL 288
#define EPOLL_CREATE1_SYSCALL 291
#define DUP3_SYSCALL 292
Expand Down
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/clock_nanosleep.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ __clock_nanosleep_time64 (clockid_t clock_id, int flags,
uint64_t host_req = TRANSLATE_GUEST_POINTER_TO_HOST (req);
uint64_t host_rem = TRANSLATE_GUEST_POINTER_TO_HOST (rem);
return MAKE_LEGACY_SYSCALL (
NANOSLEEP_TIME64_SYSCALL, "syscall|nanosleep", (uint64_t) clock_id,
NANOSLEEP_SYSCALL, "syscall|nanosleep", (uint64_t) clock_id,
(uint64_t) flags, host_req, host_rem, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/fstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ __fstat (int fd, struct stat *buf)

uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);

return MAKE_LEGACY_SYSCALL (FXSTAT_SYSCALL, "syscall|fstat", (uint64_t) fd,
return MAKE_LEGACY_SYSCALL (FSTAT_SYSCALL, "syscall|fstat", (uint64_t) fd,
host_buf, NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}

Expand Down
4 changes: 2 additions & 2 deletions src/glibc/sysdeps/unix/sysv/linux/fstat64.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
int
__fstat64_time64 (int fd, struct __stat64_t64 *buf)
{
return MAKE_LEGACY_SYSCALL(FXSTAT_SYSCALL, "syscall|fstat", (uint64_t)fd, (uint64_t) TRANSLATE_GUEST_POINTER_TO_HOST(buf), NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
return MAKE_LEGACY_SYSCALL(FSTAT_SYSCALL, "syscall|fstat", (uint64_t)fd, (uint64_t) TRANSLATE_GUEST_POINTER_TO_HOST(buf), NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
#if __TIMESIZE != 64
hidden_def (__fstat64_time64)
Expand All @@ -45,7 +45,7 @@ hidden_def (__fstat64_time64)
}
// Added MAKE_SYSCALL macro to interface with Lind - Qianxi Chen
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (FXSTAT_SYSCALL, "syscall|fstat", (uint64_t) fd,
return MAKE_LEGACY_SYSCALL (FSTAT_SYSCALL, "syscall|fstat", (uint64_t) fd,
host_buf, NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/fxstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int
__fxstat (int vers, int fd, struct stat *buf)
{
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (FXSTAT_SYSCALL, "syscall|fxstat", (uint64_t) vers,
return MAKE_LEGACY_SYSCALL (FSTAT_SYSCALL, "syscall|fstat", (uint64_t) vers,
(uint64_t) fd, host_buf,
NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand Down
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/fxstat64.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ int
___fxstat64 (int vers, int fd, struct stat64 *buf)
{
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (FXSTAT_SYSCALL, "syscall|fxstat", (uint64_t) vers,
return MAKE_LEGACY_SYSCALL (FSTAT_SYSCALL, "syscall|fstat", (uint64_t) vers,
(uint64_t) fd, host_buf,
NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand Down
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/i386/execve.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ int __execve (const char *__path, char *const __argv[], char *const __envp[])
uint64_t host_argv_ptr = TRANSLATE_GUEST_POINTER_TO_HOST(host_argv);
uint64_t host_envp_ptr = TRANSLATE_GUEST_POINTER_TO_HOST(host_envp);

return MAKE_LEGACY_SYSCALL(EXECVE_SYSCALL, "syscall|execve", host_path, host_argv_ptr, host_envp_ptr, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
return MAKE_LEGACY_SYSCALL(EXEC_SYSCALL, "syscall|execve", host_path, host_argv_ptr, host_envp_ptr, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
strong_alias (__execve, execve)
libc_hidden_def (__execve)
6 changes: 3 additions & 3 deletions src/glibc/sysdeps/unix/sysv/linux/lstat64.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ int
__lstat64_time64 (const char *file, struct __stat64_t64 *buf)
{
// BUG: we do not have fstatat syscall in rawposix
// so let's just use xstat - Qianxi Chen
// so let's just use stat - Qianxi Chen
uint64_t host_file = TRANSLATE_GUEST_POINTER_TO_HOST (file);
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (XSTAT_SYSCALL, "syscall|xstat",
return MAKE_LEGACY_SYSCALL (STAT_SYSCALL, "syscall|stat",
host_file, host_buf,
NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand All @@ -45,7 +45,7 @@ __lstat64 (const char *file, struct stat64 *buf)
{
uint64_t host_file = TRANSLATE_GUEST_POINTER_TO_HOST (file);
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (XSTAT_SYSCALL, "syscall|xstat",
return MAKE_LEGACY_SYSCALL (STAT_SYSCALL, "syscall|stat",
host_file, host_buf,
NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand Down
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/stat.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ __stat (const char *fd, struct stat *buf)
uint64_t host_fd = TRANSLATE_GUEST_POINTER_TO_HOST (fd);
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);

return MAKE_LEGACY_SYSCALL (XSTAT_SYSCALL, "syscall|xstat",
return MAKE_LEGACY_SYSCALL (STAT_SYSCALL, "syscall|stat",
host_fd, host_buf,
NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand Down
6 changes: 3 additions & 3 deletions src/glibc/sysdeps/unix/sysv/linux/stat64.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ int
__stat64_time64 (const char *file, struct __stat64_t64 *buf)
{
// BUG: we do not have fstatat syscall in rawposix
// so let's just use xstat - Qianxi Chen
// so let's just use stat - Qianxi Chen
uint64_t host_file = TRANSLATE_GUEST_POINTER_TO_HOST (file);
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (XSTAT_SYSCALL, "syscall|xstat",
return MAKE_LEGACY_SYSCALL (STAT_SYSCALL, "syscall|stat",
host_file, host_buf,
NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand All @@ -45,7 +45,7 @@ __stat64 (const char *file, struct stat64 *buf)
{
uint64_t host_file = TRANSLATE_GUEST_POINTER_TO_HOST (file);
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (XSTAT_SYSCALL, "syscall|xstat",
return MAKE_LEGACY_SYSCALL (STAT_SYSCALL, "syscall|stat",
host_file, host_buf,
NOTUSED, NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand Down
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/sync_file_range.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@
int
sync_file_range (int fd, __off64_t offset, __off64_t len, unsigned int flags)
{
return MAKE_LEGACY_SYSCALL(SYNC_FILE_RANGE, "syscall|sync_file_range", (uint64_t) fd, (uint64_t) offset, (uint64_t) len, (uint64_t) flags, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
return MAKE_LEGACY_SYSCALL(SYNC_FILE_RANGE_SYSCALL, "syscall|sync_file_range", (uint64_t) fd, (uint64_t) offset, (uint64_t) len, (uint64_t) flags, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
2 changes: 1 addition & 1 deletion src/glibc/sysdeps/unix/sysv/linux/xstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ __xstat (int vers, const char *name, struct stat *buf)
{
uint64_t host_name = TRANSLATE_GUEST_POINTER_TO_HOST (name);
uint64_t host_buf = TRANSLATE_GUEST_POINTER_TO_HOST (buf);
return MAKE_LEGACY_SYSCALL (XSTAT_SYSCALL, "syscall|xstat", (uint64_t) vers,
return MAKE_LEGACY_SYSCALL (STAT_SYSCALL, "syscall|stat", (uint64_t) vers,
host_name, host_buf,
NOTUSED, NOTUSED, NOTUSED, TRANSLATE_ERRNO_ON);
}
Expand Down
Loading