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, 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, err
82 }
83 }
84 return textStart, pclntab, nil
85 }
86
87 func (f *plan9File) text() (textStart uint64, text []byte, err error) {
88 sect := f.plan9.Section("text")
89 if sect == nil {
90 return 0, nil, fmt.Errorf("text section not found")
91 }
92 textStart = f.plan9.LoadAddress + f.plan9.HdrSize
93 text, err = sect.Data()
94 return
95 }
96
97 func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) {
98 syms, err := f.Symbols()
99 if err != nil {
100 return nil, err
101 }
102 for _, s := range syms {
103 if s.Name != name {
104 continue
105 }
106 return &s, nil
107 }
108 return nil, fmt.Errorf("no %s symbol found", name)
109 }
110
111 func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) {
112 ssym, err := findPlan9Symbol(f, sname)
113 if err != nil {
114 return nil, err
115 }
116 esym, err := findPlan9Symbol(f, ename)
117 if err != nil {
118 return nil, err
119 }
120 sect := f.Section("text")
121 if sect == nil {
122 return nil, err
123 }
124 data, err := sect.Data()
125 if err != nil {
126 return nil, err
127 }
128 textStart := f.LoadAddress + f.HdrSize
129 return data[ssym.Value-textStart : esym.Value-textStart], nil
130 }
131
132 func (f *plan9File) goarch() string {
133 switch f.plan9.Magic {
134 case plan9obj.Magic386:
135 return "386"
136 case plan9obj.MagicAMD64:
137 return "amd64"
138 case plan9obj.MagicARM:
139 return "arm"
140 }
141 return ""
142 }
143
144 func (f *plan9File) loadAddress() (uint64, error) {
145 return 0, fmt.Errorf("unknown load address")
146 }
147
148 func (f *plan9File) dwarf() (*dwarf.Data, error) {
149 return nil, errors.New("no DWARF data in Plan 9 file")
150 }
151
View as plain text