1
2
3
4
5 package riscv64
6
7 import (
8 "cmd/internal/obj/riscv"
9 "cmd/internal/objabi"
10 "cmd/internal/sys"
11 "cmd/link/internal/ld"
12 "cmd/link/internal/loader"
13 "cmd/link/internal/sym"
14 "debug/elf"
15 "fmt"
16 "log"
17 "sort"
18 )
19
20
21 const fakeLabelName = ".L0 "
22
23 func gentext(ctxt *ld.Link, ldr *loader.Loader) {
24 }
25
26 func genSymsLate(ctxt *ld.Link, ldr *loader.Loader) {
27 if ctxt.LinkMode != ld.LinkExternal {
28 return
29 }
30
31
32
33 if ctxt.Textp == nil {
34 log.Fatal("genSymsLate called before Textp has been assigned")
35 }
36 var hi20Syms []loader.Sym
37 for _, s := range ctxt.Textp {
38 relocs := ldr.Relocs(s)
39 for ri := 0; ri < relocs.Count(); ri++ {
40 r := relocs.At(ri)
41 if r.Type() != objabi.R_RISCV_PCREL_ITYPE && r.Type() != objabi.R_RISCV_PCREL_STYPE &&
42 r.Type() != objabi.R_RISCV_TLS_IE_ITYPE && r.Type() != objabi.R_RISCV_TLS_IE_STYPE {
43 continue
44 }
45 if r.Off() == 0 && ldr.SymType(s) == sym.STEXT {
46
47
48 continue
49 }
50
51
52
53
54
55 sb := ldr.MakeSymbolBuilder(fakeLabelName)
56 sb.SetType(sym.STEXT)
57 sb.SetValue(ldr.SymValue(s) + int64(r.Off()))
58 sb.SetLocal(true)
59 sb.SetReachable(true)
60 sb.SetVisibilityHidden(true)
61 sb.SetSect(ldr.SymSect(s))
62 if outer := ldr.OuterSym(s); outer != 0 {
63 ldr.AddInteriorSym(outer, sb.Sym())
64 }
65 hi20Syms = append(hi20Syms, sb.Sym())
66 }
67 }
68 ctxt.Textp = append(ctxt.Textp, hi20Syms...)
69 ldr.SortSyms(ctxt.Textp)
70 }
71
72 func findHI20Symbol(ctxt *ld.Link, ldr *loader.Loader, val int64) loader.Sym {
73 idx := sort.Search(len(ctxt.Textp), func(i int) bool { return ldr.SymValue(ctxt.Textp[i]) >= val })
74 if idx >= len(ctxt.Textp) {
75 return 0
76 }
77 if s := ctxt.Textp[idx]; ldr.SymValue(s) == val && ldr.SymType(s) == sym.STEXT {
78 return s
79 }
80 return 0
81 }
82
83 func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, r loader.ExtReloc, ri int, sectoff int64) bool {
84 elfsym := ld.ElfSymForReloc(ctxt, r.Xsym)
85 switch r.Type {
86 case objabi.R_ADDR, objabi.R_DWARFSECREF:
87 out.Write64(uint64(sectoff))
88 switch r.Size {
89 case 4:
90 out.Write64(uint64(elf.R_RISCV_32) | uint64(elfsym)<<32)
91 case 8:
92 out.Write64(uint64(elf.R_RISCV_64) | uint64(elfsym)<<32)
93 default:
94 ld.Errorf(nil, "unknown size %d for %v relocation", r.Size, r.Type)
95 return false
96 }
97 out.Write64(uint64(r.Xadd))
98
99 case objabi.R_CALLRISCV:
100
101
102
103
104 case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
105
106
107 relocs := ldr.Relocs(s)
108 offset := int64(relocs.At(ri).Off())
109 hi20Sym := findHI20Symbol(ctxt, ldr, ldr.SymValue(s)+offset)
110 if hi20Sym == 0 {
111 ld.Errorf(nil, "failed to find text symbol for HI20 relocation at %d (%x)", sectoff, ldr.SymValue(s)+offset)
112 return false
113 }
114 hi20ElfSym := ld.ElfSymForReloc(ctxt, hi20Sym)
115
116
117
118
119
120
121
122
123
124 var hiRel, loRel elf.R_RISCV
125 switch r.Type {
126 case objabi.R_RISCV_PCREL_ITYPE:
127 hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_I
128 case objabi.R_RISCV_PCREL_STYPE:
129 hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_S
130 case objabi.R_RISCV_TLS_IE_ITYPE:
131 hiRel, loRel = elf.R_RISCV_TLS_GOT_HI20, elf.R_RISCV_PCREL_LO12_I
132 case objabi.R_RISCV_TLS_IE_STYPE:
133 hiRel, loRel = elf.R_RISCV_TLS_GOT_HI20, elf.R_RISCV_PCREL_LO12_S
134 }
135 out.Write64(uint64(sectoff))
136 out.Write64(uint64(hiRel) | uint64(elfsym)<<32)
137 out.Write64(uint64(r.Xadd))
138 out.Write64(uint64(sectoff + 4))
139 out.Write64(uint64(loRel) | uint64(hi20ElfSym)<<32)
140 out.Write64(uint64(0))
141
142 default:
143 return false
144 }
145
146 return true
147 }
148
149 func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
150 log.Fatalf("elfsetupplt")
151 }
152
153 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
154 log.Fatalf("machoreloc1 not implemented")
155 return false
156 }
157
158 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) {
159 if target.IsExternal() {
160 switch r.Type() {
161 case objabi.R_CALLRISCV:
162 return val, 0, true
163
164 case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
165 return val, 2, true
166 }
167
168 return val, 0, false
169 }
170
171 rs := ldr.ResolveABIAlias(r.Sym())
172
173 switch r.Type() {
174 case objabi.R_CALLRISCV:
175
176 return val, 0, true
177
178 case objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
179
180
181
182
183
184
185 const ebreakIns = 0x00100073
186 return ebreakIns<<32 | ebreakIns, 0, true
187
188 case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
189 pc := ldr.SymValue(s) + int64(r.Off())
190 off := ldr.SymValue(rs) + r.Add() - pc
191
192
193 low, high, err := riscv.Split32BitImmediate(off)
194 if err != nil {
195 ldr.Errorf(s, "R_RISCV_PCREL_ relocation does not fit in 32-bits: %d", off)
196 }
197
198 auipcImm, err := riscv.EncodeUImmediate(high)
199 if err != nil {
200 ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", ldr.SymName(rs), err)
201 }
202
203 var secondImm, secondImmMask int64
204 switch r.Type() {
205 case objabi.R_RISCV_PCREL_ITYPE:
206 secondImmMask = riscv.ITypeImmMask
207 secondImm, err = riscv.EncodeIImmediate(low)
208 if err != nil {
209 ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ITYPE I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
210 }
211 case objabi.R_RISCV_PCREL_STYPE:
212 secondImmMask = riscv.STypeImmMask
213 secondImm, err = riscv.EncodeSImmediate(low)
214 if err != nil {
215 ldr.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
216 }
217 default:
218 panic(fmt.Sprintf("Unknown relocation type: %v", r.Type()))
219 }
220
221 auipc := int64(uint32(val))
222 second := int64(uint32(val >> 32))
223
224 auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
225 second = (second &^ secondImmMask) | int64(uint32(secondImm))
226
227 return second<<32 | auipc, 0, true
228 }
229
230 return val, 0, false
231 }
232
233 func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant, loader.Sym, int64, []byte) int64 {
234 log.Fatalf("archrelocvariant")
235 return -1
236 }
237
238 func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sym) (loader.ExtReloc, bool) {
239 switch r.Type() {
240 case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
241 return ld.ExtrelocViaOuterSym(ldr, r, s), true
242 }
243 return loader.ExtReloc{}, false
244 }
245
View as plain text