]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/nm: windows pe handling fixes
authorAlex Brainman <alex.brainman@gmail.com>
Thu, 17 Apr 2014 02:17:38 +0000 (22:17 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 17 Apr 2014 02:17:38 +0000 (22:17 -0400)
- 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

src/cmd/nm/doc.go
src/cmd/nm/nm_test.go [new file with mode: 0644]
src/cmd/nm/pe.go

index 81662f8721888cd9616677d8b9dacafb1bcd62e7..b62da47c009067597143f10e4ef3e04d90241a22 100644 (file)
@@ -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 (file)
index 0000000..ba9dc00
--- /dev/null
@@ -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))
+               }
+       }
+}
index bf78238d6e5e647b0594e49c1861a4d42c2e8ddb..7175e2295c1063595b572bc844d4f62a2781faa6 100644 (file)
@@ -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)
        }