1
2
3
4
5 package loong64
6
7 import (
8 "cmd/internal/objabi"
9 "cmd/internal/sys"
10 "cmd/link/internal/ld"
11 "cmd/link/internal/loader"
12 "cmd/link/internal/sym"
13 "debug/elf"
14 "fmt"
15 "log"
16 )
17
18 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
19 initfunc, addmoduledata := ld.PrepareAddmoduledata(ctxt)
20 if initfunc == nil {
21 return
22 }
23
24 o := func(op uint32) {
25 initfunc.AddUint32(ctxt.Arch, op)
26 }
27
28
29
30
31
32
33
34
35
36
37 o(0x1a000004)
38 rel, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_HI)
39 rel.SetOff(0)
40 rel.SetSiz(4)
41 rel.SetSym(ctxt.Moduledata)
42
43
44
45 o(0x02c00084)
46 rel2, _ := initfunc.AddRel(objabi.R_LOONG64_ADDR_LO)
47 rel2.SetOff(4)
48 rel2.SetSiz(4)
49 rel2.SetSym(ctxt.Moduledata)
50
51
52
53 o(0x50000000)
54 rel3, _ := initfunc.AddRel(objabi.R_CALLLOONG64)
55 rel3.SetOff(8)
56 rel3.SetSiz(4)
57 rel3.SetSym(addmoduledata)
58 }
59
60 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
61 log.Fatalf("adddynrel not implemented")
62 return false
63 }
64
65 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
66
67
68
69
70
71 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
72 switch r.Type {
73 default:
74 return false
75 case objabi.R_ADDR, objabi.R_DWARFSECREF:
76 switch r.Size {
77 case 4:
78 out.Write64(uint64(sectoff))
79 out.Write64(uint64(elf.R_LARCH_32) | uint64(elfsym)<<32)
80 out.Write64(uint64(r.Xadd))
81 case 8:
82 out.Write64(uint64(sectoff))
83 out.Write64(uint64(elf.R_LARCH_64) | uint64(elfsym)<<32)
84 out.Write64(uint64(r.Xadd))
85 default:
86 return false
87 }
88 case objabi.R_LOONG64_TLS_LE_LO:
89 out.Write64(uint64(sectoff))
90 out.Write64(uint64(elf.R_LARCH_TLS_LE_LO12) | uint64(elfsym)<<32)
91 out.Write64(uint64(r.Xadd))
92
93 case objabi.R_LOONG64_TLS_LE_HI:
94 out.Write64(uint64(sectoff))
95 out.Write64(uint64(elf.R_LARCH_TLS_LE_HI20) | uint64(elfsym)<<32)
96 out.Write64(uint64(r.Xadd))
97
98 case objabi.R_CALLLOONG64:
99 out.Write64(uint64(sectoff))
100 out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32)
101 out.Write64(uint64(r.Xadd))
102
103 case objabi.R_LOONG64_TLS_IE_HI:
104 out.Write64(uint64(sectoff))
105 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32)
106 out.Write64(uint64(0x0))
107
108 case objabi.R_LOONG64_TLS_IE_LO:
109 out.Write64(uint64(sectoff))
110 out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_LO12) | uint64(elfsym)<<32)
111 out.Write64(uint64(0x0))
112
113 case objabi.R_LOONG64_ADDR_LO:
114 out.Write64(uint64(sectoff))
115 out.Write64(uint64(elf.R_LARCH_PCALA_LO12) | uint64(elfsym)<<32)
116 out.Write64(uint64(r.Xadd))
117
118 case objabi.R_LOONG64_ADDR_HI:
119 out.Write64(uint64(sectoff))
120 out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32)
121 out.Write64(uint64(r.Xadd))
122
123 case objabi.R_LOONG64_GOT_HI:
124 out.Write64(uint64(sectoff))
125 out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32)
126 out.Write64(uint64(0x0))
127
128 case objabi.R_LOONG64_GOT_LO:
129 out.Write64(uint64(sectoff))
130 out.Write64(uint64(elf.R_LARCH_GOT_PC_LO12) | uint64(elfsym)<<32)
131 out.Write64(uint64(0x0))
132 }
133
134 return true
135 }
136
137 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
138 return
139 }
140
141 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
142 return false
143 }
144
145 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) {
146 rs := r.Sym()
147 if target.IsExternal() {
148 switch r.Type() {
149 default:
150 return val, 0, false
151 case objabi.R_LOONG64_ADDR_HI,
152 objabi.R_LOONG64_ADDR_LO:
153
154 rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
155 rst := ldr.SymType(rs)
156 if rst != sym.SHOSTOBJ && rst != sym.SDYNIMPORT && ldr.SymSect(rs) == nil {
157 ldr.Errorf(s, "missing section for %s", ldr.SymName(rs))
158 }
159 return val, 1, true
160 case objabi.R_LOONG64_TLS_LE_HI,
161 objabi.R_LOONG64_TLS_LE_LO,
162 objabi.R_CALLLOONG64,
163 objabi.R_JMPLOONG64,
164 objabi.R_LOONG64_TLS_IE_HI,
165 objabi.R_LOONG64_TLS_IE_LO,
166 objabi.R_LOONG64_GOT_HI,
167 objabi.R_LOONG64_GOT_LO:
168 return val, 1, true
169 }
170 }
171
172 const isOk = true
173 const noExtReloc = 0
174
175 switch r.Type() {
176 case objabi.R_CONST:
177 return r.Add(), noExtReloc, isOk
178 case objabi.R_GOTOFF:
179 return ldr.SymValue(r.Sym()) + r.Add() - ldr.SymValue(syms.GOT), noExtReloc, isOk
180 case objabi.R_LOONG64_ADDR_HI,
181 objabi.R_LOONG64_ADDR_LO:
182 pc := ldr.SymValue(s) + int64(r.Off())
183 t := calculatePCAlignedReloc(r.Type(), ldr.SymAddr(rs)+r.Add(), pc)
184 if r.Type() == objabi.R_LOONG64_ADDR_LO {
185 return int64(val&0xffc003ff | (t << 10)), noExtReloc, isOk
186 }
187 return int64(val&0xfe00001f | (t << 5)), noExtReloc, isOk
188 case objabi.R_LOONG64_TLS_LE_HI,
189 objabi.R_LOONG64_TLS_LE_LO:
190 t := ldr.SymAddr(rs) + r.Add()
191 if r.Type() == objabi.R_LOONG64_TLS_LE_LO {
192 return int64(val&0xffc003ff | ((t & 0xfff) << 10)), noExtReloc, isOk
193 }
194 return int64(val&0xfe00001f | (((t) >> 12 << 5) & 0x1ffffe0)), noExtReloc, isOk
195 case objabi.R_CALLLOONG64,
196 objabi.R_JMPLOONG64:
197 pc := ldr.SymValue(s) + int64(r.Off())
198 t := ldr.SymAddr(rs) + r.Add() - pc
199 return int64(val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16)), noExtReloc, isOk
200 }
201
202 return val, 0, false
203 }
204
205 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
206 return -1
207 }
208
209 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
210 switch r.Type() {
211 case objabi.R_LOONG64_ADDR_HI,
212 objabi.R_LOONG64_ADDR_LO,
213 objabi.R_LOONG64_GOT_HI,
214 objabi.R_LOONG64_GOT_LO:
215 return ld.ExtrelocViaOuterSym(ldr, r, s), true
216
217 case objabi.R_LOONG64_TLS_LE_HI,
218 objabi.R_LOONG64_TLS_LE_LO,
219 objabi.R_CONST,
220 objabi.R_GOTOFF,
221 objabi.R_CALLLOONG64,
222 objabi.R_JMPLOONG64,
223 objabi.R_LOONG64_TLS_IE_HI,
224 objabi.R_LOONG64_TLS_IE_LO:
225 return ld.ExtrelocSimple(ldr, r), true
226 }
227 return loader.ExtReloc{}, false
228 }
229
230 func isRequestingLowPageBits(t objabi.RelocType) bool {
231 switch t {
232 case objabi.R_LOONG64_ADDR_LO:
233 return true
234 }
235 return false
236 }
237
238
239
240
241
242
243
244
245 func calculatePCAlignedReloc(t objabi.RelocType, tgt int64, pc int64) int64 {
246 if isRequestingLowPageBits(t) {
247
248 return tgt & 0xfff
249 }
250
251 pageDelta := (tgt >> 12) - (pc >> 12)
252 if tgt&0xfff >= 0x800 {
253
254 pageDelta += 1
255 }
256
257 return pageDelta & 0xfffff
258 }
259
260
261 func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
262 relocs := ldr.Relocs(s)
263 r := relocs.At(ri)
264 switch r.Type() {
265 case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26):
266
267
268 fallthrough
269 case objabi.R_CALLLOONG64:
270 var t int64
271
272
273
274 if ldr.SymValue(rs) != 0 {
275 t = ldr.SymValue(rs) + r.Add() - (ldr.SymValue(s) + int64(r.Off()))
276 }
277 if t >= 1<<27 || t < -1<<27 || ldr.SymValue(rs) == 0 || (*ld.FlagDebugTramp > 1 && (ldr.SymPkg(s) == "" || ldr.SymPkg(s) != ldr.SymPkg(rs))) {
278
279
280
281 var tramp loader.Sym
282 for i := 0; ; i++ {
283 oName := ldr.SymName(rs)
284 name := oName + fmt.Sprintf("%+x-tramp%d", r.Add(), i)
285 tramp = ldr.LookupOrCreateSym(name, int(ldr.SymVersion(rs)))
286 ldr.SetAttrReachable(tramp, true)
287 if ldr.SymType(tramp) == sym.SDYNIMPORT {
288
289 continue
290 }
291 if oName == "runtime.deferreturn" {
292 ldr.SetIsDeferReturnTramp(tramp, true)
293 }
294 if ldr.SymValue(tramp) == 0 {
295
296
297
298 break
299 }
300
301 t = ldr.SymValue(tramp) - (ldr.SymValue(s) + int64(r.Off()))
302 if t >= -1<<27 && t < 1<<27 {
303
304
305 break
306 }
307 }
308 if ldr.SymType(tramp) == 0 {
309
310 trampb := ldr.MakeSymbolUpdater(tramp)
311 ctxt.AddTramp(trampb, ldr.SymType(s))
312 if ldr.SymType(rs) == sym.SDYNIMPORT {
313 if r.Add() != 0 {
314 ctxt.Errorf(s, "nonzero addend for DYNIMPORT call: %v+%d", ldr.SymName(rs), r.Add())
315 }
316 gentrampgot(ctxt, ldr, trampb, rs)
317 } else {
318 gentramp(ctxt, ldr, trampb, rs, r.Add())
319 }
320 }
321
322 sb := ldr.MakeSymbolUpdater(s)
323 relocs := sb.Relocs()
324 r := relocs.At(ri)
325 r.SetSym(tramp)
326 r.SetAdd(0)
327 }
328 default:
329 ctxt.Errorf(s, "trampoline called with non-jump reloc: %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()))
330 }
331 }
332
333
334 func gentramp(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
335 tramp.SetSize(12)
336 P := make([]byte, tramp.Size())
337
338 o1 := uint32(0x1a00001e)
339 ctxt.Arch.ByteOrder.PutUint32(P, o1)
340 r1, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_HI)
341 r1.SetOff(0)
342 r1.SetSiz(4)
343 r1.SetSym(target)
344 r1.SetAdd(offset)
345
346 o2 := uint32(0x02c003de)
347 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
348 r2, _ := tramp.AddRel(objabi.R_LOONG64_ADDR_LO)
349 r2.SetOff(4)
350 r2.SetSiz(4)
351 r2.SetSym(target)
352 r2.SetAdd(offset)
353
354 o3 := uint32(0x4c0003c0)
355 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
356
357 tramp.SetData(P)
358 }
359
360 func gentrampgot(ctxt *ld.Link, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym) {
361 tramp.SetSize(12)
362 P := make([]byte, tramp.Size())
363
364 o1 := uint32(0x1a00001e)
365 ctxt.Arch.ByteOrder.PutUint32(P, o1)
366 r1, _ := tramp.AddRel(objabi.R_LOONG64_GOT_HI)
367 r1.SetOff(0)
368 r1.SetSiz(4)
369 r1.SetSym(target)
370
371 o2 := uint32(0x28c003de)
372 ctxt.Arch.ByteOrder.PutUint32(P[4:], o2)
373 r2, _ := tramp.AddRel(objabi.R_LOONG64_GOT_LO)
374 r2.SetOff(4)
375 r2.SetSiz(4)
376 r2.SetSym(target)
377
378 o3 := uint32(0x4c0003c0)
379 ctxt.Arch.ByteOrder.PutUint32(P[8:], o3)
380
381 tramp.SetData(P)
382 }
383
View as plain text