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