Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1229)

Side by Side Diff: src/cmd/objdump/main.go

Issue 104770046: code review 104770046: cmd/objdump: add arm disassembler (Closed)
Patch Set: diff -r 5dd1aec48e8f https://code.google.com/p/go/ Created 9 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/cmd/objdump/armasm.go ('k') | src/cmd/objdump/objdump_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Go Authors. All rights reserved. 1 // Copyright 2012 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 // Objdump disassembles executable files. 5 // Objdump disassembles executable files.
6 // 6 //
7 // Usage: 7 // Usage:
8 // 8 //
9 // go tool objdump [-s symregexp] binary 9 // go tool objdump [-s symregexp] binary
10 // 10 //
(...skipping 24 matching lines...) Expand all
35 package main 35 package main
36 36
37 import ( 37 import (
38 "bufio" 38 "bufio"
39 "bytes" 39 "bytes"
40 "debug/elf" 40 "debug/elf"
41 "debug/gosym" 41 "debug/gosym"
42 "debug/macho" 42 "debug/macho"
43 "debug/pe" 43 "debug/pe"
44 "debug/plan9obj" 44 "debug/plan9obj"
45 "encoding/binary"
45 "flag" 46 "flag"
46 "fmt" 47 "fmt"
47 "io" 48 "io"
48 "log" 49 "log"
49 "os" 50 "os"
50 "regexp" 51 "regexp"
51 "sort" 52 "sort"
52 "strconv" 53 "strconv"
53 "strings" 54 "strings"
54 "text/tabwriter" 55 "text/tabwriter"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 } 129 }
129 130
130 pcln := gosym.NewLineTable(pclntab, textStart) 131 pcln := gosym.NewLineTable(pclntab, textStart)
131 tab, err := gosym.NewTable(symtab, pcln) 132 tab, err := gosym.NewTable(symtab, pcln)
132 if err != nil { 133 if err != nil {
133 log.Fatalf("reading %s: %v", flag.Arg(0), err) 134 log.Fatalf("reading %s: %v", flag.Arg(0), err)
134 } 135 }
135 136
136 if flag.NArg() == 1 { 137 if flag.NArg() == 1 {
137 // disassembly of entire object - our format 138 // disassembly of entire object - our format
138 » » dump(tab, lookup, disasm, syms, textData, textStart) 139 » » dump(tab, lookup, disasm, goarch, syms, textData, textStart)
139 os.Exit(exitCode) 140 os.Exit(exitCode)
140 } 141 }
141 142
142 // disassembly of specific piece of object - gnu objdump format for ppro f 143 // disassembly of specific piece of object - gnu objdump format for ppro f
143 gnuDump(tab, lookup, disasm, textData, textStart) 144 gnuDump(tab, lookup, disasm, textData, textStart)
144 os.Exit(exitCode) 145 os.Exit(exitCode)
145 } 146 }
146 147
147 // base returns the final element in the path. 148 // base returns the final element in the path.
148 // It works on both Windows and Unix paths. 149 // It works on both Windows and Unix paths.
149 func base(path string) string { 150 func base(path string) string {
150 path = path[strings.LastIndex(path, "/")+1:] 151 path = path[strings.LastIndex(path, "/")+1:]
151 path = path[strings.LastIndex(path, `\`)+1:] 152 path = path[strings.LastIndex(path, `\`)+1:]
152 return path 153 return path
153 } 154 }
154 155
155 func dump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, syms []Sym, te xtData []byte, textStart uint64) { 156 func dump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, goarch string, syms []Sym, textData []byte, textStart uint64) {
156 stdout := bufio.NewWriter(os.Stdout) 157 stdout := bufio.NewWriter(os.Stdout)
157 defer stdout.Flush() 158 defer stdout.Flush()
158 159
159 printed := false 160 printed := false
160 for _, sym := range syms { 161 for _, sym := range syms {
161 if sym.Code != 'T' || sym.Size == 0 || sym.Name == "_text" || sy m.Name == "text" || sym.Addr < textStart || symRE != nil && !symRE.MatchString(s ym.Name) { 162 if sym.Code != 'T' || sym.Size == 0 || sym.Name == "_text" || sy m.Name == "text" || sym.Addr < textStart || symRE != nil && !symRE.MatchString(s ym.Name) {
162 continue 163 continue
163 } 164 }
164 if sym.Addr >= textStart+uint64(len(textData)) || sym.Addr+uint6 4(sym.Size) > textStart+uint64(len(textData)) { 165 if sym.Addr >= textStart+uint64(len(textData)) || sym.Addr+uint6 4(sym.Size) > textStart+uint64(len(textData)) {
165 break 166 break
166 } 167 }
167 if printed { 168 if printed {
168 fmt.Fprintf(stdout, "\n") 169 fmt.Fprintf(stdout, "\n")
169 } else { 170 } else {
170 printed = true 171 printed = true
171 } 172 }
172 file, _, _ := tab.PCToLine(sym.Addr) 173 file, _, _ := tab.PCToLine(sym.Addr)
173 fmt.Fprintf(stdout, "TEXT %s(SB) %s\n", sym.Name, file) 174 fmt.Fprintf(stdout, "TEXT %s(SB) %s\n", sym.Name, file)
174 tw := tabwriter.NewWriter(stdout, 1, 8, 1, '\t', 0) 175 tw := tabwriter.NewWriter(stdout, 1, 8, 1, '\t', 0)
175 start := sym.Addr 176 start := sym.Addr
176 end := sym.Addr + uint64(sym.Size) 177 end := sym.Addr + uint64(sym.Size)
177 for pc := start; pc < end; { 178 for pc := start; pc < end; {
178 i := pc - textStart 179 i := pc - textStart
179 text, size := disasm(textData[i:end-textStart], pc, look up) 180 text, size := disasm(textData[i:end-textStart], pc, look up)
180 file, line, _ := tab.PCToLine(pc) 181 file, line, _ := tab.PCToLine(pc)
181 » » » fmt.Fprintf(tw, "\t%s:%d\t%#x\t%x\t%s\n", base(file), li ne, pc, textData[i:i+uint64(size)], text) 182
183 » » » // ARM is word-based, so show actual word hex, not byte hex.
184 » » » // Since ARM is little endian, they're different.
185 » » » if goarch == "arm" && size == 4 {
186 » » » » fmt.Fprintf(tw, "\t%s:%d\t%#x\t%08x\t%s\n", base (file), line, pc, binary.LittleEndian.Uint32(textData[i:i+uint64(size)]), text)
187 » » » } else {
188 » » » » fmt.Fprintf(tw, "\t%s:%d\t%#x\t%x\t%s\n", base(f ile), line, pc, textData[i:i+uint64(size)], text)
189 » » » }
182 pc += uint64(size) 190 pc += uint64(size)
183 } 191 }
184 tw.Flush() 192 tw.Flush()
185 } 193 }
186 } 194 }
187 195
188 func disasm_386(code []byte, pc uint64, lookup lookupFunc) (string, int) { 196 func disasm_386(code []byte, pc uint64, lookup lookupFunc) (string, int) {
189 return disasm_x86(code, pc, lookup, 32) 197 return disasm_x86(code, pc, lookup, 32)
190 } 198 }
191 199
192 func disasm_amd64(code []byte, pc uint64, lookup lookupFunc) (string, int) { 200 func disasm_amd64(code []byte, pc uint64, lookup lookupFunc) (string, int) {
193 return disasm_x86(code, pc, lookup, 64) 201 return disasm_x86(code, pc, lookup, 64)
194 } 202 }
195 203
196 func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, in t) { 204 func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, in t) {
197 inst, err := x86_Decode(code, 64) 205 inst, err := x86_Decode(code, 64)
198 var text string 206 var text string
199 size := inst.Len 207 size := inst.Len
200 if err != nil || size == 0 || inst.Op == 0 { 208 if err != nil || size == 0 || inst.Op == 0 {
201 size = 1 209 size = 1
202 text = "?" 210 text = "?"
203 } else { 211 } else {
204 text = x86_plan9Syntax(inst, pc, lookup) 212 text = x86_plan9Syntax(inst, pc, lookup)
205 } 213 }
206 return text, size 214 return text, size
207 } 215 }
208 216
217 type textReader struct {
218 code []byte
219 pc uint64
220 }
221
222 func (r textReader) ReadAt(data []byte, off int64) (n int, err error) {
223 if off < 0 || uint64(off) < r.pc {
224 return 0, io.EOF
225 }
226 d := uint64(off) - r.pc
227 if d >= uint64(len(r.code)) {
228 return 0, io.EOF
229 }
230 n = copy(data, r.code[d:])
231 if n < len(data) {
232 err = io.ErrUnexpectedEOF
233 }
234 return
235 }
236
209 func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) { 237 func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) {
210 » /* 238 » inst, err := arm_Decode(code, arm_ModeARM)
211 » » inst, size, err := arm_Decode(code, 64) 239 » var text string
212 » » var text string 240 » size := inst.Len
213 » » if err != nil || size == 0 || inst.Op == 0 { 241 » if err != nil || size == 0 || inst.Op == 0 {
214 » » » size = 1 242 » » size = 4
215 » » » text = "?" 243 » » text = "?"
216 » » } else { 244 » } else {
217 » » » text = arm_plan9Syntax(inst, pc, lookup) 245 » » text = arm_plan9Syntax(inst, pc, lookup, textReader{code, pc})
218 » » } 246 » }
219 » » return text, size 247 » return text, size
220 » */
221 » return "?", 4
222 } 248 }
223 249
224 var disasms = map[string]disasmFunc{ 250 var disasms = map[string]disasmFunc{
225 "386": disasm_386, 251 "386": disasm_386,
226 "amd64": disasm_amd64, 252 "amd64": disasm_amd64,
227 "arm": disasm_arm, 253 "arm": disasm_arm,
228 } 254 }
229 255
230 func gnuDump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, textData [] byte, textStart uint64) { 256 func gnuDump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, textData [] byte, textStart uint64) {
231 start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 1 6, 64) 257 start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 1 6, 64)
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 {[]byte("\x00\x00\x04\x07"), plan9Symbols}, // mips 510 {[]byte("\x00\x00\x04\x07"), plan9Symbols}, // mips
485 {[]byte("\x00\x00\x06\x47"), plan9Symbols}, // arm 511 {[]byte("\x00\x00\x06\x47"), plan9Symbols}, // arm
486 {[]byte("\x00\x00\x8A\x97"), plan9Symbols}, // amd64 512 {[]byte("\x00\x00\x8A\x97"), plan9Symbols}, // amd64
487 } 513 }
488 514
489 type byAddr []Sym 515 type byAddr []Sym
490 516
491 func (x byAddr) Len() int { return len(x) } 517 func (x byAddr) Len() int { return len(x) }
492 func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 518 func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
493 func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr } 519 func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr }
OLDNEW
« no previous file with comments | « src/cmd/objdump/armasm.go ('k') | src/cmd/objdump/objdump_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b