...
Run Format

Source file src/cmd/addr2line/main.go

Documentation: cmd/addr2line

  // Copyright 2012 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // Addr2line is a minimal simulation of the GNU addr2line tool,
  // just enough to support pprof.
  //
  // Usage:
  //	go tool addr2line binary
  //
  // Addr2line reads hexadecimal addresses, one per line and with optional 0x prefix,
  // from standard input. For each input address, addr2line prints two output lines,
  // first the name of the function containing the address and second the file:line
  // of the source code corresponding to that address.
  //
  // This tool is intended for use only by pprof; its interface may change or
  // it may be deleted entirely in future releases.
  package main
  
  import (
  	"bufio"
  	"flag"
  	"fmt"
  	"log"
  	"os"
  	"strconv"
  	"strings"
  
  	"cmd/internal/objfile"
  )
  
  func printUsage(w *os.File) {
  	fmt.Fprintf(w, "usage: addr2line binary\n")
  	fmt.Fprintf(w, "reads addresses from standard input and writes two lines for each:\n")
  	fmt.Fprintf(w, "\tfunction name\n")
  	fmt.Fprintf(w, "\tfile:line\n")
  }
  
  func usage() {
  	printUsage(os.Stderr)
  	os.Exit(2)
  }
  
  func main() {
  	log.SetFlags(0)
  	log.SetPrefix("addr2line: ")
  
  	// pprof expects this behavior when checking for addr2line
  	if len(os.Args) > 1 && os.Args[1] == "--help" {
  		printUsage(os.Stdout)
  		os.Exit(0)
  	}
  
  	flag.Usage = usage
  	flag.Parse()
  	if flag.NArg() != 1 {
  		usage()
  	}
  
  	f, err := objfile.Open(flag.Arg(0))
  	if err != nil {
  		log.Fatal(err)
  	}
  
  	tab, err := f.PCLineTable()
  	if err != nil {
  		log.Fatalf("reading %s: %v", flag.Arg(0), err)
  	}
  
  	stdin := bufio.NewScanner(os.Stdin)
  	stdout := bufio.NewWriter(os.Stdout)
  
  	for stdin.Scan() {
  		p := stdin.Text()
  		if strings.Contains(p, ":") {
  			// Reverse translate file:line to pc.
  			// This was an extension in the old C version of 'go tool addr2line'
  			// and is probably not used by anyone, but recognize the syntax.
  			// We don't have an implementation.
  			fmt.Fprintf(stdout, "!reverse translation not implemented\n")
  			continue
  		}
  		pc, _ := strconv.ParseUint(strings.TrimPrefix(p, "0x"), 16, 64)
  		file, line, fn := tab.PCToLine(pc)
  		name := "?"
  		if fn != nil {
  			name = fn.Name
  		} else {
  			file = "?"
  			line = 0
  		}
  		fmt.Fprintf(stdout, "%s\n%s:%d\n", name, file, line)
  	}
  	stdout.Flush()
  }
  

View as plain text