1
2
3
4
5
6
7 package objfile
8
9 import (
10 "debug/dwarf"
11 "debug/plan9obj"
12 "errors"
13 "fmt"
14 "io"
15 "sort"
16 )
17
18 var validSymType = map[rune]bool{
19 'T': true,
20 't': true,
21 'D': true,
22 'd': true,
23 'B': true,
24 'b': true,
25 }
26
27 type plan9File struct {
28 plan9 *plan9obj.File
29 }
30
31 func openPlan9(r io.ReaderAt) (rawFile, error) {
32 f, err := plan9obj.NewFile(r)
33 if err != nil {
34 return nil, err
35 }
36 return &plan9File{f}, nil
37 }
38
39 func (f *plan9File) symbols() ([]Sym, error) {
40 plan9Syms, err := f.plan9.Symbols()
41 if err != nil {
42 return nil, err
43 }
44
45
46
47 var addrs []uint64
48 for _, s := range plan9Syms {
49 if !validSymType[s.Type] {
50 continue
51 }
52 addrs = append(addrs, s.Value)
53 }
54 sort.Sort(uint64s(addrs))
55
56 var syms []Sym
57
58 for _, s := range plan9Syms {
59 if !validSymType[s.Type] {
60 continue
61 }
62 sym := Sym{Addr: s.Value, Name: s.Name, Code: s.Type}
63 i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value })
64 if i < len(addrs) {
65 sym.Size = int64(addrs[i] - s.Value)
66 }
67 syms = append(syms, sym)
68 }
69
70 return syms, nil
71 }
72
73 func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
74 textStart = f.plan9.LoadAddress + f.plan9.HdrSize
75 if pclntab, err = loadPlan9Table(f.plan9, "runtime.pclntab", "runtime.epclntab"); err != nil {
76
77
78 var err2 error
79 if pclntab, err2 = loadPlan9Table(f.plan9, "pclntab", "epclntab"); err2 != nil {
80 return 0, nil, nil, err
81 }
82 }
83 if symtab, err = loadPlan9Table(f.plan9, "runtime.symtab", "runtime.esymtab"); err != nil {
84
85 var err2 error
86 if symtab, err2 = loadPlan9Table(f.plan9, "symtab", "esymtab"); err2 != nil {
87 return 0, nil, nil, err
88 }
89 }
90 return textStart, symtab, pclntab, nil
91 }
92
93 func (f *plan9File) text() (textStart uint64, text []byte, err error) {
94 sect := f.plan9.Section("text")
95 if sect == nil {
96 return 0, nil, fmt.Errorf("text section not found")
97 }
98 textStart = f.plan9.LoadAddress + f.plan9.HdrSize
99 text, err = sect.Data()
100 return
101 }
102
103 func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) {
104 syms, err := f.Symbols()
105 if err != nil {
106 return nil, err
107 }
108 for _, s := range syms {
109 if s.Name != name {
110 continue
111 }
112 return &s, nil
113 }
114 return nil, fmt.Errorf("no %s symbol found", name)
115 }
116
117 func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) {
118 ssym, err := findPlan9Symbol(f, sname)
119 if err != nil {
120 return nil, err
121 }
122 esym, err := findPlan9Symbol(f, ename)
123 if err != nil {
124 return nil, err
125 }
126 sect := f.Section("text")
127 if sect == nil {
128 return nil, err
129 }
130 data, err := sect.Data()
131 if err != nil {
132 return nil, err
133 }
134 textStart := f.LoadAddress + f.HdrSize
135 return data[ssym.Value-textStart : esym.Value-textStart], nil
136 }
137
138 func (f *plan9File) goarch() string {
139 switch f.plan9.Magic {
140 case plan9obj.Magic386:
141 return "386"
142 case plan9obj.MagicAMD64:
143 return "amd64"
144 case plan9obj.MagicARM:
145 return "arm"
146 }
147 return ""
148 }
149
150 func (f *plan9File) loadAddress() (uint64, error) {
151 return 0, fmt.Errorf("unknown load address")
152 }
153
154 func (f *plan9File) dwarf() (*dwarf.Data, error) {
155 return nil, errors.New("no DWARF data in Plan 9 file")
156 }
157
View as plain text