From 0ff9df6b53076a9402f691b07707f7d88d352722 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Cl=C3=A9ment=20Chigot?= Date: Wed, 20 Feb 2019 16:39:09 +0100 Subject: [PATCH] cmd: disable DWARF with old ld on aix/ppc64 DWARF relocations isn't working with some older ld, because of -Wl,-bnoobjreorder which is needed on Go. This commit checks ld's version and disable DWARF generation in cmd/link if it's too old. Some tests must therefore be skipped. Change-Id: I2e794c263eb0dfe0b42e7062fb80c26f086b44d1 Reviewed-on: https://go-review.googlesource.com/c/go/+/164007 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- .../compile/internal/ssa/stmtlines_test.go | 16 +++++++ src/cmd/internal/dwarf/dwarf.go | 42 +++++++++++++++++++ src/cmd/link/dwarf_test.go | 14 +++++++ src/cmd/link/internal/ld/dwarf.go | 5 +++ src/cmd/link/internal/ld/lib.go | 22 +++++----- 5 files changed, 89 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go index c71f8befd9..b8a9388b61 100644 --- a/src/cmd/compile/internal/ssa/stmtlines_test.go +++ b/src/cmd/compile/internal/ssa/stmtlines_test.go @@ -1,6 +1,7 @@ package ssa_test import ( + cmddwarf "cmd/internal/dwarf" "debug/dwarf" "debug/elf" "debug/macho" @@ -9,6 +10,7 @@ import ( "internal/testenv" "internal/xcoff" "io" + "os" "runtime" "testing" ) @@ -49,6 +51,20 @@ func TestStmtLines(t *testing.T) { t.Skip("skipping on plan9; no DWARF symbol table in executables") } + if runtime.GOOS == "aix" { + extld := os.Getenv("CC") + if extld == "" { + extld = "gcc" + } + enabled, err := cmddwarf.IsDWARFEnabledOnAIXLd(extld) + if err != nil { + t.Fatal(err) + } + if !enabled { + t.Skip("skipping on aix: no DWARF with ld version < 7.2.2 ") + } + } + lines := map[Line]bool{} dw, err := open(testenv.GoToolPath(t)) must(err) diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index 8ad84105a4..7f37cf059d 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -8,10 +8,13 @@ package dwarf import ( + "bytes" "cmd/internal/objabi" "errors" "fmt" + "os/exec" "sort" + "strconv" "strings" ) @@ -1526,3 +1529,42 @@ type byChildIndex []*Var func (s byChildIndex) Len() int { return len(s) } func (s byChildIndex) Less(i, j int) bool { return s[i].ChildIndex < s[j].ChildIndex } func (s byChildIndex) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +// IsDWARFEnabledOnAIX returns true if DWARF is possible on the +// current extld. +// AIX ld doesn't support DWARF with -bnoobjreorder with version +// prior to 7.2.2. +func IsDWARFEnabledOnAIXLd(extld string) (bool, error) { + out, err := exec.Command(extld, "-Wl,-V").CombinedOutput() + if err != nil { + // The normal output should display ld version and + // then fails because ".main" is not defined: + // ld: 0711-317 ERROR: Undefined symbol: .main + if !bytes.Contains(out, []byte("0711-317")) { + return false, fmt.Errorf("%s -Wl,-V failed: %v\n%s", extld, err, out) + } + } + // gcc -Wl,-V output should be: + // /usr/bin/ld: LD X.X.X(date) + // ... + out = bytes.TrimPrefix(out, []byte("/usr/bin/ld: LD ")) + vers := string(bytes.Split(out, []byte("("))[0]) + subvers := strings.Split(vers, ".") + if len(subvers) != 3 { + return false, fmt.Errorf("cannot parse %s -Wl,-V (%s): %v\n", extld, out, err) + } + if v, err := strconv.Atoi(subvers[0]); err != nil || v < 7 { + return false, nil + } else if v > 7 { + return true, nil + } + if v, err := strconv.Atoi(subvers[1]); err != nil || v < 2 { + return false, nil + } else if v > 2 { + return true, nil + } + if v, err := strconv.Atoi(subvers[2]); err != nil || v < 2 { + return false, nil + } + return true, nil +} diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index 9c3bc624ef..ecc96019be 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -5,6 +5,7 @@ package main import ( + cmddwarf "cmd/internal/dwarf" "cmd/internal/objfile" "debug/dwarf" "internal/testenv" @@ -39,6 +40,19 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) for _, prog := range []string{"testprog", "testprogcgo"} { prog := prog + expectDWARF := expectDWARF + if runtime.GOOS == "aix" && prog == "testprogcgo" { + extld := os.Getenv("CC") + if extld == "" { + extld = "gcc" + } + expectDWARF, err = cmddwarf.IsDWARFEnabledOnAIXLd(extld) + if err != nil { + t.Fatal(err) + } + + } + t.Run(prog, func(t *testing.T) { t.Parallel() diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 446fd572ac..d923b7599d 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1721,6 +1721,11 @@ func dwarfEnabled(ctxt *Link) bool { case ctxt.HeadType == objabi.Hdarwin: case ctxt.HeadType == objabi.Hwindows: case ctxt.HeadType == objabi.Haix: + res, err := dwarf.IsDWARFEnabledOnAIXLd(ctxt.extld()) + if err != nil { + Exitf("%v", err) + } + return res default: return false } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 44befc9637..d5efcee34b 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -322,18 +322,24 @@ func loadinternal(ctxt *Link, name string) *sym.Library { return nil } -// findLibPathCmd uses cmd command to find gcc library libname. -// It returns library full path if found, or "none" if not found. -func (ctxt *Link) findLibPathCmd(cmd, libname string) string { +// extld returns the current external linker. +func (ctxt *Link) extld() string { if *flagExtld == "" { *flagExtld = "gcc" } + return *flagExtld +} + +// findLibPathCmd uses cmd command to find gcc library libname. +// It returns library full path if found, or "none" if not found. +func (ctxt *Link) findLibPathCmd(cmd, libname string) string { + extld := ctxt.extld() args := hostlinkArchArgs(ctxt.Arch) args = append(args, cmd) if ctxt.Debugvlog != 0 { - ctxt.Logf("%s %v\n", *flagExtld, args) + ctxt.Logf("%s %v\n", extld, args) } - out, err := exec.Command(*flagExtld, args...).Output() + out, err := exec.Command(extld, args...).Output() if err != nil { if ctxt.Debugvlog != 0 { ctxt.Logf("not using a %s file because compiler failed\n%v\n%s\n", libname, err, out) @@ -1111,12 +1117,8 @@ func (ctxt *Link) hostlink() { return } - if *flagExtld == "" { - *flagExtld = "gcc" - } - var argv []string - argv = append(argv, *flagExtld) + argv = append(argv, ctxt.extld()) argv = append(argv, hostlinkArchArgs(ctxt.Arch)...) if *FlagS || debug_s { -- 2.50.0