github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/objdump/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) (syms []Sym, goarch string) { 16 p, err := macho.NewFile(f) 17 if err != nil { 18 errorf("parsing %s: %v", f.Name(), err) 19 return 20 } 21 22 if p.Symtab == nil { 23 errorf("%s: no symbol table", f.Name()) 24 return 25 } 26 27 switch p.Cpu { 28 case macho.Cpu386: 29 goarch = "386" 30 case macho.CpuAmd64: 31 goarch = "amd64" 32 case macho.CpuArm: 33 goarch = "arm" 34 } 35 36 // Build sorted list of addresses of all symbols. 37 // We infer the size of a symbol by looking at where the next symbol begins. 38 var addrs []uint64 39 for _, s := range p.Symtab.Syms { 40 addrs = append(addrs, s.Value) 41 } 42 sort.Sort(uint64s(addrs)) 43 44 for _, s := range p.Symtab.Syms { 45 sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'} 46 i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) 47 if i < len(addrs) { 48 sym.Size = int64(addrs[i] - s.Value) 49 } 50 if s.Sect == 0 { 51 sym.Code = 'U' 52 } else if int(s.Sect) <= len(p.Sections) { 53 sect := p.Sections[s.Sect-1] 54 switch sect.Seg { 55 case "__TEXT": 56 sym.Code = 'R' 57 case "__DATA": 58 sym.Code = 'D' 59 } 60 switch sect.Seg + " " + sect.Name { 61 case "__TEXT __text": 62 sym.Code = 'T' 63 case "__DATA __bss", "__DATA __noptrbss": 64 sym.Code = 'B' 65 } 66 } 67 syms = append(syms, sym) 68 } 69 70 return 71 } 72 73 type uint64s []uint64 74 75 func (x uint64s) Len() int { return len(x) } 76 func (x uint64s) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 77 func (x uint64s) Less(i, j int) bool { return x[i] < x[j] }