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