diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp @@ -232,6 +232,26 @@ 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: + case BinOpToken::Sub: { + EvalResult Number; + std::tie(Number, RemainingExpr) = evalNumberExpr(RemainingExpr); + Offset = + BinOp == BinOpToken::Add ? Number.getValue() : -Number.getValue(); + break; + } + case BinOpToken::Invalid: + break; + default: + return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, + "expected '+ or -' for offset or ',' if no offset"), ""); + } + if (!RemainingExpr.startswith(",")) return std::make_pair( unexpectedToken(RemainingExpr, RemainingExpr, "expected ','"), ""); @@ -249,7 +269,7 @@ 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 @@ 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 @@ 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 SymbolBytes(SymbolMem.bytes_begin(), SymbolMem.size()); + if (SymbolMem.size() < Offset + Size) + return false; + ArrayRef SymbolBytes(SymbolMem.bytes_begin() + Offset, + SymbolMem.size() - Offset); MCDisassembler::DecodeStatus S = Dis->getInstruction(Inst, Size, SymbolBytes, 0, nulls()); @@ -675,7 +699,7 @@ return (S == MCDisassembler::Success); } }; -} +} // namespace llvm RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl( IsSymbolValidFunction IsSymbolValid, GetSymbolInfoFunction GetSymbolInfo, diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s --- a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s @@ -18,7 +18,8 @@ .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