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