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