diff options
| author | LemonBoy <thatlemon@gmail.com> | 2020-11-02 12:11:07 +0100 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2020-11-02 12:11:07 +0100 |
| commit | dc872a221d8301cfac4b9ead09196c5b18cf63b2 (patch) | |
| tree | ccd12100a4a4de5758e5eaf28e31b654e14c0631 /lib | |
| parent | 76e9a4ae8377a9329170b038ce7b393db0402862 (diff) | |
| download | zig-dc872a221d8301cfac4b9ead09196c5b18cf63b2.tar.gz zig-dc872a221d8301cfac4b9ead09196c5b18cf63b2.zip | |
std: Fix syscall stubs passing 64bit offsets for BE targets
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/std/io/test.zig | 3 | ||||
| -rw-r--r-- | lib/std/os/linux.zig | 68 |
2 files changed, 46 insertions, 25 deletions
diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig index ecad26a448..ad519a9199 100644 --- a/lib/std/io/test.zig +++ b/lib/std/io/test.zig @@ -140,9 +140,6 @@ test "File seek ops" { } test "setEndPos" { - // https://github.com/ziglang/zig/issues/5127 - if (std.Target.current.cpu.arch == .mips) return error.SkipZigTest; - var tmp = tmpDir(.{}); defer tmp.cleanup(); diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 96e8a5edf4..c5fbd0bcfe 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -48,13 +48,27 @@ pub fn getauxval(index: usize) usize { return 0; } -// Some architectures require 64bit parameters for some syscalls to be passed in -// even-aligned register pair +// Some architectures (and some syscalls) require 64bit parameters to be passed +// in a even-aligned register pair. const require_aligned_register_pair = // std.Target.current.cpu.arch.isMIPS() or std.Target.current.cpu.arch.isARM() or std.Target.current.cpu.arch.isThumb(); +// Split a 64bit value into a {LSB,MSB} pair. +fn splitValue64(val: u64) [2]u32 { + switch (builtin.endian) { + .Little => return [2]u32{ + @truncate(u32, val), + @truncate(u32, val >> 32), + }, + .Big => return [2]u32{ + @truncate(u32, val >> 32), + @truncate(u32, val), + }, + } +} + /// Get the errno from a syscall return value, or 0 for no error. pub fn getErrno(r: usize) u12 { const signed_r = @bitCast(isize, r); @@ -263,24 +277,26 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { } pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { + const offset_halves = splitValue64(offset); return syscall5( .preadv, @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], ); } pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: kernel_rwf) usize { + const offset_halves = splitValue64(offset); return syscall6( .preadv2, @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], flags, ); } @@ -294,24 +310,26 @@ pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { } pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { + const offset_halves = splitValue64(offset); return syscall5( .pwritev, @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], ); } pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64, flags: kernel_rwf) usize { + const offset_halves = splitValue64(offset); return syscall6( .pwritev2, @bitCast(usize, @as(isize, fd)), @ptrToInt(iov), count, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], flags, ); } @@ -338,6 +356,7 @@ pub fn symlinkat(existing: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) us pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { if (@hasField(SYS, "pread64")) { + const offset_halves = splitValue64(offset); if (require_aligned_register_pair) { return syscall6( .pread64, @@ -345,8 +364,8 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { @ptrToInt(buf), count, 0, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], ); } else { return syscall5( @@ -354,8 +373,8 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], ); } } else { @@ -401,20 +420,21 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { pub fn ftruncate(fd: i32, length: u64) usize { if (@hasField(SYS, "ftruncate64")) { + const length_halves = splitValue64(length); if (require_aligned_register_pair) { return syscall4( .ftruncate64, @bitCast(usize, @as(isize, fd)), 0, - @truncate(usize, length), - @truncate(usize, length >> 32), + length_halves[0], + length_halves[1], ); } else { return syscall3( .ftruncate64, @bitCast(usize, @as(isize, fd)), - @truncate(usize, length), - @truncate(usize, length >> 32), + length_halves[0], + length_halves[1], ); } } else { @@ -428,6 +448,8 @@ pub fn ftruncate(fd: i32, length: u64) usize { pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { if (@hasField(SYS, "pwrite64")) { + const offset_halves = splitValue64(offset); + if (require_aligned_register_pair) { return syscall6( .pwrite64, @@ -435,8 +457,8 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { @ptrToInt(buf), count, 0, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], ); } else { return syscall5( @@ -444,8 +466,8 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count, - @truncate(usize, offset), - @truncate(usize, offset >> 32), + offset_halves[0], + offset_halves[1], ); } } else { @@ -540,6 +562,8 @@ pub fn close(fd: i32) usize { /// Can only be called on 32 bit systems. For 64 bit see `lseek`. pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { + // NOTE: The offset parameter splitting is independent from the target + // endianness. return syscall5( ._llseek, @bitCast(usize, @as(isize, fd)), |
