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/loader"
38 "cmd/link/internal/sym"
39 "debug/elf"
40 )
41
42
43
44
45
46
47
48
49
50
51
52 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
53 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
54 if initfunc == nil {
55 return
56 }
57
58
59 initfunc.AddUint8(0xc0)
60 initfunc.AddUint8(0x20)
61 initfunc.AddSymRef(ctxt.Arch, ctxt.Moduledata, 6, objabi.R_PCREL, 4)
62 r1 := initfunc.Relocs()
63 ldr.SetRelocVariant(initfunc.Sym(), r1.Count()-1, sym.RV_390_DBL)
64
65
66 initfunc.AddUint8(0xc0)
67 initfunc.AddUint8(0xf4)
68 initfunc.AddSymRef(ctxt.Arch, addmoduledata, 6, objabi.R_CALL, 4)
69 r2 := initfunc.Relocs()
70 ldr.SetRelocVariant(initfunc.Sym(), r2.Count()-1, sym.RV_390_DBL)
71
72
73 initfunc.AddUint32(ctxt.Arch, 0)
74 }
75
76 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
77 targ := r.Sym()
78 var targType sym.SymKind
79 if targ != 0 {
80 targType = ldr.SymType(targ)
81 }
82
83 switch r.Type() {
84 default:
85 if r.Type() >= objabi.ElfRelocOffset {
86 ldr.Errorf(s, "unexpected relocation type %d", r.Type())
87 return false
88 }
89
90
91 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_12),
92 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT12):
93 ldr.Errorf(s, "s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type()-objabi.ElfRelocOffset)
94 return false
95
96 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_8),
97 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_16),
98 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_32),
99 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_64):
100 if targType == sym.SDYNIMPORT {
101 ldr.Errorf(s, "unexpected R_390_nn relocation for dynamic symbol %s", ldr.SymName(targ))
102 }
103
104 su := ldr.MakeSymbolUpdater(s)
105 su.SetRelocType(rIdx, objabi.R_ADDR)
106 return true
107
108 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16),
109 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32),
110 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC64):
111 if targType == sym.SDYNIMPORT {
112 ldr.Errorf(s, "unexpected R_390_PCnn relocation for dynamic symbol %s", ldr.SymName(targ))
113 }
114
115
116 if (targType == 0 || targType == sym.SXREF) && !ldr.AttrVisibilityHidden(targ) {
117 ldr.Errorf(s, "unknown symbol %s in pcrel", ldr.SymName(targ))
118 }
119 su := ldr.MakeSymbolUpdater(s)
120 su.SetRelocType(rIdx, objabi.R_PCREL)
121 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
122 return true
123
124 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT16),
125 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT32),
126 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOT64):
127 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset)
128 return true
129
130 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT16DBL),
131 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32DBL):
132 su := ldr.MakeSymbolUpdater(s)
133 su.SetRelocType(rIdx, objabi.R_PCREL)
134 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL)
135 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
136 if targType == sym.SDYNIMPORT {
137 addpltsym(target, ldr, syms, targ)
138 r.SetSym(syms.PLT)
139 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
140 }
141 return true
142
143 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT32),
144 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PLT64):
145 su := ldr.MakeSymbolUpdater(s)
146 su.SetRelocType(rIdx, objabi.R_PCREL)
147 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
148 if targType == sym.SDYNIMPORT {
149 addpltsym(target, ldr, syms, targ)
150 r.SetSym(syms.PLT)
151 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
152 }
153 return true
154
155 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_COPY):
156 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset)
157 return false
158
159 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GLOB_DAT):
160 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset)
161 return false
162
163 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_JMP_SLOT):
164 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset)
165 return false
166
167 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_RELATIVE):
168 ldr.Errorf(s, "unimplemented S390x relocation: %v", r.Type()-objabi.ElfRelocOffset)
169 return false
170
171 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTOFF):
172 if targType == sym.SDYNIMPORT {
173 ldr.Errorf(s, "unexpected R_390_GOTOFF relocation for dynamic symbol %s", ldr.SymName(targ))
174 }
175 su := ldr.MakeSymbolUpdater(s)
176 su.SetRelocType(rIdx, objabi.R_GOTOFF)
177 return true
178
179 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPC):
180 su := ldr.MakeSymbolUpdater(s)
181 su.SetRelocType(rIdx, objabi.R_PCREL)
182 r.SetSym(syms.GOT)
183 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
184 return true
185
186 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC16DBL),
187 objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_PC32DBL):
188 su := ldr.MakeSymbolUpdater(s)
189 su.SetRelocType(rIdx, objabi.R_PCREL)
190 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL)
191 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
192 if targType == sym.SDYNIMPORT {
193 ldr.Errorf(s, "unexpected R_390_PCnnDBL relocation for dynamic symbol %s", ldr.SymName(targ))
194 }
195 return true
196
197 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTPCDBL):
198 su := ldr.MakeSymbolUpdater(s)
199 su.SetRelocType(rIdx, objabi.R_PCREL)
200 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL)
201 r.SetSym(syms.GOT)
202 su.SetRelocAdd(rIdx, r.Add()+int64(r.Siz()))
203 return true
204
205 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_390_GOTENT):
206 ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_390_GLOB_DAT))
207 su := ldr.MakeSymbolUpdater(s)
208 su.SetRelocType(rIdx, objabi.R_PCREL)
209 ldr.SetRelocVariant(s, rIdx, sym.RV_390_DBL)
210 r.SetSym(syms.GOT)
211 su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ))+int64(r.Siz()))
212 return true
213 }
214
215 if targType != sym.SDYNIMPORT {
216 return true
217 }
218
219 return false
220 }
221
222 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
223 out.Write64(uint64(sectoff))
224
225 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
226 siz := r.Size
227 switch r.Type {
228 default:
229 return false
230 case objabi.R_TLS_LE:
231 switch siz {
232 default:
233 return false
234 case 4:
235
236 out.Write64(uint64(elf.R_390_TLS_LE32) | uint64(elfsym)<<32)
237 case 8:
238
239 out.Write64(uint64(elf.R_390_TLS_LE64) | uint64(elfsym)<<32)
240 }
241 case objabi.R_TLS_IE:
242 switch siz {
243 default:
244 return false
245 case 4:
246 out.Write64(uint64(elf.R_390_TLS_IEENT) | uint64(elfsym)<<32)
247 }
248 case objabi.R_ADDR, objabi.R_DWARFSECREF:
249 switch siz {
250 default:
251 return false
252 case 4:
253 out.Write64(uint64(elf.R_390_32) | uint64(elfsym)<<32)
254 case 8:
255 out.Write64(uint64(elf.R_390_64) | uint64(elfsym)<<32)
256 }
257 case objabi.R_GOTPCREL:
258 if siz == 4 {
259 out.Write64(uint64(elf.R_390_GOTENT) | uint64(elfsym)<<32)
260 } else {
261 return false
262 }
263 case objabi.R_PCREL, objabi.R_PCRELDBL, objabi.R_CALL:
264 elfrel := elf.R_390_NONE
265 rVariant := ldr.RelocVariant(s, ri)
266 isdbl := rVariant&sym.RV_TYPE_MASK == sym.RV_390_DBL
267
268
269 switch r.Type {
270 case objabi.R_PCRELDBL, objabi.R_CALL:
271 isdbl = true
272 }
273 if ldr.SymType(r.Xsym) == sym.SDYNIMPORT && (ldr.SymElfType(r.Xsym) == elf.STT_FUNC || r.Type == objabi.R_CALL) {
274 if isdbl {
275 switch siz {
276 case 2:
277 elfrel = elf.R_390_PLT16DBL
278 case 4:
279 elfrel = elf.R_390_PLT32DBL
280 }
281 } else {
282 switch siz {
283 case 4:
284 elfrel = elf.R_390_PLT32
285 case 8:
286 elfrel = elf.R_390_PLT64
287 }
288 }
289 } else {
290 if isdbl {
291 switch siz {
292 case 2:
293 elfrel = elf.R_390_PC16DBL
294 case 4:
295 elfrel = elf.R_390_PC32DBL
296 }
297 } else {
298 switch siz {
299 case 2:
300 elfrel = elf.R_390_PC16
301 case 4:
302 elfrel = elf.R_390_PC32
303 case 8:
304 elfrel = elf.R_390_PC64
305 }
306 }
307 }
308 if elfrel == elf.R_390_NONE {
309 return false
310 }
311 out.Write64(uint64(elfrel) | uint64(elfsym)<<32)
312 }
313
314 out.Write64(uint64(r.Xadd))
315 return true
316 }
317
318 func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
319 if plt.Size() == 0 {
320
321 plt.AddUint8(0xe3)
322 plt.AddUint8(0x10)
323 plt.AddUint8(0xf0)
324 plt.AddUint8(0x38)
325 plt.AddUint8(0x00)
326 plt.AddUint8(0x24)
327
328 plt.AddUint8(0xc0)
329 plt.AddUint8(0x10)
330 plt.AddSymRef(ctxt.Arch, got.Sym(), 6, objabi.R_PCRELDBL, 4)
331
332 plt.AddUint8(0xd2)
333 plt.AddUint8(0x07)
334 plt.AddUint8(0xf0)
335 plt.AddUint8(0x30)
336 plt.AddUint8(0x10)
337 plt.AddUint8(0x08)
338
339 plt.AddUint8(0xe3)
340 plt.AddUint8(0x10)
341 plt.AddUint8(0x10)
342 plt.AddUint8(0x10)
343 plt.AddUint8(0x00)
344 plt.AddUint8(0x04)
345
346 plt.AddUint8(0x07)
347 plt.AddUint8(0xf1)
348
349 plt.AddUint8(0x07)
350 plt.AddUint8(0x00)
351
352 plt.AddUint8(0x07)
353 plt.AddUint8(0x00)
354
355 plt.AddUint8(0x07)
356 plt.AddUint8(0x00)
357
358
359 got.AddAddrPlus(ctxt.Arch, dynamic, 0)
360
361 got.AddUint64(ctxt.Arch, 0)
362 got.AddUint64(ctxt.Arch, 0)
363 }
364 }
365
366 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
367 return false
368 }
369
370 func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loader.Reloc, s loader.Sym, val int64) (o int64, nExtReloc int, ok bool) {
371 return val, 0, false
372 }
373
374 func archrelocvariant(target *ld.Target, ldr *loader.Loader, r loader.Reloc, rv sym.RelocVariant, s loader.Sym, t int64, p []byte) int64 {
375 switch rv & sym.RV_TYPE_MASK {
376 default:
377 ldr.Errorf(s, "unexpected relocation variant %d", rv)
378 return t
379
380 case sym.RV_NONE:
381 return t
382
383 case sym.RV_390_DBL:
384 if t&1 != 0 {
385 ldr.Errorf(s, "%s+%v is not 2-byte aligned", ldr.SymName(r.Sym()), ldr.SymValue(r.Sym()))
386 }
387 return t >> 1
388 }
389 }
390
391 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
392 if ldr.SymPlt(s) >= 0 {
393 return
394 }
395
396 ld.Adddynsym(ldr, target, syms, s)
397
398 if target.IsElf() {
399 plt := ldr.MakeSymbolUpdater(syms.PLT)
400 got := ldr.MakeSymbolUpdater(syms.GOT)
401 rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
402 if plt.Size() == 0 {
403 panic("plt is not set up")
404 }
405
406
407 plt.AddUint8(0xc0)
408 plt.AddUint8(0x10)
409 plt.AddPCRelPlus(target.Arch, got.Sym(), got.Size()+6)
410 pltrelocs := plt.Relocs()
411 ldr.SetRelocVariant(plt.Sym(), pltrelocs.Count()-1, sym.RV_390_DBL)
412
413
414 got.AddAddrPlus(target.Arch, plt.Sym(), plt.Size()+8)
415
416 plt.AddUint8(0xe3)
417 plt.AddUint8(0x10)
418 plt.AddUint8(0x10)
419 plt.AddUint8(0x00)
420 plt.AddUint8(0x00)
421 plt.AddUint8(0x04)
422
423 plt.AddUint8(0x07)
424 plt.AddUint8(0xf1)
425
426 plt.AddUint8(0x0d)
427 plt.AddUint8(0x10)
428
429 plt.AddUint8(0xe3)
430 plt.AddUint8(0x10)
431 plt.AddUint8(0x10)
432 plt.AddUint8(0x0c)
433 plt.AddUint8(0x00)
434 plt.AddUint8(0x14)
435
436 plt.AddUint8(0xc0)
437 plt.AddUint8(0xf4)
438
439 plt.AddUint32(target.Arch, uint32(-((plt.Size() - 2) >> 1)))
440
441 plt.AddUint32(target.Arch, uint32(rela.Size()))
442
443
444 rela.AddAddrPlus(target.Arch, got.Sym(), got.Size()-8)
445
446 sDynid := ldr.SymDynid(s)
447 rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_390_JMP_SLOT)))
448 rela.AddUint64(target.Arch, 0)
449
450 ldr.SetPlt(s, int32(plt.Size()-32))
451
452 } else {
453 ldr.Errorf(s, "addpltsym: unsupported binary format")
454 }
455 }
456
View as plain text