github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/cmd/internal/objfile/plan9obj.go (about) 1 // Copyright 2014 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 Plan 9 a.out executables. 6 7 package objfile 8 9 import ( 10 "debug/plan9obj" 11 "fmt" 12 "os" 13 "sort" 14 ) 15 16 var validSymType = map[rune]bool{ 17 'T': true, 18 't': true, 19 'D': true, 20 'd': true, 21 'B': true, 22 'b': true, 23 } 24 25 type plan9File struct { 26 plan9 *plan9obj.File 27 } 28 29 func openPlan9(r *os.File) (rawFile, error) { 30 f, err := plan9obj.NewFile(r) 31 if err != nil { 32 return nil, err 33 } 34 return &plan9File{f}, nil 35 } 36 37 func (f *plan9File) symbols() ([]Sym, error) { 38 plan9Syms, err := f.plan9.Symbols() 39 if err != nil { 40 return nil, err 41 } 42 43 // Build sorted list of addresses of all symbols. 44 // We infer the size of a symbol by looking at where the next symbol begins. 45 var addrs []uint64 46 for _, s := range plan9Syms { 47 if !validSymType[s.Type] { 48 continue 49 } 50 addrs = append(addrs, s.Value) 51 } 52 sort.Sort(uint64s(addrs)) 53 54 var syms []Sym 55 56 for _, s := range plan9Syms { 57 if !validSymType[s.Type] { 58 continue 59 } 60 sym := Sym{Addr: s.Value, Name: s.Name, Code: rune(s.Type)} 61 i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) 62 if i < len(addrs) { 63 sym.Size = int64(addrs[i] - s.Value) 64 } 65 syms = append(syms, sym) 66 } 67 68 return syms, nil 69 } 70 71 func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 72 textStart = f.plan9.LoadAddress + f.plan9.HdrSize 73 if pclntab, err = loadPlan9Table(f.plan9, "runtime.pclntab", "runtime.epclntab"); err != nil { 74 // We didn't find the symbols, so look for the names used in 1.3 and earlier. 75 // TODO: Remove code looking for the old symbols when we no longer care about 1.3. 76 var err2 error 77 if pclntab, err2 = loadPlan9Table(f.plan9, "pclntab", "epclntab"); err2 != nil { 78 return 0, nil, nil, err 79 } 80 } 81 if symtab, err = loadPlan9Table(f.plan9, "runtime.symtab", "runtime.esymtab"); err != nil { 82 // Same as above. 83 var err2 error 84 if symtab, err2 = loadPlan9Table(f.plan9, "symtab", "esymtab"); err2 != nil { 85 return 0, nil, nil, err 86 } 87 } 88 return textStart, symtab, pclntab, nil 89 } 90 91 func (f *plan9File) text() (textStart uint64, text []byte, err error) { 92 sect := f.plan9.Section("text") 93 if sect == nil { 94 return 0, nil, fmt.Errorf("text section not found") 95 } 96 textStart = f.plan9.LoadAddress + f.plan9.HdrSize 97 text, err = sect.Data() 98 return 99 } 100 101 func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) { 102 syms, err := f.Symbols() 103 if err != nil { 104 return nil, err 105 } 106 for _, s := range syms { 107 if s.Name != name { 108 continue 109 } 110 return &s, nil 111 } 112 return nil, fmt.Errorf("no %s symbol found", name) 113 } 114 115 func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) { 116 ssym, err := findPlan9Symbol(f, sname) 117 if err != nil { 118 return nil, err 119 } 120 esym, err := findPlan9Symbol(f, ename) 121 if err != nil { 122 return nil, err 123 } 124 sect := f.Section("text") 125 if sect == nil { 126 return nil, err 127 } 128 data, err := sect.Data() 129 if err != nil { 130 return nil, err 131 } 132 textStart := f.LoadAddress + f.HdrSize 133 return data[ssym.Value-textStart : esym.Value-textStart], nil 134 } 135 136 func (f *plan9File) goarch() string { 137 switch f.plan9.Magic { 138 case plan9obj.Magic386: 139 return "386" 140 case plan9obj.MagicAMD64: 141 return "amd64" 142 case plan9obj.MagicARM: 143 return "arm" 144 } 145 return "" 146 }