LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package main | 5 package main |
6 | 6 |
7 import ( | 7 import ( |
8 "bufio" | 8 "bufio" |
9 "bytes" | |
10 "flag" | 9 "flag" |
11 "fmt" | 10 "fmt" |
12 "io" | |
13 "log" | 11 "log" |
14 "os" | 12 "os" |
15 "sort" | 13 "sort" |
| 14 |
| 15 "cmd/internal/objfile" |
16 ) | 16 ) |
17 | 17 |
18 func usage() { | 18 func usage() { |
19 fmt.Fprintf(os.Stderr, "usage: go tool nm [-n] [-size] [-sort order] [-t
ype] file...\n") | 19 fmt.Fprintf(os.Stderr, "usage: go tool nm [-n] [-size] [-sort order] [-t
ype] file...\n") |
20 os.Exit(2) | 20 os.Exit(2) |
21 } | 21 } |
22 | 22 |
23 var ( | 23 var ( |
24 sortOrder = flag.String("sort", "name", "") | 24 sortOrder = flag.String("sort", "name", "") |
25 printSize = flag.Bool("size", false, "") | 25 printSize = flag.Bool("size", false, "") |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 os.Exit(exitCode) | 78 os.Exit(exitCode) |
79 } | 79 } |
80 | 80 |
81 var exitCode = 0 | 81 var exitCode = 0 |
82 | 82 |
83 func errorf(format string, args ...interface{}) { | 83 func errorf(format string, args ...interface{}) { |
84 log.Printf(format, args...) | 84 log.Printf(format, args...) |
85 exitCode = 1 | 85 exitCode = 1 |
86 } | 86 } |
87 | 87 |
88 type Sym struct { | |
89 Addr uint64 | |
90 Size int64 | |
91 Code rune | |
92 Name string | |
93 Type string | |
94 } | |
95 | |
96 var parsers = []struct { | |
97 prefix []byte | |
98 parse func(*os.File) []Sym | |
99 }{ | |
100 {[]byte("!<arch>\n"), goobjSymbols}, | |
101 {[]byte("go object "), goobjSymbols}, | |
102 {[]byte("\x7FELF"), elfSymbols}, | |
103 {[]byte("\xFE\xED\xFA\xCE"), machoSymbols}, | |
104 {[]byte("\xFE\xED\xFA\xCF"), machoSymbols}, | |
105 {[]byte("\xCE\xFA\xED\xFE"), machoSymbols}, | |
106 {[]byte("\xCF\xFA\xED\xFE"), machoSymbols}, | |
107 {[]byte("MZ"), peSymbols}, | |
108 {[]byte("\x00\x00\x01\xEB"), plan9Symbols}, // 386 | |
109 {[]byte("\x00\x00\x04\x07"), plan9Symbols}, // mips | |
110 {[]byte("\x00\x00\x06\x47"), plan9Symbols}, // arm | |
111 {[]byte("\x00\x00\x8A\x97"), plan9Symbols}, // amd64 | |
112 } | |
113 | |
114 func nm(file string) { | 88 func nm(file string) { |
115 » f, err := os.Open(file) | 89 » f, err := objfile.Open(file) |
116 if err != nil { | 90 if err != nil { |
117 errorf("%v", err) | 91 errorf("%v", err) |
118 return | 92 return |
119 } | 93 } |
120 defer f.Close() | 94 defer f.Close() |
121 | 95 |
122 » buf := make([]byte, 16) | 96 » syms, err := f.Symbols() |
123 » io.ReadFull(f, buf) | 97 » if err != nil { |
124 » f.Seek(0, 0) | 98 » » errorf("reading %s: %v", file, err) |
| 99 » } |
| 100 » if len(syms) == 0 { |
| 101 » » errorf("reading %s: no symbols", file) |
| 102 » } |
125 | 103 |
126 var syms []Sym | |
127 for _, p := range parsers { | |
128 if bytes.HasPrefix(buf, p.prefix) { | |
129 syms = p.parse(f) | |
130 goto HaveSyms | |
131 } | |
132 } | |
133 errorf("%v: unknown file format", file) | |
134 return | |
135 | |
136 HaveSyms: | |
137 switch *sortOrder { | 104 switch *sortOrder { |
138 case "address": | 105 case "address": |
139 sort.Sort(byAddr(syms)) | 106 sort.Sort(byAddr(syms)) |
140 case "name": | 107 case "name": |
141 sort.Sort(byName(syms)) | 108 sort.Sort(byName(syms)) |
142 case "size": | 109 case "size": |
143 sort.Sort(bySize(syms)) | 110 sort.Sort(bySize(syms)) |
144 } | 111 } |
145 | 112 |
146 w := bufio.NewWriter(os.Stdout) | 113 w := bufio.NewWriter(os.Stdout) |
(...skipping 11 matching lines...) Expand all Loading... |
158 } | 125 } |
159 fmt.Fprintf(w, " %c %s", sym.Code, sym.Name) | 126 fmt.Fprintf(w, " %c %s", sym.Code, sym.Name) |
160 if *printType && sym.Type != "" { | 127 if *printType && sym.Type != "" { |
161 fmt.Fprintf(w, " %s", sym.Type) | 128 fmt.Fprintf(w, " %s", sym.Type) |
162 } | 129 } |
163 fmt.Fprintf(w, "\n") | 130 fmt.Fprintf(w, "\n") |
164 } | 131 } |
165 w.Flush() | 132 w.Flush() |
166 } | 133 } |
167 | 134 |
168 type byAddr []Sym | 135 type byAddr []objfile.Sym |
169 | 136 |
170 func (x byAddr) Len() int { return len(x) } | 137 func (x byAddr) Len() int { return len(x) } |
171 func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } | 138 func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } |
172 func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr } | 139 func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr } |
173 | 140 |
174 type byName []Sym | 141 type byName []objfile.Sym |
175 | 142 |
176 func (x byName) Len() int { return len(x) } | 143 func (x byName) Len() int { return len(x) } |
177 func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } | 144 func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } |
178 func (x byName) Less(i, j int) bool { return x[i].Name < x[j].Name } | 145 func (x byName) Less(i, j int) bool { return x[i].Name < x[j].Name } |
179 | 146 |
180 type bySize []Sym | 147 type bySize []objfile.Sym |
181 | 148 |
182 func (x bySize) Len() int { return len(x) } | 149 func (x bySize) Len() int { return len(x) } |
183 func (x bySize) Swap(i, j int) { x[i], x[j] = x[j], x[i] } | 150 func (x bySize) Swap(i, j int) { x[i], x[j] = x[j], x[i] } |
184 func (x bySize) Less(i, j int) bool { return x[i].Size > x[j].Size } | 151 func (x bySize) Less(i, j int) bool { return x[i].Size > x[j].Size } |
LEFT | RIGHT |