Skip to content

Commit 08df152

Browse files
committed
compiler: use variadic wrappers for darwin FuncPCABI0 trampolines
The standard library's function-based trampoline pattern has the same variadic problem as the address-global pattern: of the libc functions darwin's zsyscall wrappers import, open, openat, fcntl, and ioctl are variadic, but createDarwinFuncPCABI0Call only routed open through a fixed-signature wrapper. As a result syscall.SetNonblock (fcntl F_SETFL with the new flags in the variadic slot) observably wrote garbage file flags on darwin/arm64, and the stdlib ioctl and openat paths were equally unsound. Use the shared darwinVariadicImports table for this path too, replacing the open-only special case. Signed-off-by: Evan Wies <evan@neomantra.net>
1 parent 107d407 commit 08df152

1 file changed

Lines changed: 11 additions & 10 deletions

File tree

compiler/syscall.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,10 @@ func (b *builder) createDarwinFuncPCABI0Call(instr *ssa.CallCommon) llvm.Value {
524524

525525
// Extract the libc function name.
526526
name := strings.TrimPrefix(strings.TrimSuffix(calledFn.Name(), "_trampoline"), "libc_")
527-
if name == "open" {
528-
// Special case: open() is a variadic function and can't be called like
529-
// a regular function. Therefore, we need to use a wrapper implemented
530-
// in C.
531-
name = "syscall_libc_open"
527+
if wrapper, ok := darwinVariadicImports[name]; ok {
528+
// Variadic functions can't be called like a regular function, so use a
529+
// wrapper implemented in C. See the comment on darwinVariadicImports.
530+
name = wrapper
532531
}
533532
if b.GOARCH == "amd64" {
534533
if name == "fdopendir" || name == "readdir_r" {
@@ -542,16 +541,18 @@ func (b *builder) createDarwinFuncPCABI0Call(instr *ssa.CallCommon) llvm.Value {
542541
return b.createDarwinImportedFunctionAddr(name)
543542
}
544543

545-
// darwinVariadicImports maps the variadic libc functions imported with
546-
// //go:cgo_import_dynamic on Darwin to fixed-signature C wrappers defined in
544+
// darwinVariadicImports maps the variadic libc functions imported by Darwin
545+
// syscall wrappers to fixed-signature C wrappers defined in
547546
// src/runtime/os_darwin.c. The syscall engine calls an imported address
548547
// through a fixed-signature function pointer (tinygo_syscallX and friends in
549548
// src/runtime/os_darwin.c), which passes every argument in a register. A
550549
// variadic callee, however, takes its variadic arguments from the stack on
551550
// darwin/arm64, so calling one of these functions directly makes it read
552-
// garbage arguments (the direct ioctl call observably failed with EFAULT).
553-
// The same problem is solved the same way for the standard library's open in
554-
// createDarwinFuncPCABI0Call above.
551+
// garbage arguments (a direct ioctl call observably failed with EFAULT, and
552+
// a direct fcntl(F_SETFL) wrote garbage flags). This applies to both
553+
// trampoline flavors: the standard library's function-based pattern
554+
// (createDarwinFuncPCABI0Call above) and the address-global pattern used by
555+
// golang.org/x/sys (createDarwinCgoImportDynamicLoad below).
555556
//
556557
// The set comes from cross-referencing the symbols that darwin's generated
557558
// syscall wrappers import (the //go:cgo_import_dynamic directives in

0 commit comments

Comments
 (0)