github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/nm/macho.go (about)

     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  // Parsing of Mach-O executables (OS X).
     6  
     7  package main
     8  
     9  import (
    10  	"debug/macho"
    11  	"os"
    12  	"sort"
    13  )
    14  
    15  func machoSymbols(f *os.File) []Sym {
    16  	p, err := macho.NewFile(f)
    17  	if err != nil {
    18  		errorf("parsing %s: %v", f.Name(), err)
    19  		return nil
    20  	}
    21  
    22  	if p.Symtab == nil {
    23  		errorf("%s: no symbol table", f.Name())
    24  		return nil
    25  	}
    26  
    27  	// Build sorted list of addresses of all symbols.
    28  	// We infer the size of a symbol by looking at where the next symbol begins.
    29  	var addrs []uint64
    30  	for _, s := range p.Symtab.Syms {
    31  		addrs = append(addrs, s.Value)
    32  	}
    33  	sort.Sort(uint64s(addrs))
    34  
    35  	var syms []Sym
    36  	for _, s := range p.Symtab.Syms {
    37  		sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}
    38  		i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
    39  		if i < len(addrs) {
    40  			sym.Size = int64(addrs[i] - s.Value)
    41  		}
    42  		if s.Sect == 0 {
    43  			sym.Code = 'U'
    44  		} else if int(s.Sect) <= len(p.Sections) {
    45  			sect := p.Sections[s.Sect-1]
    46  			switch sect.Seg {
    47  			case "__TEXT":
    48  				sym.Code = 'R'
    49  			case "__DATA":
    50  				sym.Code = 'D'
    51  			}
    52  			switch sect.Seg + " " + sect.Name {
    53  			case "__TEXT __text":
    54  				sym.Code = 'T'
    55  			case "__DATA __bss", "__DATA __noptrbss":
    56  				sym.Code = 'B'
    57  			}
    58  		}
    59  		syms = append(syms, sym)
    60  	}
    61  
    62  	return syms
    63  }
    64  
    65  type uint64s []uint64
    66  
    67  func (x uint64s) Len() int           { return len(x) }
    68  func (x uint64s) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
    69  func (x uint64s) Less(i, j int) bool { return x[i] < x[j] }