mirror of
https://github.com/golang/go
synced 2024-11-17 16:54:44 -07:00
cmd/internal/obj/riscv,cmd/link: add support for internal cgo linking on riscv64
Make it possible to internally link cgo on riscv64, which also adds support for SDYNIMPORT calls without external linking being required. This reduces the time of an ./all.bash run on a Sifive Hifive Unleashed by approximately 20% (~140 minutes down to ~110 minutes). Change-Id: I43f1348de31672718ae8676cc82f6fdc1dfee054 Reviewed-on: https://go-review.googlesource.com/c/go/+/431104 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>
This commit is contained in:
parent
70a8a41e97
commit
e68c027204
4
src/cmd/dist/build.go
vendored
4
src/cmd/dist/build.go
vendored
@ -576,9 +576,7 @@ func setup() {
|
||||
func mustLinkExternal(goos, goarch string, cgoEnabled bool) bool {
|
||||
if cgoEnabled {
|
||||
switch goarch {
|
||||
case "loong64",
|
||||
"mips", "mipsle", "mips64", "mips64le",
|
||||
"riscv64":
|
||||
case "loong64", "mips", "mipsle", "mips64", "mips64le":
|
||||
// Internally linking cgo is incomplete on some architectures.
|
||||
// https://golang.org/issue/14449
|
||||
return true
|
||||
|
@ -619,14 +619,26 @@ var unaryDst = map[obj.As]bool{
|
||||
|
||||
// Instruction encoding masks.
|
||||
const (
|
||||
// JTypeImmMask is a mask including only the immediate portion of
|
||||
// J-type instructions.
|
||||
JTypeImmMask = 0xfffff000
|
||||
// BTypeImmMask is a mask including only the immediate portion of
|
||||
// B-type instructions.
|
||||
BTypeImmMask = 0xfe000f80
|
||||
|
||||
// CBTypeImmMask is a mask including only the immediate portion of
|
||||
// CB-type instructions.
|
||||
CBTypeImmMask = 0x1c7c
|
||||
|
||||
// CJTypeImmMask is a mask including only the immediate portion of
|
||||
// CJ-type instructions.
|
||||
CJTypeImmMask = 0x1f7c
|
||||
|
||||
// ITypeImmMask is a mask including only the immediate portion of
|
||||
// I-type instructions.
|
||||
ITypeImmMask = 0xfff00000
|
||||
|
||||
// JTypeImmMask is a mask including only the immediate portion of
|
||||
// J-type instructions.
|
||||
JTypeImmMask = 0xfffff000
|
||||
|
||||
// STypeImmMask is a mask including only the immediate portion of
|
||||
// S-type instructions.
|
||||
STypeImmMask = 0xfe000f80
|
||||
|
@ -1181,6 +1181,12 @@ func validateRaw(ctxt *obj.Link, ins *instruction) {
|
||||
}
|
||||
}
|
||||
|
||||
// extractBitAndShift extracts the specified bit from the given immediate,
|
||||
// before shifting it to the requested position and returning it.
|
||||
func extractBitAndShift(imm uint32, bit, pos int) uint32 {
|
||||
return ((imm >> bit) & 1) << pos
|
||||
}
|
||||
|
||||
// encodeR encodes an R-type RISC-V instruction.
|
||||
func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
|
||||
enc := encode(as)
|
||||
@ -1272,6 +1278,11 @@ func encodeSF(ins *instruction) uint32 {
|
||||
return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm))
|
||||
}
|
||||
|
||||
// encodeBImmediate encodes an immediate for a B-type RISC-V instruction.
|
||||
func encodeBImmediate(imm uint32) uint32 {
|
||||
return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
|
||||
}
|
||||
|
||||
// encodeB encodes a B-type RISC-V instruction.
|
||||
func encodeB(ins *instruction) uint32 {
|
||||
imm := immI(ins.as, ins.imm, 13)
|
||||
@ -1281,7 +1292,7 @@ func encodeB(ins *instruction) uint32 {
|
||||
if enc == nil {
|
||||
panic("encodeB: could not encode instruction")
|
||||
}
|
||||
return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7 | enc.opcode
|
||||
return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
|
||||
}
|
||||
|
||||
// encodeU encodes a U-type RISC-V instruction.
|
||||
@ -1315,6 +1326,37 @@ func encodeJ(ins *instruction) uint32 {
|
||||
return encodeJImmediate(imm) | rd<<7 | enc.opcode
|
||||
}
|
||||
|
||||
// encodeCBImmediate encodes an immediate for a CB-type RISC-V instruction.
|
||||
func encodeCBImmediate(imm uint32) uint32 {
|
||||
// Bit order - [8|4:3|7:6|2:1|5]
|
||||
bits := extractBitAndShift(imm, 8, 7)
|
||||
bits |= extractBitAndShift(imm, 4, 6)
|
||||
bits |= extractBitAndShift(imm, 3, 5)
|
||||
bits |= extractBitAndShift(imm, 7, 4)
|
||||
bits |= extractBitAndShift(imm, 6, 3)
|
||||
bits |= extractBitAndShift(imm, 2, 2)
|
||||
bits |= extractBitAndShift(imm, 1, 1)
|
||||
bits |= extractBitAndShift(imm, 5, 0)
|
||||
return (bits>>5)<<10 | (bits&0x1f)<<2
|
||||
}
|
||||
|
||||
// encodeCJImmediate encodes an immediate for a CJ-type RISC-V instruction.
|
||||
func encodeCJImmediate(imm uint32) uint32 {
|
||||
// Bit order - [11|4|9:8|10|6|7|3:1|5]
|
||||
bits := extractBitAndShift(imm, 11, 10)
|
||||
bits |= extractBitAndShift(imm, 4, 9)
|
||||
bits |= extractBitAndShift(imm, 9, 8)
|
||||
bits |= extractBitAndShift(imm, 8, 7)
|
||||
bits |= extractBitAndShift(imm, 10, 6)
|
||||
bits |= extractBitAndShift(imm, 6, 5)
|
||||
bits |= extractBitAndShift(imm, 7, 4)
|
||||
bits |= extractBitAndShift(imm, 3, 3)
|
||||
bits |= extractBitAndShift(imm, 2, 2)
|
||||
bits |= extractBitAndShift(imm, 1, 1)
|
||||
bits |= extractBitAndShift(imm, 5, 0)
|
||||
return bits << 2
|
||||
}
|
||||
|
||||
func encodeRawIns(ins *instruction) uint32 {
|
||||
// Treat the raw value specially as a 32-bit unsigned integer.
|
||||
// Nobody wants to enter negative machine code.
|
||||
@ -1324,6 +1366,43 @@ func encodeRawIns(ins *instruction) uint32 {
|
||||
return uint32(ins.imm)
|
||||
}
|
||||
|
||||
func EncodeBImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 13) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 13 bits", imm)
|
||||
}
|
||||
if imm&1 != 0 {
|
||||
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
|
||||
}
|
||||
return int64(encodeBImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeCBImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 9) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 9 bits", imm)
|
||||
}
|
||||
if imm&1 != 0 {
|
||||
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
|
||||
}
|
||||
return int64(encodeCBImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeCJImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
}
|
||||
if imm&1 != 0 {
|
||||
return 0, fmt.Errorf("immediate %#x is not a multiple of two", imm)
|
||||
}
|
||||
return int64(encodeCJImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeIImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
}
|
||||
return imm << 20, nil
|
||||
}
|
||||
|
||||
func EncodeJImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 21) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 21 bits", imm)
|
||||
@ -1334,13 +1413,6 @@ func EncodeJImmediate(imm int64) (int64, error) {
|
||||
return int64(encodeJImmediate(uint32(imm))), nil
|
||||
}
|
||||
|
||||
func EncodeIImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
}
|
||||
return imm << 20, nil
|
||||
}
|
||||
|
||||
func EncodeSImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
|
@ -285,6 +285,33 @@ const (
|
||||
// LUI + I-type instruction sequence.
|
||||
R_RISCV_TLS_LE
|
||||
|
||||
// R_RISCV_GOT_HI20 resolves the high 20 bits of a 32-bit PC-relative GOT
|
||||
// address.
|
||||
R_RISCV_GOT_HI20
|
||||
|
||||
// R_RISCV_PCREL_HI20 resolves the high 20 bits of a 32-bit PC-relative
|
||||
// address.
|
||||
R_RISCV_PCREL_HI20
|
||||
|
||||
// R_RISCV_PCREL_LO12_I resolves the low 12 bits of a 32-bit PC-relative
|
||||
// address using an I-type instruction.
|
||||
R_RISCV_PCREL_LO12_I
|
||||
|
||||
// R_RISCV_PCREL_LO12_S resolves the low 12 bits of a 32-bit PC-relative
|
||||
// address using an S-type instruction.
|
||||
R_RISCV_PCREL_LO12_S
|
||||
|
||||
// R_RISCV_BRANCH resolves a 12-bit PC-relative branch offset.
|
||||
R_RISCV_BRANCH
|
||||
|
||||
// R_RISCV_RVC_BRANCH resolves an 8-bit PC-relative offset for a CB-type
|
||||
// instruction.
|
||||
R_RISCV_RVC_BRANCH
|
||||
|
||||
// R_RISCV_RVC_JUMP resolves an 11-bit PC-relative offset for a CJ-type
|
||||
// instruction.
|
||||
R_RISCV_RVC_JUMP
|
||||
|
||||
// R_PCRELDBL relocates s390x 2-byte aligned PC-relative addresses.
|
||||
// TODO(mundaym): remove once variants can be serialized - see issue 14218.
|
||||
R_PCRELDBL
|
||||
|
@ -73,27 +73,34 @@ func _() {
|
||||
_ = x[R_RISCV_PCREL_STYPE-63]
|
||||
_ = x[R_RISCV_TLS_IE-64]
|
||||
_ = x[R_RISCV_TLS_LE-65]
|
||||
_ = x[R_PCRELDBL-66]
|
||||
_ = x[R_ADDRLOONG64-67]
|
||||
_ = x[R_ADDRLOONG64U-68]
|
||||
_ = x[R_ADDRLOONG64TLS-69]
|
||||
_ = x[R_ADDRLOONG64TLSU-70]
|
||||
_ = x[R_CALLLOONG64-71]
|
||||
_ = x[R_LOONG64_TLS_IE_PCREL_HI-72]
|
||||
_ = x[R_LOONG64_TLS_IE_LO-73]
|
||||
_ = x[R_JMPLOONG64-74]
|
||||
_ = x[R_ADDRMIPSU-75]
|
||||
_ = x[R_ADDRMIPSTLS-76]
|
||||
_ = x[R_ADDRCUOFF-77]
|
||||
_ = x[R_WASMIMPORT-78]
|
||||
_ = x[R_XCOFFREF-79]
|
||||
_ = x[R_PEIMAGEOFF-80]
|
||||
_ = x[R_INITORDER-81]
|
||||
_ = 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]
|
||||
}
|
||||
|
||||
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_USEGENERICIFACEMETHODR_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_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_USEGENERICIFACEMETHODR_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"
|
||||
|
||||
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, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 394, 414, 434, 454, 467, 481, 495, 509, 524, 538, 552, 563, 585, 607, 621, 636, 659, 676, 694, 715, 730, 749, 761, 779, 798, 817, 831, 845, 855, 868, 882, 898, 915, 928, 953, 972, 984, 995, 1008, 1019, 1031, 1041, 1053, 1064}
|
||||
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, 233, 244, 250, 261, 271, 280, 293, 307, 321, 335, 351, 362, 375, 394, 414, 434, 454, 467, 481, 495, 509, 524, 538, 552, 563, 585, 607, 621, 636, 659, 676, 694, 715, 730, 749, 761, 779, 798, 817, 831, 845, 861, 879, 899, 919, 933, 951, 967, 977, 990, 1004, 1020, 1037, 1050, 1075, 1094, 1106, 1117, 1130, 1141, 1153, 1163, 1175, 1186}
|
||||
|
||||
func (i RelocType) String() string {
|
||||
i -= 1
|
||||
|
@ -577,7 +577,7 @@ func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant
|
||||
return -1
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() == 0 {
|
||||
// pushq got+8(IP)
|
||||
plt.AddUint8(0xff)
|
||||
|
@ -304,7 +304,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
return true
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() == 0 {
|
||||
// str lr, [sp, #-4]!
|
||||
plt.AddUint32(ctxt.Arch, 0xe52de004)
|
||||
|
@ -1091,7 +1091,7 @@ func extreloc(target *ld.Target, ldr *loader.Loader, r loader.Reloc, s loader.Sy
|
||||
return loader.ExtReloc{}, false
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() == 0 {
|
||||
// stp x16, x30, [sp, #-16]!
|
||||
// identifying information
|
||||
|
@ -582,19 +582,17 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) {
|
||||
case 1:
|
||||
P[off] = byte(int8(o))
|
||||
case 2:
|
||||
if o != int64(int16(o)) {
|
||||
st.err.Errorf(s, "relocation address for %s is too big: %#x", ldr.SymName(rs), o)
|
||||
if (rt == objabi.R_PCREL || rt == objabi.R_CALL) && o != int64(int16(o)) {
|
||||
st.err.Errorf(s, "pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), o)
|
||||
} else if o != int64(int16(o)) && o != int64(uint16(o)) {
|
||||
st.err.Errorf(s, "non-pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), uint64(o))
|
||||
}
|
||||
target.Arch.ByteOrder.PutUint16(P[off:], uint16(o))
|
||||
case 4:
|
||||
if rt == objabi.R_PCREL || rt == objabi.R_CALL {
|
||||
if o != int64(int32(o)) {
|
||||
st.err.Errorf(s, "pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), o)
|
||||
}
|
||||
} else {
|
||||
if o != int64(int32(o)) && o != int64(uint32(o)) {
|
||||
st.err.Errorf(s, "non-pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), uint64(o))
|
||||
}
|
||||
if (rt == objabi.R_PCREL || rt == objabi.R_CALL) && o != int64(int32(o)) {
|
||||
st.err.Errorf(s, "pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), o)
|
||||
} else if o != int64(int32(o)) && o != int64(uint32(o)) {
|
||||
st.err.Errorf(s, "non-pc-relative relocation address for %s is too big: %#x", ldr.SymName(rs), uint64(o))
|
||||
}
|
||||
target.Arch.ByteOrder.PutUint32(P[off:], uint32(o))
|
||||
case 8:
|
||||
|
@ -208,7 +208,7 @@ type ELFArch struct {
|
||||
|
||||
Reloc1 func(*Link, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int, int64) bool
|
||||
RelocSize uint32 // size of an ELF relocation record, must match Reloc1.
|
||||
SetupPLT func(ctxt *Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
|
||||
SetupPLT func(ctxt *Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym)
|
||||
|
||||
// DynamicReadOnly can be set to true to make the .dynamic
|
||||
// section read-only. By default it is writable.
|
||||
@ -1585,7 +1585,7 @@ func (ctxt *Link) doelf() {
|
||||
// S390X uses .got instead of .got.plt
|
||||
gotplt = got
|
||||
}
|
||||
thearch.ELF.SetupPLT(ctxt, plt, gotplt, dynamic.Sym())
|
||||
thearch.ELF.SetupPLT(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym())
|
||||
|
||||
/*
|
||||
* .dynamic table
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
"internal/buildcfg"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const funcSize = 11 * 4 // funcSize is the size of the _func object in runtime/runtime2.go
|
||||
@ -99,6 +100,19 @@ func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.Compilat
|
||||
}
|
||||
|
||||
func emitPcln(ctxt *Link, s loader.Sym, container loader.Bitmap) bool {
|
||||
if ctxt.Target.IsRISCV64() {
|
||||
// Avoid adding local symbols to the pcln table - RISC-V
|
||||
// linking generates a very large number of these, particularly
|
||||
// for HI20 symbols (which we need to load in order to be able
|
||||
// to resolve relocations). Unnecessarily including all of
|
||||
// these symbols quickly blows out the size of the pcln table
|
||||
// and overflows hash buckets.
|
||||
symName := ctxt.loader.SymName(s)
|
||||
if symName == "" || strings.HasPrefix(symName, ".L") {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// We want to generate func table entries only for the "lowest
|
||||
// level" symbols, not containers of subsymbols.
|
||||
return !container.Has(s)
|
||||
|
@ -584,27 +584,41 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader,
|
||||
}
|
||||
sect = &elfobj.sect[elfsym.shndx]
|
||||
if sect.sym == 0 {
|
||||
if strings.HasPrefix(elfsym.name, ".Linfo_string") { // clang does this
|
||||
if elfsym.type_ == 0 {
|
||||
if strings.HasPrefix(sect.name, ".debug_") && elfsym.name == "" {
|
||||
// clang on arm and riscv64.
|
||||
// This reportedly happens with clang 3.7 on ARM.
|
||||
// See issue 13139.
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(elfsym.name, ".Ldebug_") || elfsym.name == ".L0 " {
|
||||
// gcc on riscv64.
|
||||
continue
|
||||
}
|
||||
if elfsym.name == ".Lline_table_start0" {
|
||||
// clang on riscv64.
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(elfsym.name, "$d") && sect.name == ".debug_frame" {
|
||||
// "$d" is a marker, not a real symbol.
|
||||
// This happens with gcc on ARM64.
|
||||
// See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(elfsym.name, ".Linfo_string") {
|
||||
// clang does this
|
||||
continue
|
||||
}
|
||||
|
||||
if elfsym.name == "" && elfsym.type_ == 0 && sect.name == ".debug_str" {
|
||||
// This reportedly happens with clang 3.7 on ARM.
|
||||
// See issue 13139.
|
||||
if strings.HasPrefix(elfsym.name, ".LASF") || strings.HasPrefix(elfsym.name, ".LLRL") || strings.HasPrefix(elfsym.name, ".LLST") {
|
||||
// gcc on s390x and riscv64 does this.
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(elfsym.name, "$d") && elfsym.type_ == 0 && sect.name == ".debug_frame" {
|
||||
// "$d" is a marker, not a real symbol.
|
||||
// This happens with gcc on ARM64.
|
||||
// See https://sourceware.org/bugzilla/show_bug.cgi?id=21809
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(elfsym.name, ".LASF") { // gcc on s390x does this
|
||||
continue
|
||||
}
|
||||
return errorf("%v: sym#%d (%s): ignoring symbol in section %d (type %d)", elfsym.sym, i, elfsym.name, elfsym.shndx, elfsym.type_)
|
||||
return errorf("%v: sym#%d (%q): ignoring symbol in section %d (%q) (type %d)", elfsym.sym, i, elfsym.name, elfsym.shndx, sect.name, elfsym.type_)
|
||||
}
|
||||
|
||||
s := elfsym.sym
|
||||
|
@ -83,7 +83,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
return true
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
return true
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
return true
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() != 0 {
|
||||
return
|
||||
}
|
||||
|
@ -1014,7 +1014,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
return true
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() == 0 {
|
||||
// The dynamic linker stores the address of the
|
||||
// dynamic resolver and the DSO identifier in the two
|
||||
|
@ -20,7 +20,139 @@ import (
|
||||
// fakeLabelName matches the RISCV_FAKE_LABEL_NAME from binutils.
|
||||
const fakeLabelName = ".L0 "
|
||||
|
||||
func gentext(ctxt *ld.Link, ldr *loader.Loader) {
|
||||
func gentext(ctxt *ld.Link, ldr *loader.Loader) {}
|
||||
|
||||
func findHI20Reloc(ldr *loader.Loader, s loader.Sym, val int64) *loader.Reloc {
|
||||
outer := ldr.OuterSym(s)
|
||||
if outer == 0 {
|
||||
return nil
|
||||
}
|
||||
relocs := ldr.Relocs(outer)
|
||||
start := sort.Search(relocs.Count(), func(i int) bool { return ldr.SymValue(outer)+int64(relocs.At(i).Off()) >= val })
|
||||
for idx := start; idx < relocs.Count(); idx++ {
|
||||
r := relocs.At(idx)
|
||||
if ldr.SymValue(outer)+int64(r.Off()) != val {
|
||||
break
|
||||
}
|
||||
if r.Type() == objabi.R_RISCV_GOT_HI20 || r.Type() == objabi.R_RISCV_PCREL_HI20 {
|
||||
return &r
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
|
||||
targ := r.Sym()
|
||||
|
||||
var targType sym.SymKind
|
||||
if targ != 0 {
|
||||
targType = ldr.SymType(targ)
|
||||
}
|
||||
|
||||
switch r.Type() {
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_CALL),
|
||||
objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_CALL_PLT):
|
||||
|
||||
if targType == sym.SDYNIMPORT {
|
||||
addpltsym(target, ldr, syms, targ)
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocSym(rIdx, syms.PLT)
|
||||
su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
|
||||
}
|
||||
if targType == 0 || targType == sym.SXREF {
|
||||
ldr.Errorf(s, "unknown symbol %s in RISCV call", ldr.SymName(targ))
|
||||
}
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_ITYPE)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_GOT_HI20):
|
||||
if targType != sym.SDYNIMPORT {
|
||||
// TODO(jsing): Could convert to non-GOT reference.
|
||||
}
|
||||
|
||||
ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_RISCV_64))
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_GOT_HI20)
|
||||
su.SetRelocSym(rIdx, syms.GOT)
|
||||
su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_HI20):
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_HI20)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_LO12_I):
|
||||
if r.Add() != 0 {
|
||||
ldr.Errorf(s, "R_RISCV_PCREL_LO12_I with non-zero addend")
|
||||
}
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_I)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_LO12_S):
|
||||
if r.Add() != 0 {
|
||||
ldr.Errorf(s, "R_RISCV_PCREL_LO12_S with non-zero addend")
|
||||
}
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_S)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_BRANCH):
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_RVC_BRANCH)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_JUMP):
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_RVC_JUMP)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_BRANCH):
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocType(rIdx, objabi.R_RISCV_BRANCH)
|
||||
return true
|
||||
|
||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RELAX):
|
||||
// Ignore relaxations, at least for now.
|
||||
return true
|
||||
|
||||
default:
|
||||
if r.Type() >= objabi.ElfRelocOffset {
|
||||
ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Reread the reloc to incorporate any changes in type above.
|
||||
relocs := ldr.Relocs(s)
|
||||
r = relocs.At(rIdx)
|
||||
|
||||
switch r.Type() {
|
||||
case objabi.R_RISCV_PCREL_ITYPE:
|
||||
if targType != sym.SDYNIMPORT {
|
||||
// nothing to do, the relocation will be laid out in reloc
|
||||
return true
|
||||
}
|
||||
if target.IsExternal() {
|
||||
// External linker will do this relocation.
|
||||
return true
|
||||
}
|
||||
// Internal linking.
|
||||
if r.Add() != 0 {
|
||||
ldr.Errorf(s, "PLT reference with non-zero addend (%v)", r.Add())
|
||||
}
|
||||
// Build a PLT entry and change the relocation target to that entry.
|
||||
addpltsym(target, ldr, syms, targ)
|
||||
su := ldr.MakeSymbolUpdater(s)
|
||||
su.SetRelocSym(rIdx, syms.PLT)
|
||||
su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func genSymsLate(ctxt *ld.Link, ldr *loader.Loader) {
|
||||
@ -117,9 +249,10 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
// corresponding R_RISCV_PCREL_LO12_I or R_RISCV_PCREL_LO12_S relocation.
|
||||
// Note that the LO12 relocation must point to a target that has a valid
|
||||
// HI20 PC-relative relocation text symbol, which in turn points to the
|
||||
// given symbol. For further details see the ELF specification for RISC-V:
|
||||
// given symbol. For further details see section 8.4.9 of the RISC-V ABIs
|
||||
// Specification:
|
||||
//
|
||||
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#pc-relative-symbol-addresses
|
||||
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/releases/download/v1.0/riscv-abi.pdf
|
||||
//
|
||||
var hiRel, loRel elf.R_RISCV
|
||||
switch r.Type {
|
||||
@ -152,8 +285,106 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
return true
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
log.Fatalf("elfsetupplt")
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() != 0 {
|
||||
return
|
||||
}
|
||||
if gotplt.Size() != 0 {
|
||||
ctxt.Errorf(gotplt.Sym(), "got.plt is not empty")
|
||||
}
|
||||
|
||||
// See section 8.4.6 of the RISC-V ABIs Specification:
|
||||
//
|
||||
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/releases/download/v1.0/riscv-abi.pdf
|
||||
//
|
||||
// 1: auipc t2, %pcrel_hi(.got.plt)
|
||||
// sub t1, t1, t3 # shifted .got.plt offset + hdr size + 12
|
||||
// l[w|d] t3, %pcrel_lo(1b)(t2) # _dl_runtime_resolve
|
||||
// addi t1, t1, -(hdr size + 12) # shifted .got.plt offset
|
||||
// addi t0, t2, %pcrel_lo(1b) # &.got.plt
|
||||
// srli t1, t1, log2(16/PTRSIZE) # .got.plt offset
|
||||
// l[w|d] t0, PTRSIZE(t0) # link map
|
||||
// jr t3
|
||||
|
||||
plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_RISCV_PCREL_HI20, 4)
|
||||
plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x00000397) // auipc t2,0x0
|
||||
|
||||
sb := ldr.MakeSymbolBuilder(fakeLabelName)
|
||||
sb.SetType(sym.STEXT)
|
||||
sb.SetValue(ldr.SymValue(plt.Sym()) + plt.Size() - 4)
|
||||
sb.SetLocal(true)
|
||||
sb.SetReachable(true)
|
||||
sb.SetVisibilityHidden(true)
|
||||
plt.AddInteriorSym(sb.Sym())
|
||||
|
||||
plt.AddUint32(ctxt.Arch, 0x41c30333) // sub t1,t1,t3
|
||||
|
||||
plt.AddSymRef(ctxt.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
|
||||
plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x0003be03) // ld t3,0(t2)
|
||||
|
||||
plt.AddUint32(ctxt.Arch, 0xfd430313) // addi t1,t1,-44
|
||||
|
||||
plt.AddSymRef(ctxt.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
|
||||
plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x00038293) // addi t0,t2,0
|
||||
|
||||
plt.AddUint32(ctxt.Arch, 0x00135313) // srli t1,t1,0x1
|
||||
plt.AddUint32(ctxt.Arch, 0x0082b283) // ld t0,8(t0)
|
||||
plt.AddUint32(ctxt.Arch, 0x00008e02) // jr t3
|
||||
|
||||
gotplt.AddAddrPlus(ctxt.Arch, dynamic, 0) // got.plt[0] = _dl_runtime_resolve
|
||||
gotplt.AddUint64(ctxt.Arch, 0) // got.plt[1] = link map
|
||||
}
|
||||
|
||||
func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
|
||||
if ldr.SymPlt(s) >= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
ld.Adddynsym(ldr, target, syms, s)
|
||||
|
||||
plt := ldr.MakeSymbolUpdater(syms.PLT)
|
||||
gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
|
||||
rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
|
||||
if plt.Size() == 0 {
|
||||
panic("plt is not set up")
|
||||
}
|
||||
|
||||
// See section 8.4.6 of the RISC-V ABIs Specification:
|
||||
//
|
||||
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/releases/download/v1.0/riscv-abi.pdf
|
||||
//
|
||||
// 1: auipc t3, %pcrel_hi(function@.got.plt)
|
||||
// l[w|d] t3, %pcrel_lo(1b)(t3)
|
||||
// jalr t1, t3
|
||||
// nop
|
||||
|
||||
plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_RISCV_PCREL_HI20, 4)
|
||||
plt.SetUint32(target.Arch, plt.Size()-4, 0x00000e17) // auipc t3,0x0
|
||||
|
||||
sb := ldr.MakeSymbolBuilder(fakeLabelName)
|
||||
sb.SetType(sym.STEXT)
|
||||
sb.SetValue(ldr.SymValue(plt.Sym()) + plt.Size() - 4)
|
||||
sb.SetLocal(true)
|
||||
sb.SetReachable(true)
|
||||
sb.SetVisibilityHidden(true)
|
||||
plt.AddInteriorSym(sb.Sym())
|
||||
|
||||
plt.AddSymRef(target.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
|
||||
plt.SetUint32(target.Arch, plt.Size()-4, 0x000e3e03) // ld t3,0(t3)
|
||||
plt.AddUint32(target.Arch, 0x000e0367) // jalr t1,t3
|
||||
plt.AddUint32(target.Arch, 0x00000001) // nop
|
||||
|
||||
ldr.SetPlt(s, int32(plt.Size()-16))
|
||||
|
||||
// add to got.plt: pointer to plt[0]
|
||||
gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
|
||||
|
||||
// rela
|
||||
rela.AddAddrPlus(target.Arch, gotplt.Sym(), gotplt.Size()-8)
|
||||
sDynid := ldr.SymDynid(s)
|
||||
|
||||
rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_RISCV_JUMP_SLOT)))
|
||||
rela.AddUint64(target.Arch, 0)
|
||||
}
|
||||
|
||||
func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
|
||||
@ -217,15 +448,131 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
|
||||
|
||||
return val, 0, true
|
||||
|
||||
case objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE:
|
||||
// TLS relocations are not currently handled for internal linking.
|
||||
// For now, TLS is only used when cgo is in use and cgo currently
|
||||
// requires external linking. However, we need to accept these
|
||||
// relocations so that code containing TLS variables will link,
|
||||
// even when they're not being used. For now, replace these
|
||||
// instructions with EBREAK to detect accidental use.
|
||||
const ebreakIns = 0x00100073
|
||||
return ebreakIns<<32 | ebreakIns, 0, true
|
||||
case objabi.R_RISCV_TLS_IE:
|
||||
log.Fatalf("cannot handle R_RISCV_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
|
||||
return val, 0, false
|
||||
|
||||
case objabi.R_RISCV_TLS_LE:
|
||||
// Generate LUI and ADDIW instruction immediates.
|
||||
off := r.Add()
|
||||
|
||||
low, high, err := riscv.Split32BitImmediate(off)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
|
||||
}
|
||||
|
||||
luiImm, err := riscv.EncodeUImmediate(high)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode R_RISCV_TLS_LE LUI relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
|
||||
addiwImm, err := riscv.EncodeIImmediate(low)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode R_RISCV_TLS_LE I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
|
||||
lui := int64(uint32(val))
|
||||
addiw := int64(uint32(val >> 32))
|
||||
|
||||
lui = (lui &^ riscv.UTypeImmMask) | int64(uint32(luiImm))
|
||||
addiw = (addiw &^ riscv.ITypeImmMask) | int64(uint32(addiwImm))
|
||||
|
||||
return addiw<<32 | lui, 0, true
|
||||
|
||||
case objabi.R_RISCV_BRANCH:
|
||||
pc := ldr.SymValue(s) + int64(r.Off())
|
||||
off := ldr.SymValue(rs) + r.Add() - pc
|
||||
|
||||
imm, err := riscv.EncodeBImmediate(off)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode B-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
ins := (int64(uint32(val)) &^ riscv.BTypeImmMask) | int64(uint32(imm))
|
||||
|
||||
return ins, 0, true
|
||||
|
||||
case objabi.R_RISCV_RVC_BRANCH, objabi.R_RISCV_RVC_JUMP:
|
||||
pc := ldr.SymValue(s) + int64(r.Off())
|
||||
off := ldr.SymValue(rs) + r.Add() - pc
|
||||
|
||||
var err error
|
||||
var imm, immMask int64
|
||||
switch r.Type() {
|
||||
case objabi.R_RISCV_RVC_BRANCH:
|
||||
immMask = riscv.CBTypeImmMask
|
||||
imm, err = riscv.EncodeCBImmediate(off)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode CB-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
case objabi.R_RISCV_RVC_JUMP:
|
||||
immMask = riscv.CJTypeImmMask
|
||||
imm, err = riscv.EncodeCJImmediate(off)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode CJ-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
|
||||
}
|
||||
|
||||
ins := (int64(uint16(val)) &^ immMask) | int64(uint16(imm))
|
||||
|
||||
return ins, 0, true
|
||||
|
||||
case objabi.R_RISCV_GOT_HI20, objabi.R_RISCV_PCREL_HI20:
|
||||
pc := ldr.SymValue(s) + int64(r.Off())
|
||||
off := ldr.SymValue(rs) + r.Add() - pc
|
||||
|
||||
// Generate AUIPC immediates.
|
||||
_, high, err := riscv.Split32BitImmediate(off)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
|
||||
}
|
||||
|
||||
auipcImm, err := riscv.EncodeUImmediate(high)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
|
||||
auipc := int64(uint32(val))
|
||||
auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
|
||||
|
||||
return auipc, 0, true
|
||||
|
||||
case objabi.R_RISCV_PCREL_LO12_I, objabi.R_RISCV_PCREL_LO12_S:
|
||||
hi20Reloc := findHI20Reloc(ldr, rs, ldr.SymValue(rs))
|
||||
if hi20Reloc == nil {
|
||||
ldr.Errorf(s, "missing HI20 relocation for LO12 relocation with %s (%d)", ldr.SymName(rs), rs)
|
||||
}
|
||||
|
||||
pc := ldr.SymValue(s) + int64(hi20Reloc.Off())
|
||||
off := ldr.SymValue(hi20Reloc.Sym()) + hi20Reloc.Add() - pc
|
||||
|
||||
low, _, err := riscv.Split32BitImmediate(off)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
|
||||
}
|
||||
|
||||
var imm, immMask int64
|
||||
switch r.Type() {
|
||||
case objabi.R_RISCV_PCREL_LO12_I:
|
||||
immMask = riscv.ITypeImmMask
|
||||
imm, err = riscv.EncodeIImmediate(low)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode objabi.R_RISCV_PCREL_LO12_I I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
case objabi.R_RISCV_PCREL_LO12_S:
|
||||
immMask = riscv.STypeImmMask
|
||||
imm, err = riscv.EncodeSImmediate(low)
|
||||
if err != nil {
|
||||
ldr.Errorf(s, "cannot encode R_RISCV_PCREL_LO12_S S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
|
||||
}
|
||||
|
||||
ins := int64(uint32(val))
|
||||
ins = (ins &^ immMask) | int64(uint32(imm))
|
||||
return ins, 0, true
|
||||
|
||||
case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
|
||||
// Generate AUIPC and second instruction immediates.
|
||||
@ -254,7 +601,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
|
||||
ldr.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown relocation type: %v", r.Type()))
|
||||
panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
|
||||
}
|
||||
|
||||
auipc := int64(uint32(val))
|
||||
@ -358,7 +705,7 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri int, rs, s loader.Sym) {
|
||||
|
||||
func genCallTramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
|
||||
tramp.AddUint32(arch, 0x00000f97) // AUIPC $0, X31
|
||||
tramp.AddUint32(arch, 0x000f8067) // JALR X0, (X31)
|
||||
tramp.AddUint32(arch, 0x000f8067) // JALR X0, (X31)
|
||||
|
||||
r, _ := tramp.AddRel(objabi.R_RISCV_PCREL_ITYPE)
|
||||
r.SetSiz(8)
|
||||
|
@ -20,6 +20,7 @@ func Init() (*sys.Arch, ld.Arch) {
|
||||
Dwarfregsp: dwarfRegSP,
|
||||
Dwarfreglr: dwarfRegLR,
|
||||
|
||||
Adddynrel: adddynrel,
|
||||
Archinit: archinit,
|
||||
Archreloc: archreloc,
|
||||
Archrelocvariant: archrelocvariant,
|
||||
|
@ -309,7 +309,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym,
|
||||
return true
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() == 0 {
|
||||
// stg %r1,56(%r15)
|
||||
plt.AddUint8(0xe3)
|
||||
|
@ -67,6 +67,8 @@ func RelocName(arch *sys.Arch, r objabi.RelocType) string {
|
||||
return elf.R_PPC64(nr).String()
|
||||
case sys.S390X:
|
||||
return elf.R_390(nr).String()
|
||||
case sys.RISCV64:
|
||||
return elf.R_RISCV(nr).String()
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
@ -421,7 +421,7 @@ func archrelocvariant(*ld.Target, *loader.Loader, loader.Reloc, sym.RelocVariant
|
||||
return -1
|
||||
}
|
||||
|
||||
func elfsetupplt(ctxt *ld.Link, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, got *loader.SymbolBuilder, dynamic loader.Sym) {
|
||||
if plt.Size() == 0 {
|
||||
// pushl got+4
|
||||
plt.AddUint8(0xff)
|
||||
|
@ -85,9 +85,7 @@ func FuzzInstrumented(goos, goarch string) bool {
|
||||
func MustLinkExternal(goos, goarch string, withCgo bool) bool {
|
||||
if withCgo {
|
||||
switch goarch {
|
||||
case "loong64",
|
||||
"mips", "mipsle", "mips64", "mips64le",
|
||||
"riscv64":
|
||||
case "loong64", "mips", "mipsle", "mips64", "mips64le":
|
||||
// Internally linking cgo is incomplete on some architectures.
|
||||
// https://go.dev/issue/14449
|
||||
return true
|
||||
|
Loading…
Reference in New Issue
Block a user