LEFT | RIGHT |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
| 4 |
| 5 // Parsing of Mach-O executables (OS X). |
4 | 6 |
5 package main | 7 package main |
6 | 8 |
7 import ( | 9 import ( |
8 "debug/macho" | 10 "debug/macho" |
9 "os" | 11 "os" |
| 12 "sort" |
10 ) | 13 ) |
11 | 14 |
12 func machoSymbols(f *os.File) []Sym { | 15 func machoSymbols(f *os.File) []Sym { |
13 p, err := macho.NewFile(f) | 16 p, err := macho.NewFile(f) |
14 if err != nil { | 17 if err != nil { |
15 errorf("parsing %s: %v", f.Name(), err) | 18 errorf("parsing %s: %v", f.Name(), err) |
16 return nil | 19 return nil |
17 } | 20 } |
18 | 21 |
19 if p.Symtab == nil { | 22 if p.Symtab == nil { |
20 errorf("%s: no symbol table", f.Name()) | 23 errorf("%s: no symbol table", f.Name()) |
21 return nil | 24 return nil |
22 } | 25 } |
23 | 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 beg
ins. |
| 29 var addrs []uint64 |
| 30 for _, s := range p.Symtab.Syms { |
| 31 addrs = append(addrs, s.Value) |
| 32 } |
| 33 sort.Sort(uint64s(addrs)) |
| 34 |
24 var syms []Sym | 35 var syms []Sym |
25 for _, s := range p.Symtab.Syms { | 36 for _, s := range p.Symtab.Syms { |
26 sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'} | 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 } |
27 if s.Sect == 0 { | 42 if s.Sect == 0 { |
28 sym.Code = 'U' | 43 sym.Code = 'U' |
29 } else if int(s.Sect) <= len(p.Sections) { | 44 } else if int(s.Sect) <= len(p.Sections) { |
30 sect := p.Sections[s.Sect-1] | 45 sect := p.Sections[s.Sect-1] |
31 switch sect.Seg { | 46 switch sect.Seg { |
32 case "__TEXT": | 47 case "__TEXT": |
33 sym.Code = 'R' | 48 sym.Code = 'R' |
34 case "__DATA": | 49 case "__DATA": |
35 sym.Code = 'D' | 50 sym.Code = 'D' |
36 } | 51 } |
37 switch sect.Seg + " " + sect.Name { | 52 switch sect.Seg + " " + sect.Name { |
38 case "__TEXT __text": | 53 case "__TEXT __text": |
39 sym.Code = 'T' | 54 sym.Code = 'T' |
40 case "__DATA __bss", "__DATA __noptrbss": | 55 case "__DATA __bss", "__DATA __noptrbss": |
41 sym.Code = 'B' | 56 sym.Code = 'B' |
42 } | 57 } |
43 } | 58 } |
44 syms = append(syms, sym) | 59 syms = append(syms, sym) |
45 } | 60 } |
46 | 61 |
47 return syms | 62 return syms |
48 } | 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] } |
LEFT | RIGHT |