--- /dev/null
+// 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))
+ }
+ }
+}
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
case ch&bss != 0:
sym.Code = 'B'
}
+ sym.Addr += imageBase + uint64(sect.VirtualAddress)
}
syms = append(syms, sym)
}