1
2
3
4
5
6 package loadxcoff
7
8 import (
9 "cmd/internal/bio"
10 "cmd/internal/objabi"
11 "cmd/internal/sys"
12 "cmd/link/internal/loader"
13 "cmd/link/internal/sym"
14 "errors"
15 "fmt"
16 "internal/xcoff"
17 )
18
19
20 type ldSection struct {
21 xcoff.Section
22 sym loader.Sym
23 }
24
25
26
27
28 type xcoffBiobuf bio.Reader
29
30 func (f *xcoffBiobuf) ReadAt(p []byte, off int64) (int, error) {
31 ret := ((*bio.Reader)(f)).MustSeek(off, 0)
32 if ret < 0 {
33 return 0, errors.New("fail to seek")
34 }
35 n, err := f.Read(p)
36 if err != nil {
37 return 0, err
38 }
39 return n, nil
40 }
41
42
43
44 func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, err error) {
45 errorf := func(str string, args ...interface{}) ([]loader.Sym, error) {
46 return nil, fmt.Errorf("loadxcoff: %v: %v", pn, fmt.Sprintf(str, args...))
47 }
48
49 var ldSections []*ldSection
50
51 f, err := xcoff.NewFile((*xcoffBiobuf)(input))
52 if err != nil {
53 return nil, err
54 }
55 defer f.Close()
56
57 for _, sect := range f.Sections {
58
59 if sect.Type < xcoff.STYP_TEXT || sect.Type > xcoff.STYP_BSS {
60 continue
61 }
62 lds := new(ldSection)
63 lds.Section = *sect
64 name := fmt.Sprintf("%s(%s)", pkg, lds.Name)
65 symbol := l.LookupOrCreateSym(name, localSymVersion)
66 s := l.MakeSymbolUpdater(symbol)
67
68 switch lds.Type {
69 default:
70 return errorf("unrecognized section type 0x%x", lds.Type)
71 case xcoff.STYP_TEXT:
72 s.SetType(sym.STEXT)
73 case xcoff.STYP_DATA:
74 s.SetType(sym.SNOPTRDATA)
75 case xcoff.STYP_BSS:
76 s.SetType(sym.SNOPTRBSS)
77 }
78
79 s.SetSize(int64(lds.Size))
80 if s.Type() != sym.SNOPTRBSS {
81 data, err := lds.Section.Data()
82 if err != nil {
83 return nil, err
84 }
85 s.SetData(data)
86 }
87
88 lds.sym = symbol
89 ldSections = append(ldSections, lds)
90 }
91
92
93
94 for _, sx := range f.Symbols {
95
96 stype, errmsg := getSymbolType(f, sx)
97 if errmsg != "" {
98 return errorf("error reading symbol %s: %s", sx.Name, errmsg)
99 }
100 if stype == sym.Sxxx {
101 continue
102 }
103
104 s := l.LookupOrCreateSym(sx.Name, 0)
105
106
107 if l.SymType(s).IsText() {
108 if l.AttrOnList(s) {
109 return errorf("symbol %s listed multiple times", l.SymName(s))
110 }
111 l.SetAttrOnList(s, true)
112 textp = append(textp, s)
113 }
114 }
115
116
117 for _, sect := range ldSections {
118
119 if sect.Type != xcoff.STYP_TEXT && sect.Type != xcoff.STYP_DATA {
120 continue
121 }
122 sb := l.MakeSymbolUpdater(sect.sym)
123 for _, rx := range sect.Relocs {
124 rSym := l.LookupOrCreateCgoExport(rx.Symbol.Name, 0)
125 if uint64(int32(rx.VirtualAddress)) != rx.VirtualAddress {
126 return errorf("virtual address of a relocation is too big: 0x%x", rx.VirtualAddress)
127 }
128 rOff := int32(rx.VirtualAddress)
129 var rSize uint8
130 var rType objabi.RelocType
131 var rAdd int64
132 switch rx.Type {
133 default:
134 return errorf("section %s: unknown relocation of type 0x%x", sect.Name, rx.Type)
135 case xcoff.R_POS:
136
137
138 if rx.Length != 64 {
139 return errorf("section %s: relocation R_POS has length different from 64: %d", sect.Name, rx.Length)
140 }
141 rSize = 8
142 rType = objabi.R_CONST
143 rAdd = int64(rx.Symbol.Value)
144
145 case xcoff.R_RBR:
146 rSize = 4
147 rType = objabi.R_CALLPOWER
148 rAdd = 0
149 }
150 r, _ := sb.AddRel(rType)
151 r.SetOff(rOff)
152 r.SetSiz(rSize)
153 r.SetSym(rSym)
154 r.SetAdd(rAdd)
155 }
156 }
157 return textp, nil
158 }
159
160
161
162 func getSymbolType(f *xcoff.File, s *xcoff.Symbol) (stype sym.SymKind, err string) {
163
164 if s.SectionNumber == -2 {
165 if s.StorageClass == xcoff.C_FILE {
166 return sym.Sxxx, ""
167 }
168 return sym.Sxxx, "unrecognised StorageClass for sectionNumber = -2"
169 }
170
171
172
173 if s.SectionNumber == 0 {
174 return sym.Sxxx, ""
175 }
176
177 sectType := f.Sections[s.SectionNumber-1].SectionHeader.Type
178 switch sectType {
179 default:
180 return sym.Sxxx, fmt.Sprintf("getSymbolType for Section type 0x%x not implemented", sectType)
181 case xcoff.STYP_DWARF, xcoff.STYP_DEBUG:
182 return sym.Sxxx, ""
183 case xcoff.STYP_DATA, xcoff.STYP_BSS, xcoff.STYP_TEXT:
184 }
185
186 switch s.StorageClass {
187 default:
188 return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x not implemented", s.StorageClass)
189 case xcoff.C_HIDEXT, xcoff.C_EXT, xcoff.C_WEAKEXT:
190 switch s.AuxCSect.StorageMappingClass {
191 default:
192 return sym.Sxxx, fmt.Sprintf("getSymbolType for Storage class 0x%x and Storage Map 0x%x not implemented", s.StorageClass, s.AuxCSect.StorageMappingClass)
193
194
195 case xcoff.XMC_PR:
196 if sectType == xcoff.STYP_TEXT {
197 return sym.STEXT, ""
198 }
199 return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_PR", sectType, s.StorageClass)
200
201
202 case xcoff.XMC_RW:
203 if sectType == xcoff.STYP_DATA {
204 return sym.SDATA, ""
205 }
206 if sectType == xcoff.STYP_BSS {
207 return sym.SBSS, ""
208 }
209 return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_RW", sectType, s.StorageClass)
210
211
212 case xcoff.XMC_DS:
213 if sectType == xcoff.STYP_DATA {
214 return sym.SDATA, ""
215 }
216 return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
217
218
219 case xcoff.XMC_TC0, xcoff.XMC_TE:
220 if sectType == xcoff.STYP_DATA {
221 return sym.SXCOFFTOC, ""
222 }
223 return sym.Sxxx, fmt.Sprintf("unrecognised Section Type 0x%x for Storage Class 0x%x with Storage Map XMC_DS", sectType, s.StorageClass)
224
225 }
226 }
227 }
228
View as plain text