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