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