Commit 0ff9df6b authored by Clément Chigot's avatar Clément Chigot Committed by Ian Lance Taylor

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 <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent bea58ef3
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)
......
......@@ -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
}
......@@ -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()
......
......@@ -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
}
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment