mirror of https://github.com/golang/go.git
cmd: allow build with gccgo on AIX
This commit adapts cmd/internal/buildid and cmd/go to allow the use of gccgo on AIX. Buildid is supported only for AIX archives. Change-Id: I14c790a8994ae8d2ee629d8751e04189c30ffd94 Reviewed-on: https://go-review.googlesource.com/c/145417 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
0ad332d80c
commit
faafcc606e
|
|
@ -322,13 +322,16 @@ func assemblerIsGas() bool {
|
|||
}
|
||||
}
|
||||
|
||||
// gccgoBuildIDELFFile creates an assembler file that records the
|
||||
// action's build ID in an SHF_EXCLUDE section.
|
||||
func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) {
|
||||
// gccgoBuildIDFile creates an assembler file that records the
|
||||
// action's build ID in an SHF_EXCLUDE section for ELF files or
|
||||
// in a CSECT in XCOFF files.
|
||||
func (b *Builder) gccgoBuildIDFile(a *Action) (string, error) {
|
||||
sfile := a.Objdir + "_buildid.s"
|
||||
|
||||
var buf bytes.Buffer
|
||||
if cfg.Goos != "solaris" || assemblerIsGas() {
|
||||
if cfg.Goos == "aix" {
|
||||
fmt.Fprintf(&buf, "\t.csect .go.buildid[XO]\n")
|
||||
} else if cfg.Goos != "solaris" || assemblerIsGas() {
|
||||
fmt.Fprintf(&buf, "\t"+`.section .go.buildid,"e"`+"\n")
|
||||
} else if cfg.Goarch == "sparc" || cfg.Goarch == "sparc64" {
|
||||
fmt.Fprintf(&buf, "\t"+`.section ".go.buildid",#exclude`+"\n")
|
||||
|
|
@ -347,7 +350,7 @@ func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) {
|
|||
fmt.Fprintf(&buf, "%#02x", a.buildID[i])
|
||||
}
|
||||
fmt.Fprintf(&buf, "\n")
|
||||
if cfg.Goos != "solaris" {
|
||||
if cfg.Goos != "solaris" && cfg.Goos != "aix" {
|
||||
secType := "@progbits"
|
||||
if cfg.Goarch == "arm" {
|
||||
secType = "%progbits"
|
||||
|
|
|
|||
|
|
@ -699,8 +699,8 @@ func (b *Builder) build(a *Action) (err error) {
|
|||
// This is read by readGccgoArchive in cmd/internal/buildid/buildid.go.
|
||||
if a.buildID != "" && cfg.BuildToolchainName == "gccgo" {
|
||||
switch cfg.Goos {
|
||||
case "android", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||
asmfile, err := b.gccgoBuildIDELFFile(a)
|
||||
case "aix", "android", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||
asmfile, err := b.gccgoBuildIDFile(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -2297,6 +2297,10 @@ func (b *Builder) gccArchArgs() []string {
|
|||
return []string{"-mabi=64"}
|
||||
case "mips", "mipsle":
|
||||
return []string{"-mabi=32", "-march=mips32"}
|
||||
case "ppc64":
|
||||
if cfg.Goos == "aix" {
|
||||
return []string{"-maix64"}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,7 +186,15 @@ func (gccgoToolchain) pack(b *Builder, a *Action, afile string, ofiles []string)
|
|||
for _, f := range ofiles {
|
||||
absOfiles = append(absOfiles, mkAbs(objdir, f))
|
||||
}
|
||||
return b.run(a, p.Dir, p.ImportPath, nil, "ar", "rc", mkAbs(objdir, afile), absOfiles)
|
||||
var arArgs string
|
||||
if cfg.Goos == "aix" && cfg.Goarch == "ppc64" {
|
||||
// AIX puts both 32-bit and 64-bit objects in the same archive.
|
||||
// Tell the AIX "ar" command to only care about 64-bit objects.
|
||||
// AIX "ar" command does not know D option.
|
||||
arArgs = "-X64"
|
||||
}
|
||||
|
||||
return b.run(a, p.Dir, p.ImportPath, nil, "ar", arArgs, "rc", mkAbs(objdir, afile), absOfiles)
|
||||
}
|
||||
|
||||
func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string, allactions []*Action, buildmode, desc string) error {
|
||||
|
|
@ -342,17 +350,24 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
|
|||
}
|
||||
}
|
||||
|
||||
ldflags = append(ldflags, "-Wl,--whole-archive")
|
||||
wholeArchive := []string{"-Wl,--whole-archive"}
|
||||
noWholeArchive := []string{"-Wl,--no-whole-archive"}
|
||||
if cfg.Goos == "aix" {
|
||||
wholeArchive = nil
|
||||
noWholeArchive = nil
|
||||
}
|
||||
ldflags = append(ldflags, wholeArchive...)
|
||||
ldflags = append(ldflags, afiles...)
|
||||
ldflags = append(ldflags, "-Wl,--no-whole-archive")
|
||||
ldflags = append(ldflags, noWholeArchive...)
|
||||
|
||||
ldflags = append(ldflags, cgoldflags...)
|
||||
ldflags = append(ldflags, envList("CGO_LDFLAGS", "")...)
|
||||
if root.Package != nil {
|
||||
ldflags = append(ldflags, root.Package.CgoLDFLAGS...)
|
||||
}
|
||||
|
||||
ldflags = str.StringList("-Wl,-(", ldflags, "-Wl,-)")
|
||||
if cfg.Goos != "aix" {
|
||||
ldflags = str.StringList("-Wl,-(", ldflags, "-Wl,-)")
|
||||
}
|
||||
|
||||
if root.buildID != "" {
|
||||
// On systems that normally use gold or the GNU linker,
|
||||
|
|
@ -363,11 +378,17 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
|
|||
}
|
||||
}
|
||||
|
||||
var rLibPath string
|
||||
if cfg.Goos == "aix" {
|
||||
rLibPath = "-Wl,-blibpath="
|
||||
} else {
|
||||
rLibPath = "-Wl,-rpath="
|
||||
}
|
||||
for _, shlib := range shlibs {
|
||||
ldflags = append(
|
||||
ldflags,
|
||||
"-L"+filepath.Dir(shlib),
|
||||
"-Wl,-rpath="+filepath.Dir(shlib),
|
||||
rLibPath+filepath.Dir(shlib),
|
||||
"-l"+strings.TrimSuffix(
|
||||
strings.TrimPrefix(filepath.Base(shlib), "lib"),
|
||||
".so"))
|
||||
|
|
@ -412,7 +433,10 @@ func (tools gccgoToolchain) link(b *Builder, root *Action, out, importcfg string
|
|||
case "c-shared":
|
||||
ldflags = append(ldflags, "-shared", "-nostdlib", "-Wl,--whole-archive", "-lgolibbegin", "-Wl,--no-whole-archive", "-lgo", "-lgcc_s", "-lgcc", "-lc", "-lgcc")
|
||||
case "shared":
|
||||
ldflags = append(ldflags, "-zdefs", "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
|
||||
if cfg.Goos != "aix" {
|
||||
ldflags = append(ldflags, "-zdefs")
|
||||
}
|
||||
ldflags = append(ldflags, "-shared", "-nostdlib", "-lgo", "-lgcc_s", "-lgcc", "-lc")
|
||||
|
||||
default:
|
||||
base.Fatalf("-buildmode=%s not supported for gccgo", buildmode)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package buildid
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"cmd/internal/xcoff"
|
||||
"debug/elf"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -40,6 +41,9 @@ func ReadFile(name string) (id string, err error) {
|
|||
return "", err
|
||||
}
|
||||
if string(buf) != "!<arch>\n" {
|
||||
if string(buf) == "<bigaf>\n" {
|
||||
return readGccgoBigArchive(name, f)
|
||||
}
|
||||
return readBinary(name, f)
|
||||
}
|
||||
|
||||
|
|
@ -157,6 +161,85 @@ func readGccgoArchive(name string, f *os.File) (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
// readGccgoBigArchive tries to parse the archive as an AIX big
|
||||
// archive file, and fetch the build ID from the _buildid.o entry.
|
||||
// The _buildid.o entry is written by (*Builder).gccgoBuildIDXCOFFFile
|
||||
// in cmd/go/internal/work/exec.go.
|
||||
func readGccgoBigArchive(name string, f *os.File) (string, error) {
|
||||
bad := func() (string, error) {
|
||||
return "", &os.PathError{Op: "parse", Path: name, Err: errBuildIDMalformed}
|
||||
}
|
||||
|
||||
// Read fixed-length header.
|
||||
if _, err := f.Seek(0, io.SeekStart); err != nil {
|
||||
return "", err
|
||||
}
|
||||
var flhdr [128]byte
|
||||
if _, err := io.ReadFull(f, flhdr[:]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Read first member offset.
|
||||
offStr := strings.TrimSpace(string(flhdr[68:88]))
|
||||
off, err := strconv.ParseInt(offStr, 10, 64)
|
||||
if err != nil {
|
||||
return bad()
|
||||
}
|
||||
for {
|
||||
if off == 0 {
|
||||
// No more entries, no build ID.
|
||||
return "", nil
|
||||
}
|
||||
if _, err := f.Seek(off, io.SeekStart); err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Read member header.
|
||||
var hdr [112]byte
|
||||
if _, err := io.ReadFull(f, hdr[:]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
// Read member name length.
|
||||
namLenStr := strings.TrimSpace(string(hdr[108:112]))
|
||||
namLen, err := strconv.ParseInt(namLenStr, 10, 32)
|
||||
if err != nil {
|
||||
return bad()
|
||||
}
|
||||
if namLen == 10 {
|
||||
var nam [10]byte
|
||||
if _, err := io.ReadFull(f, nam[:]); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if string(nam[:]) == "_buildid.o" {
|
||||
sizeStr := strings.TrimSpace(string(hdr[0:20]))
|
||||
size, err := strconv.ParseInt(sizeStr, 10, 64)
|
||||
if err != nil {
|
||||
return bad()
|
||||
}
|
||||
off += int64(len(hdr)) + namLen + 2
|
||||
if off&1 != 0 {
|
||||
off++
|
||||
}
|
||||
sr := io.NewSectionReader(f, off, size)
|
||||
x, err := xcoff.NewFile(sr)
|
||||
if err != nil {
|
||||
return bad()
|
||||
}
|
||||
data := x.CSect(".go.buildid")
|
||||
if data == nil {
|
||||
return bad()
|
||||
}
|
||||
return string(data), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Read next member offset.
|
||||
offStr = strings.TrimSpace(string(hdr[20:40]))
|
||||
off, err = strconv.ParseInt(offStr, 10, 64)
|
||||
if err != nil {
|
||||
return bad()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
goBuildPrefix = []byte("\xff Go build ID: \"")
|
||||
goBuildEnd = []byte("\"\n \xff")
|
||||
|
|
|
|||
Loading…
Reference in New Issue