╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ generate_linux_syscalls.zig ──────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
117 if (!abi_match) return null; 118 119 var num = std.fmt.parseInt(u32, num_str, 10) catch @panic("Bad syscall number"); 120 num += self.offset; 121 122 return .{ name, num }; 123 } 124 }; 125 126 const architectures: []const Arch = &.{ 127 .{ .@"var" = "X86", .table = .{ .specific = "arch/x86/entry/syscalls/syscall_32.tbl" } }, 128 .{ .@"var" = "X64", .table = .{ .specific = "arch/x86/entry/syscalls/syscall_64.tbl" }, .abi = &.{ .common, .@"64" } }, 129 .{ .@"var" = "X32", .table = .{ .specific = "arch/x86/entry/syscalls/syscall_64.tbl" }, .abi = &.{ .common, .x32 }, .offset = __X32_SYSCALL_BIT }, 130 .{ 131 .@"var" = "Arm", 132 .table = .{ .specific = "arch/arm/tools/syscall.tbl" }, 133 .abi = &.{ .common, .eabi }, 134 // These values haven't been brought over from `arch/arm/include/uapi/asm/unistd.h`, 135 // so we are forced to add them ourselves. 136 .header = " const arm_base = 0x0f0000;\n\n", 137 .footer = 138 \\ 139 \\ breakpoint = arm_base + 1, 140 \\ cacheflush = arm_base + 2, 141 \\ usr26 = arm_base + 3, 142 \\ usr32 = arm_base + 4, 143 \\ set_tls = arm_base + 5, 144 \\ get_tls = arm_base + 6, 145 \\ 146 , 147 }, 148 .{ .@"var" = "Sparc", .table = .{ .specific = "arch/sparc/kernel/syscalls/syscall.tbl" }, .abi = &.{ .common, .@"32" } }, 149 .{ .@"var" = "Sparc64", .table = .{ .specific = "arch/sparc/kernel/syscalls/syscall.tbl" }, .abi = &.{ .common, .@"64" } }, 150 .{ .@"var" = "M68k", .table = .{ .specific = "arch/m68k/kernel/syscalls/syscall.tbl" } }, 151 // For Mips, the abi for these tables is always o32/n64/n32. 152 .{ .@"var" = "MipsO32", .table = .{ .specific = "arch/mips/kernel/syscalls/syscall_o32.tbl" }, .offset = __NR_Linux_O32 }, 153 .{ .@"var" = "MipsN64", .table = .{ .specific = "arch/mips/kernel/syscalls/syscall_n64.tbl" }, .offset = __NR_Linux_N64 }, 154 .{ .@"var" = "MipsN32", .table = .{ .specific = "arch/mips/kernel/syscalls/syscall_n32.tbl" }, .offset = __NR_Linux_N32 }, 155 .{ .@"var" = "PowerPC", .table = .{ .specific = "arch/powerpc/kernel/syscalls/syscall.tbl" }, .abi = &.{ .common, .@"32", .nospu } }, 156 .{ .@"var" = "PowerPC64", .table = .{ .specific = "arch/powerpc/kernel/syscalls/syscall.tbl" }, .abi = &.{ .common, .@"64", .nospu } }, 157 .{ .@"var" = "S390x", .table = .{ .specific = "arch/s390/kernel/syscalls/syscall.tbl" }, .abi = &.{ .common, .@"64" } }, 158 .{ .@"var" = "Xtensa", .table = .{ .specific = "arch/xtensa/kernel/syscalls/syscall.tbl" } }, 159 .{ .@"var" = "Alpha", .table = .{ .specific = "arch/alpha/kernel/syscalls/syscall.tbl" } }, 160 .{ .@"var" = "Arm64", .table = .generic, .abi = &.{ .common, .@"64", .renameat, .rlimit, .memfd_secret } }, 161 .{ .@"var" = "RiscV32", .table = .generic, .abi = &.{ .common, .@"32", .riscv, .memfd_secret } }, 162 .{ .@"var" = "RiscV64", .table = .generic, .abi = &.{ .common, .@"64", .riscv, .rlimit, .memfd_secret } }, 163 .{ .@"var" = "LoongArch32", .table = .generic, .abi = &.{ .common, .@"32" } }, 164 .{ .@"var" = "LoongArch64", .table = .generic, .abi = &.{ .common, .@"64" } }, 165 .{ .@"var" = "Arc", .table = .generic, .abi = &.{ .common, .@"32", .arc, .time32, .renameat, .stat64, .rlimit } }, 166 .{ .@"var" = "CSky", .table = .generic, .abi = &.{ .common, .@"32", .csky, .time32, .stat64, .rlimit } }, 167 .{ .@"var" = "Hexagon", .table = .generic, .abi = &.{ .common, .@"32", .hexagon, .time32, .stat64, .rlimit, .renameat } }, 168 .{ .@"var" = "OpenRisc", .table = .generic, .abi = &.{ .common, .@"32", .or1k, .time32, .stat64, .rlimit, .renameat } }, 169 .{ .@"var" = "Hppa", .table = .{ .specific = "arch/parisc/kernel/syscalls/syscall.tbl" }, .abi = &.{ .common, .@"32" } }, 170 .{ .@"var" = "Hppa64", .table = .{ .specific = "arch/parisc/kernel/syscalls/syscall.tbl" }, .abi = &.{ .common, .@"64" } }, 171 .{ .@"var" = "Sh", .table = .{ .specific = "arch/sh/kernel/syscalls/syscall.tbl" } }, 172 .{ .@"var" = "Microblaze", .table = .{ .specific = "arch/microblaze/kernel/syscalls/syscall.tbl" } }, 173 }; 174 175 pub fn main(init: std.process.Init) !void { 176 const gpa = init.gpa; 177 const io = init.io; 178 179 const args = try init.minimal.args.toSlice(init.arena.allocator()); 180 if (args.len < 2 or mem.eql(u8, args[1], "--help")) { 181 const stderr = std.debug.lockStderr(&.{}); 182 const w = &stderr.file_writer.interface; 183 usage(w, args[0]) catch std.process.exit(2); 184 std.process.exit(1); 185 } 186 const linux_path = args[1]; 187 188 var stdout_buffer: [2048]u8 = undefined; 189 var stdout_writer = Io.File.stdout().writerStreaming(io, &stdout_buffer); 190 const stdout = &stdout_writer.interface; 191 192 var linux_dir = try Io.Dir.cwd().openDir(io, linux_path, .{}); 193 defer linux_dir.close(io); 194 195 // As of 6.11, the largest table is 24195 bytes. 196 // 32k should be enough for now. 197 const buf = try gpa.alloc(u8, 1 << 15); 198 defer gpa.free(buf); 199 200 // Fetch the kernel version from the Makefile variables. 201 const version = blk: { 202 const head = try linux_dir.readFile(io, "Makefile", buf[0..128]); 203 var lines = mem.tokenizeScalar(u8, head, '\n'); 204 _ = lines.next(); // Skip SPDX identifier 205 206 var ver = mem.zeroes(std.SemanticVersion); 207 inline for (.{ "major", "minor", "patch" }, .{ "VERSION", "PATCHLEVEL", "SUBLEVEL" }) |field, make_var| { 208 const line = lines.next() orelse @panic("Bad line"); 209 const offset = (make_var ++ " = ").len; 210 @field(ver, field) = try std.fmt.parseInt(usize, line[offset..], 10); 211 } 212 213 break :blk ver; 214 }; 215 216 try Io.Writer.print(stdout, 217 \\// This file is automatically generated by tools/generate_linux_syscalls.zig 218 \\// This list current as of kernel: {f} 219 \\ 220 \\ 221 , .{version}); 222 223 for (architectures, 0..) |arch, i| { 224 const table = try linux_dir.readFile(io, switch (arch.table) { 225 .generic => "scripts/syscall.tbl", 226 .specific => |f| f, 227 }, buf); 228 229 try Io.Writer.print(stdout, "pub const {s} = enum(usize) {{\n", .{arch.@"var"}); 230 if (arch.header) |h| 231 try Io.Writer.writeAll(stdout, h); 232 233 var lines = mem.tokenizeScalar(u8, table, '\n'); 234 while (lines.next()) |line| { 235 if (line[0] == '#') continue; 236 if (arch.get(line)) |res| { 237 const name, const num = res; 238 const final_name = stdlib_renames.get(name) orelse name; 239 try Io.Writer.print(stdout, " {f} = {d},\n", .{ std.zig.fmtId(final_name), num }); 240 } 241 } 242 243 if (arch.footer) |f| 244 try Io.Writer.writeAll(stdout, f); 245 try Io.Writer.writeAll(stdout, "};\n"); 246 if (i != architectures.len - 1) 247 try Io.Writer.writeByte(stdout, '\n'); 248 } 249 250 try Io.Writer.flush(stdout); 251 } 252 253 fn usage(w: *std.Io.Writer, arg0: []const u8) std.Io.Writer.Error!void { 254 try w.print( 255 \\Usage: {s} /path/to/linux 256 \\Alternative Usage: zig run /path/to/git/zig/tools/generate_linux_syscalls.zig -- /path/to/linux 257 \\ 258 \\Generates the list of Linux syscalls for each supported cpu arch, using the Linux development tree. 259 \\Prints to stdout Zig code which you can use to replace the file lib/std/os/linux/syscalls.zig. 260 \\ 261 , .{arg0}); 262 } 263