1// Copyright 2012 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// Addr2line is a minimal simulation of the GNU addr2line tool, 6// just enough to support pprof. 7// 8// Usage: 9// 10// go tool addr2line binary 11// 12// Addr2line reads hexadecimal addresses, one per line and with optional 0x prefix, 13// from standard input. For each input address, addr2line prints two output lines, 14// first the name of the function containing the address and second the file:line 15// of the source code corresponding to that address. 16// 17// This tool is intended for use only by pprof; its interface may change or 18// it may be deleted entirely in future releases. 19package main 20 21import ( 22 "bufio" 23 "flag" 24 "fmt" 25 "log" 26 "os" 27 "strconv" 28 "strings" 29 30 "cmd/internal/objfile" 31 "cmd/internal/telemetry/counter" 32) 33 34func printUsage(w *os.File) { 35 fmt.Fprintf(w, "usage: addr2line binary\n") 36 fmt.Fprintf(w, "reads addresses from standard input and writes two lines for each:\n") 37 fmt.Fprintf(w, "\tfunction name\n") 38 fmt.Fprintf(w, "\tfile:line\n") 39} 40 41func usage() { 42 printUsage(os.Stderr) 43 os.Exit(2) 44} 45 46func main() { 47 log.SetFlags(0) 48 log.SetPrefix("addr2line: ") 49 counter.Open() 50 51 // pprof expects this behavior when checking for addr2line 52 if len(os.Args) > 1 && os.Args[1] == "--help" { 53 printUsage(os.Stdout) 54 os.Exit(0) 55 } 56 57 flag.Usage = usage 58 flag.Parse() 59 counter.Inc("addr2line/invocations") 60 counter.CountFlags("addr2line/flag:", *flag.CommandLine) 61 if flag.NArg() != 1 { 62 usage() 63 } 64 65 f, err := objfile.Open(flag.Arg(0)) 66 if err != nil { 67 log.Fatal(err) 68 } 69 defer f.Close() 70 71 tab, err := f.PCLineTable() 72 if err != nil { 73 log.Fatalf("reading %s: %v", flag.Arg(0), err) 74 } 75 76 stdin := bufio.NewScanner(os.Stdin) 77 stdout := bufio.NewWriter(os.Stdout) 78 79 for stdin.Scan() { 80 p := stdin.Text() 81 if strings.Contains(p, ":") { 82 // Reverse translate file:line to pc. 83 // This was an extension in the old C version of 'go tool addr2line' 84 // and is probably not used by anyone, but recognize the syntax. 85 // We don't have an implementation. 86 fmt.Fprintf(stdout, "!reverse translation not implemented\n") 87 continue 88 } 89 pc, _ := strconv.ParseUint(strings.TrimPrefix(p, "0x"), 16, 64) 90 file, line, fn := tab.PCToLine(pc) 91 name := "?" 92 if fn != nil { 93 name = fn.Name 94 } else { 95 file = "?" 96 line = 0 97 } 98 fmt.Fprintf(stdout, "%s\n%s:%d\n", name, file, line) 99 } 100 stdout.Flush() 101} 102