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  //
    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.
    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  )
    32  
    33  func printUsage(w *os.File) {
    34  	fmt.Fprintf(w, "usage: addr2line binary\n")
    35  	fmt.Fprintf(w, "reads addresses from standard input and writes two lines for each:\n")
    36  	fmt.Fprintf(w, "\tfunction name\n")
    37  	fmt.Fprintf(w, "\tfile:line\n")
    38  }
    39  
    40  func usage() {
    41  	printUsage(os.Stderr)
    42  	os.Exit(2)
    43  }
    44  
    45  func main() {
    46  	log.SetFlags(0)
    47  	log.SetPrefix("addr2line: ")
    48  
    49  	// pprof expects this behavior when checking for addr2line
    50  	if len(os.Args) > 1 && os.Args[1] == "--help" {
    51  		printUsage(os.Stdout)
    52  		os.Exit(0)
    53  	}
    54  
    55  	flag.Usage = usage
    56  	flag.Parse()
    57  	if flag.NArg() != 1 {
    58  		usage()
    59  	}
    60  
    61  	f, err := objfile.Open(flag.Arg(0))
    62  	if err != nil {
    63  		log.Fatal(err)
    64  	}
    65  	defer f.Close()
    66  
    67  	tab, err := f.PCLineTable()
    68  	if err != nil {
    69  		log.Fatalf("reading %s: %v", flag.Arg(0), err)
    70  	}
    71  
    72  	stdin := bufio.NewScanner(os.Stdin)
    73  	stdout := bufio.NewWriter(os.Stdout)
    74  
    75  	for stdin.Scan() {
    76  		p := stdin.Text()
    77  		if strings.Contains(p, ":") {
    78  			// Reverse translate file:line to pc.
    79  			// This was an extension in the old C version of 'go tool addr2line'
    80  			// and is probably not used by anyone, but recognize the syntax.
    81  			// We don't have an implementation.
    82  			fmt.Fprintf(stdout, "!reverse translation not implemented\n")
    83  			continue
    84  		}
    85  		pc, _ := strconv.ParseUint(strings.TrimPrefix(p, "0x"), 16, 64)
    86  		file, line, fn := tab.PCToLine(pc)
    87  		name := "?"
    88  		if fn != nil {
    89  			name = fn.Name
    90  		} else {
    91  			file = "?"
    92  			line = 0
    93  		}
    94  		fmt.Fprintf(stdout, "%s\n%s:%d\n", name, file, line)
    95  	}
    96  	stdout.Flush()
    97  }
    98  

View as plain text