summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShenghou Ma <minux.ma@gmail.com>2014-05-10 13:35:40 -0400
committerShenghou Ma <minux.ma@gmail.com>2014-05-10 13:35:40 -0400
commit6385536da047132b421be02b2069fa0ceb01d6bd (patch)
tree457a7eb760ee2705f8ab2ca82125276b1b735b36
parent1625b5d6590663d12295cb0a87fc928f093085e4 (diff)
downloadgo-6385536da047132b421be02b2069fa0ceb01d6bd.tar.gz
cmd/addr2line: accept optional "0x" prefix for addresses.
LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/91250043
-rw-r--r--src/cmd/addr2line/main.go52
1 files changed, 42 insertions, 10 deletions
diff --git a/src/cmd/addr2line/main.go b/src/cmd/addr2line/main.go
index c09b2616e..d6d14a733 100644
--- a/src/cmd/addr2line/main.go
+++ b/src/cmd/addr2line/main.go
@@ -8,7 +8,7 @@
// Usage:
// go tool addr2line binary
//
-// Addr2line reads hexadecimal addresses, one per line and without a 0x prefix,
+// Addr2line reads hexadecimal addresses, one per line and with optional 0x prefix,
// from standard input. For each input address, addr2line prints two output lines,
// first the name of the function containing the address and second the file:line
// of the source code corresponding to that address.
@@ -88,7 +88,7 @@ func main() {
fmt.Fprintf(stdout, "!reverse translation not implemented\n")
continue
}
- pc, _ := strconv.ParseUint(p, 16, 64)
+ pc, _ := strconv.ParseUint(strings.TrimPrefix(p, "0x"), 16, 64)
file, line, fn := tab.PCToLine(pc)
name := "?"
if fn != nil {
@@ -141,18 +141,50 @@ func loadTables(f *os.File) (textStart uint64, symtab, pclntab []byte, err error
if sect := obj.Section(".text"); sect != nil {
textStart = uint64(sect.VirtualAddress)
}
- if sect := obj.Section(".gosymtab"); sect != nil {
- if symtab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
+ if pclntab, err = loadPETable(obj, "pclntab", "epclntab"); err != nil {
+ return 0, nil, nil, err
}
- if sect := obj.Section(".gopclntab"); sect != nil {
- if pclntab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
+ if symtab, err = loadPETable(obj, "symtab", "esymtab"); err != nil {
+ return 0, nil, nil, err
}
return textStart, symtab, pclntab, nil
}
return 0, nil, nil, fmt.Errorf("unrecognized binary format")
}
+
+func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) {
+ for _, s := range f.Symbols {
+ if s.Name != name {
+ continue
+ }
+ if s.SectionNumber <= 0 {
+ return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber)
+ }
+ if len(f.Sections) < int(s.SectionNumber) {
+ return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
+ }
+ return s, nil
+ }
+ return nil, fmt.Errorf("no %s symbol found", name)
+}
+
+func loadPETable(f *pe.File, sname, ename string) ([]byte, error) {
+ ssym, err := findPESymbol(f, sname)
+ if err != nil {
+ return nil, err
+ }
+ esym, err := findPESymbol(f, ename)
+ if err != nil {
+ return nil, err
+ }
+ if ssym.SectionNumber != esym.SectionNumber {
+ return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
+ }
+ sect := f.Sections[ssym.SectionNumber-1]
+ data, err := sect.Data()
+ if err != nil {
+ return nil, err
+ }
+ return data[ssym.Value:esym.Value], nil
+}