...

Source file src/pkg/cmd/nm/nm.go

     1	// Copyright 2013 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	package main
     6	
     7	import (
     8		"bufio"
     9		"flag"
    10		"fmt"
    11		"log"
    12		"os"
    13		"sort"
    14	
    15		"cmd/internal/objfile"
    16	)
    17	
    18	const helpText = `usage: go tool nm [options] file...
    19	  -n
    20	      an alias for -sort address (numeric),
    21	      for compatibility with other nm commands
    22	  -size
    23	      print symbol size in decimal between address and type
    24	  -sort {address,name,none,size}
    25	      sort output in the given order (default name)
    26	      size orders from largest to smallest
    27	  -type
    28	      print symbol type after name
    29	`
    30	
    31	func usage() {
    32		fmt.Fprintf(os.Stderr, helpText)
    33		os.Exit(2)
    34	}
    35	
    36	var (
    37		sortOrder = flag.String("sort", "name", "")
    38		printSize = flag.Bool("size", false, "")
    39		printType = flag.Bool("type", false, "")
    40	
    41		filePrefix = false
    42	)
    43	
    44	func init() {
    45		flag.Var(nflag(0), "n", "") // alias for -sort address
    46	}
    47	
    48	type nflag int
    49	
    50	func (nflag) IsBoolFlag() bool {
    51		return true
    52	}
    53	
    54	func (nflag) Set(value string) error {
    55		if value == "true" {
    56			*sortOrder = "address"
    57		}
    58		return nil
    59	}
    60	
    61	func (nflag) String() string {
    62		if *sortOrder == "address" {
    63			return "true"
    64		}
    65		return "false"
    66	}
    67	
    68	func main() {
    69		log.SetFlags(0)
    70		flag.Usage = usage
    71		flag.Parse()
    72	
    73		switch *sortOrder {
    74		case "address", "name", "none", "size":
    75			// ok
    76		default:
    77			fmt.Fprintf(os.Stderr, "nm: unknown sort order %q\n", *sortOrder)
    78			os.Exit(2)
    79		}
    80	
    81		args := flag.Args()
    82		filePrefix = len(args) > 1
    83		if len(args) == 0 {
    84			flag.Usage()
    85		}
    86	
    87		for _, file := range args {
    88			nm(file)
    89		}
    90	
    91		os.Exit(exitCode)
    92	}
    93	
    94	var exitCode = 0
    95	
    96	func errorf(format string, args ...interface{}) {
    97		log.Printf(format, args...)
    98		exitCode = 1
    99	}
   100	
   101	func nm(file string) {
   102		f, err := objfile.Open(file)
   103		if err != nil {
   104			errorf("%v", err)
   105			return
   106		}
   107		defer f.Close()
   108	
   109		w := bufio.NewWriter(os.Stdout)
   110	
   111		entries := f.Entries()
   112	
   113		var found bool
   114	
   115		for _, e := range entries {
   116			syms, err := e.Symbols()
   117			if err != nil {
   118				errorf("reading %s: %v", file, err)
   119			}
   120			if len(syms) == 0 {
   121				continue
   122			}
   123	
   124			found = true
   125	
   126			switch *sortOrder {
   127			case "address":
   128				sort.Slice(syms, func(i, j int) bool { return syms[i].Addr < syms[j].Addr })
   129			case "name":
   130				sort.Slice(syms, func(i, j int) bool { return syms[i].Name < syms[j].Name })
   131			case "size":
   132				sort.Slice(syms, func(i, j int) bool { return syms[i].Size > syms[j].Size })
   133			}
   134	
   135			for _, sym := range syms {
   136				if len(entries) > 1 {
   137					name := e.Name()
   138					if name == "" {
   139						fmt.Fprintf(w, "%s(%s):\t", file, "_go_.o")
   140					} else {
   141						fmt.Fprintf(w, "%s(%s):\t", file, name)
   142					}
   143				} else if filePrefix {
   144					fmt.Fprintf(w, "%s:\t", file)
   145				}
   146				if sym.Code == 'U' {
   147					fmt.Fprintf(w, "%8s", "")
   148				} else {
   149					fmt.Fprintf(w, "%8x", sym.Addr)
   150				}
   151				if *printSize {
   152					fmt.Fprintf(w, " %10d", sym.Size)
   153				}
   154				fmt.Fprintf(w, " %c %s", sym.Code, sym.Name)
   155				if *printType && sym.Type != "" {
   156					fmt.Fprintf(w, " %s", sym.Type)
   157				}
   158				fmt.Fprintf(w, "\n")
   159			}
   160		}
   161	
   162		if !found {
   163			errorf("reading %s: no symbols", file)
   164		}
   165	
   166		w.Flush()
   167	}
   168	

View as plain text