diff options
author | Alex Brainman <alex.brainman@gmail.com> | 2014-04-16 22:17:38 -0400 |
---|---|---|
committer | Alex Brainman <alex.brainman@gmail.com> | 2014-04-16 22:17:38 -0400 |
commit | beff529388fb6fce8053307754582a2552c55a75 (patch) | |
tree | 044983d84c0070f90a1a79889149701dcfd6a412 | |
parent | ea5400b70634c741cf7fde3cf0fb940cdf7da1d5 (diff) | |
download | go-beff529388fb6fce8053307754582a2552c55a75.tar.gz |
cmd/nm: windows pe handling fixes
- output absolute addresses, not relative;
- accept negative section numbers.
Update issue 6936
Fixes issue 7738
LGTM=rsc
R=golang-codereviews, bradfitz, ruiu, rsc
CC=golang-codereviews
https://codereview.appspot.com/85240046
Committer: Russ Cox <rsc@golang.org>
-rw-r--r-- | src/cmd/nm/doc.go | 1 | ||||
-rw-r--r-- | src/cmd/nm/nm_test.go | 40 | ||||
-rw-r--r-- | src/cmd/nm/pe.go | 34 |
3 files changed, 73 insertions, 2 deletions
diff --git a/src/cmd/nm/doc.go b/src/cmd/nm/doc.go index 81662f872..b62da47c0 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 000000000..ba9dc00f5 --- /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 bf78238d6..7175e2295 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) } |