#include "go_tls.h"
#include "textflag.h"
+// Most linux systems use glibc's dynamic linker, which puts the
+// __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position
+// independent code and setldt in this file does the same in the statically
+// linked case. Android, however, uses bionic's dynamic linker, which does not
+// save the helper anywhere, and so the only way to invoke a syscall from
+// position independent code is boring old int $0x80 (which is also what
+// bionic's syscall wrappers use).
+#ifdef GOOS_android
+#define INVOKE_SYSCALL INT $0x80
+#else
+#define INVOKE_SYSCALL CALL 0x10(GS)
+#endif
+
TEXT runtime·exit(SB),NOSPLIT,$0
MOVL $252, AX // syscall number
MOVL code+0(FP), BX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
INT $3 // not reached
RET
TEXT runtime·exit1(SB),NOSPLIT,$0
MOVL $1, AX // exit - exit the current os thread
MOVL code+0(FP), BX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
INT $3 // not reached
RET
MOVL name+0(FP), BX
MOVL mode+4(FP), CX
MOVL perm+8(FP), DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
TEXT runtime·closefd(SB),NOSPLIT,$0
MOVL $6, AX // syscall - close
MOVL fd+0(FP), BX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
MOVL fd+0(FP), BX
MOVL p+4(FP), CX
MOVL n+8(FP), DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
MOVL fd+0(FP), BX
MOVL p+4(FP), CX
MOVL n+8(FP), DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 2(PC)
MOVL $-1, AX
MOVL $191, AX // syscall - ugetrlimit
MOVL kind+0(FP), BX
MOVL limit+4(FP), CX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+8(FP)
RET
MOVL $0, DX
MOVL $0, SI
LEAL 0(SP), DI
- CALL 0x10(GS)
+ INVOKE_SYSCALL
RET
TEXT runtime·gettid(SB),NOSPLIT,$0-4
MOVL $224, AX // syscall - gettid
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+0(FP)
RET
TEXT runtime·raise(SB),NOSPLIT,$12
MOVL $224, AX // syscall - gettid
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, BX // arg 1 tid
MOVL sig+0(FP), CX // arg 2 signal
MOVL $238, AX // syscall - tkill
- CALL 0x10(GS)
+ INVOKE_SYSCALL
RET
TEXT runtime·raiseproc(SB),NOSPLIT,$12
MOVL $20, AX // syscall - getpid
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, BX // arg 1 pid
MOVL sig+0(FP), CX // arg 2 signal
MOVL $37, AX // syscall - kill
- CALL 0x10(GS)
+ INVOKE_SYSCALL
RET
TEXT runtime·setitimer(SB),NOSPLIT,$0-12
MOVL mode+0(FP), BX
MOVL new+4(FP), CX
MOVL old+8(FP), DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
RET
TEXT runtime·mincore(SB),NOSPLIT,$0-16
MOVL addr+0(FP), BX
MOVL n+4(FP), CX
MOVL dst+8(FP), DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+12(FP)
RET
MOVL $0, BX // CLOCK_REALTIME
LEAL 8(SP), CX
MOVL $0, DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL 8(SP), AX // sec
MOVL 12(SP), BX // nsec
MOVL $1, BX // CLOCK_MONOTONIC
LEAL 8(SP), CX
MOVL $0, DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL 8(SP), AX // sec
MOVL 12(SP), BX // nsec
MOVL new+4(FP), CX
MOVL old+8(FP), DX
MOVL size+12(FP), SI
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 2(PC)
INT $3
MOVL new+4(FP), CX
MOVL old+8(FP), DX
MOVL size+12(FP), SI
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+16(FP)
RET
MOVL fd+16(FP), DI
MOVL off+20(FP), BP
SHRL $12, BP
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 3(PC)
NOTL AX
MOVL $91, AX // munmap
MOVL addr+0(FP), BX
MOVL n+4(FP), CX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 2(PC)
INT $3
MOVL addr+0(FP), BX
MOVL n+4(FP), CX
MOVL flags+8(FP), DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
// ignore failure - maybe pages are locked
RET
MOVL ts+12(FP), SI
MOVL addr2+16(FP), DI
MOVL val3+20(FP), BP
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+24(FP)
RET
// Initialize AX to Linux tid
MOVL $224, AX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL 0(SP), BX // m
MOVL 4(SP), DX // g
MOVL $186, AX // sigaltstack
MOVL new+4(SP), BX
MOVL old+8(SP), CX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS 2(PC)
INT $3
*/
ADDL $0x4, CX // address
MOVL CX, 0(CX)
-#endif
- // We copy the dynamic linker behaviour of storing the vsyscall entry point
- // at 0x10(GS) so that it can be invoked by "CALL 0x10(GS)" in all
- // situations, not only those where the binary is actually dynamically
- // linked.
+ // We copy the glibc dynamic linker behaviour of storing the
+ // __kernel_vsyscall entry point at 0x10(GS) so that it can be invoked
+ // by "CALL 0x10(GS)" in all situations, not only those where the
+ // binary is actually dynamically linked.
MOVL runtime·_vdso(SB), AX
MOVL AX, 0x10(CX)
+#endif
// set up user_desc
LEAL 16(SP), AX // struct user_desc
TEXT runtime·osyield(SB),NOSPLIT,$0
MOVL $158, AX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
RET
TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0
MOVL pid+0(FP), BX
MOVL len+4(FP), CX
MOVL buf+8(FP), DX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+12(FP)
RET
TEXT runtime·epollcreate(SB),NOSPLIT,$0
MOVL $254, AX
MOVL size+0(FP), BX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+4(FP)
RET
TEXT runtime·epollcreate1(SB),NOSPLIT,$0
MOVL $329, AX
MOVL flags+0(FP), BX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+4(FP)
RET
MOVL op+4(FP), CX
MOVL fd+8(FP), DX
MOVL ev+12(FP), SI
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+16(FP)
RET
MOVL ev+4(FP), CX
MOVL nev+8(FP), DX
MOVL timeout+12(FP), SI
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+16(FP)
RET
MOVL fd+0(FP), BX // fd
MOVL $2, CX // F_SETFD
MOVL $1, DX // FD_CLOEXEC
- CALL 0x10(GS)
+ INVOKE_SYSCALL
RET
// int access(const char *name, int mode)
MOVL $33, AX // syscall - access
MOVL name+0(FP), BX
MOVL mode+4(FP), CX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+8(FP)
RET
MOVL $102, AX // syscall - socketcall
MOVL $3, BX // connect
LEAL fd+0(FP), CX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+12(FP)
RET
MOVL $102, AX // syscall - socketcall
MOVL $1, BX // socket
LEAL domain+0(FP), CX
- CALL 0x10(GS)
+ INVOKE_SYSCALL
MOVL AX, ret+12(FP)
RET
// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr);
// Trap # in AX, args in BX CX DX SI DI, return in AX
+// Most linux systems use glibc's dynamic linker, which puts the
+// __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position
+// independent code and setldt in runtime does the same in the statically
+// linked case. Android, however, uses bionic's dynamic linker, which does not
+// save the helper anywhere, and so the only way to invoke a syscall from
+// position independent code is boring old int $0x80 (which is also what
+// bionic's syscall wrappers use).
+#ifdef GOOS_android
+#define INVOKE_SYSCALL INT $0x80
+#else
+#define INVOKE_SYSCALL CALL 0x10(GS)
+#endif
+
TEXT ·Syscall(SB),NOSPLIT,$0-28
CALL runtime·entersyscall(SB)
MOVL trap+0(FP), AX // syscall entry
MOVL a3+12(FP), DX
MOVL $0, SI
MOVL $0, DI
- CALL *runtime·_vdso(SB)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS ok
MOVL $-1, r1+16(FP)
MOVL a4+16(FP), SI
MOVL a5+20(FP), DI
MOVL a6+24(FP), BP
- CALL *runtime·_vdso(SB)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS ok6
MOVL $-1, r1+28(FP)
MOVL a3+12(FP), DX
MOVL $0, SI
MOVL $0, DI
- CALL *runtime·_vdso(SB)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS ok1
MOVL $-1, r1+16(FP)
MOVL a4+16(FP), SI
MOVL a5+20(FP), DI
MOVL a6+24(FP), BP
- CALL *runtime·_vdso(SB)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS ok2
MOVL $-1, r1+28(FP)
MOVL $0, DX
MOVL $0, SI
MOVL $0, DI
- CALL *runtime·_vdso(SB)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS oksock
MOVL $-1, n+28(FP)
MOVL $0, DX
MOVL $0, SI
MOVL $0, DI
- CALL *runtime·_vdso(SB)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS oksock1
MOVL $-1, n+28(FP)
MOVL offset_lo+4(FP), DX
LEAL newoffset_lo+16(FP), SI // result pointer
MOVL whence+12(FP), DI
- CALL *runtime·_vdso(SB)
+ INVOKE_SYSCALL
CMPL AX, $0xfffff001
JLS okseek
MOVL $-1, newoffset_lo+16(FP)