1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package main
20
21 import (
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
34 func 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
41 func usage() {
42 printUsage(os.Stderr)
43 os.Exit(2)
44 }
45
46 func main() {
47 log.SetFlags(0)
48 log.SetPrefix("addr2line: ")
49 counter.Open()
50
51
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
83
84
85
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
View as plain text