@@ -11,20 +11,138 @@ import (
11
11
"cmd/link/internal/ld"
12
12
"cmd/link/internal/loader"
13
13
"cmd/link/internal/sym"
14
+ "debug/elf"
14
15
"fmt"
15
16
"log"
17
+ "sort"
16
18
)
17
19
20
+ // fakeLabelName matches the RISCV_FAKE_LABEL_NAME from binutils.
21
+ const fakeLabelName = ".L0 "
22
+
18
23
func gentext (ctxt * ld.Link , ldr * loader.Loader ) {
19
24
}
20
25
26
+ func genSymsLate (ctxt * ld.Link , ldr * loader.Loader ) {
27
+ if ctxt .LinkMode != ld .LinkExternal {
28
+ return
29
+ }
30
+
31
+ // Generate a local text symbol for each relocation target, as the
32
+ // R_RISCV_PCREL_LO12_* relocations generated by elfreloc1 need it.
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
+ continue
43
+ }
44
+ if r .Off () == 0 && ldr .SymType (s ) == sym .STEXT {
45
+ // Use the symbol for the function instead of creating
46
+ // an overlapping symbol.
47
+ continue
48
+ }
49
+
50
+ // TODO(jsing): Consider generating ELF symbols without needing
51
+ // loader symbols, in order to reduce memory consumption. This
52
+ // would require changes to genelfsym so that it called
53
+ // putelfsym and putelfsyment as appropriate.
54
+ sb := ldr .MakeSymbolBuilder (fakeLabelName )
55
+ sb .SetType (sym .STEXT )
56
+ sb .SetValue (ldr .SymValue (s ) + int64 (r .Off ()))
57
+ sb .SetLocal (true )
58
+ sb .SetReachable (true )
59
+ sb .SetVisibilityHidden (true )
60
+ sb .SetSect (ldr .SymSect (s ))
61
+ if outer := ldr .OuterSym (s ); outer != 0 {
62
+ ldr .AddInteriorSym (outer , sb .Sym ())
63
+ }
64
+ hi20Syms = append (hi20Syms , sb .Sym ())
65
+ }
66
+ }
67
+ ctxt .Textp = append (ctxt .Textp , hi20Syms ... )
68
+ ldr .SortSyms (ctxt .Textp )
69
+ }
70
+
71
+ func findHI20Symbol (ctxt * ld.Link , ldr * loader.Loader , val int64 ) loader.Sym {
72
+ idx := sort .Search (len (ctxt .Textp ), func (i int ) bool { return ldr .SymValue (ctxt .Textp [i ]) >= val })
73
+ if idx >= len (ctxt .Textp ) {
74
+ return 0
75
+ }
76
+ if s := ctxt .Textp [idx ]; ldr .SymValue (s ) == val && ldr .SymType (s ) == sym .STEXT {
77
+ return s
78
+ }
79
+ return 0
80
+ }
81
+
21
82
func elfreloc1 (ctxt * ld.Link , out * ld.OutBuf , ldr * loader.Loader , s loader.Sym , r loader.ExtReloc , ri int , sectoff int64 ) bool {
22
- log .Fatalf ("elfreloc1" )
23
- return false
83
+ elfsym := ld .ElfSymForReloc (ctxt , r .Xsym )
84
+ switch r .Type {
85
+ case objabi .R_ADDR , objabi .R_DWARFSECREF :
86
+ out .Write64 (uint64 (sectoff ))
87
+ switch r .Size {
88
+ case 4 :
89
+ out .Write64 (uint64 (elf .R_RISCV_32 ) | uint64 (elfsym )<< 32 )
90
+ case 8 :
91
+ out .Write64 (uint64 (elf .R_RISCV_64 ) | uint64 (elfsym )<< 32 )
92
+ default :
93
+ ld .Errorf (nil , "unknown size %d for %v relocation" , r .Size , r .Type )
94
+ return false
95
+ }
96
+ out .Write64 (uint64 (r .Xadd ))
97
+
98
+ case objabi .R_CALLRISCV :
99
+ // Call relocations are currently handled via R_RISCV_PCREL_ITYPE.
100
+ // TODO(jsing): Consider generating elf.R_RISCV_CALL instead of a
101
+ // HI20/LO12_I pair.
102
+
103
+ case objabi .R_RISCV_PCREL_ITYPE , objabi .R_RISCV_PCREL_STYPE :
104
+ // Find the text symbol for the AUIPC instruction targeted
105
+ // by this relocation.
106
+ relocs := ldr .Relocs (s )
107
+ offset := int64 (relocs .At (ri ).Off ())
108
+ hi20Sym := findHI20Symbol (ctxt , ldr , ldr .SymValue (s )+ offset )
109
+ if hi20Sym == 0 {
110
+ ld .Errorf (nil , "failed to find text symbol for HI20 relocation at %d (%x)" , sectoff , ldr .SymValue (s )+ offset )
111
+ return false
112
+ }
113
+ hi20ElfSym := ld .ElfSymForReloc (ctxt , hi20Sym )
114
+
115
+ // Emit two relocations - a R_RISCV_PCREL_HI20 relocation and a
116
+ // corresponding R_RISCV_PCREL_LO12_I or R_RISCV_PCREL_LO12_S relocation.
117
+ // Note that the LO12 relocation must point to a target that has a valid
118
+ // HI20 PC-relative relocation text symbol, which in turn points to the
119
+ // given symbol. For further details see the ELF specification for RISC-V:
120
+ //
121
+ // https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#pc-relative-symbol-addresses
122
+ //
123
+ var hiRel , loRel elf.R_RISCV
124
+ switch r .Type {
125
+ case objabi .R_RISCV_PCREL_ITYPE :
126
+ hiRel , loRel = elf .R_RISCV_PCREL_HI20 , elf .R_RISCV_PCREL_LO12_I
127
+ case objabi .R_RISCV_PCREL_STYPE :
128
+ hiRel , loRel = elf .R_RISCV_PCREL_HI20 , elf .R_RISCV_PCREL_LO12_S
129
+ }
130
+ out .Write64 (uint64 (sectoff ))
131
+ out .Write64 (uint64 (hiRel ) | uint64 (elfsym )<< 32 )
132
+ out .Write64 (uint64 (r .Xadd ))
133
+ out .Write64 (uint64 (sectoff + 4 ))
134
+ out .Write64 (uint64 (loRel ) | uint64 (hi20ElfSym )<< 32 )
135
+ out .Write64 (uint64 (0 ))
136
+
137
+ default :
138
+ return false
139
+ }
140
+
141
+ return true
24
142
}
25
143
26
144
func elfsetupplt (ctxt * ld.Link , plt , gotplt * loader.SymbolBuilder , dynamic loader.Sym ) {
27
- log .Fatalf ("elfsetuplt " )
145
+ log .Fatalf ("elfsetupplt " )
28
146
}
29
147
30
148
func machoreloc1 (* sys.Arch , * ld.OutBuf , * loader.Loader , loader.Sym , loader.ExtReloc , int64 ) bool {
@@ -33,8 +151,20 @@ func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtRe
33
151
}
34
152
35
153
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 ) {
36
- rs := r .Sym ()
37
- rs = ldr .ResolveABIAlias (rs )
154
+ if target .IsExternal () {
155
+ switch r .Type () {
156
+ case objabi .R_CALLRISCV :
157
+ return val , 0 , true
158
+
159
+ case objabi .R_RISCV_PCREL_ITYPE , objabi .R_RISCV_PCREL_STYPE :
160
+ return val , 2 , true
161
+ }
162
+
163
+ return val , 0 , false
164
+ }
165
+
166
+ rs := ldr .ResolveABIAlias (r .Sym ())
167
+
38
168
switch r .Type () {
39
169
case objabi .R_CALLRISCV :
40
170
// Nothing to do.
@@ -89,3 +219,11 @@ func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant
89
219
log .Fatalf ("archrelocvariant" )
90
220
return - 1
91
221
}
222
+
223
+ func extreloc (target * ld.Target , ldr * loader.Loader , r loader.Reloc , s loader.Sym ) (loader.ExtReloc , bool ) {
224
+ switch r .Type () {
225
+ case objabi .R_RISCV_PCREL_ITYPE , objabi .R_RISCV_PCREL_STYPE :
226
+ return ld .ExtrelocViaOuterSym (ldr , r , s ), true
227
+ }
228
+ return loader.ExtReloc {}, false
229
+ }
0 commit comments