diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-01-23 04:44:12 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-01-23 04:44:12 +0000 |
commit | 38ad6f8a440f7594b9cea5fb999078035ee36a57 (patch) | |
tree | 2499e11d4df673826314f3f14158f8467d4a42db /libgo | |
parent | f991f1022c6254678cc61304ecd1e0fba0ac79db (diff) | |
download | gcc-38ad6f8a440f7594b9cea5fb999078035ee36a57.zip gcc-38ad6f8a440f7594b9cea5fb999078035ee36a57.tar.gz gcc-38ad6f8a440f7594b9cea5fb999078035ee36a57.tar.bz2 |
cmd/go: buildid support for AIX archives.
Reviewed-on: https://go-review.googlesource.com/88935
From-SVN: r256971
Diffstat (limited to 'libgo')
-rw-r--r-- | libgo/go/cmd/go/internal/work/buildid.go | 37 | ||||
-rw-r--r-- | libgo/go/cmd/go/internal/work/exec.go | 10 | ||||
-rw-r--r-- | libgo/go/cmd/internal/buildid/buildid.go | 83 |
3 files changed, 130 insertions, 0 deletions
diff --git a/libgo/go/cmd/go/internal/work/buildid.go b/libgo/go/cmd/go/internal/work/buildid.go index 39ca20e..e2ae850 100644 --- a/libgo/go/cmd/go/internal/work/buildid.go +++ b/libgo/go/cmd/go/internal/work/buildid.go @@ -330,6 +330,43 @@ func (b *Builder) gccgoBuildIDELFFile(a *Action) (string, error) { return sfile, nil } +// gccgoBuildIDXCOFFFile creates an assembler file that records the +// action's build ID in a CSECT (AIX linker deletes CSECTs that are +// not referenced in the output file). +func (b *Builder) gccgoBuildIDXCOFFFile(a *Action) (string, error) { + sfile := a.Objdir + "_buildid.s" + + var buf bytes.Buffer + fmt.Fprintf(&buf, "\t.csect .go.buildid[XO]\n") + fmt.Fprintf(&buf, "\t.byte ") + for i := 0; i < len(a.buildID); i++ { + if i > 0 { + if i%8 == 0 { + fmt.Fprintf(&buf, "\n\t.byte ") + } else { + fmt.Fprintf(&buf, ",") + } + } + fmt.Fprintf(&buf, "%#02x", a.buildID[i]) + } + fmt.Fprintf(&buf, "\n") + + if cfg.BuildN || cfg.BuildX { + for _, line := range bytes.Split(buf.Bytes(), []byte("\n")) { + b.Showcmd("", "echo '%s' >> %s", line, sfile) + } + if cfg.BuildN { + return sfile, nil + } + } + + if err := ioutil.WriteFile(sfile, buf.Bytes(), 0666); err != nil { + return "", err + } + + return sfile, nil +} + // buildID returns the build ID found in the given file. // If no build ID is found, buildID returns the content hash of the file. func (b *Builder) buildID(file string) string { diff --git a/libgo/go/cmd/go/internal/work/exec.go b/libgo/go/cmd/go/internal/work/exec.go index c2704c4..edd2694 100644 --- a/libgo/go/cmd/go/internal/work/exec.go +++ b/libgo/go/cmd/go/internal/work/exec.go @@ -637,6 +637,16 @@ func (b *Builder) build(a *Action) (err error) { return err } objects = append(objects, ofiles...) + case "aix": + asmfile, err := b.gccgoBuildIDXCOFFFile(a) + if err != nil { + return err + } + ofiles, err := BuildToolchain.asm(b, a, []string{asmfile}) + if err != nil { + return err + } + objects = append(objects, ofiles...) } } diff --git a/libgo/go/cmd/internal/buildid/buildid.go b/libgo/go/cmd/internal/buildid/buildid.go index fa3d7f3..41e6c77 100644 --- a/libgo/go/cmd/internal/buildid/buildid.go +++ b/libgo/go/cmd/internal/buildid/buildid.go @@ -7,6 +7,7 @@ package buildid import ( "bytes" "debug/elf" + "debug/xcoff" "fmt" "io" "os" @@ -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") |