...

Source file src/cmd/addr2line/main.go

     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		defer f.Close()
    65	
    66		tab, err := f.PCLineTable()
    67		if err != nil {
    68			log.Fatalf("reading %s: %v", flag.Arg(0), err)
    69		}
    70	
    71		stdin := bufio.NewScanner(os.Stdin)
    72		stdout := bufio.NewWriter(os.Stdout)
    73	
    74		for stdin.Scan() {
    75			p := stdin.Text()
    76			if strings.Contains(p, ":") {
    77				// Reverse translate file:line to pc.
    78				// This was an extension in the old C version of 'go tool addr2line'
    79				// and is probably not used by anyone, but recognize the syntax.
    80				// We don't have an implementation.
    81				fmt.Fprintf(stdout, "!reverse translation not implemented\n")
    82				continue
    83			}
    84			pc, _ := strconv.ParseUint(strings.TrimPrefix(p, "0x"), 16, 64)
    85			file, line, fn := tab.PCToLine(pc)
    86			name := "?"
    87			if fn != nil {
    88				name = fn.Name
    89			} else {
    90				file = "?"
    91				line = 0
    92			}
    93			fmt.Fprintf(stdout, "%s\n%s:%d\n", name, file, line)
    94		}
    95		stdout.Flush()
    96	}
    97	

View as plain text