1
2
3
4
5
6 package objfile
7
8 import (
9 "cmd/internal/archive"
10 "cmp"
11 "debug/dwarf"
12 "debug/gosym"
13 "fmt"
14 "io"
15 "os"
16 "slices"
17 )
18
19 type rawFile interface {
20 symbols() (syms []Sym, err error)
21 pcln() (textStart uint64, symtab, pclntab []byte, err error)
22 text() (textStart uint64, text []byte, err error)
23 goarch() string
24 loadAddress() (uint64, error)
25 dwarf() (*dwarf.Data, error)
26 }
27
28
29 type File struct {
30 r *os.File
31 entries []*Entry
32 }
33
34 type Entry struct {
35 name string
36 raw rawFile
37 }
38
39
40 type Sym struct {
41 Name string
42 Addr uint64
43 Size int64
44 Code rune
45 Type string
46 Relocs []Reloc
47 }
48
49 type Reloc struct {
50 Addr uint64
51 Size uint64
52 Stringer RelocStringer
53 }
54
55 type RelocStringer interface {
56
57
58 String(insnOffset uint64) string
59 }
60
61 var openers = []func(io.ReaderAt) (rawFile, error){
62 openElf,
63 openMacho,
64 openPE,
65 openPlan9,
66 openXcoff,
67 }
68
69
70
71 func Open(name string) (*File, error) {
72 r, err := os.Open(name)
73 if err != nil {
74 return nil, err
75 }
76 if f, err := openGoFile(r); err == nil {
77 return f, nil
78 } else if _, ok := err.(archive.ErrGoObjOtherVersion); ok {
79 return nil, fmt.Errorf("open %s: %v", name, err)
80 }
81 for _, try := range openers {
82 if raw, err := try(r); err == nil {
83 return &File{r, []*Entry{{raw: raw}}}, nil
84 }
85 }
86 r.Close()
87 return nil, fmt.Errorf("open %s: unrecognized object file", name)
88 }
89
90 func (f *File) Close() error {
91 return f.r.Close()
92 }
93
94 func (f *File) Entries() []*Entry {
95 return f.entries
96 }
97
98 func (f *File) Symbols() ([]Sym, error) {
99 return f.entries[0].Symbols()
100 }
101
102 func (f *File) PCLineTable() (Liner, error) {
103 return f.entries[0].PCLineTable()
104 }
105
106 func (f *File) Text() (uint64, []byte, error) {
107 return f.entries[0].Text()
108 }
109
110 func (f *File) GOARCH() string {
111 return f.entries[0].GOARCH()
112 }
113
114 func (f *File) LoadAddress() (uint64, error) {
115 return f.entries[0].LoadAddress()
116 }
117
118 func (f *File) DWARF() (*dwarf.Data, error) {
119 return f.entries[0].DWARF()
120 }
121
122 func (f *File) Disasm() (*Disasm, error) {
123 return f.entries[0].Disasm()
124 }
125
126 func (e *Entry) Name() string {
127 return e.name
128 }
129
130 func (e *Entry) Symbols() ([]Sym, error) {
131 syms, err := e.raw.symbols()
132 if err != nil {
133 return nil, err
134 }
135 slices.SortFunc(syms, func(a, b Sym) int {
136 return cmp.Compare(a.Addr, b.Addr)
137 })
138 return syms, nil
139 }
140
141 func (e *Entry) PCLineTable() (Liner, error) {
142
143
144 if pcln, ok := e.raw.(Liner); ok {
145 return pcln, nil
146 }
147
148 textStart, symtab, pclntab, err := e.raw.pcln()
149 if err != nil {
150 return nil, err
151 }
152 syms, err := e.raw.symbols()
153 if err == nil {
154 for _, s := range syms {
155 if s.Name == "runtime.text" {
156 textStart = s.Addr
157 break
158 }
159 }
160 }
161 return gosym.NewTable(symtab, gosym.NewLineTable(pclntab, textStart))
162 }
163
164 func (e *Entry) Text() (uint64, []byte, error) {
165 return e.raw.text()
166 }
167
168 func (e *Entry) GOARCH() string {
169 return e.raw.goarch()
170 }
171
172
173
174
175 func (e *Entry) LoadAddress() (uint64, error) {
176 return e.raw.loadAddress()
177 }
178
179
180
181 func (e *Entry) DWARF() (*dwarf.Data, error) {
182 return e.raw.dwarf()
183 }
184
View as plain text