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 out.Write64(uint64(sectoff))
146
147 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
148 out.Write32(uint32(elfsym))
149 out.Write8(0)
150 out.Write8(0)
151 out.Write8(0)
152 switch r.Type {
153 default:
154 return false
155 case objabi.R_ADDR, objabi.R_DWARFSECREF:
156 switch r.Size {
157 case 4:
158 out.Write8(uint8(elf.R_MIPS_32))
159 case 8:
160 out.Write8(uint8(elf.R_MIPS_64))
161 default:
162 return false
163 }
164 case objabi.R_ADDRMIPS:
165 out.Write8(uint8(elf.R_MIPS_LO16))
166 case objabi.R_ADDRMIPSU:
167 out.Write8(uint8(elf.R_MIPS_HI16))
168 case objabi.R_ADDRMIPSTLS:
169 out.Write8(uint8(elf.R_MIPS_TLS_TPREL_LO16))
170 case objabi.R_CALLMIPS,
171 objabi.R_JMPMIPS:
172 out.Write8(uint8(elf.R_MIPS_26))
173 }
174 out.Write64(uint64(r.Xadd))
175
176 return true
177 }
178
179 func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
180 if plt.Size() != 0 {
181 return
182 }
183
184
185 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_ADDRMIPSU, 4)
186 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x3c0e0000)
187 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_ADDRMIPS, 4)
188 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0xddd90000)
189
190
191
192
193 plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_ADDRMIPS, 4)
194 plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x25ce0000)
195 plt.AddUint32(ctxt.Arch, 0x030ec023)
196 plt.AddUint32(ctxt.Arch, 0x03e07825)
197 plt.AddUint32(ctxt.Arch, 0x0018c0c2)
198 plt.AddUint32(ctxt.Arch, 0x0320f809)
199 plt.AddUint32(ctxt.Arch, 0x2718fffe)
200
201 if gotplt.Size() != 0 {
202 ctxt.Errorf(gotplt.Sym(), "got.plt is not empty")
203 }
204
205
206 gotplt.AddUint32(ctxt.Arch, 0)
207 gotplt.AddUint32(ctxt.Arch, 0)
208 gotLocalCount++
209
210
211 gotplt.AddUint32(ctxt.Arch, 0)
212 gotplt.AddUint32(ctxt.Arch, 0)
213 gotLocalCount++
214 }
215
216 func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
217 if ldr.SymPlt(s) >= 0 {
218 return
219 }
220
221 dynamic := ldr.MakeSymbolUpdater(syms.Dynamic)
222
223 const dynSymEntrySize = 20
224 if gotSymIndex == 0 {
225
226 gotSymIndex = uint64(ldr.SymSize(syms.DynSym) / dynSymEntrySize)
227 dynamic.SetUint(target.Arch, dtOffsets[elf.DT_MIPS_GOTSYM], gotSymIndex)
228 }
229 if dynSymCount == 0 {
230 dynSymCount = uint64(ldr.SymSize(syms.DynSym) / dynSymEntrySize)
231 }
232
233 ld.Adddynsym(ldr, target, syms, s)
234 dynSymCount++
235
236 if !target.IsElf() {
237 ldr.Errorf(s, "addpltsym: unsupported binary format")
238 }
239
240 plt := ldr.MakeSymbolUpdater(syms.PLT)
241 gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
242 if plt.Size() == 0 {
243 panic("plt is not set up")
244 }
245
246
247 plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_ADDRMIPSU, 4)
248 plt.SetUint32(target.Arch, plt.Size()-4, 0x3c0f0000)
249 plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_ADDRMIPS, 4)
250 plt.SetUint32(target.Arch, plt.Size()-4, 0xddf90000)
251
252
253 plt.AddUint32(target.Arch, 0x03200008)
254 plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_ADDRMIPS, 4)
255 plt.SetUint32(target.Arch, plt.Size()-4, 0x65f80000)
256
257
258 gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
259
260 ldr.SetPlt(s, int32(plt.Size()-16))
261
262
263 dynamic.SetUint(target.Arch, dtOffsets[elf.DT_MIPS_SYMTABNO], dynSymCount)
264 }
265
266 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
267 return false
268 }
269
270 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) {
271 if target.IsExternal() {
272 switch r.Type() {
273 default:
274 return val, 0, false
275
276 case objabi.R_ADDRMIPS,
277 objabi.R_ADDRMIPSU,
278 objabi.R_ADDRMIPSTLS,
279 objabi.R_CALLMIPS,
280 objabi.R_JMPMIPS:
281 return val, 1, true
282 }
283 }
284
285 const isOk = true
286 const noExtReloc = 0
287 rs := r.Sym()
288 switch r.Type() {
289 case objabi.R_ADDRMIPS,
290 objabi.R_ADDRMIPSU:
291 t := ldr.SymValue(rs) + r.Add()
292 if r.Type() == objabi.R_ADDRMIPS {
293 return val&0xffff0000 | t&0xffff, noExtReloc, isOk
294 }
295 return val&0xffff0000 | ((t+1<<15)>>16)&0xffff, noExtReloc, isOk
296 case objabi.R_ADDRMIPSTLS:
297
298 t := ldr.SymValue(rs) + r.Add() - 0x7000
299 if t < -32768 || t >= 32678 {
300 ldr.Errorf(s, "TLS offset out of range %d", t)
301 }
302 return val&0xffff0000 | t&0xffff, noExtReloc, isOk
303 case objabi.R_CALLMIPS,
304 objabi.R_JMPMIPS:
305
306 t := ldr.SymValue(rs) + r.Add()
307 return val&0xfc000000 | (t>>2)&^0xfc000000, noExtReloc, isOk
308 }
309
310 return val, 0, false
311 }
312
313 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
314 return -1
315 }
316
317 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
318 switch r.Type() {
319 case objabi.R_ADDRMIPS,
320 objabi.R_ADDRMIPSU:
321 return ld.ExtrelocViaOuterSym(ldr, r, s), true
322
323 case objabi.R_ADDRMIPSTLS,
324 objabi.R_CALLMIPS,
325 objabi.R_JMPMIPS:
326 return ld.ExtrelocSimple(ldr, r), true
327 }
328 return loader.ExtReloc{}, false
329 }
330
View as plain text