| ... | @@ -48,13 +48,27 @@ pub fn getauxval(index: usize) usize { | ... | @@ -48,13 +48,27 @@ pub fn getauxval(index: usize) usize { |
| 48 | return 0; | 48 | return 0; |
| 49 | } | 49 | } |
| 50 | | 50 | |
| 51 | // Some architectures require 64bit parameters for some syscalls to be passed in | 51 | // Some architectures (and some syscalls) require 64bit parameters to be passed |
| 52 | // even-aligned register pair | 52 | // in a even-aligned register pair. |
| 53 | const require_aligned_register_pair = // | 53 | const require_aligned_register_pair = // |
| 54 | std.Target.current.cpu.arch.isMIPS() or | 54 | std.Target.current.cpu.arch.isMIPS() or |
| 55 | std.Target.current.cpu.arch.isARM() or | 55 | std.Target.current.cpu.arch.isARM() or |
| 56 | std.Target.current.cpu.arch.isThumb(); | 56 | std.Target.current.cpu.arch.isThumb(); |
| 57 | | 57 | |
| | 58 | // Split a 64bit value into a {LSB,MSB} pair. |
| | 59 | fn splitValue64(val: u64) [2]u32 { |
| | 60 | switch (builtin.endian) { |
| | 61 | .Little => return [2]u32{ |
| | 62 | @truncate(u32, val), |
| | 63 | @truncate(u32, val >> 32), |
| | 64 | }, |
| | 65 | .Big => return [2]u32{ |
| | 66 | @truncate(u32, val >> 32), |
| | 67 | @truncate(u32, val), |
| | 68 | }, |
| | 69 | } |
| | 70 | } |
| | 71 | |
| 58 | /// Get the errno from a syscall return value, or 0 for no error. | 72 | /// Get the errno from a syscall return value, or 0 for no error. |
| 59 | pub fn getErrno(r: usize) u12 { | 73 | pub fn getErrno(r: usize) u12 { |
| 60 | const signed_r = @bitCast(isize, r); | 74 | const signed_r = @bitCast(isize, r); |
| ... | @@ -263,24 +277,26 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { | ... | @@ -263,24 +277,26 @@ pub fn read(fd: i32, buf: [*]u8, count: usize) usize { |
| 263 | } | 277 | } |
| 264 | | 278 | |
| 265 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { | 279 | pub fn preadv(fd: i32, iov: [*]const iovec, count: usize, offset: u64) usize { |
| | 280 | const offset_halves = splitValue64(offset); |
| 266 | return syscall5( | 281 | return syscall5( |
| 267 | .preadv, | 282 | .preadv, |
| 268 | @bitCast(usize, @as(isize, fd)), | 283 | @bitCast(usize, @as(isize, fd)), |
| 269 | @ptrToInt(iov), | 284 | @ptrToInt(iov), |
| 270 | count, | 285 | count, |
| 271 | @truncate(usize, offset), | 286 | offset_halves[0], |
| 272 | @truncate(usize, offset >> 32), | 287 | offset_halves[1], |
| 273 | ); | 288 | ); |
| 274 | } | 289 | } |
| 275 | | 290 | |
| 276 | pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: kernel_rwf) usize { | 291 | pub fn preadv2(fd: i32, iov: [*]const iovec, count: usize, offset: u64, flags: kernel_rwf) usize { |
| | 292 | const offset_halves = splitValue64(offset); |
| 277 | return syscall6( | 293 | return syscall6( |
| 278 | .preadv2, | 294 | .preadv2, |
| 279 | @bitCast(usize, @as(isize, fd)), | 295 | @bitCast(usize, @as(isize, fd)), |
| 280 | @ptrToInt(iov), | 296 | @ptrToInt(iov), |
| 281 | count, | 297 | count, |
| 282 | @truncate(usize, offset), | 298 | offset_halves[0], |
| 283 | @truncate(usize, offset >> 32), | 299 | offset_halves[1], |
| 284 | flags, | 300 | flags, |
| 285 | ); | 301 | ); |
| 286 | } | 302 | } |
| ... | @@ -294,24 +310,26 @@ pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { | ... | @@ -294,24 +310,26 @@ pub fn writev(fd: i32, iov: [*]const iovec_const, count: usize) usize { |
| 294 | } | 310 | } |
| 295 | | 311 | |
| 296 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { | 312 | pub fn pwritev(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64) usize { |
| | 313 | const offset_halves = splitValue64(offset); |
| 297 | return syscall5( | 314 | return syscall5( |
| 298 | .pwritev, | 315 | .pwritev, |
| 299 | @bitCast(usize, @as(isize, fd)), | 316 | @bitCast(usize, @as(isize, fd)), |
| 300 | @ptrToInt(iov), | 317 | @ptrToInt(iov), |
| 301 | count, | 318 | count, |
| 302 | @truncate(usize, offset), | 319 | offset_halves[0], |
| 303 | @truncate(usize, offset >> 32), | 320 | offset_halves[1], |
| 304 | ); | 321 | ); |
| 305 | } | 322 | } |
| 306 | | 323 | |
| 307 | pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64, flags: kernel_rwf) usize { | 324 | pub fn pwritev2(fd: i32, iov: [*]const iovec_const, count: usize, offset: u64, flags: kernel_rwf) usize { |
| | 325 | const offset_halves = splitValue64(offset); |
| 308 | return syscall6( | 326 | return syscall6( |
| 309 | .pwritev2, | 327 | .pwritev2, |
| 310 | @bitCast(usize, @as(isize, fd)), | 328 | @bitCast(usize, @as(isize, fd)), |
| 311 | @ptrToInt(iov), | 329 | @ptrToInt(iov), |
| 312 | count, | 330 | count, |
| 313 | @truncate(usize, offset), | 331 | offset_halves[0], |
| 314 | @truncate(usize, offset >> 32), | 332 | offset_halves[1], |
| 315 | flags, | 333 | flags, |
| 316 | ); | 334 | ); |
| 317 | } | 335 | } |
| ... | @@ -338,6 +356,7 @@ pub fn symlinkat(existing: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) us | ... | @@ -338,6 +356,7 @@ pub fn symlinkat(existing: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) us |
| 338 | | 356 | |
| 339 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { | 357 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { |
| 340 | if (@hasField(SYS, "pread64")) { | 358 | if (@hasField(SYS, "pread64")) { |
| | 359 | const offset_halves = splitValue64(offset); |
| 341 | if (require_aligned_register_pair) { | 360 | if (require_aligned_register_pair) { |
| 342 | return syscall6( | 361 | return syscall6( |
| 343 | .pread64, | 362 | .pread64, |
| ... | @@ -345,8 +364,8 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { | ... | @@ -345,8 +364,8 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { |
| 345 | @ptrToInt(buf), | 364 | @ptrToInt(buf), |
| 346 | count, | 365 | count, |
| 347 | 0, | 366 | 0, |
| 348 | @truncate(usize, offset), | 367 | offset_halves[0], |
| 349 | @truncate(usize, offset >> 32), | 368 | offset_halves[1], |
| 350 | ); | 369 | ); |
| 351 | } else { | 370 | } else { |
| 352 | return syscall5( | 371 | return syscall5( |
| ... | @@ -354,8 +373,8 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { | ... | @@ -354,8 +373,8 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { |
| 354 | @bitCast(usize, @as(isize, fd)), | 373 | @bitCast(usize, @as(isize, fd)), |
| 355 | @ptrToInt(buf), | 374 | @ptrToInt(buf), |
| 356 | count, | 375 | count, |
| 357 | @truncate(usize, offset), | 376 | offset_halves[0], |
| 358 | @truncate(usize, offset >> 32), | 377 | offset_halves[1], |
| 359 | ); | 378 | ); |
| 360 | } | 379 | } |
| 361 | } else { | 380 | } else { |
| ... | @@ -401,20 +420,21 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | ... | @@ -401,20 +420,21 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { |
| 401 | | 420 | |
| 402 | pub fn ftruncate(fd: i32, length: u64) usize { | 421 | pub fn ftruncate(fd: i32, length: u64) usize { |
| 403 | if (@hasField(SYS, "ftruncate64")) { | 422 | if (@hasField(SYS, "ftruncate64")) { |
| | 423 | const length_halves = splitValue64(length); |
| 404 | if (require_aligned_register_pair) { | 424 | if (require_aligned_register_pair) { |
| 405 | return syscall4( | 425 | return syscall4( |
| 406 | .ftruncate64, | 426 | .ftruncate64, |
| 407 | @bitCast(usize, @as(isize, fd)), | 427 | @bitCast(usize, @as(isize, fd)), |
| 408 | 0, | 428 | 0, |
| 409 | @truncate(usize, length), | 429 | length_halves[0], |
| 410 | @truncate(usize, length >> 32), | 430 | length_halves[1], |
| 411 | ); | 431 | ); |
| 412 | } else { | 432 | } else { |
| 413 | return syscall3( | 433 | return syscall3( |
| 414 | .ftruncate64, | 434 | .ftruncate64, |
| 415 | @bitCast(usize, @as(isize, fd)), | 435 | @bitCast(usize, @as(isize, fd)), |
| 416 | @truncate(usize, length), | 436 | length_halves[0], |
| 417 | @truncate(usize, length >> 32), | 437 | length_halves[1], |
| 418 | ); | 438 | ); |
| 419 | } | 439 | } |
| 420 | } else { | 440 | } else { |
| ... | @@ -428,6 +448,8 @@ pub fn ftruncate(fd: i32, length: u64) usize { | ... | @@ -428,6 +448,8 @@ pub fn ftruncate(fd: i32, length: u64) usize { |
| 428 | | 448 | |
| 429 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { | 449 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { |
| 430 | if (@hasField(SYS, "pwrite64")) { | 450 | if (@hasField(SYS, "pwrite64")) { |
| | 451 | const offset_halves = splitValue64(offset); |
| | 452 | |
| 431 | if (require_aligned_register_pair) { | 453 | if (require_aligned_register_pair) { |
| 432 | return syscall6( | 454 | return syscall6( |
| 433 | .pwrite64, | 455 | .pwrite64, |
| ... | @@ -435,8 +457,8 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { | ... | @@ -435,8 +457,8 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { |
| 435 | @ptrToInt(buf), | 457 | @ptrToInt(buf), |
| 436 | count, | 458 | count, |
| 437 | 0, | 459 | 0, |
| 438 | @truncate(usize, offset), | 460 | offset_halves[0], |
| 439 | @truncate(usize, offset >> 32), | 461 | offset_halves[1], |
| 440 | ); | 462 | ); |
| 441 | } else { | 463 | } else { |
| 442 | return syscall5( | 464 | return syscall5( |
| ... | @@ -444,8 +466,8 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { | ... | @@ -444,8 +466,8 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { |
| 444 | @bitCast(usize, @as(isize, fd)), | 466 | @bitCast(usize, @as(isize, fd)), |
| 445 | @ptrToInt(buf), | 467 | @ptrToInt(buf), |
| 446 | count, | 468 | count, |
| 447 | @truncate(usize, offset), | 469 | offset_halves[0], |
| 448 | @truncate(usize, offset >> 32), | 470 | offset_halves[1], |
| 449 | ); | 471 | ); |
| 450 | } | 472 | } |
| 451 | } else { | 473 | } else { |
| ... | @@ -540,6 +562,8 @@ pub fn close(fd: i32) usize { | ... | @@ -540,6 +562,8 @@ pub fn close(fd: i32) usize { |
| 540 | | 562 | |
| 541 | /// Can only be called on 32 bit systems. For 64 bit see `lseek`. | 563 | /// Can only be called on 32 bit systems. For 64 bit see `lseek`. |
| 542 | pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { | 564 | pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { |
| | 565 | // NOTE: The offset parameter splitting is independent from the target |
| | 566 | // endianness. |
| 543 | return syscall5( | 567 | return syscall5( |
| 544 | ._llseek, | 568 | ._llseek, |
| 545 | @bitCast(usize, @as(isize, fd)), | 569 | @bitCast(usize, @as(isize, fd)), |