qemu-riscv32: Syscall LSEEK returns -14 (EFAULT) Description of problem: The lseek() system call returns -14 (EFAULT) if the file descriptor is correct, which it should never do (According to the lseek(2) man page). Here is some demonstrative code: ``` /* System Call numbers, according to https://github.com/riscv-software-src/riscv-pk/blob/master/pk/syscall.h */ .set SYS_OPENAT, 0x38 .set SYS_CLOSE, 0x39 .set SYS_LSEEK, 0x3e .set SYS_READ, 0x3f .set SYS_WRITE, 0x40 .set SYS_EXIT, 0x5d .set SEEK_CUR, 1 /* According to https://elixir.bootlin.com/linux/v5.16.2/C/ident/AT_FDCWD */ .set AT_FDCWD, (-100) .section .text .global _start _start: /* Open the file with SYS_OPENAT, because SYS_OPEN does not exist on riscv32 for some reason. Effectively: s0 = open(argv[1], 0, 0644); */ li a7, SYS_OPENAT li a0, AT_FDCWD lw a1, 8(sp) li a2, 0 li a3, 0644 ecall /* Error checking. This succeeds. */ blt a0, zero, unrelated_error mv s0, a0 /* The broken lseek() call. Same also happens no matter the position in the file. Effectively: lseek(s0, 0, SEEK_CUR); */ li a7, SYS_LSEEK mv a0, s0 li a1, 0 li a2, SEEK_CUR ecall /* XXX: lseek() returns -14 */ blt a0, zero, lseek_error /* Close the file. */ li a7, SYS_CLOSE mv a0, s0 ecall /* Error checking. This also succeeds. */ blt a0, zero, unrelated_error /* exit(0); */ li a7, SYS_EXIT li a0, 0 ecall /* exit(-return_value); */ lseek_error: li a7, SYS_EXIT sub a0, zero, a0 ecall unrelated_error: li a7, SYS_EXIT li a0, 128 ecall ``` Steps to reproduce: 1. riscv32-unknown-linux-gnu-as test.s -o test.o 2. riscv32-unknown-linux-gnu-ld test.o 3. qemu-riscv32 ./a.out test 4. echo $? # This returns 14 Additional information: Complete test setup: [test.tgz](/uploads/af68c9a5236628a9c6f31f2ce94e2f04/test.tgz)