about summary refs log tree commit diff
path: root/src/unistd
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-07-16 21:05:24 -0400
committerRich Felker <dalias@aerifal.cx>2019-07-16 21:05:24 -0400
commit918c5fa0fc656e49b1ab9ce47183a23e3a36bc00 (patch)
tree4d1f8a2802bbd43f47032bd72fdd51cfb24a559e /src/unistd
parentddc7c4f936c7a90781072f10dbaa122007e939d0 (diff)
downloadmusl-918c5fa0fc656e49b1ab9ce47183a23e3a36bc00.tar.gz
musl-918c5fa0fc656e49b1ab9ce47183a23e3a36bc00.tar.xz
musl-918c5fa0fc656e49b1ab9ce47183a23e3a36bc00.zip
fix broken lseek on mipsn32 with offsets larger than LONG_MAX
mips n32 has 32-bit long, and generally uses long syscall arguments
and return values, but provides only SYS_lseek, not SYS_llseek. we
have some framework (syscall_arg_t, added for x32) to make syscall
arguments 64-bit in such a setting, but it's not clear whether this
could match the sign-extension semantics needed for 32-bit args to all
the other syscalls, and we don't have any existing mechanism to allow
the return value of syscalls to be something other than long.

instead, just provide a custom mipsn32 version of the lseek function
doing its own syscall asm with 64-bit arguments. as a result of commit
03919b26ed41c31876db41f7cee076ced4513fad, stdio will also get the new
code, fixing fseeko/ftello too.
Diffstat (limited to 'src/unistd')
-rw-r--r--src/unistd/mipsn32/lseek.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/unistd/mipsn32/lseek.c b/src/unistd/mipsn32/lseek.c
new file mode 100644
index 00000000..60e74a51
--- /dev/null
+++ b/src/unistd/mipsn32/lseek.c
@@ -0,0 +1,20 @@
+#include <unistd.h>
+#include "syscall.h"
+
+off_t __lseek(int fd, off_t offset, int whence)
+{
+	register long long r4 __asm__("$4") = fd;
+	register long long r5 __asm__("$5") = offset;
+	register long long r6 __asm__("$6") = whence;
+	register long long r7 __asm__("$7");
+	register long long r2 __asm__("$2") = SYS_lseek;
+	__asm__ __volatile__ (
+		"syscall"
+		: "+&r"(r2), "=r"(r7)
+		: "r"(r4), "r"(r5), "r"(r6)
+		: SYSCALL_CLOBBERLIST);
+	return r7 ? __syscall_ret(-r2) : r2;
+}
+
+weak_alias(__lseek, lseek);
+weak_alias(__lseek, lseek64);