diff options
author | Shenghou Ma <minux.ma@gmail.com> | 2014-05-10 13:35:40 -0400 |
---|---|---|
committer | Shenghou Ma <minux.ma@gmail.com> | 2014-05-10 13:35:40 -0400 |
commit | 6385536da047132b421be02b2069fa0ceb01d6bd (patch) | |
tree | 457a7eb760ee2705f8ab2ca82125276b1b735b36 | |
parent | 1625b5d6590663d12295cb0a87fc928f093085e4 (diff) | |
download | go-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.go | 52 |
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 +} |