Source file src/pkg/cmd/link/internal/s390x/asm.go
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 s390x
32
33 import (
34 "cmd/internal/objabi"
35 "cmd/internal/sys"
36 "cmd/link/internal/ld"
37 "cmd/link/internal/sym"
38 "debug/elf"
39 "fmt"
40 )
41
42
43
44
45
46
47
48
49
50
51
52 func gentext(ctxt *ld.Link) {
53 if !ctxt.DynlinkingGo() {
54 return
55 }
56 addmoduledata := ctxt.Syms.Lookup("runtime.addmoduledata", 0)
57 if addmoduledata.Type == sym.STEXT && ctxt.BuildMode != ld.BuildModePlugin {
58
59
60 return
61 }
62 addmoduledata.Attr |= sym.AttrReachable
63 initfunc := ctxt.Syms.Lookup("go.link.addmoduledata", 0)
64 initfunc.Type = sym.STEXT
65 initfunc.Attr |= sym.AttrLocal
66 initfunc.Attr |= sym.AttrReachable
67
68
69 initfunc.AddUint8(0xc0)
70 initfunc.AddUint8(0x20)
71 lmd := initfunc.AddRel()
72 lmd.InitExt()
73 lmd.Off = int32(initfunc.Size)
74 lmd.Siz = 4
75 lmd.Sym = ctxt.Moduledata
76 lmd.Type = objabi.R_PCREL
77 lmd.Variant = sym.RV_390_DBL
78 lmd.Add = 2 + int64(lmd.Siz)
79 initfunc.AddUint32(ctxt.Arch, 0)
80
81
82 initfunc.AddUint8(0xc0)
83 initfunc.AddUint8(0xf4)
84 rel := initfunc.AddRel()
85 rel.InitExt()
86 rel.Off = int32(initfunc.Size)
87 rel.Siz = 4
88 rel.Sym = ctxt.Syms.Lookup("runtime.addmoduledata", 0)
89 rel.Type = objabi.R_CALL
90 rel.Variant = sym.RV_390_DBL
91 rel.Add = 2 + int64(rel.Siz)
92 initfunc.AddUint32(ctxt.Arch, 0)
93
94
95 initfunc.AddUint32(ctxt.Arch, 0)
96 if ctxt.BuildMode == ld.BuildModePlugin {
97 ctxt.Textp = append(ctxt.Textp, addmoduledata)
98 }
99 ctxt.Textp = append(ctxt.Textp, initfunc)
100 initarray_entry := ctxt.Syms.Lookup("go.link.addmoduledatainit", 0)
101 initarray_entry.Attr |= sym.AttrLocal
102 initarray_entry.Attr |= sym.AttrReachable
103 initarray_entry.Type = sym.SINITARR
104 initarray_entry.AddAddr(ctxt.Arch, initfunc)
105 }
106
107 func adddynrel(ctxt *ld.Link, s *sym.Symbol, r *sym.Reloc) bool {
108 targ := r.Sym
109 r.InitExt()
110
111 switch r.Type {
112 default:
113 if r.Type >= objabi.ElfRelocOffset {
114 ld.Errorf(s, "unexpected relocation type %d", r.Type)
115 return false
116 }
117
118
119 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_12),
120 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT12):
121 ld.Errorf(s, "s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type-objabi.ElfRelocOffset)
122 return false
123
124 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_8),
125 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_16),
126 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_32),
127 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_64):
128 if targ.Type == sym.SDYNIMPORT {
129 ld.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", targ.Name)
130 }
131 r.Type = objabi.R_ADDR
132 return true
133
134 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16),
135 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32),
136 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC64):
137 if targ.Type == sym.SDYNIMPORT {
138 ld.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", targ.Name)
139 }
140
141
142 if (targ.Type == 0 || targ.Type == sym.SXREF) && !targ.Attr.VisibilityHidden() {
143 ld.Errorf(s, "unknown symbol %s in pcrel", targ.Name)
144 }
145 r.Type = objabi.R_PCREL
146 r.Add += int64(r.Siz)
147 return true
148
149 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT16),
150 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT32),
151 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT64):
152 ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
153 return true
154
155 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT16DBL),
156 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32DBL):
157 r.Type = objabi.R_PCREL
158 r.Variant = sym.RV_390_DBL
159 r.Add += int64(r.Siz)
160 if targ.Type == sym.SDYNIMPORT {
161 addpltsym(ctxt, targ)
162 r.Sym = ctxt.Syms.Lookup(".plt", 0)
163 r.Add += int64(targ.Plt())
164 }
165 return true
166
167 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32),
168 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT64):
169 r.Type = objabi.R_PCREL
170 r.Add += int64(r.Siz)
171 if targ.Type == sym.SDYNIMPORT {
172 addpltsym(ctxt, targ)
173 r.Sym = ctxt.Syms.Lookup(".plt", 0)
174 r.Add += int64(targ.Plt())
175 }
176 return true
177
178 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_COPY):
179 ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
180 return false
181
182 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GLOB_DAT):
183 ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
184 return false
185
186 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_JMP_SLOT):
187 ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
188 return false
189
190 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_RELATIVE):
191 ld.Errorf(s, "unimplemented S390x relocation: %v", r.Type-objabi.ElfRelocOffset)
192 return false
193
194 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTOFF):
195 if targ.Type == sym.SDYNIMPORT {
196 ld.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name)
197 }
198 r.Type = objabi.R_GOTOFF
199 return true
200
201 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPC):
202 r.Type = objabi.R_PCREL
203 r.Sym = ctxt.Syms.Lookup(".got", 0)
204 r.Add += int64(r.Siz)
205 return true
206
207 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16DBL),
208 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32DBL):
209 r.Type = objabi.R_PCREL
210 r.Variant = sym.RV_390_DBL
211 r.Add += int64(r.Siz)
212 if targ.Type == sym.SDYNIMPORT {
213 ld.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", targ.Name)
214 }
215 return true
216
217 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPCDBL):
218 r.Type = objabi.R_PCREL
219 r.Variant = sym.RV_390_DBL
220 r.Sym = ctxt.Syms.Lookup(".got", 0)
221 r.Add += int64(r.Siz)
222 return true
223
224 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTENT):
225 addgotsym(ctxt, targ)
226
227 r.Type = objabi.R_PCREL
228 r.Variant = sym.RV_390_DBL
229 r.Sym = ctxt.Syms.Lookup(".got", 0)
230 r.Add += int64(targ.Got())
231 r.Add += int64(r.Siz)
232 return true
233 }
234
235 if targ.Type != sym.SDYNIMPORT {
236 return true
237 }
238
239 return false
240 }
241
242 func elfreloc1(ctxt *ld.Link, r *sym.Reloc, sectoff int64) bool {
243 ctxt.Out.Write64(uint64(sectoff))
244
245 elfsym := r.Xsym.ElfsymForReloc()
246 switch r.Type {
247 default:
248 return false
249 case objabi.R_TLS_LE:
250 switch r.Siz {
251 default:
252 return false
253 case 4:
254
255 ctxt.Out.Write64(uint64(elf.R_390_TLS_LE32) | uint64(elfsym)<<32)
256 case 8:
257
258 ctxt.Out.Write64(uint64(elf.R_390_TLS_LE64) | uint64(elfsym)<<32)
259 }
260 case objabi.R_TLS_IE:
261 switch r.Siz {
262 default:
263 return false
264 case 4:
265 ctxt.Out.Write64(uint64(elf.R_390_TLS_IEENT) | uint64(elfsym)<<32)
266 }
267 case objabi.R_ADDR:
268 switch r.Siz {
269 default:
270 return false
271 case 4:
272 ctxt.Out.Write64(uint64(elf.R_390_32) | uint64(elfsym)<<32)
273 case 8:
274 ctxt.Out.Write64(uint64(elf.R_390_64) | uint64(elfsym)<<32)
275 }
276 case objabi.R_GOTPCREL:
277 if r.Siz == 4 {
278 ctxt.Out.Write64(uint64(elf.R_390_GOTENT) | uint64(elfsym)<<32)
279 } else {
280 return false
281 }
282 case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL:
283 elfrel := elf.R_390_NONE
284 isdbl := r.Variant&sym.RV_TYPE_MASK == sym.RV_390_DBL
285
286
287 switch r.Type {
288 case objabi.R_PCRELDBL, objabi.R_CALL:
289 isdbl = true
290 }
291 if r.Xsym.Type == sym.SDYNIMPORT && (r.Xsym.ElfType() == elf.STT_FUNC || r.Type == objabi.R_CALL) {
292 if isdbl {
293 switch r.Siz {
294 case 2:
295 elfrel = elf.R_390_PLT16DBL
296 case 4:
297 elfrel = elf.R_390_PLT32DBL
298 }
299 } else {
300 switch r.Siz {
301 case 4:
302 elfrel = elf.R_390_PLT32
303 case 8:
304 elfrel = elf.R_390_PLT64
305 }
306 }
307 } else {
308 if isdbl {
309 switch r.Siz {
310 case 2:
311 elfrel = elf.R_390_PC16DBL
312 case 4:
313 elfrel = elf.R_390_PC32DBL
314 }
315 } else {
316 switch r.Siz {
317 case 2:
318 elfrel = elf.R_390_PC16
319 case 4:
320 elfrel = elf.R_390_PC32
321 case 8:
322 elfrel = elf.R_390_PC64
323 }
324 }
325 }
326 if elfrel == elf.R_390_NONE {
327 return false
328 }
329 ctxt.Out.Write64(uint64(elfrel) | uint64(elfsym)<<32)
330 }
331
332 ctxt.Out.Write64(uint64(r.Xadd))
333 return true
334 }
335
336 func elfsetupplt(ctxt *ld.Link) {
337 plt := ctxt.Syms.Lookup(".plt", 0)
338 got := ctxt.Syms.Lookup(".got", 0)
339 if plt.Size == 0 {
340
341 plt.AddUint8(0xe3)
342 plt.AddUint8(0x10)
343 plt.AddUint8(0xf0)
344 plt.AddUint8(0x38)
345 plt.AddUint8(0x00)
346 plt.AddUint8(0x24)
347
348 plt.AddUint8(0xc0)
349 plt.AddUint8(0x10)
350 plt.AddPCRelPlus(ctxt.Arch, got, 6)
351
352 plt.AddUint8(0xd2)
353 plt.AddUint8(0x07)
354 plt.AddUint8(0xf0)
355 plt.AddUint8(0x30)
356 plt.AddUint8(0x10)
357 plt.AddUint8(0x08)
358
359 plt.AddUint8(0xe3)
360 plt.AddUint8(0x10)
361 plt.AddUint8(0x10)
362 plt.AddUint8(0x10)
363 plt.AddUint8(0x00)
364 plt.AddUint8(0x04)
365
366 plt.AddUint8(0x07)
367 plt.AddUint8(0xf1)
368
369 plt.AddUint8(0x07)
370 plt.AddUint8(0x00)
371
372 plt.AddUint8(0x07)
373 plt.AddUint8(0x00)
374
375 plt.AddUint8(0x07)
376 plt.AddUint8(0x00)
377
378
379 got.AddAddrPlus(ctxt.Arch, ctxt.Syms.Lookup(".dynamic", 0), 0)
380
381 got.AddUint64(ctxt.Arch, 0)
382 got.AddUint64(ctxt.Arch, 0)
383 }
384 }
385
386 func machoreloc1(arch *sys.Arch, out *ld.OutBuf, s *sym.Symbol, r *sym.Reloc, sectoff int64) bool {
387 return false
388 }
389
390 func archreloc(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, val int64) (int64, bool) {
391 if ctxt.LinkMode == ld.LinkExternal {
392 return val, false
393 }
394
395 switch r.Type {
396 case objabi.R_CONST:
397 return r.Add, true
398 case objabi.R_GOTOFF:
399 return ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ctxt.Syms.Lookup(".got", 0)), true
400 }
401
402 return val, false
403 }
404
405 func archrelocvariant(ctxt *ld.Link, r *sym.Reloc, s *sym.Symbol, t int64) int64 {
406 switch r.Variant & sym.RV_TYPE_MASK {
407 default:
408 ld.Errorf(s, "unexpected relocation variant %d", r.Variant)
409 return t
410
411 case sym.RV_NONE:
412 return t
413
414 case sym.RV_390_DBL:
415 if (t & 1) != 0 {
416 ld.Errorf(s, "%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value)
417 }
418 return t >> 1
419 }
420 }
421
422 func addpltsym(ctxt *ld.Link, s *sym.Symbol) {
423 if s.Plt() >= 0 {
424 return
425 }
426
427 ld.Adddynsym(ctxt, s)
428
429 if ctxt.IsELF {
430 plt := ctxt.Syms.Lookup(".plt", 0)
431 got := ctxt.Syms.Lookup(".got", 0)
432 rela := ctxt.Syms.Lookup(".rela.plt", 0)
433 if plt.Size == 0 {
434 elfsetupplt(ctxt)
435 }
436
437
438 plt.AddUint8(0xc0)
439 plt.AddUint8(0x10)
440 plt.AddPCRelPlus(ctxt.Arch, got, got.Size+6)
441
442
443 got.AddAddrPlus(ctxt.Arch, plt, plt.Size+8)
444
445 plt.AddUint8(0xe3)
446 plt.AddUint8(0x10)
447 plt.AddUint8(0x10)
448 plt.AddUint8(0x00)
449 plt.AddUint8(0x00)
450 plt.AddUint8(0x04)
451
452 plt.AddUint8(0x07)
453 plt.AddUint8(0xf1)
454
455 plt.AddUint8(0x0d)
456 plt.AddUint8(0x10)
457
458 plt.AddUint8(0xe3)
459 plt.AddUint8(0x10)
460 plt.AddUint8(0x10)
461 plt.AddUint8(0x0c)
462 plt.AddUint8(0x00)
463 plt.AddUint8(0x14)
464
465 plt.AddUint8(0xc0)
466 plt.AddUint8(0xf4)
467
468 plt.AddUint32(ctxt.Arch, uint32(-((plt.Size - 2) >> 1)))
469
470 plt.AddUint32(ctxt.Arch, uint32(rela.Size))
471
472
473 rela.AddAddrPlus(ctxt.Arch, got, got.Size-8)
474
475 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_JMP_SLOT)))
476 rela.AddUint64(ctxt.Arch, 0)
477
478 s.SetPlt(int32(plt.Size - 32))
479
480 } else {
481 ld.Errorf(s, "addpltsym: unsupported binary format")
482 }
483 }
484
485 func addgotsym(ctxt *ld.Link, s *sym.Symbol) {
486 if s.Got() >= 0 {
487 return
488 }
489
490 ld.Adddynsym(ctxt, s)
491 got := ctxt.Syms.Lookup(".got", 0)
492 s.SetGot(int32(got.Size))
493 got.AddUint64(ctxt.Arch, 0)
494
495 if ctxt.IsELF {
496 rela := ctxt.Syms.Lookup(".rela", 0)
497 rela.AddAddrPlus(ctxt.Arch, got, int64(s.Got()))
498 rela.AddUint64(ctxt.Arch, ld.ELF64_R_INFO(uint32(s.Dynid), uint32(elf.R_390_GLOB_DAT)))
499 rela.AddUint64(ctxt.Arch, 0)
500 } else {
501 ld.Errorf(s, "addgotsym: unsupported binary format")
502 }
503 }
504
505 func asmb(ctxt *ld.Link) {
506 if ctxt.Debugvlog != 0 {
507 ctxt.Logf("%5.2f asmb\n", ld.Cputime())
508 }
509
510 if ctxt.IsELF {
511 ld.Asmbelfsetup()
512 }
513
514 sect := ld.Segtext.Sections[0]
515 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
516 ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
517 for _, sect = range ld.Segtext.Sections[1:] {
518 ctxt.Out.SeekSet(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff))
519 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length))
520 }
521
522 if ld.Segrodata.Filelen > 0 {
523 if ctxt.Debugvlog != 0 {
524 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
525 }
526 ctxt.Out.SeekSet(int64(ld.Segrodata.Fileoff))
527 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen))
528 }
529 if ld.Segrelrodata.Filelen > 0 {
530 if ctxt.Debugvlog != 0 {
531 ctxt.Logf("%5.2f rodatblk\n", ld.Cputime())
532 }
533 ctxt.Out.SeekSet(int64(ld.Segrelrodata.Fileoff))
534 ld.Datblk(ctxt, int64(ld.Segrelrodata.Vaddr), int64(ld.Segrelrodata.Filelen))
535 }
536
537 if ctxt.Debugvlog != 0 {
538 ctxt.Logf("%5.2f datblk\n", ld.Cputime())
539 }
540
541 ctxt.Out.SeekSet(int64(ld.Segdata.Fileoff))
542 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen))
543
544 ctxt.Out.SeekSet(int64(ld.Segdwarf.Fileoff))
545 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen))
546 }
547
548 func asmb2(ctxt *ld.Link) {
549
550 ld.Symsize = 0
551
552 ld.Lcsize = 0
553 symo := uint32(0)
554 if !*ld.FlagS {
555 if !ctxt.IsELF {
556 ld.Errorf(nil, "unsupported executable format")
557 }
558 if ctxt.Debugvlog != 0 {
559 ctxt.Logf("%5.2f sym\n", ld.Cputime())
560 }
561 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen)
562 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound)))
563
564 ctxt.Out.SeekSet(int64(symo))
565 if ctxt.Debugvlog != 0 {
566 ctxt.Logf("%5.2f elfsym\n", ld.Cputime())
567 }
568 ld.Asmelfsym(ctxt)
569 ctxt.Out.Flush()
570 ctxt.Out.Write(ld.Elfstrdat)
571
572 if ctxt.Debugvlog != 0 {
573 ctxt.Logf("%5.2f dwarf\n", ld.Cputime())
574 }
575
576 if ctxt.LinkMode == ld.LinkExternal {
577 ld.Elfemitreloc(ctxt)
578 }
579 }
580
581 if ctxt.Debugvlog != 0 {
582 ctxt.Logf("%5.2f header\n", ld.Cputime())
583 }
584 ctxt.Out.SeekSet(0)
585 switch ctxt.HeadType {
586 default:
587 ld.Errorf(nil, "unsupported operating system")
588 case objabi.Hlinux:
589 ld.Asmbelf(ctxt, int64(symo))
590 }
591
592 ctxt.Out.Flush()
593 if *ld.FlagC {
594 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen)
595 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen)
596 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen)
597 fmt.Printf("symsize=%d\n", ld.Symsize)
598 fmt.Printf("lcsize=%d\n", ld.Lcsize)
599 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize))
600 }
601 }
602
View as plain text