This is an archive of the discontinued LLVM Phabricator instance.

[tsan] On OS X, build Go runtime with -mmacosx-version-min
ClosedPublic

Authored by kubamracek on May 26 2016, 2:40 AM.

Details

Summary

We're not building the Go runtime with -mmacosx-version-min, which means it'll have a minimum deployment target set to the system you're building on. Let's make the code compile (and link) with the same -mmacosx-version-min flag as the rest of TSan.

Diff Detail

Repository
rL LLVM

Event Timeline

kubamracek updated this revision to Diff 58582.May 26 2016, 2:40 AM
kubamracek retitled this revision from to [tsan] On OS X, build Go runtime with -mmacosx-version-min.
kubamracek updated this object.
kubamracek added reviewers: dvyukov, kcc, glider, samsonov.
kubamracek added a project: Restricted Project.
dvyukov added inline comments.May 28 2016, 11:30 PM
lib/tsan/CMakeLists.txt
129 ↗(On Diff #58582)

Result of this invocation is discarded. buildgo.sh itself should produce valid object file. Add -mmacosx-version-min to buildgo.sh and set it to 10.7 -- that's the minimum supported Mac version for Go.

kubamracek updated this revision to Diff 59023.May 31 2016, 1:48 AM
dvyukov accepted this revision.Jun 3 2016, 4:58 AM
dvyukov edited edge metadata.
This revision is now accepted and ready to land.Jun 3 2016, 4:58 AM
dvyukov requested changes to this revision.Jun 3 2016, 5:00 AM
dvyukov edited edge metadata.

Wait, will it work if -mmacosx-version-min is _not_ passed to linker? As far as I see, Go toolchain does not use -mmacosx-version-min when linking this object file.

This revision now requires changes to proceed.Jun 3 2016, 5:00 AM

-mmacosx-version-min needs to be passed to both compiler and linker. The compiler uses it to make sure it doesn’t use functions/symbols that are not available on older OS versions (and error out or warn). Linker needs this to weak-link appropriately (and strong-link whatever is already available in the specified OS version). When it’s not specified, it uses your system version, which is almost certainly not what you want -- your library will then only work on your system and higher.

There are cases where you’ll be lucky (e.g. if you only use functions/symbols that are available everywhere) even without -mmacosx-version-min.

When it’s not specified, it uses your system version

This applies to both compiler and linker? Just want to make sure.
What we will have is: compiler uses -mmacosx-version-min=10.7 when building this object file, but then linker does not have this flag. This still should work, right?
I understand that the resulting binary will work only versions >= build machine version. Nobody complained about this for Go as far as I know. Go runtime does not use any system headers and libraries and is very conservative about syscalls. If a particular user program uses system-dependent C/C++ code, then I guess it's its concern to pass -mmacosx-version-min.

Yes, this needs to be both compiler and linker. If not specified (in either case), it will assume you’re building only for your system and higher. If you “otool -l” a dylib, look for LC_VERSION_MIN_MACOSX, which says what minimal OS X version this dylib supports.

dvyukov accepted this revision.Jun 3 2016, 5:41 AM
dvyukov edited edge metadata.

I don't have a mac machine right now. OK, let's land this. I know what to revert if anything :)

This revision is now accepted and ready to land.Jun 3 2016, 5:41 AM

How are you shipping TSan with Go? Is it a dylib? It seems to me that it’s in a “.a” archive, linking it statically into user’s programs. In this case it depends how you link the resulting programs.

It's a single .o file (renamed to .syso).

It's a single .o file (renamed to .syso).

I see. In that case the Go compiler should already be passing *some* -mmacosx-version-min to the linker. If it isn’t then the resulting program will inherit your system OS version as the minimum supported OS X. Anyway, this is either a non-issue (Go compiler is already passing the correct flags) or the issue is not TSan-specific (Go compiler doesn’t set -mmacosx-version-min, all resulting binaries can only run on your system and newer).

Note that it’s okay to compile with some -mmacosx-version-min and link with a higher version. In this case only the higher version is supported.

It’s *not* okay to do it the other way, i.e. compile with some version and link with a lower version. This can introduce terrible bugs.

This is the 1.6.2 Go distribution from golang.org:

$ otool -l usr/local/go/src/runtime/race/race_darwin_amd64.syso | grep -A3 LC_VERSION_MIN_MACOSX
      cmd LC_VERSION_MIN_MACOSX
  cmdsize 16
  version 10.10
      sdk n/a

What is the version of the binaries produced by the toolchain? You need to do:
$ go test -c -race fmt
This will produce fmt.test binary linked with race_darwin_amd64.syso.
There are changes that Go linker does the right thing and plain ignores LC_VERSION_MIN_MACOSX. Yes, there is own linker, check src/cmd/link/internal/ld/macho.go.

But there is also "external" linking mode when the host system linker is invoked. And this change can affect that mode. So that's still a positive change... though I don't know if external linking mode supports tsan.

What is the version of the binaries produced by the toolchain? You need to do:
$ go test -c -race fmt

    cmd LC_VERSION_MIN_MACOSX
cmdsize 16
version 10.7
    sdk 10.7

This will produce fmt.test binary linked with race_darwin_amd64.syso.
There are changes that Go linker does the right thing and plain ignores LC_VERSION_MIN_MACOSX. Yes, there is own linker, check src/cmd/link/internal/ld/macho.go.

Wow. I didn’t expect that.

This revision was automatically updated to reflect the committed changes.