argv = append(argv, "-Wl,-x")
}
}
+ if *flagHostBuildid == "none" {
+ argv = append(argv, "-Wl,-no_uuid")
+ }
case objabi.Hopenbsd:
argv = append(argv, "-pthread")
if ctxt.BuildMode != BuildModePIE {
uuidUpdated = true
}
}
- if ctxt.IsDarwin() && !uuidUpdated && *flagBuildid != "" {
+ if ctxt.IsDarwin() && !uuidUpdated && len(buildinfo) > 0 {
updateMachoOutFile("rewriting uuid",
func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error {
return machoRewriteUuid(ctxt, exef, exem, outexe)
"strings"
"testing"
+ imacho "cmd/internal/macho"
"cmd/internal/sys"
)
t.Fatal(err)
}
found := false
- const LC_BUILD_VERSION = 0x32
checkMin := func(ver uint32) {
major, minor, patch := (ver>>16)&0xff, (ver>>8)&0xff, (ver>>0)&0xff
if major < 11 {
for _, cmd := range exem.Loads {
raw := cmd.Raw()
type_ := exem.ByteOrder.Uint32(raw)
- if type_ != LC_BUILD_VERSION {
+ if type_ != imacho.LC_BUILD_VERSION {
continue
}
osVer := exem.ByteOrder.Uint32(raw[12:])
}
}
+func TestMachOUUID(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+ if runtime.GOOS != "darwin" {
+ t.Skip("this is only for darwin")
+ }
+
+ t.Parallel()
+
+ tmpdir := t.TempDir()
+
+ src := filepath.Join(tmpdir, "main.go")
+ err := os.WriteFile(src, []byte(trivialSrc), 0666)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ extractUUID := func(exe string) string {
+ exem, err := macho.Open(exe)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer exem.Close()
+ for _, cmd := range exem.Loads {
+ raw := cmd.Raw()
+ type_ := exem.ByteOrder.Uint32(raw)
+ if type_ != imacho.LC_UUID {
+ continue
+ }
+ return string(raw[8:24])
+ }
+ return ""
+ }
+
+ tests := []struct{ name, ldflags, expect string }{
+ {"default", "", "gobuildid"},
+ {"gobuildid", "-B=gobuildid", "gobuildid"},
+ {"specific", "-B=0x0123456789ABCDEF0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45\x67\x89\xAB\xCD\xEF"},
+ {"none", "-B=none", ""},
+ }
+ if testenv.HasCGO() {
+ for _, test := range tests {
+ t1 := test
+ t1.name += "_external"
+ t1.ldflags += " -linkmode=external"
+ tests = append(tests, t1)
+ }
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ exe := filepath.Join(tmpdir, test.name)
+ cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-ldflags="+test.ldflags, "-o", exe, src)
+ if out, err := cmd.CombinedOutput(); err != nil {
+ t.Fatalf("%v: %v:\n%s", cmd.Args, err, out)
+ }
+ uuid := extractUUID(exe)
+ if test.expect == "gobuildid" {
+ // Go buildid is not known in source code. Check UUID is present,
+ // and satisifies UUIDv3.
+ if uuid == "" {
+ t.Fatal("expect nonempty UUID, got empty")
+ }
+ // The version number is the high 4 bits of byte 6.
+ if uuid[6]>>4 != 3 {
+ t.Errorf("expect v3 UUID, got %X (version %d)", uuid, uuid[6]>>4)
+ }
+ } else if uuid != test.expect {
+ t.Errorf("UUID mismatch: got %X, want %X", uuid, test.expect)
+ }
+ })
+ }
+}
+
const Issue34788src = `
package blah