aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2014-04-16 22:17:38 -0400
committerRuss Cox <rsc@golang.org>2014-04-16 22:17:38 -0400
commit06dc4e78c4c925f0e3763241b9695e6f3a36d8d6 (patch)
tree5ab648994c58459f7bcef47e135615a06771faed
parent387895f9ac5d34bfd32f23c1640b598c105bcb73 (diff)
downloadgo-06dc4e78c4c925f0e3763241b9695e6f3a36d8d6.tar.gz
go-06dc4e78c4c925f0e3763241b9695e6f3a36d8d6.zip
cmd/nm: windows pe handling fixes
- output absolute addresses, not relative; - accept negative section numbers. Update #6936 Fixes #7738 LGTM=rsc R=golang-codereviews, bradfitz, ruiu, rsc CC=golang-codereviews https://golang.org/cl/85240046
-rw-r--r--src/cmd/nm/doc.go1
-rw-r--r--src/cmd/nm/nm_test.go40
-rw-r--r--src/cmd/nm/pe.go34
3 files changed, 73 insertions, 2 deletions
diff --git a/src/cmd/nm/doc.go b/src/cmd/nm/doc.go
index 81662f8721..b62da47c00 100644
--- a/src/cmd/nm/doc.go
+++ b/src/cmd/nm/doc.go
@@ -19,6 +19,7 @@
// d static data segment symbol
// B bss segment symbol
// b static bss segment symbol
+// C constant address
// U referenced but undefined symbol
//
// Following established convention, the address is omitted for undefined
diff --git a/src/cmd/nm/nm_test.go b/src/cmd/nm/nm_test.go
new file mode 100644
index 0000000000..ba9dc00f56
--- /dev/null
+++ b/src/cmd/nm/nm_test.go
@@ -0,0 +1,40 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "testing"
+)
+
+func TestNM(t *testing.T) {
+ out, err := exec.Command("go", "build", "-o", "testnm.exe", "cmd/nm").CombinedOutput()
+ if err != nil {
+ t.Fatalf("go build -o testnm.exe cmd/nm: %v\n%s", err, string(out))
+ }
+ defer os.Remove("testnm.exe")
+
+ testfiles := []string{
+ "elf/testdata/gcc-386-freebsd-exec",
+ "elf/testdata/gcc-amd64-linux-exec",
+ "macho/testdata/gcc-386-darwin-exec",
+ "macho/testdata/gcc-amd64-darwin-exec",
+ "pe/testdata/gcc-amd64-mingw-exec",
+ "pe/testdata/gcc-386-mingw-exec",
+ "plan9obj/testdata/amd64-plan9-exec",
+ "plan9obj/testdata/386-plan9-exec",
+ }
+ for _, f := range testfiles {
+ exepath := filepath.Join(runtime.GOROOT(), "src", "pkg", "debug", f)
+ cmd := exec.Command("./testnm.exe", exepath)
+ out, err := cmd.CombinedOutput()
+ if err != nil {
+ t.Fatalf("go tool nm %v: %v\n%s", exepath, err, string(out))
+ }
+ }
+}
diff --git a/src/cmd/nm/pe.go b/src/cmd/nm/pe.go
index bf78238d6e..7175e2295c 100644
--- a/src/cmd/nm/pe.go
+++ b/src/cmd/nm/pe.go
@@ -18,12 +18,41 @@ func peSymbols(f *os.File) []Sym {
return nil
}
+ var imageBase uint64
+ switch oh := p.OptionalHeader.(type) {
+ case *pe.OptionalHeader32:
+ imageBase = uint64(oh.ImageBase)
+ case *pe.OptionalHeader64:
+ imageBase = oh.ImageBase
+ default:
+ errorf("parsing %s: file format not recognized", f.Name())
+ return nil
+ }
+
var syms []Sym
for _, s := range p.Symbols {
+ const (
+ N_UNDEF = 0 // An undefined (extern) symbol
+ N_ABS = -1 // An absolute symbol (e_value is a constant, not an address)
+ N_DEBUG = -2 // A debugging symbol
+ )
sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'}
- if s.SectionNumber == 0 {
+ switch s.SectionNumber {
+ case N_UNDEF:
sym.Code = 'U'
- } else if int(s.SectionNumber) <= len(p.Sections) {
+ case N_ABS:
+ sym.Code = 'C'
+ case N_DEBUG:
+ sym.Code = '?'
+ default:
+ if s.SectionNumber < 0 {
+ errorf("parsing %s: invalid section number %d", f.Name(), s.SectionNumber)
+ return nil
+ }
+ if len(p.Sections) < int(s.SectionNumber) {
+ errorf("parsing %s: section number %d is large then max %d", f.Name(), s.SectionNumber, len(p.Sections))
+ return nil
+ }
sect := p.Sections[s.SectionNumber-1]
const (
text = 0x20
@@ -46,6 +75,7 @@ func peSymbols(f *os.File) []Sym {
case ch&bss != 0:
sym.Code = 'B'
}
+ sym.Addr += imageBase + uint64(sect.VirtualAddress)
}
syms = append(syms, sym)
}