}
}
-// 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")
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"
// 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
}
return []string{"-mabi=64"}
case "mips", "mipsle":
return []string{"-mabi=32", "-march=mips32"}
+ case "ppc64":
+ if cfg.Goos == "aix" {
+ return []string{"-maix64"}
+ }
}
return nil
}
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 {
}
}
- 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,
}
}
+ 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"))
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)
import (
"bytes"
+ "cmd/internal/xcoff"
"debug/elf"
"fmt"
"io"
return "", err
}
if string(buf) != "!<arch>\n" {
+ if string(buf) == "<bigaf>\n" {
+ return readGccgoBigArchive(name, f)
+ }
return readBinary(name, f)
}
}
}
+// 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")