2014-02-19 12:33:11 -07:00
|
|
|
// Copyright 2012 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.
|
|
|
|
|
2014-04-15 18:06:08 -06:00
|
|
|
// Addr2line is a minimal simulation of the GNU addr2line tool,
|
|
|
|
// just enough to support pprof.
|
|
|
|
//
|
|
|
|
// Usage:
|
|
|
|
// go tool addr2line binary
|
|
|
|
//
|
2014-05-10 11:35:40 -06:00
|
|
|
// Addr2line reads hexadecimal addresses, one per line and with optional 0x prefix,
|
2014-04-15 18:06:08 -06:00
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// This tool is intended for use only by pprof; its interface may change or
|
|
|
|
// it may be deleted entirely in future releases.
|
2014-02-19 12:33:11 -07:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2014-08-07 10:33:06 -06:00
|
|
|
|
|
|
|
"cmd/internal/objfile"
|
2014-02-19 12:33:11 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
func printUsage(w *os.File) {
|
|
|
|
fmt.Fprintf(w, "usage: addr2line binary\n")
|
|
|
|
fmt.Fprintf(w, "reads addresses from standard input and writes two lines for each:\n")
|
|
|
|
fmt.Fprintf(w, "\tfunction name\n")
|
|
|
|
fmt.Fprintf(w, "\tfile:line\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func usage() {
|
|
|
|
printUsage(os.Stderr)
|
|
|
|
os.Exit(2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
log.SetFlags(0)
|
|
|
|
log.SetPrefix("addr2line: ")
|
|
|
|
|
|
|
|
// pprof expects this behavior when checking for addr2line
|
|
|
|
if len(os.Args) > 1 && os.Args[1] == "--help" {
|
|
|
|
printUsage(os.Stdout)
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
flag.Usage = usage
|
|
|
|
flag.Parse()
|
|
|
|
if flag.NArg() != 1 {
|
|
|
|
usage()
|
|
|
|
}
|
|
|
|
|
2014-08-07 10:33:06 -06:00
|
|
|
f, err := objfile.Open(flag.Arg(0))
|
2014-02-19 12:33:11 -07:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2014-08-07 10:33:06 -06:00
|
|
|
tab, err := f.PCLineTable()
|
2014-02-19 12:33:11 -07:00
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("reading %s: %v", flag.Arg(0), err)
|
|
|
|
}
|
|
|
|
|
|
|
|
stdin := bufio.NewScanner(os.Stdin)
|
|
|
|
stdout := bufio.NewWriter(os.Stdout)
|
|
|
|
|
|
|
|
for stdin.Scan() {
|
|
|
|
p := stdin.Text()
|
|
|
|
if strings.Contains(p, ":") {
|
|
|
|
// Reverse translate file:line to pc.
|
|
|
|
// This was an extension in the old C version of 'go tool addr2line'
|
|
|
|
// and is probably not used by anyone, but recognize the syntax.
|
|
|
|
// We don't have an implementation.
|
|
|
|
fmt.Fprintf(stdout, "!reverse translation not implemented\n")
|
|
|
|
continue
|
|
|
|
}
|
2014-05-10 11:35:40 -06:00
|
|
|
pc, _ := strconv.ParseUint(strings.TrimPrefix(p, "0x"), 16, 64)
|
2014-02-19 12:33:11 -07:00
|
|
|
file, line, fn := tab.PCToLine(pc)
|
|
|
|
name := "?"
|
|
|
|
if fn != nil {
|
|
|
|
name = fn.Name
|
|
|
|
} else {
|
|
|
|
file = "?"
|
|
|
|
line = 0
|
|
|
|
}
|
|
|
|
fmt.Fprintf(stdout, "%s\n%s:%d\n", name, file, line)
|
|
|
|
}
|
|
|
|
stdout.Flush()
|
|
|
|
}
|