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] }