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