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 mips
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 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
43 return
44 }
45
46 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
47 out.Write32(uint32(sectoff))
48
49 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
50 switch r.Type {
51 default:
52 return false
53 case objabi.R_ADDR, objabi.R_DWARFSECREF:
54 if r.Size != 4 {
55 return false
56 }
57 out.Write32(uint32(elf.R_MIPS_32) | uint32(elfsym)<<8)
58 case objabi.R_ADDRMIPS:
59 out.Write32(uint32(elf.R_MIPS_LO16) | uint32(elfsym)<<8)
60 case objabi.R_ADDRMIPSU:
61 out.Write32(uint32(elf.R_MIPS_HI16) | uint32(elfsym)<<8)
62 case objabi.R_ADDRMIPSTLS:
63 out.Write32(uint32(elf.R_MIPS_TLS_TPREL_LO16) | uint32(elfsym)<<8)
64 case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
65 out.Write32(uint32(elf.R_MIPS_26) | uint32(elfsym)<<8)
66 }
67
68 return true
69 }
70
71 func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
72 return
73 }
74
75 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
76 return false
77 }
78
79 func applyrel(arch *sys.Arch, ldr *loader.Loader, rt objabi.RelocType, off int32, s loader.Sym, val int64, t int64) int64 {
80 o := uint32(val)
81 switch rt {
82 case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSTLS:
83 return int64(o&0xffff0000 | uint32(t)&0xffff)
84 case objabi.R_ADDRMIPSU:
85 return int64(o&0xffff0000 | uint32((t+(1<<15))>>16)&0xffff)
86 case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
87 return int64(o&0xfc000000 | uint32(t>>2)&^0xfc000000)
88 default:
89 return val
90 }
91 }
92
93 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) {
94 rs := r.Sym()
95 if target.IsExternal() {
96 switch r.Type() {
97 default:
98 return val, 0, false
99
100 case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
101
102 _, off := ld.FoldSubSymbolOffset(ldr, rs)
103 xadd := r.Add() + off
104 return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, xadd), 1, true
105
106 case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
107 return applyrel(target.Arch, ldr, r.Type(), r.Off(), s, val, r.Add()), 1, true
108 }
109 }
110
111 const isOk = true
112 const noExtReloc = 0
113 switch rt := r.Type(); rt {
114 case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
115 t := ldr.SymValue(rs) + r.Add()
116 return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
117 case objabi.R_CALLMIPS, objabi.R_JMPMIPS:
118 t := ldr.SymValue(rs) + r.Add()
119
120 if t&3 != 0 {
121 ldr.Errorf(s, "direct call is not aligned: %s %x", ldr.SymName(rs), t)
122 }
123
124
125 if (ldr.SymValue(s)+int64(r.Off())+4)&0xf0000000 != (t & 0xf0000000) {
126 ldr.Errorf(s, "direct call too far: %s %x", ldr.SymName(rs), t)
127 }
128
129 return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
130 case objabi.R_ADDRMIPSTLS:
131
132 t := ldr.SymValue(rs) + r.Add() - 0x7000
133 if t < -32768 || t >= 32678 {
134 ldr.Errorf(s, "TLS offset out of range %d", t)
135 }
136 return applyrel(target.Arch, ldr, rt, r.Off(), s, val, t), noExtReloc, isOk
137 }
138
139 return val, 0, false
140 }
141
142 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
143 return -1
144 }
145
146 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
147 switch r.Type() {
148 case objabi.R_ADDRMIPS, objabi.R_ADDRMIPSU:
149 return ld.ExtrelocViaOuterSym(ldr, r, s), true
150
151 case objabi.R_ADDRMIPSTLS, objabi.R_CALLMIPS, objabi.R_JMPMIPS:
152 return ld.ExtrelocSimple(ldr, r), true
153 }
154 return loader.ExtReloc{}, false
155 }
156
View as plain text