From ea51acbabc687a2270438b05bf765ada2968b69a Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Sun, 28 Jun 2020 16:28:52 +1000 Subject: [PATCH] cmd/internal/objfile: use pe.FileHeader.Machine to reliably determine GOARCH Current peFile.goarch looks for symbols like "_rt0_386_windows" to determine GOARCH. But "_rt0_386_windows" is not present in executables built with cgo. Use pe.FileHeader.Machine instead. This should work with any Windows executable, not just with Go built executable. Fixes #39682 Change-Id: Ie0ffce664f4b8b8fed69b2ecc482425b042a38d5 Reviewed-on: https://go-review.googlesource.com/c/go/+/240957 Run-TryBot: Alex Brainman TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang Reviewed-by: Emmanuel Odeke --- src/cmd/internal/objfile/pe.go | 14 +++++------ src/cmd/objdump/objdump_test.go | 31 ++++++++++++++++--------- src/cmd/objdump/testdata/fmthellocgo.go | 21 +++++++++++++++++ 3 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 src/cmd/objdump/testdata/fmthellocgo.go diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go index 259b59a4f4a..b20cda9a44b 100644 --- a/src/cmd/internal/objfile/pe.go +++ b/src/cmd/internal/objfile/pe.go @@ -182,18 +182,16 @@ func loadPETable(f *pe.File, sname, ename string) ([]byte, error) { } func (f *peFile) goarch() string { - // Not sure how to get the info we want from PE header. - // Look in symbol table for telltale rt0 symbol. - if _, err := findPESymbol(f.pe, "_rt0_386_windows"); err == nil { + switch f.pe.Machine { + case pe.IMAGE_FILE_MACHINE_I386: return "386" - } - if _, err := findPESymbol(f.pe, "_rt0_amd64_windows"); err == nil { + case pe.IMAGE_FILE_MACHINE_AMD64: return "amd64" - } - if _, err := findPESymbol(f.pe, "_rt0_arm_windows"); err == nil { + case pe.IMAGE_FILE_MACHINE_ARMNT: return "arm" + default: + return "" } - return "" } func (f *peFile) loadAddress() (uint64, error) { diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go index a9dc7d1a5e2..d9c1660ffd6 100644 --- a/src/cmd/objdump/objdump_test.go +++ b/src/cmd/objdump/objdump_test.go @@ -117,8 +117,7 @@ var target = flag.String("target", "", "test disassembly of `goos/goarch` binary // binary for the current system (only) and test that objdump // can handle that one. -func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string) { - t.Parallel() +func testDisasm(t *testing.T, srcfname string, printCode bool, printGnuAsm bool, flags ...string) { goarch := runtime.GOARCH if *target != "" { f := strings.Split(*target, "/") @@ -132,11 +131,11 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string) goarch = f[1] } - hash := md5.Sum([]byte(fmt.Sprintf("%v-%v-%v", flags, printCode, printGnuAsm))) + hash := md5.Sum([]byte(fmt.Sprintf("%v-%v-%v-%v", srcfname, flags, printCode, printGnuAsm))) hello := filepath.Join(tmp, fmt.Sprintf("hello-%x.exe", hash)) args := []string{"build", "-o", hello} args = append(args, flags...) - args = append(args, "fmthello.go") + args = append(args, srcfname) cmd := exec.Command(testenv.GoToolPath(t), args...) // "Bad line" bug #36683 is sensitive to being run in the source directory. cmd.Dir = "testdata" @@ -146,7 +145,7 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string) t.Logf("Running %v", cmd.Args) out, err := cmd.CombinedOutput() if err != nil { - t.Fatalf("go build fmthello.go: %v\n%s", err, out) + t.Fatalf("go build %s: %v\n%s", srcfname, err, out) } need := []string{ "TEXT main.main(SB)", @@ -155,7 +154,7 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string) if printCode { need = append(need, ` Println("hello, world")`) } else { - need = append(need, "fmthello.go:6") + need = append(need, srcfname+":6") } switch goarch { @@ -199,7 +198,8 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string) t.Logf("Running %v", cmd.Args) if err != nil { - t.Fatalf("objdump fmthello.exe: %v\n%s", err, out) + exename := srcfname[:len(srcfname)-len(filepath.Ext(srcfname))] + ".exe" + t.Fatalf("objdump %q: %v\n%s", exename, err, out) } text := string(out) @@ -222,6 +222,14 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string) } } +func testGoAndCgoDisasm(t *testing.T, printCode bool, printGnuAsm bool) { + t.Parallel() + testDisasm(t, "fmthello.go", printCode, printGnuAsm) + if build.Default.CgoEnabled { + testDisasm(t, "fmthellocgo.go", printCode, printGnuAsm) + } +} + func TestDisasm(t *testing.T) { switch runtime.GOARCH { case "mips", "mipsle", "mips64", "mips64le": @@ -231,7 +239,7 @@ func TestDisasm(t *testing.T) { case "s390x": t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) } - testDisasm(t, false, false) + testGoAndCgoDisasm(t, false, false) } func TestDisasmCode(t *testing.T) { @@ -239,7 +247,7 @@ func TestDisasmCode(t *testing.T) { case "mips", "mipsle", "mips64", "mips64le", "riscv64", "s390x": t.Skipf("skipping on %s, issue 19160", runtime.GOARCH) } - testDisasm(t, true, false) + testGoAndCgoDisasm(t, true, false) } func TestDisasmGnuAsm(t *testing.T) { @@ -247,7 +255,7 @@ func TestDisasmGnuAsm(t *testing.T) { case "mips", "mipsle", "mips64", "mips64le", "riscv64", "s390x": t.Skipf("skipping on %s, issue 19160", runtime.GOARCH) } - testDisasm(t, false, true) + testGoAndCgoDisasm(t, false, true) } func TestDisasmExtld(t *testing.T) { @@ -268,7 +276,8 @@ func TestDisasmExtld(t *testing.T) { if !build.Default.CgoEnabled { t.Skip("skipping because cgo is not enabled") } - testDisasm(t, false, false, "-ldflags=-linkmode=external") + t.Parallel() + testDisasm(t, "fmthello.go", false, false, "-ldflags=-linkmode=external") } func TestDisasmGoobj(t *testing.T) { diff --git a/src/cmd/objdump/testdata/fmthellocgo.go b/src/cmd/objdump/testdata/fmthellocgo.go new file mode 100644 index 00000000000..6555c3bacfa --- /dev/null +++ b/src/cmd/objdump/testdata/fmthellocgo.go @@ -0,0 +1,21 @@ +package main + +import "fmt" +import "C" + +func main() { + Println("hello, world") + if flag { +//line fmthello.go:999999 + Println("bad line") + for { + } + } +} + +//go:noinline +func Println(s string) { + fmt.Println(s) +} + +var flag bool