mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/goobj: parse native objects in the archive
Also add HasCGO() to internal/testenv for tests. Updates #21706 Change-Id: I938188047024052bdb42b3ac1a77708f3c2a6dbb Reviewed-on: https://go-review.googlesource.com/62591 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
d254c61309
commit
1053ae5cf5
8 changed files with 274 additions and 21 deletions
|
|
@ -5,8 +5,12 @@
|
|||
package goobj
|
||||
|
||||
import (
|
||||
"debug/elf"
|
||||
"debug/macho"
|
||||
"debug/pe"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -16,10 +20,11 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
buildDir string
|
||||
go1obj string
|
||||
go2obj string
|
||||
goarchive string
|
||||
buildDir string
|
||||
go1obj string
|
||||
go2obj string
|
||||
goarchive string
|
||||
cgoarchive string
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
@ -47,6 +52,48 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(exit)
|
||||
}
|
||||
|
||||
func copyDir(dst, src string) error {
|
||||
err := os.MkdirAll(dst, 0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fis, err := ioutil.ReadDir(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, fi := range fis {
|
||||
err = copyFile(filepath.Join(dst, fi.Name()), filepath.Join(src, fi.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyFile(dst, src string) (err error) {
|
||||
var s, d *os.File
|
||||
s, err = os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
d, err = os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
e := d.Close()
|
||||
if err == nil {
|
||||
err = e
|
||||
}
|
||||
}()
|
||||
_, err = io.Copy(d, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildGoobj() error {
|
||||
var err error
|
||||
|
||||
|
|
@ -80,6 +127,29 @@ func buildGoobj() error {
|
|||
return fmt.Errorf("go tool pack c %s %s %s: %v\n%s", goarchive, go1obj, go2obj, err, out)
|
||||
}
|
||||
|
||||
if testenv.HasCGO() {
|
||||
gopath := filepath.Join(buildDir, "gopath")
|
||||
err = copyDir(filepath.Join(gopath, "src", "mycgo"), filepath.Join("testdata", "mycgo"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := exec.Command(gotool, "install", "mycgo")
|
||||
cmd.Env = append(os.Environ(), "GOPATH="+gopath)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go install mycgo: %v\n%s", err, out)
|
||||
}
|
||||
pat := filepath.Join(gopath, "pkg", "*", "mycgo.a")
|
||||
ms, err := filepath.Glob(pat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ms) == 0 {
|
||||
return fmt.Errorf("cannot found paths for pattern %s", pat)
|
||||
}
|
||||
cgoarchive = ms[0]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -144,3 +214,110 @@ func TestParseArchive(t *testing.T) {
|
|||
t.Errorf(`%s: symbol "mypkg.go2" not found`, path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCGOArchive(t *testing.T) {
|
||||
testenv.MustHaveCGO(t)
|
||||
|
||||
path := cgoarchive
|
||||
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
p, err := Parse(f, "mycgo")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if p.Arch != runtime.GOARCH {
|
||||
t.Errorf("%s: got %v, want %v", path, p.Arch, runtime.GOARCH)
|
||||
}
|
||||
var found1 bool
|
||||
var found2 bool
|
||||
for _, s := range p.Syms {
|
||||
if s.Name == "mycgo.go1" {
|
||||
found1 = true
|
||||
}
|
||||
if s.Name == "mycgo.go2" {
|
||||
found2 = true
|
||||
}
|
||||
}
|
||||
if !found1 {
|
||||
t.Errorf(`%s: symbol "mycgo.go1" not found`, path)
|
||||
}
|
||||
if !found2 {
|
||||
t.Errorf(`%s: symbol "mycgo.go2" not found`, path)
|
||||
}
|
||||
|
||||
c1 := "c1"
|
||||
c2 := "c2"
|
||||
|
||||
found1 = false
|
||||
found2 = false
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
c1 = "_" + c1
|
||||
c2 = "_" + c2
|
||||
for _, obj := range p.Native {
|
||||
mf, err := macho.NewFile(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, s := range mf.Symtab.Syms {
|
||||
switch s.Name {
|
||||
case c1:
|
||||
found1 = true
|
||||
case c2:
|
||||
found2 = true
|
||||
}
|
||||
}
|
||||
}
|
||||
case "windows":
|
||||
if runtime.GOARCH == "386" {
|
||||
c1 = "_" + c1
|
||||
c2 = "_" + c2
|
||||
}
|
||||
for _, obj := range p.Native {
|
||||
pf, err := pe.NewFile(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, s := range pf.Symbols {
|
||||
switch s.Name {
|
||||
case c1:
|
||||
found1 = true
|
||||
case c2:
|
||||
found2 = true
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
for _, obj := range p.Native {
|
||||
ef, err := elf.NewFile(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
syms, err := ef.Symbols()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, s := range syms {
|
||||
switch s.Name {
|
||||
case c1:
|
||||
found1 = true
|
||||
case c2:
|
||||
found2 = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found1 {
|
||||
t.Errorf(`%s: symbol %q not found`, path, c1)
|
||||
}
|
||||
if !found2 {
|
||||
t.Errorf(`%s: symbol %q not found`, path, c2)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue