mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-04 11:07:46 +00:00
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.
This commit is contained in:
committed by
Ron Evans
parent
753f4b38b4
commit
105fe9b25d
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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_<functionname>_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, "")
|
||||
}
|
||||
|
||||
+1
-1
Submodule lib/macos-minimal-sdk updated: 91ac2eabd8...4e4113e3b1
+1
-1
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package os
|
||||
|
||||
import "syscall"
|
||||
|
||||
func pipe(p []int) error {
|
||||
return syscall.Pipe(p)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
+1
-1
@@ -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
|
||||
}
|
||||
|
||||
+27
-2
@@ -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 <fcntl.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
+100
-2
@@ -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 <errno.h>
|
||||
// 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build darwin || nintendoswitch || wasip1
|
||||
//go:build nintendoswitch || wasip1
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build !wasip1 && !wasip2 && !darwin
|
||||
//go:build !wasip1 && !wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build darwin || nintendoswitch || wasip1 || wasip2
|
||||
//go:build nintendoswitch || wasip1 || wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -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 <errno.h>
|
||||
// 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user