1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Parsing of XCOFF executable (AIX)
package objfile
import (
"debug/dwarf"
"fmt"
"internal/xcoff"
"io"
"unicode"
)
type xcoffFile struct {
xcoff *xcoff.File
}
func openXcoff(r io.ReaderAt) (rawFile, error) {
f, err := xcoff.NewFile(r)
if err != nil {
return nil, err
}
return &xcoffFile{f}, nil
}
func (f *xcoffFile) symbols() ([]Sym, error) {
var syms []Sym
for _, s := range f.xcoff.Symbols {
const (
N_UNDEF = 0 // An undefined (extern) symbol
N_ABS = -1 // An absolute symbol (e_value is a constant, not an address)
N_DEBUG = -2 // A debugging symbol
)
sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'}
switch s.SectionNumber {
case N_UNDEF:
sym.Code = 'U'
case N_ABS:
sym.Code = 'C'
case N_DEBUG:
sym.Code = '?'
default:
if s.SectionNumber < 0 || len(f.xcoff.Sections) < int(s.SectionNumber) {
return nil, fmt.Errorf("invalid section number in symbol table")
}
sect := f.xcoff.Sections[s.SectionNumber-1]
// debug/xcoff returns an offset in the section not the actual address
sym.Addr += sect.VirtualAddress
if s.AuxCSect.SymbolType&0x3 == xcoff.XTY_LD {
// The size of a function is contained in the
// AUX_FCN entry
sym.Size = s.AuxFcn.Size
} else {
sym.Size = s.AuxCSect.Length
}
sym.Size = s.AuxCSect.Length
switch sect.Type {
case xcoff.STYP_TEXT:
if s.AuxCSect.StorageMappingClass == xcoff.XMC_RO {
sym.Code = 'R'
} else {
sym.Code = 'T'
}
case xcoff.STYP_DATA:
sym.Code = 'D'
case xcoff.STYP_BSS:
sym.Code = 'B'
}
if s.StorageClass == xcoff.C_HIDEXT {
// Local symbol
sym.Code = unicode.ToLower(sym.Code)
}
}
syms = append(syms, sym)
}
return syms, nil
}
func (f *xcoffFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) {
if sect := f.xcoff.Section(".text"); sect != nil {
textStart = sect.VirtualAddress
}
if pclntab, err = loadXCOFFTable(f.xcoff, "runtime.pclntab", "runtime.epclntab"); err != nil {
return 0, nil, nil, err
}
symtab, _ = loadXCOFFTable(f.xcoff, "runtime.symtab", "runtime.esymtab") // ignore error, this symbol is not useful anyway
return textStart, symtab, pclntab, nil
}
func (f *xcoffFile) text() (textStart uint64, text []byte, err error) {
sect := f.xcoff.Section(".text")
if sect == nil {
return 0, nil, fmt.Errorf("text section not found")
}
textStart = sect.VirtualAddress
text, err = sect.Data()
return
}
func findXCOFFSymbol(f *xcoff.File, name string) (*xcoff.Symbol, error) {
for _, s := range f.Symbols {
if s.Name != name {
continue
}
if s.SectionNumber <= 0 {
return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber)
}
if len(f.Sections) < int(s.SectionNumber) {
return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections))
}
return s, nil
}
return nil, fmt.Errorf("no %s symbol found", name)
}
func loadXCOFFTable(f *xcoff.File, sname, ename string) ([]byte, error) {
ssym, err := findXCOFFSymbol(f, sname)
if err != nil {
return nil, err
}
esym, err := findXCOFFSymbol(f, ename)
if err != nil {
return nil, err
}
if ssym.SectionNumber != esym.SectionNumber {
return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename)
}
sect := f.Sections[ssym.SectionNumber-1]
data, err := sect.Data()
if err != nil {
return nil, err
}
return data[ssym.Value:esym.Value], nil
}
func (f *xcoffFile) goarch() string {
switch f.xcoff.TargetMachine {
case xcoff.U802TOCMAGIC:
return "ppc"
case xcoff.U64_TOCMAGIC:
return "ppc64"
}
return ""
}
func (f *xcoffFile) loadAddress() (uint64, error) {
return 0, fmt.Errorf("unknown load address")
}
func (f *xcoffFile) dwarf() (*dwarf.Data, error) {
return f.xcoff.DWARF()
}
|