From d3f5e3691712a2098fc8171574748389cec931a1 Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Sun, 5 Mar 2017 19:57:26 +1100 Subject: [PATCH] cmd/link: use IMAGE_SYM_CLASS_STATIC for local symbols Sometimes asm code in 2 different packages name its global symbols with the same name. When these symbols are passed to gcc, it refuses to link them thinking they are duplicate. Mark these symbols with IMAGE_SYM_CLASS_STATIC. Fixes #19198. Change-Id: Ia5f59ede47354a2b48ce60b7d406c9f097ff2000 Reviewed-on: https://go-review.googlesource.com/37810 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/cmd/go/go_test.go | 44 ++++++++++++++++++++++++++++++++++ src/cmd/link/internal/ld/pe.go | 6 ++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 2f8f36b162..5786defb8b 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -3803,3 +3803,47 @@ func TestFFLAGS(t *testing.T) { tg.grepStderr("no-such-fortran-flag", `missing expected "-no-such-fortran-flag"`) } + +// Issue 19198. +// This is really a cmd/link issue but this is a convenient place to test it. +func TestDuplicateGlobalAsmSymbols(t *testing.T) { + if runtime.GOARCH != "386" && runtime.GOARCH != "amd64" { + t.Skipf("skipping test on %s", runtime.GOARCH) + } + if !canCgo { + t.Skip("skipping because cgo not enabled") + } + + tg := testgo(t) + defer tg.cleanup() + tg.parallel() + + asm := ` +#include "textflag.h" + +DATA sym<>+0x0(SB)/8,$0 +GLOBL sym<>(SB),(NOPTR+RODATA),$8 + +TEXT ·Data(SB),NOSPLIT,$0 + MOVB sym<>(SB), AX + MOVB AX, ret+0(FP) + RET +` + tg.tempFile("go/src/a/a.s", asm) + tg.tempFile("go/src/a/a.go", `package a; func Data() uint8`) + tg.tempFile("go/src/b/b.s", asm) + tg.tempFile("go/src/b/b.go", `package b; func Data() uint8`) + tg.tempFile("go/src/p/p.go", ` +package main +import "a" +import "b" +import "C" +func main() { + _ = a.Data() + b.Data() +} +`) + tg.setenv("GOPATH", tg.path("go")) + exe := filepath.Join(tg.tempdir, "p.exe") + tg.creatingTemp(exe) + tg.run("build", "-o", exe, "p") +} diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 77c86fecbd..79e7890a38 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -1040,7 +1040,11 @@ func writePESymTableRecords(ctxt *Link) int { typ = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT typ = 0x0308 // "array of structs" } - writeOneSymbol(s, value, sect, typ, IMAGE_SYM_CLASS_EXTERNAL) + class := IMAGE_SYM_CLASS_EXTERNAL + if s.Version != 0 || (s.Type&obj.SHIDDEN != 0) || s.Attr.Local() { + class = IMAGE_SYM_CLASS_STATIC + } + writeOneSymbol(s, value, sect, typ, uint8(class)) } if Linkmode == LinkExternal {