authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-06-17 07:18:25+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-06-17 07:22:07+02:00
log3f956f98903214a6a79a123d62c4084ea3ba49f9
tree84639c6497a69dd67debd86e4f63e60e4b02b7a1
parente74fd3ce555c675235fa65fa3647caeb4757b4cd
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.os.linux: fix lseek() for x32/n32

This is the one syscall that returns a u64 despite usize == u32 in these ABIs. Rather than huge API churn for all return types in std.os.linux just to benefit these incredibly niche ABIs, just special-case this particular syscall, as we do with a few others depending on arch.

3 files changed, 44 insertions(+), 3 deletions(-)

lib/std/os/linux.zig+11-3
......@@ -80,6 +80,7 @@ pub const restore_rt = syscall_bits.restore_rt;
8080pub const socketcall = syscall_bits.socketcall;
8181pub const syscall_pipe = syscall_bits.syscall_pipe;
8282pub const syscall_fork = syscall_bits.syscall_fork;
83pub const syscall_lseek = syscall_bits.syscall_lseek;
8384
8485pub fn clone(
8586 func: *const fn (arg: usize) callconv(.c) u8,
......@@ -1809,7 +1810,7 @@ pub fn fchmodat2(fd: fd_t, path: [*:0]const u8, mode: mode_t, flags: u32) usize
18091810}
18101811
18111812/// Can only be called on 32 bit systems. For 64 bit see `lseek`.
1812pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize {
1813pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) u32 {
18131814 // NOTE: The offset parameter splitting is independent from the target
18141815 // endianness.
18151816 return syscall5(
......@@ -1823,8 +1824,15 @@ pub fn llseek(fd: fd_t, offset: off_t, result: ?*off_t, whence: u32) usize {
18231824}
18241825
18251826/// Can only be called on 64 bit systems. For 32 bit see `llseek`.
1826pub fn lseek(fd: fd_t, offset: off_t, whence: u32) usize {
1827 return syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence);
1827pub fn lseek(fd: fd_t, offset: off_t, whence: u32) u64 {
1828 return switch (builtin.abi) {
1829 .gnuabin32,
1830 .muslabin32,
1831 .gnux32,
1832 .muslx32,
1833 => syscall_lseek(fd, offset, whence),
1834 else => syscall3(.lseek, @as(u32, @bitCast(fd)), @as(u64, @bitCast(offset)), whence),
1835 };
18281836}
18291837
18301838pub fn exit(status: i32) noreturn {
lib/std/os/linux/mipsn32.zig+19
......@@ -163,6 +163,25 @@ pub fn syscall_pipe(
163163 : .{ .r1 = true, .r3 = true, .r5 = true, .r6 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
164164}
165165
166pub fn syscall_lseek(
167 fd: std.os.linux.fd_t,
168 offset: std.os.linux.off_t,
169 whence: u32,
170) u64 {
171 return asm volatile (
172 \\ syscall
173 \\ beq $a3, $zero, 1f
174 \\ blez $v0, 1f
175 \\ dsubu $v0, $zero, $v0
176 \\1:
177 : [ret] "={$2}" (-> u64),
178 : [number] "{$2}" (@intFromEnum(SYS.lseek)),
179 [fd] "{$4}" (@as(u32, @bitCast(fd))),
180 [offset] "{$5}" (@as(u64, @bitCast(offset))),
181 [whence] "{$6}" (whence),
182 : .{ .r1 = true, .r3 = true, .r7 = true, .r8 = true, .r9 = true, .r10 = true, .r11 = true, .r12 = true, .r13 = true, .r14 = true, .r15 = true, .r24 = true, .r25 = true, .hi = true, .lo = true, .memory = true });
183}
184
166185pub fn clone() callconv(.naked) u32 {
167186 // __clone(func, stack, flags, arg, ptid, tls, ctid)
168187 // a0, a1, a2, a3, a4, a5, a6
lib/std/os/linux/x32.zig+14
......@@ -109,6 +109,20 @@ pub fn syscall6(
109109 : .{ .rcx = true, .r11 = true, .memory = true });
110110}
111111
112pub fn syscall_lseek(
113 fd: std.os.linux.fd_t,
114 offset: std.os.linux.off_t,
115 whence: u32,
116) u64 {
117 return asm volatile ("syscall"
118 : [ret] "={rax}" (-> u64),
119 : [number] "{rax}" (@intFromEnum(SYS.lseek)),
120 [fd] "{rdi}" (@as(u32, @bitCast(fd))),
121 [offset] "{rsi}" (@as(u64, @bitCast(offset))),
122 [whence] "{rdx}" (whence),
123 : .{ .rcx = true, .r11 = true, .memory = true });
124}
125
112126pub fn clone() callconv(.naked) u32 {
113127 asm volatile (
114128 \\ movl $0x40000038,%%eax // SYS_clone