[PATCH] D60414: [RISCV] Fix range check for HI20/LO12/RVC_LUI relocations
Chih-Mao Chen via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 8 11:10:03 PDT 2019
PkmX created this revision.
PkmX added a reviewer: ruiu.
Herald added subscribers: llvm-commits, benna, psnobl, jocewei, rkruppe, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, MaskRay, jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, apazos, simoncook, johnrusso, rbar, asb, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.
The code previously specified a 32-bit range for `R_RISCV_HI20` and `R_RISCV_LO12_[IS]`, however this is incorrect as the maximum offset on RV64 that can be formed from the immediate of `lui` and the displacement of an I-type or S-type instruction is `-0x80000800` to `0x7ffff7ff`. There is also the same issue with a `c.lui` and LO12 pair, whose actual addressable range should be `-0x20800` to `0x1f7ff`.
The tests will be included in the next patch that converts all RISC-V tests to use `llvm-mc` instead of `yaml2obj`, as assembler support has matured enough to write tests in them.
Repository:
rLLD LLVM Linker
https://reviews.llvm.org/D60414
Files:
ELF/Arch/RISCV.cpp
Index: ELF/Arch/RISCV.cpp
===================================================================
--- ELF/Arch/RISCV.cpp
+++ ELF/Arch/RISCV.cpp
@@ -88,6 +88,8 @@
void RISCV::relocateOne(uint8_t *Loc, const RelType Type,
const uint64_t Val) const {
+ const unsigned Bits = Config->Wordsize * 8;
+
switch (Type) {
case R_RISCV_32:
write32le(Loc, Val);
@@ -130,8 +132,8 @@
}
case R_RISCV_RVC_LUI: {
- int32_t Imm = ((Val + 0x800) >> 12);
- checkUInt(Loc, Imm, 6, Type);
+ int64_t Imm = SignExtend64(Val + 0x800, Bits) >> 12;
+ checkInt(Loc, Imm, 6, Type);
if (Imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
write16le(Loc, (read16le(Loc) & 0x0F83) | 0x4000);
} else {
@@ -174,8 +176,9 @@
// auipc + jalr pair
case R_RISCV_CALL: {
- checkInt(Loc, Val, 32, Type);
- if (isInt<32>(Val)) {
+ int64_t Hi = SignExtend64(Val + 0x800, Bits) >> 12;
+ checkInt(Loc, Hi, 20, Type);
+ if (isInt<20>(Hi)) {
relocateOne(Loc, R_RISCV_PCREL_HI20, Val);
relocateOne(Loc + 4, R_RISCV_PCREL_LO12_I, Val);
}
@@ -184,26 +187,24 @@
case R_RISCV_PCREL_HI20:
case R_RISCV_HI20: {
- checkInt(Loc, Val, 32, Type);
- uint32_t Hi = Val + 0x800;
+ uint64_t Hi = Val + 0x800;
+ checkInt(Loc, SignExtend64(Hi, Bits) >> 12, 20, Type);
write32le(Loc, (read32le(Loc) & 0xFFF) | (Hi & 0xFFFFF000));
return;
}
case R_RISCV_PCREL_LO12_I:
case R_RISCV_LO12_I: {
- checkInt(Loc, Val, 32, Type);
- uint32_t Hi = Val + 0x800;
- uint32_t Lo = Val - (Hi & 0xFFFFF000);
+ uint64_t Hi = (Val + 0x800) >> 12;
+ uint64_t Lo = Val - (Hi << 12);
write32le(Loc, (read32le(Loc) & 0xFFFFF) | ((Lo & 0xFFF) << 20));
return;
}
case R_RISCV_PCREL_LO12_S:
case R_RISCV_LO12_S: {
- checkInt(Loc, Val, 32, Type);
- uint32_t Hi = Val + 0x800;
- uint32_t Lo = Val - (Hi & 0xFFFFF000);
+ uint64_t Hi = (Val + 0x800) >> 12;
+ uint64_t Lo = Val - (Hi << 12);
uint32_t Imm11_5 = extractBits(Lo, 11, 5) << 25;
uint32_t Imm4_0 = extractBits(Lo, 4, 0) << 7;
write32le(Loc, (read32le(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D60414.194173.patch
Type: text/x-patch
Size: 2191 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190408/551ba531/attachment.bin>
More information about the llvm-commits
mailing list