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

go/internal/gccgoimporter: add XCOFF support

This commit adds support to read XCOFF files and AIX big archives in
go/internal/gccgoimporter.

Fixes: #29113

Change-Id: Id84d40358ff98fae5a576d1ebdd65980896365b9
Reviewed-on: https://go-review.googlesource.com/c/152720
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
parent ba607240
...@@ -230,7 +230,7 @@ var pkgDeps = map[string][]string{ ...@@ -230,7 +230,7 @@ var pkgDeps = map[string][]string{
"go/constant": {"L4", "go/token", "math/big"}, "go/constant": {"L4", "go/token", "math/big"},
"go/importer": {"L4", "go/build", "go/internal/gccgoimporter", "go/internal/gcimporter", "go/internal/srcimporter", "go/token", "go/types"}, "go/importer": {"L4", "go/build", "go/internal/gccgoimporter", "go/internal/gcimporter", "go/internal/srcimporter", "go/token", "go/types"},
"go/internal/gcimporter": {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"}, "go/internal/gcimporter": {"L4", "OS", "go/build", "go/constant", "go/token", "go/types", "text/scanner"},
"go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "text/scanner"}, "go/internal/gccgoimporter": {"L4", "OS", "debug/elf", "go/constant", "go/token", "go/types", "internal/xcoff", "text/scanner"},
"go/internal/srcimporter": {"L4", "OS", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"}, "go/internal/srcimporter": {"L4", "OS", "fmt", "go/ast", "go/build", "go/parser", "go/token", "go/types", "path/filepath"},
"go/types": {"L4", "GOPARSER", "container/heap", "go/constant"}, "go/types": {"L4", "GOPARSER", "container/heap", "go/constant"},
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"debug/elf" "debug/elf"
"errors" "errors"
"fmt" "fmt"
"internal/xcoff"
"io" "io"
"strconv" "strconv"
"strings" "strings"
...@@ -65,13 +66,13 @@ func arExportData(archive io.ReadSeeker) (io.ReadSeeker, error) { ...@@ -65,13 +66,13 @@ func arExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {
case armagt: case armagt:
return nil, errors.New("unsupported thin archive") return nil, errors.New("unsupported thin archive")
case armagb: case armagb:
return nil, errors.New("unsupported AIX big archive") return aixBigArExportData(archive)
default: default:
return nil, fmt.Errorf("unrecognized archive file format %q", buf[:]) return nil, fmt.Errorf("unrecognized archive file format %q", buf[:])
} }
} }
// standardArExportData returns export data form a standard archive. // standardArExportData returns export data from a standard archive.
func standardArExportData(archive io.ReadSeeker) (io.ReadSeeker, error) { func standardArExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {
off := int64(len(armag)) off := int64(len(armag))
for { for {
...@@ -126,6 +127,28 @@ func elfFromAr(member *io.SectionReader) (io.ReadSeeker, error) { ...@@ -126,6 +127,28 @@ func elfFromAr(member *io.SectionReader) (io.ReadSeeker, error) {
return sec.Open(), nil return sec.Open(), nil
} }
// aixBigArExportData returns export data from an AIX big archive.
func aixBigArExportData(archive io.ReadSeeker) (io.ReadSeeker, error) {
archiveAt := readerAtFromSeeker(archive)
arch, err := xcoff.NewArchive(archiveAt)
if err != nil {
return nil, err
}
for _, mem := range arch.Members {
f, err := arch.GetFile(mem.Name)
if err != nil {
return nil, err
}
sdat := f.CSect(".go_export")
if sdat != nil {
return bytes.NewReader(sdat), nil
}
}
return nil, fmt.Errorf(".go_export not found in this archive")
}
// readerAtFromSeeker turns an io.ReadSeeker into an io.ReaderAt. // readerAtFromSeeker turns an io.ReadSeeker into an io.ReaderAt.
// This is only safe because there won't be any concurrent seeks // This is only safe because there won't be any concurrent seeks
// while this code is executing. // while this code is executing.
......
...@@ -6,9 +6,11 @@ ...@@ -6,9 +6,11 @@
package gccgoimporter // import "go/internal/gccgoimporter" package gccgoimporter // import "go/internal/gccgoimporter"
import ( import (
"bytes"
"debug/elf" "debug/elf"
"fmt" "fmt"
"go/types" "go/types"
"internal/xcoff"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
...@@ -65,6 +67,7 @@ const ( ...@@ -65,6 +67,7 @@ const (
gccgov3Magic = "v3;\n" gccgov3Magic = "v3;\n"
goimporterMagic = "\n$$ " goimporterMagic = "\n$$ "
archiveMagic = "!<ar" archiveMagic = "!<ar"
aixbigafMagic = "<big"
) )
// Opens the export data file at the given path. If this is an ELF file, // Opens the export data file at the given path. If this is an ELF file,
...@@ -89,33 +92,44 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e ...@@ -89,33 +92,44 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
return return
} }
var elfreader io.ReaderAt var objreader io.ReaderAt
switch string(magic[:]) { switch string(magic[:]) {
case gccgov1Magic, gccgov2Magic, gccgov3Magic, goimporterMagic: case gccgov1Magic, gccgov2Magic, gccgov3Magic, goimporterMagic:
// Raw export data. // Raw export data.
reader = f reader = f
return return
case archiveMagic: case archiveMagic, aixbigafMagic:
reader, err = arExportData(f) reader, err = arExportData(f)
return return
default: default:
elfreader = f objreader = f
} }
ef, err := elf.NewFile(elfreader) ef, err := elf.NewFile(objreader)
if err != nil { if err == nil {
sec := ef.Section(".go_export")
if sec == nil {
err = fmt.Errorf("%s: .go_export section not found", fpath)
return
}
reader = sec.Open()
return return
} }
sec := ef.Section(".go_export") xf, err := xcoff.NewFile(objreader)
if sec == nil { if err == nil {
err = fmt.Errorf("%s: .go_export section not found", fpath) sdat := xf.CSect(".go_export")
if sdat == nil {
err = fmt.Errorf("%s: .go_export section not found", fpath)
return
}
reader = bytes.NewReader(sdat)
return return
} }
reader = sec.Open() err = fmt.Errorf("%s: unrecognized file format", fpath)
return return
} }
......
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