github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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 findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) { 92 syms, err := f.Symbols() 93 if err != nil { 94 return nil, err 95 } 96 for _, s := range syms { 97 if s.Name != name { 98 continue 99 } 100 return &s, nil 101 } 102 return nil, fmt.Errorf("no %s symbol found", name) 103 } 104 105 func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) { 106 ssym, err := findPlan9Symbol(f, sname) 107 if err != nil { 108 return nil, err 109 } 110 esym, err := findPlan9Symbol(f, ename) 111 if err != nil { 112 return nil, err 113 } 114 sect := f.Section("text") 115 if sect == nil { 116 return nil, err 117 } 118 data, err := sect.Data() 119 if err != nil { 120 return nil, err 121 } 122 textStart := f.LoadAddress + f.HdrSize 123 return data[ssym.Value-textStart : esym.Value-textStart], nil 124 }