From 5bf9aeba1cfec8804425f3838b661fd6c2eb26ff Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 15 Nov 2022 20:36:10 -0500 Subject: [PATCH] runtime/race: do not use cgo on macOS The use of an empty import "C" to trigger cgo in runtime/race serves two purposes: 1. Cause the runtime to use the C library to create system threads, because the race syso implementation expects things like thread-local storage to work correctly. 2. Derive the right set of //go:cgo_import_dynamic comments to pass to the Go linker, so that it doesn't diagnose them as undefined references. On macOS, (1) is unnecessary because using the C library (via DLL calls) is the only way the runtime ever creates threads. We can accomplish (2) by writing those comments ourselves. Having done that in this CL, cgo is no longer needed to run the race detector on macOS, which means that having a pre-compiled set of .a files is no longer necessary, nor is having Xcode for use with cgo when rebuilding those .a files. Change-Id: Iee24cc67900eb542141b32beaadafb2c94f5fe26 Reviewed-on: https://go-review.googlesource.com/c/go/+/451055 Run-TryBot: Russ Cox Reviewed-by: Bryan Mills Auto-Submit: Russ Cox TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- src/cmd/go/internal/work/init.go | 4 +- ...all_msan_and_race_and_asan_require_cgo.txt | 8 +- src/runtime/race.go | 4 +- src/runtime/race/doc.go | 2 + src/runtime/race/mkcgo.sh | 20 ++++ src/runtime/race/race.go | 7 +- src/runtime/race/race_darwin_amd64.go | 101 ++++++++++++++++++ src/runtime/race/race_darwin_arm64.go | 95 ++++++++++++++++ 8 files changed, 234 insertions(+), 7 deletions(-) create mode 100755 src/runtime/race/mkcgo.sh create mode 100644 src/runtime/race/race_darwin_amd64.go create mode 100644 src/runtime/race/race_darwin_arm64.go diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index c8fee098e0..48c91d54b3 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -162,7 +162,9 @@ func instrumentInit() { } modeFlag := "-" + mode - if !cfg.BuildContext.CgoEnabled { + // Check that cgo is enabled. + // Note: On macOS, -race does not require cgo. -asan and -msan still do. + if !cfg.BuildContext.CgoEnabled && (cfg.Goos != "darwin" || cfg.BuildASan || cfg.BuildMSan) { if runtime.GOOS != cfg.Goos || runtime.GOARCH != cfg.Goarch { fmt.Fprintf(os.Stderr, "go: %s requires cgo\n", modeFlag) } else { diff --git a/src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt b/src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt index 0c68e2cf1b..d8f2abaf3f 100644 --- a/src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt +++ b/src/cmd/go/testdata/script/install_msan_and_race_and_asan_require_cgo.txt @@ -2,9 +2,11 @@ env CGO_ENABLED=0 -[race] ! go install -race triv.go -[race] stderr '-race requires cgo' -[race] ! stderr '-msan' +[GOOS:darwin] [!short] [race] go build -race triv.go + +[!GOOS:darwin] [race] ! go install -race triv.go +[!GOOS:darwin] [race] stderr '-race requires cgo' +[!GOOS:darwin] [race] ! stderr '-msan' [msan] ! go install -msan triv.go [msan] stderr '-msan requires cgo' diff --git a/src/runtime/race.go b/src/runtime/race.go index f68e1aeaac..40b6e00398 100644 --- a/src/runtime/race.go +++ b/src/runtime/race.go @@ -360,8 +360,8 @@ func isvalidaddr(addr unsafe.Pointer) bool { //go:nosplit func raceinit() (gctx, pctx uintptr) { - // cgo is required to initialize libc, which is used by race runtime - if !iscgo { + // On most machines, cgo is required to initialize libc, which is used by race runtime. + if !iscgo && GOOS != "darwin" { throw("raceinit: race build must use cgo") } diff --git a/src/runtime/race/doc.go b/src/runtime/race/doc.go index 9e93f66042..60a20df5bf 100644 --- a/src/runtime/race/doc.go +++ b/src/runtime/race/doc.go @@ -7,3 +7,5 @@ // For details about the race detector see // https://golang.org/doc/articles/race_detector.html package race + +//go:generate ./mkcgo.sh diff --git a/src/runtime/race/mkcgo.sh b/src/runtime/race/mkcgo.sh new file mode 100755 index 0000000000..6ebe5a4fc7 --- /dev/null +++ b/src/runtime/race/mkcgo.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +hdr=' +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by mkcgo.sh. DO NOT EDIT. + +//go:build race + +' + +convert() { + (echo "$hdr"; go tool cgo -dynpackage race -dynimport $1) | gofmt +} + +convert race_darwin_arm64.syso >race_darwin_arm64.go +convert internal/amd64v1/race_darwin.syso >race_darwin_amd64.go + diff --git a/src/runtime/race/race.go b/src/runtime/race/race.go index 8692066341..9c508ebc2b 100644 --- a/src/runtime/race/race.go +++ b/src/runtime/race/race.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 (race && linux && amd64) || (race && freebsd && amd64) || (race && netbsd && amd64) || (race && darwin && amd64) || (race && windows && amd64) || (race && linux && ppc64le) || (race && linux && arm64) || (race && darwin && arm64) || (race && openbsd && amd64) || (race && linux && s390x) +//go:build race && ((linux && (amd64 || arm64 || ppc64le || s390x)) || ((freebsd || netbsd || openbsd || windows) && amd64)) package race @@ -11,5 +11,10 @@ package race // The prebuilt race runtime lives in race_GOOS_GOARCH.syso. // Calls to the runtime are done directly from src/runtime/race.go. +// On darwin we always use system DLLs to create threads, +// so we use race_darwin_$GOARCH.go to provide the syso-derived +// symbol information without needing to invoke cgo. +// This allows -race to be used on Mac systems without a C toolchain. + // void __race_unused_func(void); import "C" diff --git a/src/runtime/race/race_darwin_amd64.go b/src/runtime/race/race_darwin_amd64.go new file mode 100644 index 0000000000..fbb838aa2e --- /dev/null +++ b/src/runtime/race/race_darwin_amd64.go @@ -0,0 +1,101 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by mkcgo.sh. DO NOT EDIT. + +//go:build race + +package race + +//go:cgo_import_dynamic _Block_object_assign _Block_object_assign "" +//go:cgo_import_dynamic _Block_object_dispose _Block_object_dispose "" +//go:cgo_import_dynamic _NSConcreteStackBlock _NSConcreteStackBlock "" +//go:cgo_import_dynamic _NSGetArgv _NSGetArgv "" +//go:cgo_import_dynamic _NSGetEnviron _NSGetEnviron "" +//go:cgo_import_dynamic _NSGetExecutablePath _NSGetExecutablePath "" +//go:cgo_import_dynamic __bzero __bzero "" +//go:cgo_import_dynamic __error __error "" +//go:cgo_import_dynamic __fork __fork "" +//go:cgo_import_dynamic __mmap __mmap "" +//go:cgo_import_dynamic __munmap __munmap "" +//go:cgo_import_dynamic __stack_chk_fail __stack_chk_fail "" +//go:cgo_import_dynamic __stack_chk_guard __stack_chk_guard "" +//go:cgo_import_dynamic _dyld_get_image_header _dyld_get_image_header "" +//go:cgo_import_dynamic _dyld_get_image_name _dyld_get_image_name "" +//go:cgo_import_dynamic _dyld_get_image_vmaddr_slide _dyld_get_image_vmaddr_slide "" +//go:cgo_import_dynamic _dyld_get_shared_cache_range _dyld_get_shared_cache_range "" +//go:cgo_import_dynamic _dyld_get_shared_cache_uuid _dyld_get_shared_cache_uuid "" +//go:cgo_import_dynamic _dyld_image_count _dyld_image_count "" +//go:cgo_import_dynamic _exit _exit "" +//go:cgo_import_dynamic abort abort "" +//go:cgo_import_dynamic arc4random_buf arc4random_buf "" +//go:cgo_import_dynamic close close "" +//go:cgo_import_dynamic dlsym dlsym "" +//go:cgo_import_dynamic dup dup "" +//go:cgo_import_dynamic dup2 dup2 "" +//go:cgo_import_dynamic dyld_shared_cache_iterate_text dyld_shared_cache_iterate_text "" +//go:cgo_import_dynamic execve execve "" +//go:cgo_import_dynamic exit exit "" +//go:cgo_import_dynamic fstat$INODE64 fstat$INODE64 "" +//go:cgo_import_dynamic ftruncate ftruncate "" +//go:cgo_import_dynamic getpid getpid "" +//go:cgo_import_dynamic getrlimit getrlimit "" +//go:cgo_import_dynamic gettimeofday gettimeofday "" +//go:cgo_import_dynamic getuid getuid "" +//go:cgo_import_dynamic grantpt grantpt "" +//go:cgo_import_dynamic ioctl ioctl "" +//go:cgo_import_dynamic isatty isatty "" +//go:cgo_import_dynamic lstat$INODE64 lstat$INODE64 "" +//go:cgo_import_dynamic mach_absolute_time mach_absolute_time "" +//go:cgo_import_dynamic mach_task_self_ mach_task_self_ "" +//go:cgo_import_dynamic mach_timebase_info mach_timebase_info "" +//go:cgo_import_dynamic mach_vm_region_recurse mach_vm_region_recurse "" +//go:cgo_import_dynamic madvise madvise "" +//go:cgo_import_dynamic malloc_num_zones malloc_num_zones "" +//go:cgo_import_dynamic malloc_zones malloc_zones "" +//go:cgo_import_dynamic memcpy memcpy "" +//go:cgo_import_dynamic memset_pattern16 memset_pattern16 "" +//go:cgo_import_dynamic mkdir mkdir "" +//go:cgo_import_dynamic mprotect mprotect "" +//go:cgo_import_dynamic open open "" +//go:cgo_import_dynamic pipe pipe "" +//go:cgo_import_dynamic posix_openpt posix_openpt "" +//go:cgo_import_dynamic posix_spawn posix_spawn "" +//go:cgo_import_dynamic posix_spawn_file_actions_addclose posix_spawn_file_actions_addclose "" +//go:cgo_import_dynamic posix_spawn_file_actions_adddup2 posix_spawn_file_actions_adddup2 "" +//go:cgo_import_dynamic posix_spawn_file_actions_destroy posix_spawn_file_actions_destroy "" +//go:cgo_import_dynamic posix_spawn_file_actions_init posix_spawn_file_actions_init "" +//go:cgo_import_dynamic posix_spawnattr_destroy posix_spawnattr_destroy "" +//go:cgo_import_dynamic posix_spawnattr_init posix_spawnattr_init "" +//go:cgo_import_dynamic posix_spawnattr_setflags posix_spawnattr_setflags "" +//go:cgo_import_dynamic pthread_attr_getstack pthread_attr_getstack "" +//go:cgo_import_dynamic pthread_create pthread_create "" +//go:cgo_import_dynamic pthread_get_stackaddr_np pthread_get_stackaddr_np "" +//go:cgo_import_dynamic pthread_get_stacksize_np pthread_get_stacksize_np "" +//go:cgo_import_dynamic pthread_getspecific pthread_getspecific "" +//go:cgo_import_dynamic pthread_join pthread_join "" +//go:cgo_import_dynamic pthread_self pthread_self "" +//go:cgo_import_dynamic pthread_sigmask pthread_sigmask "" +//go:cgo_import_dynamic pthread_threadid_np pthread_threadid_np "" +//go:cgo_import_dynamic read read "" +//go:cgo_import_dynamic readlink readlink "" +//go:cgo_import_dynamic realpath$DARWIN_EXTSN realpath$DARWIN_EXTSN "" +//go:cgo_import_dynamic rename rename "" +//go:cgo_import_dynamic sched_yield sched_yield "" +//go:cgo_import_dynamic setrlimit setrlimit "" +//go:cgo_import_dynamic sigaction sigaction "" +//go:cgo_import_dynamic stat$INODE64 stat$INODE64 "" +//go:cgo_import_dynamic sysconf sysconf "" +//go:cgo_import_dynamic sysctl sysctl "" +//go:cgo_import_dynamic sysctlbyname sysctlbyname "" +//go:cgo_import_dynamic task_info task_info "" +//go:cgo_import_dynamic tcgetattr tcgetattr "" +//go:cgo_import_dynamic tcsetattr tcsetattr "" +//go:cgo_import_dynamic unlink unlink "" +//go:cgo_import_dynamic unlockpt unlockpt "" +//go:cgo_import_dynamic usleep usleep "" +//go:cgo_import_dynamic vm_region_64 vm_region_64 "" +//go:cgo_import_dynamic vm_region_recurse_64 vm_region_recurse_64 "" +//go:cgo_import_dynamic waitpid waitpid "" +//go:cgo_import_dynamic write write "" diff --git a/src/runtime/race/race_darwin_arm64.go b/src/runtime/race/race_darwin_arm64.go new file mode 100644 index 0000000000..fe8584c322 --- /dev/null +++ b/src/runtime/race/race_darwin_arm64.go @@ -0,0 +1,95 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by mkcgo.sh. DO NOT EDIT. + +//go:build race + +package race + +//go:cgo_import_dynamic _NSGetArgv _NSGetArgv "" +//go:cgo_import_dynamic _NSGetEnviron _NSGetEnviron "" +//go:cgo_import_dynamic _NSGetExecutablePath _NSGetExecutablePath "" +//go:cgo_import_dynamic __error __error "" +//go:cgo_import_dynamic __fork __fork "" +//go:cgo_import_dynamic __mmap __mmap "" +//go:cgo_import_dynamic __munmap __munmap "" +//go:cgo_import_dynamic __stack_chk_fail __stack_chk_fail "" +//go:cgo_import_dynamic __stack_chk_guard __stack_chk_guard "" +//go:cgo_import_dynamic _dyld_get_image_header _dyld_get_image_header "" +//go:cgo_import_dynamic _dyld_get_image_name _dyld_get_image_name "" +//go:cgo_import_dynamic _dyld_get_image_vmaddr_slide _dyld_get_image_vmaddr_slide "" +//go:cgo_import_dynamic _dyld_image_count _dyld_image_count "" +//go:cgo_import_dynamic _exit _exit "" +//go:cgo_import_dynamic abort abort "" +//go:cgo_import_dynamic arc4random_buf arc4random_buf "" +//go:cgo_import_dynamic bzero bzero "" +//go:cgo_import_dynamic close close "" +//go:cgo_import_dynamic dlsym dlsym "" +//go:cgo_import_dynamic dup dup "" +//go:cgo_import_dynamic dup2 dup2 "" +//go:cgo_import_dynamic execve execve "" +//go:cgo_import_dynamic exit exit "" +//go:cgo_import_dynamic fstat fstat "" +//go:cgo_import_dynamic ftruncate ftruncate "" +//go:cgo_import_dynamic getpid getpid "" +//go:cgo_import_dynamic getrlimit getrlimit "" +//go:cgo_import_dynamic gettimeofday gettimeofday "" +//go:cgo_import_dynamic getuid getuid "" +//go:cgo_import_dynamic grantpt grantpt "" +//go:cgo_import_dynamic ioctl ioctl "" +//go:cgo_import_dynamic isatty isatty "" +//go:cgo_import_dynamic lstat lstat "" +//go:cgo_import_dynamic mach_absolute_time mach_absolute_time "" +//go:cgo_import_dynamic mach_task_self_ mach_task_self_ "" +//go:cgo_import_dynamic mach_timebase_info mach_timebase_info "" +//go:cgo_import_dynamic mach_vm_region_recurse mach_vm_region_recurse "" +//go:cgo_import_dynamic madvise madvise "" +//go:cgo_import_dynamic malloc_num_zones malloc_num_zones "" +//go:cgo_import_dynamic malloc_zones malloc_zones "" +//go:cgo_import_dynamic memcpy memcpy "" +//go:cgo_import_dynamic memset_pattern16 memset_pattern16 "" +//go:cgo_import_dynamic mkdir mkdir "" +//go:cgo_import_dynamic mprotect mprotect "" +//go:cgo_import_dynamic open open "" +//go:cgo_import_dynamic pipe pipe "" +//go:cgo_import_dynamic posix_openpt posix_openpt "" +//go:cgo_import_dynamic posix_spawn posix_spawn "" +//go:cgo_import_dynamic posix_spawn_file_actions_addclose posix_spawn_file_actions_addclose "" +//go:cgo_import_dynamic posix_spawn_file_actions_adddup2 posix_spawn_file_actions_adddup2 "" +//go:cgo_import_dynamic posix_spawn_file_actions_destroy posix_spawn_file_actions_destroy "" +//go:cgo_import_dynamic posix_spawn_file_actions_init posix_spawn_file_actions_init "" +//go:cgo_import_dynamic posix_spawnattr_destroy posix_spawnattr_destroy "" +//go:cgo_import_dynamic posix_spawnattr_init posix_spawnattr_init "" +//go:cgo_import_dynamic posix_spawnattr_setflags posix_spawnattr_setflags "" +//go:cgo_import_dynamic pthread_attr_getstack pthread_attr_getstack "" +//go:cgo_import_dynamic pthread_create pthread_create "" +//go:cgo_import_dynamic pthread_get_stackaddr_np pthread_get_stackaddr_np "" +//go:cgo_import_dynamic pthread_get_stacksize_np pthread_get_stacksize_np "" +//go:cgo_import_dynamic pthread_getspecific pthread_getspecific "" +//go:cgo_import_dynamic pthread_join pthread_join "" +//go:cgo_import_dynamic pthread_self pthread_self "" +//go:cgo_import_dynamic pthread_sigmask pthread_sigmask "" +//go:cgo_import_dynamic pthread_threadid_np pthread_threadid_np "" +//go:cgo_import_dynamic read read "" +//go:cgo_import_dynamic readlink readlink "" +//go:cgo_import_dynamic realpath$DARWIN_EXTSN realpath$DARWIN_EXTSN "" +//go:cgo_import_dynamic rename rename "" +//go:cgo_import_dynamic sched_yield sched_yield "" +//go:cgo_import_dynamic setrlimit setrlimit "" +//go:cgo_import_dynamic sigaction sigaction "" +//go:cgo_import_dynamic stat stat "" +//go:cgo_import_dynamic sysconf sysconf "" +//go:cgo_import_dynamic sysctl sysctl "" +//go:cgo_import_dynamic sysctlbyname sysctlbyname "" +//go:cgo_import_dynamic task_info task_info "" +//go:cgo_import_dynamic tcgetattr tcgetattr "" +//go:cgo_import_dynamic tcsetattr tcsetattr "" +//go:cgo_import_dynamic unlink unlink "" +//go:cgo_import_dynamic unlockpt unlockpt "" +//go:cgo_import_dynamic usleep usleep "" +//go:cgo_import_dynamic vm_region_64 vm_region_64 "" +//go:cgo_import_dynamic vm_region_recurse_64 vm_region_recurse_64 "" +//go:cgo_import_dynamic waitpid waitpid "" +//go:cgo_import_dynamic write write ""