| // 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. | |
| // Addr2line is a minimal simulation of the GNU addr2line tool, | |
| // just enough to support pprof. | |
| // | |
| // Usage: | |
| // go tool addr2line binary | |
| // | |
| // 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. | |
| // | |
| // This tool is intended for use only by pprof; its interface may change or | |
| // it may be deleted entirely in future releases. | |
| package main | |
| import ( | |
| "bufio" | |
| "flag" | |
| "fmt" | |
| "log" | |
| "os" | |
| "strconv" | |
| "strings" | |
| "cmd/internal/objfile" | |
| ) | |
| 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() | |
| } | |
| f, err := objfile.Open(flag.Arg(0)) | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| tab, err := f.PCLineTable() | |
| 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 | |
| } | |
| pc, _ := strconv.ParseUint(strings.TrimPrefix(p, "0x"), 16, 64) | |
| 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() | |
| } |