[RuntimeDyldChecker] Support offset in decode_operand expr

In RISCV's relocations, some relocations are comprised of two relocation types. For example, R_RISCV_PCREL_HI20 and R_RISCV_PCREL_LO12_I compose a PC relative relocation. In general the compiler will set a label in the position of R_RISCV_PCREL_HI20. So, to test the R_RISCV_PCREL_LO12_I relocation, we need decode instruction at position of the label points to R_RISCV_PCREL_HI20 plus 4 (the size of a riscv non-compress instruction).

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D105528
This commit is contained in:
luxufan 2021-08-02 23:13:11 +08:00
parent 18d10fbe87
commit f4e418ac1e
2 changed files with 31 additions and 6 deletions

View File

@ -232,6 +232,26 @@ private:
EvalResult(("Cannot decode unknown symbol '" + Symbol + "'").str()),
"");
// if there is an offset number expr
int64_t Offset = 0;
BinOpToken BinOp;
std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr);
switch (BinOp) {
case BinOpToken::Add: {
EvalResult Number;
std::tie(Number, RemainingExpr) = evalNumberExpr(RemainingExpr);
Offset = Number.getValue();
break;
}
case BinOpToken::Invalid:
break;
default:
return std::make_pair(
unexpectedToken(RemainingExpr, RemainingExpr,
"expected '+' for offset or ',' if no offset"),
"");
}
if (!RemainingExpr.startswith(","))
return std::make_pair(
unexpectedToken(RemainingExpr, RemainingExpr, "expected ','"), "");
@ -249,7 +269,7 @@ private:
MCInst Inst;
uint64_t Size;
if (!decodeInst(Symbol, Inst, Size))
if (!decodeInst(Symbol, Inst, Size, Offset))
return std::make_pair(
EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),
"");
@ -307,7 +327,7 @@ private:
MCInst Inst;
uint64_t InstSize;
if (!decodeInst(Symbol, Inst, InstSize))
if (!decodeInst(Symbol, Inst, InstSize, 0))
return std::make_pair(
EvalResult(("Couldn't decode instruction at '" + Symbol + "'").str()),
"");
@ -664,10 +684,14 @@ private:
return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx);
}
bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const {
bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size,
int64_t Offset) const {
MCDisassembler *Dis = Checker.Disassembler;
StringRef SymbolMem = Checker.getSymbolContent(Symbol);
ArrayRef<uint8_t> SymbolBytes(SymbolMem.bytes_begin(), SymbolMem.size());
if (SymbolMem.size() <= Offset)
return false;
ArrayRef<uint8_t> SymbolBytes(SymbolMem.bytes_begin() + Offset,
SymbolMem.size() - Offset);
MCDisassembler::DecodeStatus S =
Dis->getInstruction(Inst, Size, SymbolBytes, 0, nulls());
@ -675,7 +699,7 @@ private:
return (S == MCDisassembler::Success);
}
};
}
} // namespace llvm
RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(
IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo,

View File

@ -21,7 +21,8 @@ main:
.size main, .-main
# Test R_RISCV_PCREL_HI20 and R_RISCV_PCREL_LO
# jitlink-check: decode_operand(test_pcrel32, 1) = ((named_data - test_pcrel32) + 0x800)[31:12]
# jitlink-check: decode_operand(test_pcrel32, 1) = ((named_data - test_pcrel32) + 0x800)[31:12]
# jitlink-check: decode_operand(test_pcrel32+4, 2)[11:0] = (named_data - test_pcrel32)[11:0]
.globl test_pcrel32
.p2align 1
.type test_pcrel32,@function