diff --git a/runtime/vm/compiler/assembler/assembler_riscv_test.cc b/runtime/vm/compiler/assembler/assembler_riscv_test.cc index 1723d257ba7..858aa0bc96b 100644 --- a/runtime/vm/compiler/assembler/assembler_riscv_test.cc +++ b/runtime/vm/compiler/assembler/assembler_riscv_test.cc @@ -9206,6 +9206,46 @@ ASSEMBLER_TEST_RUN(ShadowStackLongJump, test) { #endif } +ASSEMBLER_TEST_GENERATE(LandingPads, assembler) { + __ SetExtensions(RV_G); + /* 00 */ __ lui(T2, 123 << 12); + /* 04 */ __ addi(T2, T2, 456); // Ignored. + /* 08 */ __ jr(A1, 16); + /* 12 */ __ trap(); + /* 16 */ __ auipc(ZR, 123 << 12); + /* 20 */ __ jr(A1, 28); + /* 24 */ __ trap(); + /* 28 */ __ auipc(ZR, 0); + /* 32 */ __ mv(T2, A1); + /* 36 */ __ jr(T2, 44); + /* 40 */ __ trap(); + /* 44 */ __ ret(); +} +ASSEMBLER_TEST_RUN(LandingPads, test) { + EXPECT_DISASSEMBLY( + "0007b3b7 lui t2, 503808\n" + "1c838393 addi t2, t2, 456\n" + "01058067 jr 16(a1)\n" + "00000000 trap\n" + "0007b017 lpad 503808\n" + "01c58067 jr 28(a1)\n" + "00000000 trap\n" + "00000017 lpad 0\n" + "00058393 mv t2, a1\n" + "02c38067 jr 44(t2)\n" + "00000000 trap\n" + "00008067 ret\n"); + +#if defined(DART_INCLUDE_SIMULATOR) + Simulator::Current()->set_lp_enabled(true); + EXPECT_EQ(0, Call(test->entry(), 0, test->entry())); + Simulator::Current()->set_lp_enabled(false); + EXPECT_EQ(0, Call(test->entry(), 0, test->entry())); +#else + EXPECT_EQ(0, Call(test->entry(), 0, test->entry())); +#endif +} + ASSEMBLER_TEST_GENERATE(LoadImmediate_MaxInt32, assembler) { __ SetExtensions(RV_GC); __ LoadImmediate(A0, kMaxInt32); diff --git a/runtime/vm/simulator_riscv.cc b/runtime/vm/simulator_riscv.cc index 0e0789eccd6..cc818ef8c4c 100644 --- a/runtime/vm/simulator_riscv.cc +++ b/runtime/vm/simulator_riscv.cc @@ -1049,6 +1049,7 @@ void Simulator::Interpret(CInstr instr) { uintx_t target = get_xreg(instr.rs1()); set_xreg(RA, pc_ + instr.length()); pc_ = target; + CheckLandingPad(instr.rs1()); return; } else { // ADD @@ -1063,6 +1064,7 @@ void Simulator::Interpret(CInstr instr) { } else { // JR pc_ = get_xreg(instr.rs1()); + CheckLandingPad(instr.rs1()); return; } } @@ -1295,6 +1297,7 @@ void Simulator::InterpretJALR(Instr instr) { uintx_t offset = static_cast(instr.itype_imm()); set_xreg(instr.rd(), pc_ + instr.length()); pc_ = base + offset; + CheckLandingPad(instr.rs1()); } DART_FORCE_INLINE @@ -3722,6 +3725,24 @@ void Simulator::Fault(const char* message) { FATAL("%s", message); } +void Simulator::CheckLandingPad(Register rs1) { + if (!lp_enabled_) return; + if ((rs1 == Register(1)) || (rs1 == Register(5)) || (rs1 == Register(7))) { + return; + } + if ((pc_ & 3) != 0) { + Fault("Landing pad misaligned"); + } + Instr instr(*reinterpret_cast(pc_)); + if ((instr.opcode() != AUIPC) || (instr.rd() != ZR)) { + Fault("Landing pad expected"); + } + uintx_t label = instr.utype_imm(); + if ((label != 0) && ((label ^ get_xreg(Register(7))) & 0xFFFFF000) != 0) { + Fault("Landing pad mismatch"); + } +} + template type Simulator::MemoryRead(uintx_t addr, Register base) { #if defined(DEBUG) diff --git a/runtime/vm/simulator_riscv.h b/runtime/vm/simulator_riscv.h index dd32eebc897..7a5afddaefd 100644 --- a/runtime/vm/simulator_riscv.h +++ b/runtime/vm/simulator_riscv.h @@ -200,6 +200,7 @@ class Simulator { uintx_t get_sp() const { return get_xreg(SP); } uintx_t get_fp() const { return get_xreg(FP); } uintx_t get_lr() const { return get_xreg(RA); } + void set_lp_enabled(bool value) { lp_enabled_ = value; } void set_ss_enabled(bool value) { ss_enabled_ = value; } void PrintRegisters(); void PrintStack(); @@ -319,6 +320,8 @@ class Simulator { DART_NORETURN void IllegalInstruction(CInstr instr); DART_NORETURN void Fault(const char* message); + void CheckLandingPad(Register rs1); + template type MemoryRead(uintx_t address, Register base); template @@ -396,7 +399,8 @@ class Simulator { double fregs_[kNumberOfFpuRegisters]; uint32_t fcsr_ = 0; - // Zicfissp state + // Zicfilp/ss state + bool lp_enabled_ = false; bool ss_enabled_ = false; uintx_t ssp_ = 0;