aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal
diff options
context:
space:
mode:
authorJoel Sing <joel@sing.id.au>2023-08-17 01:13:32 +1000
committerJoel Sing <joel@sing.id.au>2023-09-19 18:10:13 +0000
commitbda5e6c3d07c23d477f68f09e3414e495b12a87e (patch)
tree0dc955380cf1ba0bf7c9819e4a6ff5f9eb7192c6 /src/cmd/internal
parent3c4f12a7d6bc6839b3dd2f4b04aeca962745afb3 (diff)
downloadgo-bda5e6c3d07c23d477f68f09e3414e495b12a87e.tar.xz
cmd/internal/obj/riscv,cmd/link: rework riscv64 call relocations
The riscv64 assembler and linker generate three types of calls. Most calls are made via a single JAL instruction, however this is limited to +/-1MB of text. In the case where a call target is unreachable (or unknown), the JAL targets an AUIPC+JALR trampoline. All other cases use AUIPC+JALR pairs, including the case where a single function exceeds 1MB in text size, potentially making it impossible to reach trampolines. Currently, the single instruction JAL call is marked with R_RISCV_CALL and the two instruction AUIPC+JALR call is marked with R_RISCV_PCREL_ITYPE, which is also used for memory load instructions. This means that we have no way to identify that the latter is a call. Switch to using R_RISCV_CALL to mark the AUIPC+JALR pair (aligning somewhat with the elf.R_RISCV_CALL, which is deprecated in favour of elf.R_RISCV_CALL_PLT). Add R_RISCV_JAL and use this to mark the single instruction JAL direct calls. This is clearer and allows us to map elf.R_RISCV_CALL_PLT to Go's R_RISCV_CALL. Add all three types to IsDirectCall, so that direct calls are correctly identified when a function exceeds 1MB of text. Fixes #62465 Change-Id: Id3eea09688a2b7d6e481eae9ed0aa0d1f9a3a48f Reviewed-on: https://go-review.googlesource.com/c/go/+/520095 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com> Run-TryBot: Joel Sing <joel@sing.id.au> Reviewed-by: Than McIntosh <thanm@google.com>
Diffstat (limited to 'src/cmd/internal')
-rw-r--r--src/cmd/internal/obj/riscv/cpu.go9
-rw-r--r--src/cmd/internal/obj/riscv/obj.go15
-rw-r--r--src/cmd/internal/objabi/reloctype.go26
-rw-r--r--src/cmd/internal/objabi/reloctype_string.go63
4 files changed, 63 insertions, 50 deletions
diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go
index bfd5153da4..edd1ac820b 100644
--- a/src/cmd/internal/obj/riscv/cpu.go
+++ b/src/cmd/internal/obj/riscv/cpu.go
@@ -260,8 +260,13 @@ const (
// corresponding *obj.Prog uses the temporary register.
USES_REG_TMP = 1 << iota
- // NEED_CALL_RELOC is set on JAL instructions to indicate that a
- // R_RISCV_CALL relocation is needed.
+ // NEED_JAL_RELOC is set on JAL instructions to indicate that a
+ // R_RISCV_JAL relocation is needed.
+ NEED_JAL_RELOC
+
+ // NEED_CALL_RELOC is set on an AUIPC instruction to indicate that it
+ // is the first instruction in an AUIPC + JAL pair that needs a
+ // R_RISCV_CALL relocation.
NEED_CALL_RELOC
// NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that
diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go
index 4df28a43f6..501d518019 100644
--- a/src/cmd/internal/obj/riscv/obj.go
+++ b/src/cmd/internal/obj/riscv/obj.go
@@ -41,7 +41,7 @@ func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) {
}
p.As = AJAL
- p.Mark |= NEED_CALL_RELOC
+ p.Mark |= NEED_JAL_RELOC
p.From.Type = obj.TYPE_REG
p.From.Reg = lr
p.Reg = obj.REG_NONE
@@ -610,7 +610,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
var callCount int
for p := cursym.Func().Text; p != nil; p = p.Link {
markRelocs(p)
- if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
+ if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
callCount++
}
}
@@ -664,7 +664,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
p.As = AAUIPC
- p.Mark = (p.Mark &^ NEED_CALL_RELOC) | NEED_PCREL_ITYPE_RELOC
+ p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC
p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym})
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
p.Reg = obj.REG_NONE
@@ -2345,13 +2345,13 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
for p := cursym.Func().Text; p != nil; p = p.Link {
switch p.As {
case AJAL:
- if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
+ if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
rel := obj.Addrel(cursym)
rel.Off = int32(p.Pc)
rel.Siz = 4
rel.Sym = p.To.Sym
rel.Add = p.To.Offset
- rel.Type = objabi.R_RISCV_CALL
+ rel.Type = objabi.R_RISCV_JAL
}
case AJALR:
if p.To.Sym != nil {
@@ -2361,7 +2361,10 @@ func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
var addr *obj.Addr
var rt objabi.RelocType
- if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
+ if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
+ rt = objabi.R_RISCV_CALL
+ addr = &p.From
+ } else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
rt = objabi.R_RISCV_PCREL_ITYPE
addr = &p.From
} else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
diff --git a/src/cmd/internal/objabi/reloctype.go b/src/cmd/internal/objabi/reloctype.go
index 3312a4de7e..e3e042a511 100644
--- a/src/cmd/internal/objabi/reloctype.go
+++ b/src/cmd/internal/objabi/reloctype.go
@@ -259,28 +259,31 @@ const (
// RISC-V.
- // R_RISCV_CALL relocates a J-type instruction with a 21 bit PC-relative
- // address.
- R_RISCV_CALL
+ // R_RISCV_JAL resolves a 20 bit offset for a J-type instruction.
+ R_RISCV_JAL
- // R_RISCV_CALL_TRAMP is the same as R_RISCV_CALL but denotes the use of a
+ // R_RISCV_JAL_TRAMP is the same as R_RISCV_JAL but denotes the use of a
// trampoline, which we may be able to avoid during relocation. These are
// only used by the linker and are not emitted by the compiler or assembler.
- R_RISCV_CALL_TRAMP
+ R_RISCV_JAL_TRAMP
- // R_RISCV_PCREL_ITYPE resolves a 32 bit PC-relative address using an
+ // R_RISCV_CALL resolves a 32 bit PC-relative address for an AUIPC + JALR
+ // instruction pair.
+ R_RISCV_CALL
+
+ // R_RISCV_PCREL_ITYPE resolves a 32 bit PC-relative address for an
// AUIPC + I-type instruction pair.
R_RISCV_PCREL_ITYPE
- // R_RISCV_PCREL_STYPE resolves a 32 bit PC-relative address using an
+ // R_RISCV_PCREL_STYPE resolves a 32 bit PC-relative address for an
// AUIPC + S-type instruction pair.
R_RISCV_PCREL_STYPE
- // R_RISCV_TLS_IE resolves a 32 bit TLS initial-exec address using an
+ // R_RISCV_TLS_IE resolves a 32 bit TLS initial-exec address for an
// AUIPC + I-type instruction pair.
R_RISCV_TLS_IE
- // R_RISCV_TLS_LE resolves a 32 bit TLS local-exec address using an
+ // R_RISCV_TLS_LE resolves a 32 bit TLS local-exec address for a
// LUI + I-type instruction sequence.
R_RISCV_TLS_LE
@@ -387,12 +390,13 @@ const (
// IsDirectCall reports whether r is a relocation for a direct call.
// A direct call is a CALL instruction that takes the target address
-// as an immediate. The address is embedded into the instruction, possibly
+// as an immediate. The address is embedded into the instruction(s), possibly
// with limited width. An indirect call is a CALL instruction that takes
// the target address in register or memory.
func (r RelocType) IsDirectCall() bool {
switch r {
- case R_CALL, R_CALLARM, R_CALLARM64, R_CALLLOONG64, R_CALLMIPS, R_CALLPOWER, R_RISCV_CALL, R_RISCV_CALL_TRAMP:
+ case R_CALL, R_CALLARM, R_CALLARM64, R_CALLLOONG64, R_CALLMIPS, R_CALLPOWER,
+ R_RISCV_CALL, R_RISCV_JAL, R_RISCV_JAL_TRAMP:
return true
}
return false
diff --git a/src/cmd/internal/objabi/reloctype_string.go b/src/cmd/internal/objabi/reloctype_string.go
index ea4be10e4b..e8793dedc1 100644
--- a/src/cmd/internal/objabi/reloctype_string.go
+++ b/src/cmd/internal/objabi/reloctype_string.go
@@ -67,40 +67,41 @@ func _() {
_ = x[R_ADDRPOWER_TOCREL_DS-57]
_ = x[R_ADDRPOWER_D34-58]
_ = x[R_ADDRPOWER_PCREL34-59]
- _ = x[R_RISCV_CALL-60]
- _ = x[R_RISCV_CALL_TRAMP-61]
- _ = x[R_RISCV_PCREL_ITYPE-62]
- _ = x[R_RISCV_PCREL_STYPE-63]
- _ = x[R_RISCV_TLS_IE-64]
- _ = x[R_RISCV_TLS_LE-65]
- _ = x[R_RISCV_GOT_HI20-66]
- _ = x[R_RISCV_PCREL_HI20-67]
- _ = x[R_RISCV_PCREL_LO12_I-68]
- _ = x[R_RISCV_PCREL_LO12_S-69]
- _ = x[R_RISCV_BRANCH-70]
- _ = x[R_RISCV_RVC_BRANCH-71]
- _ = x[R_RISCV_RVC_JUMP-72]
- _ = x[R_PCRELDBL-73]
- _ = x[R_ADDRLOONG64-74]
- _ = x[R_ADDRLOONG64U-75]
- _ = x[R_ADDRLOONG64TLS-76]
- _ = x[R_ADDRLOONG64TLSU-77]
- _ = x[R_CALLLOONG64-78]
- _ = x[R_LOONG64_TLS_IE_PCREL_HI-79]
- _ = x[R_LOONG64_TLS_IE_LO-80]
- _ = x[R_JMPLOONG64-81]
- _ = x[R_ADDRMIPSU-82]
- _ = x[R_ADDRMIPSTLS-83]
- _ = x[R_ADDRCUOFF-84]
- _ = x[R_WASMIMPORT-85]
- _ = x[R_XCOFFREF-86]
- _ = x[R_PEIMAGEOFF-87]
- _ = x[R_INITORDER-88]
+ _ = x[R_RISCV_JAL-60]
+ _ = x[R_RISCV_JAL_TRAMP-61]
+ _ = x[R_RISCV_CALL-62]
+ _ = x[R_RISCV_PCREL_ITYPE-63]
+ _ = x[R_RISCV_PCREL_STYPE-64]
+ _ = x[R_RISCV_TLS_IE-65]
+ _ = x[R_RISCV_TLS_LE-66]
+ _ = x[R_RISCV_GOT_HI20-67]
+ _ = x[R_RISCV_PCREL_HI20-68]
+ _ = x[R_RISCV_PCREL_LO12_I-69]
+ _ = x[R_RISCV_PCREL_LO12_S-70]
+ _ = x[R_RISCV_BRANCH-71]
+ _ = x[R_RISCV_RVC_BRANCH-72]
+ _ = x[R_RISCV_RVC_JUMP-73]
+ _ = x[R_PCRELDBL-74]
+ _ = x[R_ADDRLOONG64-75]
+ _ = x[R_ADDRLOONG64U-76]
+ _ = x[R_ADDRLOONG64TLS-77]
+ _ = x[R_ADDRLOONG64TLSU-78]
+ _ = x[R_CALLLOONG64-79]
+ _ = x[R_LOONG64_TLS_IE_PCREL_HI-80]
+ _ = x[R_LOONG64_TLS_IE_LO-81]
+ _ = x[R_JMPLOONG64-82]
+ _ = x[R_ADDRMIPSU-83]
+ _ = x[R_ADDRMIPSTLS-84]
+ _ = x[R_ADDRCUOFF-85]
+ _ = x[R_WASMIMPORT-86]
+ _ = x[R_XCOFFREF-87]
+ _ = x[R_PEIMAGEOFF-88]
+ _ = x[R_INITORDER-89]
}
-const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_CALLR_RISCV_CALL_TRAMPR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_LOONG64_TLS_IE_PCREL_HIR_LOONG64_TLS_IE_LOR_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDER"
+const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_DWARFFILEREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_ADDRLOONG64R_ADDRLOONG64UR_ADDRLOONG64TLSR_ADDRLOONG64TLSUR_CALLLOONG64R_LOONG64_TLS_IE_PCREL_HIR_LOONG64_TLS_IE_LOR_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDER"
-var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 328, 344, 355, 368, 387, 407, 427, 447, 460, 474, 488, 502, 517, 531, 545, 556, 578, 600, 614, 629, 652, 669, 687, 708, 723, 742, 754, 772, 791, 810, 824, 838, 854, 872, 892, 912, 926, 944, 960, 970, 983, 997, 1013, 1030, 1043, 1068, 1087, 1099, 1110, 1123, 1134, 1146, 1156, 1168, 1179}
+var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 328, 344, 355, 368, 387, 407, 427, 447, 460, 474, 488, 502, 517, 531, 545, 556, 578, 600, 614, 629, 652, 669, 687, 708, 723, 742, 753, 770, 782, 801, 820, 834, 848, 864, 882, 902, 922, 936, 954, 970, 980, 993, 1007, 1023, 1040, 1053, 1078, 1097, 1109, 1120, 1133, 1144, 1156, 1166, 1178, 1189}
func (i RelocType) String() string {
i -= 1