From 105fe9b25df656b0683174245c2c1f6ccaf5fd66 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 18 Aug 2024 19:33:04 +0200 Subject: [PATCH] darwin: replace custom syscall package with Go native syscall package This required a few compiler and runtime tricks to work, but I ran a bunch of tests and it seems fine. (CI will of course do more exhaustive testing). The main benefit here is that we don't need to maintain the darwin version of the syscall package, and reduce extra risks for bugs (because we reuse the well-tested syscall package). For example, Go 1.23 needed a bunch of new constants in the syscall package. That would have been avoided if we had used the native syscall package on MacOS. --- compileopts/target.go | 1 + compiler/compiler.go | 9 +- compiler/syscall.go | 62 ++++ lib/macos-minimal-sdk | 2 +- loader/goroot.go | 2 +- src/internal/abi/funcpc.go | 10 +- src/os/dir_darwin.go | 5 +- src/os/file_darwin.go | 7 + src/os/file_notdarwin.go | 9 + src/os/file_unix.go | 2 +- src/runtime/os_darwin.c | 29 +- src/runtime/os_darwin.go | 102 +++++- src/syscall/env_libc.go | 2 +- src/syscall/errno_other.go | 2 +- src/syscall/mmap_unix_test.go | 2 +- src/syscall/syscall_libc.go | 2 +- src/syscall/syscall_libc_darwin.go | 432 ----------------------- src/syscall/syscall_libc_darwin_amd64.go | 43 --- src/syscall/syscall_libc_darwin_arm64.go | 37 -- 19 files changed, 229 insertions(+), 531 deletions(-) create mode 100644 src/os/file_darwin.go create mode 100644 src/os/file_notdarwin.go delete mode 100644 src/syscall/syscall_libc_darwin.go delete mode 100644 src/syscall/syscall_libc_darwin_amd64.go delete mode 100644 src/syscall/syscall_libc_darwin_arm64.go diff --git a/compileopts/target.go b/compileopts/target.go index 26a91086b..c394fa8ca 100644 --- a/compileopts/target.go +++ b/compileopts/target.go @@ -389,6 +389,7 @@ func defaultTarget(options *Options) (*TargetSpec, error) { "-platform_version", "macos", platformVersion, platformVersion, ) spec.ExtraFiles = append(spec.ExtraFiles, + "src/runtime/os_darwin.c", "src/runtime/runtime_unix.c") case "linux": spec.Linker = "ld.lld" diff --git a/compiler/compiler.go b/compiler/compiler.go index 201605d78..6756fe969 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1847,7 +1847,9 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) case strings.HasPrefix(name, "(device/riscv.CSR)."): return b.emitCSROperation(instr) case strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall"): - return b.createSyscall(instr) + if b.GOOS != "darwin" { + return b.createSyscall(instr) + } case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"): return b.createRawSyscallNoError(instr) case name == "runtime.supportsRecover": @@ -1865,6 +1867,11 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil case name == "runtime/interrupt.New": return b.createInterruptGlobal(instr) + case name == "internal/abi.FuncPCABI0": + retval := b.createDarwinFuncPCABI0Call(instr) + if !retval.IsNil() { + return retval, nil + } } calleeType, callee = b.getFunction(fn) diff --git a/compiler/syscall.go b/compiler/syscall.go index d878df027..aa40ad1a5 100644 --- a/compiler/syscall.go +++ b/compiler/syscall.go @@ -5,6 +5,7 @@ package compiler import ( "strconv" + "strings" "golang.org/x/tools/go/ssa" "tinygo.org/x/go-llvm" @@ -329,3 +330,64 @@ func (b *builder) createRawSyscallNoError(call *ssa.CallCommon) (llvm.Value, err retval = b.CreateInsertValue(retval, llvm.ConstInt(b.uintptrType, 0, false), 1, "") return retval, nil } + +// Lower a call to internal/abi.FuncPCABI0 on MacOS. +// This function is called like this: +// +// syscall(abi.FuncPCABI0(libc_mkdir_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) +// +// So we'll want to return a function pointer (as uintptr) that points to the +// libc function. Specifically, we _don't_ want to point to the trampoline +// function (which is implemented in Go assembly which we can't read), but +// rather to the actually intended function. For this we're going to assume that +// all the functions follow a specific pattern: libc__trampoline. +// +// The return value is the function pointer as an uintptr, or a nil value if +// this isn't possible (and a regular call should be made as fallback). +func (b *builder) createDarwinFuncPCABI0Call(instr *ssa.CallCommon) llvm.Value { + if b.GOOS != "darwin" { + // This has only been tested on MacOS (and only seems to be used there). + return llvm.Value{} + } + + // Check that it uses a function call like syscall.libc_*_trampoline + itf := instr.Args[0].(*ssa.MakeInterface) + calledFn := itf.X.(*ssa.Function) + if pkgName := calledFn.Pkg.Pkg.Path(); pkgName != "syscall" && pkgName != "internal/syscall/unix" { + return llvm.Value{} + } + if !strings.HasPrefix(calledFn.Name(), "libc_") || !strings.HasSuffix(calledFn.Name(), "_trampoline") { + + return llvm.Value{} + } + + // Extract the libc function name. + name := strings.TrimPrefix(strings.TrimSuffix(calledFn.Name(), "_trampoline"), "libc_") + if name == "open" { + // Special case: open() is a variadic function and can't be called like + // a regular function. Therefore, we need to use a wrapper implemented + // in C. + name = "syscall_libc_open" + } + if b.GOARCH == "amd64" { + if name == "fdopendir" || name == "readdir_r" { + // Hack to support amd64, which needs the $INODE64 suffix. + // This is also done in upstream Go: + // https://github.com/golang/go/commit/096ab3c21b88ccc7d411379d09fe6274e3159467 + name += "$INODE64" + } + } + + // Obtain the C function. + // Use a simple function (no parameters or return value) because all we need + // is the address of the function. + llvmFn := b.mod.NamedFunction(name) + if llvmFn.IsNil() { + llvmFnType := llvm.FunctionType(b.ctx.VoidType(), nil, false) + llvmFn = llvm.AddFunction(b.mod, name, llvmFnType) + } + + // Cast the function pointer to a uintptr (because that's what + // abi.FuncPCABI0 returns). + return b.CreatePtrToInt(llvmFn, b.uintptrType, "") +} diff --git a/lib/macos-minimal-sdk b/lib/macos-minimal-sdk index 91ac2eabd..4e4113e3b 160000 --- a/lib/macos-minimal-sdk +++ b/lib/macos-minimal-sdk @@ -1 +1 @@ -Subproject commit 91ac2eabd80f10d95cb4255c78999d9d2c45a3be +Subproject commit 4e4113e3b1244b8fdc5e1486577f25e22d63f36e diff --git a/loader/goroot.go b/loader/goroot.go index 09edab320..c7ac029d3 100644 --- a/loader/goroot.go +++ b/loader/goroot.go @@ -218,7 +218,7 @@ func listGorootMergeLinks(goroot, tinygoroot string, overrides map[string]bool) // with the TinyGo version. This is the case on some targets. func needsSyscallPackage(buildTags []string) bool { for _, tag := range buildTags { - if tag == "baremetal" || tag == "darwin" || tag == "nintendoswitch" || tag == "tinygo.wasm" { + if tag == "baremetal" || tag == "nintendoswitch" || tag == "tinygo.wasm" { return true } } diff --git a/src/internal/abi/funcpc.go b/src/internal/abi/funcpc.go index a926c392f..0661ed717 100644 --- a/src/internal/abi/funcpc.go +++ b/src/internal/abi/funcpc.go @@ -4,11 +4,9 @@ package abi // (in particular internal/syscall/unix on MacOS). They do not currently have an // implementation, in part because TinyGo doesn't use ABI0 or ABIInternal (it // uses a C-like calling convention). +// Calls to FuncPCABI0 however are treated specially by the compiler when +// compiling for MacOS. -func FuncPCABI0(f interface{}) uintptr { - panic("unimplemented: internal/abi.FuncPCABI0") -} +func FuncPCABI0(f interface{}) uintptr -func FuncPCABIInternal(f interface{}) uintptr { - panic("unimplemented: internal/abi.FuncPCABIInternal") -} +func FuncPCABIInternal(f interface{}) uintptr diff --git a/src/os/dir_darwin.go b/src/os/dir_darwin.go index 3883a45c6..645c91f8c 100644 --- a/src/os/dir_darwin.go +++ b/src/os/dir_darwin.go @@ -135,7 +135,7 @@ func darwinOpenDir(fd syscallFd) (uintptr, string, error) { } var dir uintptr for { - dir, err = syscall.Fdopendir(fd2) + dir, err = fdopendir(fd2) if err != syscall.EINTR { break } @@ -149,6 +149,9 @@ func darwinOpenDir(fd syscallFd) (uintptr, string, error) { // Implemented in syscall/syscall_libc_darwin_*.go. +//go:linkname fdopendir syscall.fdopendir +func fdopendir(fd int) (dir uintptr, err error) + //go:linkname closedir syscall.closedir func closedir(dir uintptr) (err error) diff --git a/src/os/file_darwin.go b/src/os/file_darwin.go new file mode 100644 index 000000000..8d96b7296 --- /dev/null +++ b/src/os/file_darwin.go @@ -0,0 +1,7 @@ +package os + +import "syscall" + +func pipe(p []int) error { + return syscall.Pipe(p) +} diff --git a/src/os/file_notdarwin.go b/src/os/file_notdarwin.go new file mode 100644 index 000000000..d59a8eb6c --- /dev/null +++ b/src/os/file_notdarwin.go @@ -0,0 +1,9 @@ +//go:build (linux && !baremetal && !wasm_unknown) || wasip1 || wasip2 + +package os + +import "syscall" + +func pipe(p []int) error { + return syscall.Pipe2(p, syscall.O_CLOEXEC) +} diff --git a/src/os/file_unix.go b/src/os/file_unix.go index d8d086e8d..efbd8ef67 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -70,7 +70,7 @@ func Truncate(name string, size int64) error { func Pipe() (r *File, w *File, err error) { var p [2]int - err = handleSyscallError(syscall.Pipe2(p[:], syscall.O_CLOEXEC)) + err = handleSyscallError(pipe(p[:])) if err != nil { return } diff --git a/src/runtime/os_darwin.c b/src/runtime/os_darwin.c index d5f6c807a..5d7cd7c71 100644 --- a/src/runtime/os_darwin.c +++ b/src/runtime/os_darwin.c @@ -1,7 +1,32 @@ -// Wrapper function because 'open' is a variadic function and variadic functions -// use a different (incompatible) calling convention on darwin/arm64. +//go:build none + +// This file is included in the build, despite the //go:build line above. #include + +// Wrapper function because 'open' is a variadic function and variadic functions +// use a different (incompatible) calling convention on darwin/arm64. +// This function is referenced from the compiler, when it sees a +// syscall.libc_open_trampoline function. int syscall_libc_open(const char *pathname, int flags, mode_t mode) { return open(pathname, flags, mode); } + +// The following functions are called by the runtime because Go can't call +// function pointers directly. + +int tinygo_syscall(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) { + return fn(a1, a2, a3); +} + +uintptr_t tinygo_syscallX(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3), uintptr_t a1, uintptr_t a2, uintptr_t a3) { + return fn(a1, a2, a3); +} + +int tinygo_syscall6(int (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) { + return fn(a1, a2, a3, a4, a5, a6); +} + +uintptr_t tinygo_syscall6X(uintptr_t (*fn)(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6), uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6) { + return fn(a1, a2, a3, a4, a5, a6); +} diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index 9255fb90f..8338d0f18 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -4,8 +4,6 @@ package runtime import "unsafe" -import "C" // dummy import so that os_darwin.c works - const GOOS = "darwin" const ( @@ -127,7 +125,107 @@ func hardwareRand() (n uint64, ok bool) { return n, true } +//go:linkname syscall_Getpagesize syscall.Getpagesize +func syscall_Getpagesize() int { + return int(libc_getpagesize()) +} + +// Call "system calls" (actually: libc functions) in a special way. +// - Most calls calls return a C int (which is 32-bits), and -1 on failure. +// - syscallX* is for functions that return a 64-bit integer (and also return +// -1 on failure). +// - syscallPtr is for functions that return a pointer on success or NULL on +// failure. +// - rawSyscall seems to avoid some stack modifications, which isn't relevant +// to TinyGo. + +//go:linkname syscall_syscall syscall.syscall +func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { + // For TinyGo we don't need to do anything special to call C functions. + return syscall_rawSyscall(fn, a1, a2, a3) +} + +//go:linkname syscall_rawSyscall syscall.rawSyscall +func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { + result := call_syscall(fn, a1, a2, a3) + r1 = uintptr(result) + if result == -1 { + // Syscall returns -1 on failure. + err = uintptr(*libc___error()) + } + return +} + +//go:linkname syscall_syscallX syscall.syscallX +func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { + r1 = call_syscallX(fn, a1, a2, a3) + if int64(r1) == -1 { + // Syscall returns -1 on failure. + err = uintptr(*libc___error()) + } + return +} + +//go:linkname syscall_syscallPtr syscall.syscallPtr +func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { + r1 = call_syscallX(fn, a1, a2, a3) + if r1 == 0 { + // Syscall returns a pointer on success, or NULL on failure. + err = uintptr(*libc___error()) + } + return +} + +//go:linkname syscall_syscall6 syscall.syscall6 +func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { + result := call_syscall6(fn, a1, a2, a3, a4, a5, a6) + r1 = uintptr(result) + if result == -1 { + // Syscall returns -1 on failure. + err = uintptr(*libc___error()) + } + return +} + +//go:linkname syscall_syscall6X syscall.syscall6X +func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { + r1 = call_syscall6X(fn, a1, a2, a3, a4, a5, a6) + if int64(r1) == -1 { + // Syscall returns -1 on failure. + err = uintptr(*libc___error()) + } + return +} + // uint32_t arc4random(void); // //export arc4random func libc_arc4random() uint32 + +// int getpagesize(void); +// +//export getpagesize +func libc_getpagesize() int32 + +// This function returns the error location in the darwin ABI. +// Discovered by compiling the following code using Clang: +// +// #include +// int getErrno() { +// return errno; +// } +// +//export __error +func libc___error() *int32 + +//export tinygo_syscall +func call_syscall(fn, a1, a2, a3 uintptr) int32 + +//export tinygo_syscallX +func call_syscallX(fn, a1, a2, a3 uintptr) uintptr + +//export tinygo_syscall6 +func call_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) int32 + +//export tinygo_syscall6X +func call_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr diff --git a/src/syscall/env_libc.go b/src/syscall/env_libc.go index f558901cf..4ad078dc5 100644 --- a/src/syscall/env_libc.go +++ b/src/syscall/env_libc.go @@ -1,4 +1,4 @@ -//go:build darwin || nintendoswitch || wasip1 +//go:build nintendoswitch || wasip1 package syscall diff --git a/src/syscall/errno_other.go b/src/syscall/errno_other.go index b988fbc1e..3a06ac018 100644 --- a/src/syscall/errno_other.go +++ b/src/syscall/errno_other.go @@ -1,4 +1,4 @@ -//go:build !wasip1 && !wasip2 && !darwin +//go:build !wasip1 && !wasip2 package syscall diff --git a/src/syscall/mmap_unix_test.go b/src/syscall/mmap_unix_test.go index 1946265d8..62748a939 100644 --- a/src/syscall/mmap_unix_test.go +++ b/src/syscall/mmap_unix_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build darwin || linux +//go:build linux package syscall_test diff --git a/src/syscall/syscall_libc.go b/src/syscall/syscall_libc.go index 2321292d9..67cf6681f 100644 --- a/src/syscall/syscall_libc.go +++ b/src/syscall/syscall_libc.go @@ -1,4 +1,4 @@ -//go:build darwin || nintendoswitch || wasip1 || wasip2 +//go:build nintendoswitch || wasip1 || wasip2 package syscall diff --git a/src/syscall/syscall_libc_darwin.go b/src/syscall/syscall_libc_darwin.go deleted file mode 100644 index 3b0341880..000000000 --- a/src/syscall/syscall_libc_darwin.go +++ /dev/null @@ -1,432 +0,0 @@ -//go:build darwin - -package syscall - -import ( - "internal/itoa" - "unsafe" -) - -// This file defines errno and constants to match the darwin libsystem ABI. -// Values have been copied from src/syscall/zerrors_darwin_amd64.go. - -// This function returns the error location in the darwin ABI. -// Discovered by compiling the following code using Clang: -// -// #include -// int getErrno() { -// return errno; -// } -// -//export __error -func libc___error() *int32 - -// getErrno returns the current C errno. It may not have been caused by the last -// call, so it should only be relied upon when the last call indicates an error -// (for example, by returning -1). -func getErrno() Errno { - errptr := libc___error() - return Errno(uintptr(*errptr)) -} - -func (e Errno) Is(target error) bool { - switch target.Error() { - case "permission denied": - return e == EACCES || e == EPERM - case "file already exists": - return e == EEXIST - case "file does not exist": - return e == ENOENT - } - return false -} - -// Source: upstream zerrors_darwin_amd64.go -const ( - DT_BLK = 0x6 - DT_CHR = 0x2 - DT_DIR = 0x4 - DT_FIFO = 0x1 - DT_LNK = 0xa - DT_REG = 0x8 - DT_SOCK = 0xc - DT_UNKNOWN = 0x0 - DT_WHT = 0xe - F_GETFL = 0x3 - F_SETFL = 0x4 - O_NONBLOCK = 0x4 - TIOCSPGRP = 0x80047476 -) - -// Source: https://opensource.apple.com/source/xnu/xnu-7195.141.2/bsd/sys/errno.h.auto.html -const ( - EPERM Errno = 1 - ENOENT Errno = 2 - ESRCH Errno = 3 - EINTR Errno = 4 - EIO Errno = 5 - ENXIO Errno = 6 - E2BIG Errno = 7 - ENOEXEC Errno = 8 - EBADF Errno = 9 - ECHILD Errno = 10 - EDEADLK Errno = 11 - ENOMEM Errno = 12 - EACCES Errno = 13 - EFAULT Errno = 14 - ENOTBLK Errno = 15 - EBUSY Errno = 16 - EEXIST Errno = 17 - EXDEV Errno = 18 - ENODEV Errno = 19 - ENOTDIR Errno = 20 - EISDIR Errno = 21 - EINVAL Errno = 22 - ENFILE Errno = 23 - EMFILE Errno = 24 - ENOTTY Errno = 25 - ETXTBSY Errno = 26 - EFBIG Errno = 27 - ENOSPC Errno = 28 - ESPIPE Errno = 29 - EROFS Errno = 30 - EMLINK Errno = 31 - EPIPE Errno = 32 - EDOM Errno = 33 - ERANGE Errno = 34 - EAGAIN Errno = 35 - EWOULDBLOCK Errno = EAGAIN - EINPROGRESS Errno = 36 - EALREADY Errno = 37 - ENOTSOCK Errno = 38 - EDESTADDRREQ Errno = 39 - EMSGSIZE Errno = 40 - EPROTOTYPE Errno = 41 - ENOPROTOOPT Errno = 42 - EPROTONOSUPPORT Errno = 43 - ESOCKTNOSUPPORT Errno = 44 - ENOTSUP Errno = 45 - EPFNOSUPPORT Errno = 46 - EAFNOSUPPORT Errno = 47 - EADDRINUSE Errno = 48 - EADDRNOTAVAIL Errno = 49 - ENETDOWN Errno = 50 - ENETUNREACH Errno = 51 - ENETRESET Errno = 52 - ECONNABORTED Errno = 53 - ECONNRESET Errno = 54 - ENOBUFS Errno = 55 - EISCONN Errno = 56 - ENOTCONN Errno = 57 - ESHUTDOWN Errno = 58 - ETOOMANYREFS Errno = 59 - ETIMEDOUT Errno = 60 - ECONNREFUSED Errno = 61 - ELOOP Errno = 62 - ENAMETOOLONG Errno = 63 - EHOSTDOWN Errno = 64 - EHOSTUNREACH Errno = 65 - ENOTEMPTY Errno = 66 - EPROCLIM Errno = 67 - EUSERS Errno = 68 - EDQUOT Errno = 69 - ESTALE Errno = 70 - EREMOTE Errno = 71 - EBADRPC Errno = 72 - ERPCMISMATCH Errno = 73 - EPROGUNAVAIL Errno = 74 - EPROGMISMATCH Errno = 75 - EPROCUNAVAIL Errno = 76 - ENOLCK Errno = 77 - ENOSYS Errno = 78 - EFTYPE Errno = 79 - EAUTH Errno = 80 - ENEEDAUTH Errno = 81 - EPWROFF Errno = 82 - EDEVERR Errno = 83 - EOVERFLOW Errno = 84 - EBADEXEC Errno = 85 - EBADARCH Errno = 86 - ESHLIBVERS Errno = 87 - EBADMACHO Errno = 88 - ECANCELED Errno = 89 - EIDRM Errno = 90 - ENOMSG Errno = 91 - EILSEQ Errno = 92 - ENOATTR Errno = 93 - EBADMSG Errno = 94 - EMULTIHOP Errno = 95 - ENODATA Errno = 96 - ENOLINK Errno = 97 - ENOSR Errno = 98 - ENOSTR Errno = 99 - EPROTO Errno = 100 - ETIME Errno = 101 - EOPNOTSUPP Errno = 102 - ENOPOLICY Errno = 103 - ENOTRECOVERABLE Errno = 104 - EOWNERDEAD Errno = 105 - EQFULL Errno = 106 - ELAST Errno = 106 -) - -type Signal int - -// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/signal.h -const ( - SIGINT Signal = 2 /* interrupt */ - SIGQUIT Signal = 3 /* quit */ - SIGILL Signal = 4 /* illegal instruction (not reset when caught) */ - SIGTRAP Signal = 5 /* trace trap (not reset when caught) */ - SIGABRT Signal = 6 /* abort() */ - SIGFPE Signal = 8 /* floating point exception */ - SIGKILL Signal = 9 /* kill (cannot be caught or ignored) */ - SIGBUS Signal = 10 /* bus error */ - SIGSEGV Signal = 11 /* segmentation violation */ - SIGPIPE Signal = 13 /* write on a pipe with no one to read it */ - SIGTERM Signal = 15 /* software termination signal from kill */ - SIGCHLD Signal = 20 /* to parent on child stop or exit */ -) - -func (s Signal) Signal() {} - -func (s Signal) String() string { - if 0 <= s && int(s) < len(signals) { - str := signals[s] - if str != "" { - return str - } - } - return "signal " + itoa.Itoa(int(s)) -} - -var signals = [...]string{} - -const ( - Stdin = 0 - Stdout = 1 - Stderr = 2 -) - -const ( - O_RDONLY = 0x0 - O_WRONLY = 0x1 - O_RDWR = 0x2 - O_APPEND = 0x8 - O_SYNC = 0x80 - O_CREAT = 0x200 - O_TRUNC = 0x400 - O_EXCL = 0x800 - - O_CLOEXEC = 0x01000000 -) - -// Source: https://opensource.apple.com/source/xnu/xnu-7195.81.3/bsd/sys/mman.h.auto.html -const ( - PROT_NONE = 0x00 // no permissions - PROT_READ = 0x01 // pages can be read - PROT_WRITE = 0x02 // pages can be written - PROT_EXEC = 0x04 // pages can be executed - - MAP_SHARED = 0x0001 // share changes - MAP_PRIVATE = 0x0002 // changes are private - - MAP_FILE = 0x0000 // map from file (default) - MAP_ANON = 0x1000 // allocated from memory, swap space - MAP_ANONYMOUS = MAP_ANON -) - -type Timespec struct { - Sec int64 - Nsec int64 -} - -// Unix returns the time stored in ts as seconds plus nanoseconds. -func (ts *Timespec) Unix() (sec int64, nsec int64) { - return int64(ts.Sec), int64(ts.Nsec) -} - -// Source: upstream ztypes_darwin_amd64.go -type Dirent struct { - Ino uint64 - Seekoff uint64 - Reclen uint16 - Namlen uint16 - Type uint8 - Name [1024]int8 - Pad_cgo_0 [3]byte -} - -type Stat_t struct { - Dev int32 - Mode uint16 - Nlink uint16 - Ino uint64 - Uid uint32 - Gid uint32 - Rdev int32 - Pad_cgo_0 [4]byte - Atimespec Timespec - Mtimespec Timespec - Ctimespec Timespec - Btimespec Timespec - Size int64 - Blocks int64 - Blksize int32 - Flags uint32 - Gen uint32 - Lspare int32 - Qspare [2]int64 -} - -// Source: https://github.com/apple/darwin-xnu/blob/main/bsd/sys/_types/_s_ifmt.h -const ( - S_IEXEC = 0x40 - S_IFBLK = 0x6000 - S_IFCHR = 0x2000 - S_IFDIR = 0x4000 - S_IFIFO = 0x1000 - S_IFLNK = 0xa000 - S_IFMT = 0xf000 - S_IFREG = 0x8000 - S_IFSOCK = 0xc000 - S_IFWHT = 0xe000 - S_IREAD = 0x100 - S_IRGRP = 0x20 - S_IROTH = 0x4 - S_IRUSR = 0x100 - S_IRWXG = 0x38 - S_IRWXO = 0x7 - S_IRWXU = 0x1c0 - S_ISGID = 0x400 - S_ISTXT = 0x200 - S_ISUID = 0x800 - S_ISVTX = 0x200 - S_IWGRP = 0x10 - S_IWOTH = 0x2 - S_IWRITE = 0x80 - S_IWUSR = 0x80 - S_IXGRP = 0x8 - S_IXOTH = 0x1 - S_IXUSR = 0x40 -) - -func Stat(path string, p *Stat_t) (err error) { - data := cstring(path) - n := libc_stat(&data[0], unsafe.Pointer(p)) - - if n < 0 { - err = getErrno() - } - return -} - -func Fstat(fd int, p *Stat_t) (err error) { - n := libc_fstat(int32(fd), unsafe.Pointer(p)) - - if n < 0 { - err = getErrno() - } - return -} - -func Lstat(path string, p *Stat_t) (err error) { - data := cstring(path) - n := libc_lstat(&data[0], unsafe.Pointer(p)) - if n < 0 { - err = getErrno() - } - return -} - -func Fdopendir(fd int) (dir uintptr, err error) { - r0 := libc_fdopendir(int32(fd)) - dir = uintptr(r0) - if dir == 0 { - err = getErrno() - } - return -} - -func Pipe2(fds []int, flags int) (err error) { - // Mac only has Pipe, which ignores the flags argument - buf := make([]int32, 2) - fail := int(libc_pipe(&buf[0])) - if fail < 0 { - err = getErrno() - } else { - fds[0] = int(buf[0]) - fds[1] = int(buf[1]) - } - return -} - -func Chmod(path string, mode uint32) (err error) { - data := cstring(path) - fail := int(libc_chmod(&data[0], mode)) - if fail < 0 { - err = getErrno() - } - return -} - -func closedir(dir uintptr) (err error) { - e := libc_closedir(unsafe.Pointer(dir)) - if e != 0 { - err = getErrno() - } - return -} - -func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (err error) { - e1 := libc_readdir_r(unsafe.Pointer(dir), unsafe.Pointer(entry), unsafe.Pointer(result)) - if e1 != 0 { - err = getErrno() - } - return -} - -func Getpagesize() int { - return int(libc_getpagesize()) -} - -// The following RawSockAddr* types have been copied from the Go source tree and -// are here purely to fix build errors. - -type RawSockaddr struct { - Len uint8 - Family uint8 - Data [14]int8 -} - -type RawSockaddrInet4 struct { - Len uint8 - Family uint8 - Port uint16 - Addr [4]byte /* in_addr */ - Zero [8]int8 -} - -type RawSockaddrInet6 struct { - Len uint8 - Family uint8 - Port uint16 - Flowinfo uint32 - Addr [16]byte /* in6_addr */ - Scope_id uint32 -} - -// int pipe(int32 *fds); -// -//export pipe -func libc_pipe(fds *int32) int32 - -// int getpagesize(); -// -//export getpagesize -func libc_getpagesize() int32 - -// int open(const char *pathname, int flags, mode_t mode); -// -//export syscall_libc_open -func libc_open(pathname *byte, flags int32, mode uint32) int32 diff --git a/src/syscall/syscall_libc_darwin_amd64.go b/src/syscall/syscall_libc_darwin_amd64.go deleted file mode 100644 index 1f5528ec5..000000000 --- a/src/syscall/syscall_libc_darwin_amd64.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build darwin - -package syscall - -import ( - "unsafe" -) - -// The odd $INODE64 suffix is an Apple compatibility feature, see -// __DARWIN_INODE64 in /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/cdefs.h -// and https://assert.cc/posts/darwin_use_64_bit_inode_vs_ctypes/ -// Without it, you get the old, smaller struct stat from mac os 10.2 or so. -// It not needed on arm64. - -// struct DIR * buf fdopendir(int fd); -// -//export fdopendir$INODE64 -func libc_fdopendir(fd int32) unsafe.Pointer - -// int closedir(struct DIR * buf); -// -//export closedir -func libc_closedir(unsafe.Pointer) int32 - -// int readdir_r(struct DIR * buf, struct dirent *entry, struct dirent **result); -// -//export readdir_r$INODE64 -func libc_readdir_r(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) int32 - -// int stat(const char *path, struct stat * buf); -// -//export stat$INODE64 -func libc_stat(pathname *byte, ptr unsafe.Pointer) int32 - -// int fstat(int fd, struct stat * buf); -// -//export fstat$INODE64 -func libc_fstat(fd int32, ptr unsafe.Pointer) int32 - -// int lstat(const char *path, struct stat * buf); -// -//export lstat$INODE64 -func libc_lstat(pathname *byte, ptr unsafe.Pointer) int32 diff --git a/src/syscall/syscall_libc_darwin_arm64.go b/src/syscall/syscall_libc_darwin_arm64.go deleted file mode 100644 index f9ce3c4e3..000000000 --- a/src/syscall/syscall_libc_darwin_arm64.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build darwin - -package syscall - -import ( - "unsafe" -) - -// struct DIR * buf fdopendir(int fd); -// -//export fdopendir -func libc_fdopendir(fd int32) unsafe.Pointer - -// int closedir(struct DIR * buf); -// -//export closedir -func libc_closedir(unsafe.Pointer) int32 - -// int readdir_r(struct DIR * buf, struct dirent *entry, struct dirent **result); -// -//export readdir_r -func libc_readdir_r(unsafe.Pointer, unsafe.Pointer, unsafe.Pointer) int32 - -// int stat(const char *path, struct stat * buf); -// -//export stat -func libc_stat(pathname *byte, ptr unsafe.Pointer) int32 - -// int fstat(int fd, struct stat * buf); -// -//export fstat -func libc_fstat(fd int32, ptr unsafe.Pointer) int32 - -// int lstat(const char *path, struct stat * buf); -// -//export lstat -func libc_lstat(pathname *byte, ptr unsafe.Pointer) int32