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 mips64
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 var (
43
44
45 dtOffsets map[elf.DynTag]int64
46
47
48
49
50 dynSymCount uint64
51
52
53
54
55 gotLocalCount uint64
56
57
58
59
60
61 gotSymIndex uint64
62 )
63
64 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
65 if *ld.FlagD || ctxt.Target.IsExternal() {
66 return
67 }
68
69 dynamic := ldr.MakeSymbolUpdater(ctxt.ArchSyms.Dynamic)
70
71 ld.Elfwritedynent(ctxt.Arch, dynamic, elf.DT_MIPS_RLD_VERSION, 1)
72 ld.Elfwritedynent(ctxt.Arch, dynamic, elf.DT_MIPS_BASE_ADDRESS, 0)
73
74
75
76 if gotLocalCount == 0 {
77 ctxt.Errorf(0, "internal error: elfsetupplt has not been called")
78 }
79 ld.Elfwritedynent(ctxt.Arch, dynamic, elf.DT_MIPS_LOCAL_GOTNO, gotLocalCount)
80
81
82
83
84
85 dts := []elf.DynTag{
86 elf.DT_MIPS_SYMTABNO,
87 elf.DT_MIPS_GOTSYM,
88 }
89 dtOffsets = make(map[elf.DynTag]int64)
90 for _, dt := range dts {
91 ld.Elfwritedynent(ctxt.Arch, dynamic, dt, 0)
92 dtOffsets[dt] = dynamic.Size() - 8
93 }
94 }
95
96 func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
97 targ := r.Sym()
98 var targType sym.SymKind
99 if targ != 0 {
100 targType = ldr.SymType(targ)
101 }
102
103 if r.Type() >= objabi.ElfRelocOffset {
104 ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
105 return false
106 }
107
108 switch r.Type() {
109 case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
110 if targType != sym.SDYNIMPORT {
111
112 return true
113 }
114 if target.IsExternal() {
115
116 return true
117 }
118
119
120
121 if r.Add() != 0 {
122 ldr.Errorf(s, "PLT call with non-zero addend (%v)", r.Add())
123 }
124 addpltsym(target, ldr, syms, targ)
125 su := ldr.MakeSymbolUpdater(s)
126 su.SetRelocSym(rIdx, syms.PLT)
127 su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
128 return true
129 }
130
131 return false
132 }
133
134 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
135
136
137
138
139
140
141
142
143
144
145 addend := r.Xadd
146
147 out.Write64(uint64(sectoff))
148
149 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
150 out.Write32(uint32(elfsym))
151 out.Write8(0)
152 out.Write8(0)
153 out.Write8(0)
154 switch r.Type {
155 default:
156 return false
157 case objabi.R_ADDR, objabi.R_DWARFSECREF:
158 switch r.Size {
159 case 4:
160 out.Write8(uint8(elf.R_MIPS_32))
161 case 8:
162 out.Write8(uint8(elf.R_MIPS_64))
163 default:
164 return false
165 }
166 case objabi.R_ADDRMIPS:
167 out.Write8(uint8(elf.R_MIPS_LO16))
168 case objabi.R_ADDRMIPSU:
169 out.Write8(uint8(elf.R_MIPS_HI16))
170 case objabi.R_ADDRMIPSTLS:
171 out.Write8(uint8(elf.R_MIPS_TLS_TPREL_LO16))
172 if ctxt.Target.IsOpenbsd() {
173
174
175
176 addend += 0x7000
177 }
178 case objabi.R_CALLMIPS,
179 objabi.R_JMPMIPS:
180 out.Write8(uint8(elf.R_MIPS_26))
181 }
182 out.Write64(uint64(addend))
183
184 return true
185 }
186
187 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
188 if plt.Size() != 0 {
189 return
190 }
191
192
193 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_ADDRMIPSU, 4)
194 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x3c0e0000)
195 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_ADDRMIPS, 4)
196 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0xddd90000)
197
198
199
200
201 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_ADDRMIPS, 4)
202 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x25ce0000)
203 plt.AddUint32(ctxt.Arch, 0x030ec023)
204 plt.AddUint32(ctxt.Arch, 0x03e07825)
205 plt.AddUint32(ctxt.Arch, 0x0018c0c2)
206 plt.AddUint32(ctxt.Arch, 0x0320f809)
207 plt.AddUint32(ctxt.Arch, 0x2718fffe)
208
209 if gotplt.Size() != 0 {
210 ctxt.Errorf(gotplt.Sym(), "got.plt is not empty")
211 }
212
213
214 gotplt.AddUint32(ctxt.Arch, 0)
215 gotplt.AddUint32(ctxt.Arch, 0)
216 gotLocalCount++
217
218
219 gotplt.AddUint32(ctxt.Arch, 0)
220 gotplt.AddUint32(ctxt.Arch, 0)
221 gotLocalCount++
222 }
223
224 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
225 if ldr.SymPlt(s) >= 0 {
226 return
227 }
228
229 dynamic := ldr.MakeSymbolUpdater(syms.Dynamic)
230
231 const dynSymEntrySize = 20
232 if gotSymIndex == 0 {
233
234 gotSymIndex = uint64(ldr.SymSize(syms.DynSym) / dynSymEntrySize)
235 dynamic.SetUint(target.Arch, dtOffsets[elf.DT_MIPS_GOTSYM], gotSymIndex)
236 }
237 if dynSymCount == 0 {
238 dynSymCount = uint64(ldr.SymSize(syms.DynSym) / dynSymEntrySize)
239 }
240
241 ld.Adddynsym(ldr, target, syms, s)
242 dynSymCount++
243
244 if !target.IsElf() {
245 ldr.Errorf(s, "addpltsym: unsupported binary format")
246 }
247
248 plt := ldr.MakeSymbolUpdater(syms.PLT)
249 gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
250 if plt.Size() == 0 {
251 panic("plt is not set up")
252 }
253
254
255 plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_ADDRMIPSU, 4)
256 plt.SetUint32(target.Arch, plt.Size()-4, 0x3c0f0000)
257 plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_ADDRMIPS, 4)
258 plt.SetUint32(target.Arch, plt.Size()-4, 0xddf90000)
259
260
261 plt.AddUint32(target.Arch, 0x03200008)
262 plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_ADDRMIPS, 4)
263 plt.SetUint32(target.Arch, plt.Size()-4, 0x65f80000)
264
265
266 gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
267
268 ldr.SetPlt(s, int32(plt.Size()-16))
269
270
271 dynamic.SetUint(target.Arch, dtOffsets[elf.DT_MIPS_SYMTABNO], dynSymCount)
272 }
273
274 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
275 return false
276 }
277
278 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) {
279 if target.IsExternal() {
280 switch r.Type() {
281 default:
282 return val, 0, false
283
284 case objabi.R_ADDRMIPS,
285 objabi.R_ADDRMIPSU,
286 objabi.R_ADDRMIPSTLS,
287 objabi.R_CALLMIPS,
288 objabi.R_JMPMIPS:
289 return val, 1, true
290 }
291 }
292
293 const isOk = true
294 const noExtReloc = 0
295 rs := r.Sym()
296 switch r.Type() {
297 case objabi.R_ADDRMIPS,
298 objabi.R_ADDRMIPSU:
299 t := ldr.SymValue(rs) + r.Add()
300 if r.Type() == objabi.R_ADDRMIPS {
301 return int64(val&0xffff0000 | t&0xffff), noExtReloc, isOk
302 }
303 return int64(val&0xffff0000 | ((t+1<<15)>>16)&0xffff), noExtReloc, isOk
304 case objabi.R_ADDRMIPSTLS:
305
306 t := ldr.SymValue(rs) + r.Add() - 0x7000
307 if target.IsOpenbsd() {
308
309
310 t += 0x7000
311 }
312 if t < -32768 || t >= 32678 {
313 ldr.Errorf(s, "TLS offset out of range %d", t)
314 }
315 return int64(val&0xffff0000 | t&0xffff), noExtReloc, isOk
316 case objabi.R_CALLMIPS,
317 objabi.R_JMPMIPS:
318
319 t := ldr.SymValue(rs) + r.Add()
320 return int64(val&0xfc000000 | (t>>2)&^0xfc000000), noExtReloc, isOk
321 }
322
323 return val, 0, false
324 }
325
326 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
327 return -1
328 }
329
330 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
331 switch r.Type() {
332 case objabi.R_ADDRMIPS,
333 objabi.R_ADDRMIPSU:
334 return ld.ExtrelocViaOuterSym(ldr, r, s), true
335
336 case objabi.R_ADDRMIPSTLS,
337 objabi.R_CALLMIPS,
338 objabi.R_JMPMIPS:
339 return ld.ExtrelocSimple(ldr, r), true
340 }
341 return loader.ExtReloc{}, false
342 }
343
View as plain text