1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package amd64
32
33 import (
34 "cmd/internal/objabi"
35 "cmd/internal/sys"
36 "cmd/link/internal/ld"
37 "cmd/link/internal/loader"
38 "cmd/link/internal/sym"
39 "debug/elf"
40 "log"
41 )
42
43 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
44 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
45 if initfunc == nil {
46 return
47 }
48
49 o := func(op ...uint8) {
50 for _, op1 := range op {
51 initfunc.AddUint8(op1)
52 }
53 }
54
55
56
57
58 o(0x48, 0x8d, 0x3d)
59 initfunc.AddPCRelPlus(ctxt.Arch, ctxt.Moduledata, 0)
60
61
62 o(0xe8)
63 initfunc.AddSymRef(ctxt.Arch, addmoduledata, 0, objabi.R_CALL, 4)
64
65 o(0xc3)
66 }
67
68 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
69 targ := r.Sym()
70 var targType sym.SymKind
71 if targ != 0 {
72 targType = ldr.SymType(targ)
73 }
74
75 switch rt := r.Type(); rt {
76 default:
77 if rt >= objabi.ElfRelocOffset {
78 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
79 return false
80 }
81
82
83 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PC32):
84 if targType == sym.SDYNIMPORT {
85 ldr.Errorf(s, "unexpected R_X86_64_PC32 relocation for dynamic symbol %s", ldr.SymName(targ))
86 }
87 if targType == 0 || targType == sym.SXREF {
88 ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ))
89 }
90 su := ldr.MakeSymbolUpdater(s)
91 su.SetRelocType(rIdx, objabi.R_PCREL)
92 su.SetRelocAdd(rIdx, r.Add()+4)
93 return true
94
95 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PC64):
96 if targType == sym.SDYNIMPORT {
97 ldr.Errorf(s, "unexpected R_X86_64_PC64 relocation for dynamic symbol %s", ldr.SymName(targ))
98 }
99 if targType == 0 || targType == sym.SXREF {
100 ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ))
101 }
102 su := ldr.MakeSymbolUpdater(s)
103 su.SetRelocType(rIdx, objabi.R_PCREL)
104 su.SetRelocAdd(rIdx, r.Add()+8)
105 return true
106
107 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_PLT32):
108 su := ldr.MakeSymbolUpdater(s)
109 su.SetRelocType(rIdx, objabi.R_PCREL)
110 su.SetRelocAdd(rIdx, r.Add()+4)
111 if targType == sym.SDYNIMPORT {
112 addpltsym(target, ldr, syms, targ)
113 su.SetRelocSym(rIdx, syms.PLT)
114 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
115 }
116
117 return true
118
119 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCREL),
120 objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_GOTPCRELX),
121 objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_REX_GOTPCRELX):
122 su := ldr.MakeSymbolUpdater(s)
123 if targType != sym.SDYNIMPORT {
124
125 sData := ldr.Data(s)
126 if r.Off() >= 2 && sData[r.Off()-2] == 0x8b {
127 su.MakeWritable()
128
129 writeableData := su.Data()
130 writeableData[r.Off()-2] = 0x8d
131 su.SetRelocType(rIdx, objabi.R_PCREL)
132 su.SetRelocAdd(rIdx, r.Add()+4)
133 return true
134 }
135 }
136
137
138
139 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_X86_64_GLOB_DAT))
140
141 su.SetRelocType(rIdx, objabi.R_PCREL)
142 su.SetRelocSym(rIdx, syms.GOT)
143 su.SetRelocAdd(rIdx, r.Add()+4+int64(ldr.SymGot(targ)))
144 return true
145
146 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_X86_64_64):
147 if targType == sym.SDYNIMPORT {
148 ldr.Errorf(s, "unexpected R_X86_64_64 relocation for dynamic symbol %s", ldr.SymName(targ))
149 }
150 su := ldr.MakeSymbolUpdater(s)
151 su.SetRelocType(rIdx, objabi.R_ADDR)
152 if target.IsPIE() && target.IsInternal() {
153
154
155
156 break
157 }
158 return true
159
160
161 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 0,
162 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 0,
163 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 0:
164 su := ldr.MakeSymbolUpdater(s)
165 su.SetRelocType(rIdx, objabi.R_ADDR)
166
167 if target.IsPIE() && target.IsInternal() {
168
169
170
171 if rt == objabi.MachoRelocOffset+ld.MACHO_X86_64_RELOC_UNSIGNED*2 {
172 break
173 } else {
174
175
176 ldr.Errorf(s, "unsupported relocation for PIE: %v", rt)
177 }
178 }
179 if targType == sym.SDYNIMPORT {
180 ldr.Errorf(s, "unexpected reloc for dynamic symbol %s", ldr.SymName(targ))
181 }
182 return true
183
184 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SUBTRACTOR*2 + 0:
185
186
187
188
189
190
191
192
193
194
195
196
197
198 su := ldr.MakeSymbolUpdater(s)
199 outer, off := ld.FoldSubSymbolOffset(ldr, targ)
200 if outer != s {
201 ldr.Errorf(s, "unsupported X86_64_RELOC_SUBTRACTOR reloc: target %s, outer %s",
202 ldr.SymName(targ), ldr.SymName(outer))
203 break
204 }
205 relocs := su.Relocs()
206 if rIdx+1 >= relocs.Count() || relocs.At(rIdx+1).Type() != objabi.MachoRelocOffset+ld.MACHO_X86_64_RELOC_UNSIGNED*2+0 || relocs.At(rIdx+1).Off() != r.Off() {
207 ldr.Errorf(s, "unexpected X86_64_RELOC_SUBTRACTOR reloc, must be followed by X86_64_RELOC_UNSIGNED at the same offset: %d %v %d", rIdx, relocs.At(rIdx+1).Type(), relocs.At(rIdx+1).Off())
208 }
209
210 su.SetRelocType(rIdx+1, objabi.R_PCREL)
211 su.SetRelocAdd(rIdx+1, r.Add()+int64(r.Off())+int64(r.Siz())-off)
212
213 su.SetRelocSiz(rIdx, 0)
214 return true
215
216 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_BRANCH*2 + 1:
217 if targType == sym.SDYNIMPORT {
218 addpltsym(target, ldr, syms, targ)
219 su := ldr.MakeSymbolUpdater(s)
220 su.SetRelocSym(rIdx, syms.PLT)
221 su.SetRelocType(rIdx, objabi.R_PCREL)
222 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
223 return true
224 }
225 fallthrough
226
227 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_UNSIGNED*2 + 1,
228 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED*2 + 1,
229 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_1*2 + 1,
230 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_2*2 + 1,
231 objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_SIGNED_4*2 + 1:
232 su := ldr.MakeSymbolUpdater(s)
233 su.SetRelocType(rIdx, objabi.R_PCREL)
234
235 if targType == sym.SDYNIMPORT {
236 ldr.Errorf(s, "unexpected pc-relative reloc for dynamic symbol %s", ldr.SymName(targ))
237 }
238 return true
239
240 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT_LOAD*2 + 1:
241 if targType != sym.SDYNIMPORT {
242
243
244 sdata := ldr.Data(s)
245 if r.Off() < 2 || sdata[r.Off()-2] != 0x8b {
246 ldr.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", ldr.SymName(targ))
247 return false
248 }
249
250 su := ldr.MakeSymbolUpdater(s)
251 su.MakeWritable()
252 sdata = su.Data()
253 sdata[r.Off()-2] = 0x8d
254 su.SetRelocType(rIdx, objabi.R_PCREL)
255 return true
256 }
257 fallthrough
258
259 case objabi.MachoRelocOffset + ld.MACHO_X86_64_RELOC_GOT*2 + 1:
260 if targType != sym.SDYNIMPORT {
261 ldr.Errorf(s, "unexpected GOT reloc for non-dynamic symbol %s", ldr.SymName(targ))
262 }
263 ld.AddGotSym(target, ldr, syms, targ, 0)
264 su := ldr.MakeSymbolUpdater(s)
265 su.SetRelocType(rIdx, objabi.R_PCREL)
266 su.SetRelocSym(rIdx, syms.GOT)
267 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
268 return true
269 }
270
271
272 relocs := ldr.Relocs(s)
273 r = relocs.At(rIdx)
274
275 switch r.Type() {
276 case objabi.R_CALL:
277 if targType != sym.SDYNIMPORT {
278
279 return true
280 }
281 if target.IsExternal() {
282
283 return true
284 }
285
286
287 addpltsym(target, ldr, syms, targ)
288 su := ldr.MakeSymbolUpdater(s)
289 su.SetRelocSym(rIdx, syms.PLT)
290 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
291 return true
292
293 case objabi.R_PCREL:
294 if targType == sym.SDYNIMPORT && ldr.SymType(s).IsText() && target.IsDarwin() {
295
296
297 if r.Add() != 0 {
298 ldr.Errorf(s, "unexpected nonzero addend for dynamic symbol %s", ldr.SymName(targ))
299 return false
300 }
301 su := ldr.MakeSymbolUpdater(s)
302 if r.Off() >= 2 && su.Data()[r.Off()-2] == 0x8d {
303 su.MakeWritable()
304 su.Data()[r.Off()-2] = 0x8b
305 if target.IsInternal() {
306 ld.AddGotSym(target, ldr, syms, targ, 0)
307 su.SetRelocSym(rIdx, syms.GOT)
308 su.SetRelocAdd(rIdx, int64(ldr.SymGot(targ)))
309 } else {
310 su.SetRelocType(rIdx, objabi.R_GOTPCREL)
311 }
312 return true
313 }
314 ldr.Errorf(s, "unexpected R_PCREL reloc for dynamic symbol %s: not preceded by LEAQ instruction", ldr.SymName(targ))
315 }
316
317 case objabi.R_ADDR:
318 if ldr.SymType(s).IsText() && target.IsElf() {
319 su := ldr.MakeSymbolUpdater(s)
320 if target.IsSolaris() {
321 addpltsym(target, ldr, syms, targ)
322 su.SetRelocSym(rIdx, syms.PLT)
323 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
324 return true
325 }
326
327
328
329 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_X86_64_GLOB_DAT))
330
331 su.SetRelocSym(rIdx, syms.GOT)
332 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
333 return true
334 }
335
336
337 if target.IsPIE() && target.IsInternal() {
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369 switch ldr.SymName(s) {
370 case ".dynsym", ".rela", ".rela.plt", ".got.plt", ".dynamic":
371 return false
372 }
373 } else {
374
375
376
377
378
379
380 if t := ldr.SymType(s); !t.IsDATA() && !t.IsRODATA() {
381 break
382 }
383 }
384
385 if target.IsElf() {
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403 rela := ldr.MakeSymbolUpdater(syms.Rela)
404 rela.AddAddrPlus(target.Arch, s, int64(r.Off()))
405 if r.Siz() == 8 {
406 rela.AddUint64(target.Arch, elf.R_INFO(0, uint32(elf.R_X86_64_RELATIVE)))
407 } else {
408 ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
409 }
410 rela.AddAddrPlus(target.Arch, targ, r.Add())
411
412
413
414
415 return true
416 }
417
418 if target.IsDarwin() {
419
420
421
422 if targType == sym.SDYNIMPORT {
423
424
425 ld.MachoAddBind(s, int64(r.Off()), targ)
426 } else {
427 ld.MachoAddRebase(s, int64(r.Off()))
428 }
429
430
431
432
433 return true
434 }
435 case objabi.R_GOTPCREL:
436 if target.IsExternal() {
437
438 return true
439 }
440
441
442 }
443
444 return false
445 }
446
447 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
448 out.Write64(uint64(sectoff))
449
450 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
451 siz := r.Size
452 switch r.Type {
453 default:
454 return false
455 case objabi.R_ADDR, objabi.R_DWARFSECREF:
456 if siz == 4 {
457 out.Write64(uint64(elf.R_X86_64_32) | uint64(elfsym)<<32)
458 } else if siz == 8 {
459 out.Write64(uint64(elf.R_X86_64_64) | uint64(elfsym)<<32)
460 } else {
461 return false
462 }
463 case objabi.R_TLS_LE:
464 if siz == 4 {
465 out.Write64(uint64(elf.R_X86_64_TPOFF32) | uint64(elfsym)<<32)
466 } else {
467 return false
468 }
469 case objabi.R_TLS_IE:
470 if siz == 4 {
471 out.Write64(uint64(elf.R_X86_64_GOTTPOFF) | uint64(elfsym)<<32)
472 } else {
473 return false
474 }
475 case objabi.R_CALL:
476 if siz == 4 {
477 if ldr.SymType(r.Xsym) == sym.SDYNIMPORT {
478 out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
479 } else {
480 out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
481 }
482 } else {
483 return false
484 }
485 case objabi.R_PCREL:
486 if siz == 4 {
487 if ldr.SymType(r.Xsym) == sym.SDYNIMPORT && ldr.SymElfType(r.Xsym) == elf.STT_FUNC {
488 out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32)
489 } else {
490 out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32)
491 }
492 } else {
493 return false
494 }
495 case objabi.R_GOTPCREL:
496 if siz == 4 {
497 out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32)
498 } else {
499 return false
500 }
501 }
502
503 out.Write64(uint64(r.Xadd))
504 return true
505 }
506
507 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
508 var v uint32
509
510 rs := r.Xsym
511 rt := r.Type
512
513 if !ldr.SymType(s).IsDWARF() {
514 if ldr.SymDynid(rs) < 0 {
515 ldr.Errorf(s, "reloc %d (%s) to non-macho symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
516 return false
517 }
518
519 v = uint32(ldr.SymDynid(rs))
520 v |= 1 << 27
521 } else {
522 v = uint32(ldr.SymSect(rs).Extnum)
523 if v == 0 {
524 ldr.Errorf(s, "reloc %d (%s) to symbol %s in non-macho section %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymSect(rs).Name, ldr.SymType(rs), ldr.SymType(rs))
525 return false
526 }
527 }
528
529 switch rt {
530 default:
531 return false
532
533 case objabi.R_ADDR:
534 v |= ld.MACHO_X86_64_RELOC_UNSIGNED << 28
535
536 case objabi.R_CALL:
537 v |= 1 << 24
538 v |= ld.MACHO_X86_64_RELOC_BRANCH << 28
539
540
541 case objabi.R_PCREL:
542 v |= 1 << 24
543 v |= ld.MACHO_X86_64_RELOC_SIGNED << 28
544 case objabi.R_GOTPCREL:
545 v |= 1 << 24
546 v |= ld.MACHO_X86_64_RELOC_GOT_LOAD << 28
547 }
548
549 switch r.Size {
550 default:
551 return false
552
553 case 1:
554 v |= 0 << 25
555
556 case 2:
557 v |= 1 << 25
558
559 case 4:
560 v |= 2 << 25
561
562 case 8:
563 v |= 3 << 25
564 }
565
566 out.Write32(uint32(sectoff))
567 out.Write32(v)
568 return true
569 }
570
571 func pereloc1(arch *sys.Arch, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, sectoff int64) bool {
572 var v uint32
573
574 rs := r.Xsym
575 rt := r.Type
576
577 if ldr.SymDynid(rs) < 0 {
578 ldr.Errorf(s, "reloc %d (%s) to non-coff symbol %s type=%d (%s)", rt, sym.RelocName(arch, rt), ldr.SymName(rs), ldr.SymType(rs), ldr.SymType(rs))
579 return false
580 }
581
582 out.Write32(uint32(sectoff))
583 out.Write32(uint32(ldr.SymDynid(rs)))
584
585 switch rt {
586 default:
587 return false
588
589 case objabi.R_DWARFSECREF:
590 v = ld.IMAGE_REL_AMD64_SECREL
591
592 case objabi.R_ADDR:
593 if r.Size == 8 {
594 v = ld.IMAGE_REL_AMD64_ADDR64
595 } else {
596 v = ld.IMAGE_REL_AMD64_ADDR32
597 }
598
599 case objabi.R_PEIMAGEOFF:
600 v = ld.IMAGE_REL_AMD64_ADDR32NB
601
602 case objabi.R_CALL,
603 objabi.R_PCREL:
604 v = ld.IMAGE_REL_AMD64_REL32
605 }
606
607 out.Write16(uint16(v))
608
609 return true
610 }
611
612 func archreloc(*ld.Target, *loader.Loader, *ld.ArchSyms, loader.Reloc, loader.Sym, int64) (int64, int, bool) {
613 return -1, 0, false
614 }
615
616 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
617 log.Fatalf("unexpected relocation variant")
618 return -1
619 }
620
621 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
622 if plt.Size() == 0 {
623
624 plt.AddUint8(0xff)
625
626 plt.AddUint8(0x35)
627 plt.AddPCRelPlus(ctxt.Arch, got.Sym(), 8)
628
629
630 plt.AddUint8(0xff)
631
632 plt.AddUint8(0x25)
633 plt.AddPCRelPlus(ctxt.Arch, got.Sym(), 16)
634
635
636 plt.AddUint32(ctxt.Arch, 0x00401f0f)
637
638
639 got.AddAddrPlus(ctxt.Arch, dynamic, 0)
640
641 got.AddUint64(ctxt.Arch, 0)
642 got.AddUint64(ctxt.Arch, 0)
643 }
644 }
645
646 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
647 if ldr.SymPlt(s) >= 0 {
648 return
649 }
650
651 ld.Adddynsym(ldr, target, syms, s)
652
653 if target.IsElf() {
654 plt := ldr.MakeSymbolUpdater(syms.PLT)
655 got := ldr.MakeSymbolUpdater(syms.GOTPLT)
656 rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
657 if plt.Size() == 0 {
658 panic("plt is not set up")
659 }
660
661
662 plt.AddUint8(0xff)
663
664 plt.AddUint8(0x25)
665 plt.AddPCRelPlus(target.Arch, got.Sym(), got.Size())
666
667
668 got.AddAddrPlus(target.Arch, plt.Sym(), plt.Size())
669
670
671 plt.AddUint8(0x68)
672
673 plt.AddUint32(target.Arch, uint32((got.Size()-24-8)/8))
674
675
676 plt.AddUint8(0xe9)
677
678 plt.AddUint32(target.Arch, uint32(-(plt.Size() + 4)))
679
680
681 rela.AddAddrPlus(target.Arch, got.Sym(), got.Size()-8)
682
683 sDynid := ldr.SymDynid(s)
684 rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_X86_64_JMP_SLOT)))
685 rela.AddUint64(target.Arch, 0)
686
687 ldr.SetPlt(s, int32(plt.Size()-16))
688 } else if target.IsDarwin() {
689 ld.AddGotSym(target, ldr, syms, s, 0)
690
691 sDynid := ldr.SymDynid(s)
692 lep := ldr.MakeSymbolUpdater(syms.LinkEditPLT)
693 lep.AddUint32(target.Arch, uint32(sDynid))
694
695 plt := ldr.MakeSymbolUpdater(syms.PLT)
696 ldr.SetPlt(s, int32(plt.Size()))
697
698
699 plt.AddUint8(0xff)
700 plt.AddUint8(0x25)
701 plt.AddPCRelPlus(target.Arch, syms.GOT, int64(ldr.SymGot(s)))
702 } else {
703 ldr.Errorf(s, "addpltsym: unsupported binary format")
704 }
705 }
706
707 func tlsIEtoLE(P []byte, off, size int) {
708
709
710
711
712
713
714
715 if off < 3 {
716 log.Fatal("R_X86_64_GOTTPOFF reloc not preceded by MOVQ or ADDQ instruction")
717 }
718 op := P[off-3 : off]
719 reg := op[2] >> 3
720
721 if op[1] == 0x8b || reg == 4 {
722
723 if op[0] == 0x4c {
724 op[0] = 0x49
725 } else if size == 4 && op[0] == 0x44 {
726 op[0] = 0x41
727 }
728 if op[1] == 0x8b {
729 op[1] = 0xc7
730 } else {
731 op[1] = 0x81
732 }
733 op[2] = 0xc0 | reg
734 } else {
735
736
737
738
739 log.Fatalf("expected TLS IE op to be MOVQ, got %v", op)
740 }
741 }
742
View as plain text