1
2
3
4
5 package loader
6
7 import (
8 "bytes"
9 "cmd/internal/goobj"
10 "cmd/internal/objabi"
11 "cmd/internal/sys"
12 "cmd/link/internal/sym"
13 "fmt"
14 "testing"
15 )
16
17
18
19
20
21
22 func addDummyObjSym(t *testing.T, ldr *Loader, or *oReader, name string) Sym {
23 idx := uint32(len(ldr.objSyms))
24 st := loadState{l: ldr}
25 return st.addSym(name, 0, or, idx, nonPkgDef, &goobj.Sym{})
26 }
27
28 func mkLoader() *Loader {
29 er := ErrorReporter{}
30 ldr := NewLoader(0, &er)
31 er.ldr = ldr
32 return ldr
33 }
34
35 func TestAddMaterializedSymbol(t *testing.T) {
36 ldr := mkLoader()
37 dummyOreader := oReader{version: -1, syms: make([]Sym, 100)}
38 or := &dummyOreader
39
40
41 ts1 := addDummyObjSym(t, ldr, or, "type:uint8")
42 ts2 := addDummyObjSym(t, ldr, or, "mumble")
43 ts3 := addDummyObjSym(t, ldr, or, "type:string")
44
45
46 es1 := ldr.LookupOrCreateSym("extnew1", 0)
47 if es1 == 0 {
48 t.Fatalf("LookupOrCreateSym failed for extnew1")
49 }
50 es1x := ldr.LookupOrCreateSym("extnew1", 0)
51 if es1x != es1 {
52 t.Fatalf("LookupOrCreateSym lookup: expected %d got %d for second lookup", es1, es1x)
53 }
54 es2 := ldr.LookupOrCreateSym("go:info.type.uint8", 0)
55 if es2 == 0 {
56 t.Fatalf("LookupOrCreateSym failed for go.info.type.uint8")
57 }
58
59 es3 := ldr.CreateStaticSym("")
60 if es3 == 0 {
61 t.Fatalf("CreateStaticSym failed for nameless sym")
62 }
63
64
65 sb1 := ldr.MakeSymbolUpdater(es1)
66 sb2 := ldr.MakeSymbolUpdater(es2)
67 sb3 := ldr.MakeSymbolUpdater(es3)
68
69
70
71
72 for i := 0; i < 9999; i++ {
73 ldr.CreateStaticSym("dummy")
74 }
75
76
77 es3typ := sb3.Type()
78 if es3typ != sym.Sxxx {
79 t.Errorf("SymType(es3): expected %v, got %v", sym.Sxxx, es3typ)
80 }
81 sb3.SetType(sym.SRODATA)
82 es3typ = sb3.Type()
83 if es3typ != sym.SRODATA {
84 t.Errorf("SymType(es3): expected %v, got %v", sym.SRODATA, es3typ)
85 }
86 es3typ = ldr.SymType(es3)
87 if es3typ != sym.SRODATA {
88 t.Errorf("SymType(es3): expected %v, got %v", sym.SRODATA, es3typ)
89 }
90
91
92 if ldr.AttrReachable(es1) || ldr.AttrReachable(es2) || ldr.AttrReachable(es3) {
93 t.Errorf("newly materialized symbols should not be reachable")
94 }
95
96
97 ldr.SetAttrReachable(es3, true)
98 if !ldr.AttrReachable(es3) {
99 t.Errorf("expected reachable symbol after update")
100 }
101 ldr.SetAttrReachable(es3, false)
102 if ldr.AttrReachable(es3) {
103 t.Errorf("expected unreachable symbol after update")
104 }
105
106
107 for idx := 0; idx < 36; idx++ {
108 es := ldr.LookupOrCreateSym(fmt.Sprintf("zext%d", idx), 0)
109 if ldr.AttrOnList(es) {
110 t.Errorf("expected OnList after creation")
111 }
112 ldr.SetAttrOnList(es, true)
113 if !ldr.AttrOnList(es) {
114 t.Errorf("expected !OnList after update")
115 }
116 if ldr.AttrDuplicateOK(es) {
117 t.Errorf("expected DupOK after creation")
118 }
119 ldr.SetAttrDuplicateOK(es, true)
120 if !ldr.AttrDuplicateOK(es) {
121 t.Errorf("expected !DupOK after update")
122 }
123 }
124
125 sb1 = ldr.MakeSymbolUpdater(es1)
126 sb2 = ldr.MakeSymbolUpdater(es2)
127
128
129 if ldr.AttrVisibilityHidden(es3) {
130 t.Errorf("expected initially not hidden")
131 }
132 ldr.SetAttrVisibilityHidden(es3, true)
133 if !ldr.AttrVisibilityHidden(es3) {
134 t.Errorf("expected hidden after update")
135 }
136
137
138 toTest := []Sym{ts2, es3}
139 for i, s := range toTest {
140 if v := ldr.SymValue(s); v != 0 {
141 t.Errorf("ldr.Value(%d): expected 0 got %d\n", s, v)
142 }
143 nv := int64(i + 101)
144 ldr.SetSymValue(s, nv)
145 if v := ldr.SymValue(s); v != nv {
146 t.Errorf("ldr.SetValue(%d,%d): expected %d got %d\n", s, nv, nv, v)
147 }
148 }
149
150
151 es3al := ldr.SymAlign(es3)
152 if es3al != 0 {
153 t.Errorf("SymAlign(es3): expected 0, got %d", es3al)
154 }
155 ldr.SetSymAlign(es3, 128)
156 es3al = ldr.SymAlign(es3)
157 if es3al != 128 {
158 t.Errorf("SymAlign(es3): expected 128, got %d", es3al)
159 }
160
161
162 r1, _ := sb1.AddRel(objabi.R_ADDR)
163 r1.SetOff(0)
164 r1.SetSiz(1)
165 r1.SetSym(ts1)
166 r2, _ := sb1.AddRel(objabi.R_CALL)
167 r2.SetOff(3)
168 r2.SetSiz(8)
169 r2.SetSym(ts2)
170 r3, _ := sb2.AddRel(objabi.R_USETYPE)
171 r3.SetOff(7)
172 r3.SetSiz(1)
173 r3.SetSym(ts3)
174
175
176 d1 := []byte{1, 2, 3}
177 d2 := []byte{4, 5, 6, 7}
178 sb1.AddBytes(d1)
179 sb2.AddBytes(d2)
180
181
182
183
184 expRel := [][]Reloc{{r1, r2}, {r3}}
185 for k, sb := range []*SymbolBuilder{sb1, sb2} {
186 rsl := sb.Relocs()
187 exp := expRel[k]
188 if !sameRelocSlice(&rsl, exp) {
189 t.Errorf("expected relocs %v, got %v", exp, rsl)
190 }
191 }
192
193
194 dat := sb2.Data()
195 if !bytes.Equal(dat, d2) {
196 t.Errorf("expected es2 data %v, got %v", d2, dat)
197 }
198
199
200 es3name := ldr.SymName(es3)
201 if "" != es3name {
202 t.Errorf("expected es3 name of '', got '%s'", es3name)
203 }
204
205
206 es1val := sb1.Value()
207 if 0 != es1val {
208 t.Errorf("expected es1 value of 0, got %v", es1val)
209 }
210
211
212 irm := ldr.IsReflectMethod(es1)
213 if 0 != es1val {
214 t.Errorf("expected IsReflectMethod(es1) value of 0, got %v", irm)
215 }
216 }
217
218 func sameRelocSlice(s1 *Relocs, s2 []Reloc) bool {
219 if s1.Count() != len(s2) {
220 return false
221 }
222 for i := 0; i < s1.Count(); i++ {
223 r1 := s1.At(i)
224 r2 := &s2[i]
225 if r1.Sym() != r2.Sym() ||
226 r1.Type() != r2.Type() ||
227 r1.Off() != r2.Off() ||
228 r1.Add() != r2.Add() ||
229 r1.Siz() != r2.Siz() {
230 return false
231 }
232 }
233 return true
234 }
235
236 type addFunc func(l *Loader, s Sym, s2 Sym) Sym
237
238 func mkReloc(l *Loader, typ objabi.RelocType, off int32, siz uint8, add int64, sym Sym) Reloc {
239 r := Reloc{&goobj.Reloc{}, l.extReader, l}
240 r.SetType(typ)
241 r.SetOff(off)
242 r.SetSiz(siz)
243 r.SetAdd(add)
244 r.SetSym(sym)
245 return r
246 }
247
248 func TestAddDataMethods(t *testing.T) {
249 ldr := mkLoader()
250 dummyOreader := oReader{version: -1, syms: make([]Sym, 100)}
251 or := &dummyOreader
252
253
254 addDummyObjSym(t, ldr, or, "type:uint8")
255 ldr.LookupOrCreateSym("hello", 0)
256
257 arch := sys.ArchAMD64
258 var testpoints = []struct {
259 which string
260 addDataFunc addFunc
261 expData []byte
262 expKind sym.SymKind
263 expRel []Reloc
264 }{
265 {
266 which: "AddUint8",
267 addDataFunc: func(l *Loader, s Sym, _ Sym) Sym {
268 sb := l.MakeSymbolUpdater(s)
269 sb.AddUint8('a')
270 return s
271 },
272 expData: []byte{'a'},
273 expKind: sym.SDATA,
274 },
275 {
276 which: "AddUintXX",
277 addDataFunc: func(l *Loader, s Sym, _ Sym) Sym {
278 sb := l.MakeSymbolUpdater(s)
279 sb.AddUintXX(arch, 25185, 2)
280 return s
281 },
282 expData: []byte{'a', 'b'},
283 expKind: sym.SDATA,
284 },
285 {
286 which: "SetUint8",
287 addDataFunc: func(l *Loader, s Sym, _ Sym) Sym {
288 sb := l.MakeSymbolUpdater(s)
289 sb.AddUint8('a')
290 sb.AddUint8('b')
291 sb.SetUint8(arch, 1, 'c')
292 return s
293 },
294 expData: []byte{'a', 'c'},
295 expKind: sym.SDATA,
296 },
297 {
298 which: "AddString",
299 addDataFunc: func(l *Loader, s Sym, _ Sym) Sym {
300 sb := l.MakeSymbolUpdater(s)
301 sb.Addstring("hello")
302 return s
303 },
304 expData: []byte{'h', 'e', 'l', 'l', 'o', 0},
305 expKind: sym.SNOPTRDATA,
306 },
307 {
308 which: "AddAddrPlus",
309 addDataFunc: func(l *Loader, s Sym, s2 Sym) Sym {
310 sb := l.MakeSymbolUpdater(s)
311 sb.AddAddrPlus(arch, s2, 3)
312 return s
313 },
314 expData: []byte{0, 0, 0, 0, 0, 0, 0, 0},
315 expKind: sym.SDATA,
316 expRel: []Reloc{mkReloc(ldr, objabi.R_ADDR, 0, 8, 3, 6)},
317 },
318 {
319 which: "AddAddrPlus4",
320 addDataFunc: func(l *Loader, s Sym, s2 Sym) Sym {
321 sb := l.MakeSymbolUpdater(s)
322 sb.AddAddrPlus4(arch, s2, 3)
323 return s
324 },
325 expData: []byte{0, 0, 0, 0},
326 expKind: sym.SDATA,
327 expRel: []Reloc{mkReloc(ldr, objabi.R_ADDR, 0, 4, 3, 7)},
328 },
329 {
330 which: "AddCURelativeAddrPlus",
331 addDataFunc: func(l *Loader, s Sym, s2 Sym) Sym {
332 sb := l.MakeSymbolUpdater(s)
333 sb.AddCURelativeAddrPlus(arch, s2, 7)
334 return s
335 },
336 expData: []byte{0, 0, 0, 0, 0, 0, 0, 0},
337 expKind: sym.SDATA,
338 expRel: []Reloc{mkReloc(ldr, objabi.R_ADDRCUOFF, 0, 8, 7, 8)},
339 },
340 {
341 which: "AddPEImageRelativeAddrPlus",
342 addDataFunc: func(l *Loader, s Sym, s2 Sym) Sym {
343 sb := l.MakeSymbolUpdater(s)
344 sb.AddPEImageRelativeAddrPlus(arch, s2, 3)
345 return s
346 },
347 expData: []byte{0, 0, 0, 0},
348 expKind: sym.SDATA,
349 expRel: []Reloc{mkReloc(ldr, objabi.R_PEIMAGEOFF, 0, 4, 3, 9)},
350 },
351 }
352
353 var pmi Sym
354 for k, tp := range testpoints {
355 name := fmt.Sprintf("new%d", k+1)
356 mi := ldr.LookupOrCreateSym(name, 0)
357 if mi == 0 {
358 t.Fatalf("LookupOrCreateSym failed for '" + name + "'")
359 }
360 mi = tp.addDataFunc(ldr, mi, pmi)
361 if ldr.SymType(mi) != tp.expKind {
362 t.Errorf("testing Loader.%s: expected kind %s got %s",
363 tp.which, tp.expKind, ldr.SymType(mi))
364 }
365 if !bytes.Equal(ldr.Data(mi), tp.expData) {
366 t.Errorf("testing Loader.%s: expected data %v got %v",
367 tp.which, tp.expData, ldr.Data(mi))
368 }
369 relocs := ldr.Relocs(mi)
370 if !sameRelocSlice(&relocs, tp.expRel) {
371 t.Fatalf("testing Loader.%s: got relocslice %+v wanted %+v",
372 tp.which, relocs, tp.expRel)
373 }
374 pmi = mi
375 }
376 }
377
378 func TestOuterSub(t *testing.T) {
379 ldr := mkLoader()
380 dummyOreader := oReader{version: -1, syms: make([]Sym, 100)}
381 or := &dummyOreader
382
383
384 addDummyObjSym(t, ldr, or, "type:uint8")
385 es1 := ldr.LookupOrCreateSym("outer", 0)
386 ldr.MakeSymbolUpdater(es1).SetSize(101)
387 es2 := ldr.LookupOrCreateSym("sub1", 0)
388 es3 := ldr.LookupOrCreateSym("sub2", 0)
389 es4 := ldr.LookupOrCreateSym("sub3", 0)
390 es5 := ldr.LookupOrCreateSym("sub4", 0)
391 es6 := ldr.LookupOrCreateSym("sub5", 0)
392
393
394 if ldr.OuterSym(es1) != 0 {
395 t.Errorf("es1 outer sym set ")
396 }
397 if ldr.SubSym(es2) != 0 {
398 t.Errorf("es2 outer sym set ")
399 }
400
401
402 ldr.AddInteriorSym(es1, es2)
403 if ldr.OuterSym(es1) != 0 {
404 t.Errorf("ldr.OuterSym(es1) got %d wanted %d", ldr.OuterSym(es1), 0)
405 }
406 if ldr.OuterSym(es2) != es1 {
407 t.Errorf("ldr.OuterSym(es2) got %d wanted %d", ldr.OuterSym(es2), es1)
408 }
409 if ldr.SubSym(es1) != es2 {
410 t.Errorf("ldr.SubSym(es1) got %d wanted %d", ldr.SubSym(es1), es2)
411 }
412 if ldr.SubSym(es2) != 0 {
413 t.Errorf("ldr.SubSym(es2) got %d wanted %d", ldr.SubSym(es2), 0)
414 }
415
416
417 ldr.AddInteriorSym(es1, es3)
418 if ldr.OuterSym(es1) != 0 {
419 t.Errorf("ldr.OuterSym(es1) got %d wanted %d", ldr.OuterSym(es1), 0)
420 }
421 if ldr.OuterSym(es2) != es1 {
422 t.Errorf("ldr.OuterSym(es2) got %d wanted %d", ldr.OuterSym(es2), es1)
423 }
424 if ldr.OuterSym(es3) != es1 {
425 t.Errorf("ldr.OuterSym(es3) got %d wanted %d", ldr.OuterSym(es3), es1)
426 }
427 if ldr.SubSym(es1) != es3 {
428 t.Errorf("ldr.SubSym(es1) got %d wanted %d", ldr.SubSym(es1), es3)
429 }
430 if ldr.SubSym(es3) != es2 {
431 t.Errorf("ldr.SubSym(es3) got %d wanted %d", ldr.SubSym(es3), es2)
432 }
433
434
435 ldr.AddInteriorSym(es1, es4)
436 ldr.AddInteriorSym(es1, es5)
437 ldr.AddInteriorSym(es1, es6)
438
439
440 ldr.SetSymValue(es2, 7)
441 ldr.SetSymValue(es3, 1)
442 ldr.SetSymValue(es4, 13)
443 ldr.SetSymValue(es5, 101)
444 ldr.SetSymValue(es6, 3)
445
446
447 news := ldr.SortSub(es1)
448 if news != es3 {
449 t.Errorf("ldr.SortSub leader got %d wanted %d", news, es3)
450 }
451 pv := int64(-1)
452 count := 0
453 for ss := ldr.SubSym(es1); ss != 0; ss = ldr.SubSym(ss) {
454 v := ldr.SymValue(ss)
455 if v <= pv {
456 t.Errorf("ldr.SortSub sortfail at %d: val %d >= prev val %d",
457 ss, v, pv)
458 }
459 pv = v
460 count++
461 }
462 if count != 5 {
463 t.Errorf("expected %d in sub list got %d", 5, count)
464 }
465 }
466
View as plain text