189 lines · cpp
1//===-- TestRiscvInstEmulation.cpp ----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "gtest/gtest.h"10 11#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"12 13#include "lldb/Core/AddressRange.h"14#include "lldb/Symbol/UnwindPlan.h"15#include "lldb/Utility/ArchSpec.h"16 17#include "Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h"18#include "Plugins/Instruction/RISCV/EmulateInstructionRISCV.h"19#include "Plugins/Process/Utility/lldb-riscv-register-enums.h"20#include "llvm/Support/TargetSelect.h"21 22using namespace lldb;23using namespace lldb_private;24 25class TestRiscvInstEmulation : public testing::Test {26public:27 static void SetUpTestCase();28 static void TearDownTestCase();29 30protected:31};32 33void TestRiscvInstEmulation::SetUpTestCase() {34 llvm::InitializeAllTargets();35 llvm::InitializeAllAsmPrinters();36 llvm::InitializeAllTargetMCs();37 llvm::InitializeAllDisassemblers();38 DisassemblerLLVMC::Initialize();39 EmulateInstructionRISCV::Initialize();40}41 42void TestRiscvInstEmulation::TearDownTestCase() {43 DisassemblerLLVMC::Terminate();44 EmulateInstructionRISCV::Terminate();45}46 47TEST_F(TestRiscvInstEmulation, TestSimpleRiscvFunction) {48 ArchSpec arch("riscv64-unknown-linux-gnu");49 // Enable compressed instruction support (RVC extension).50 arch.SetFlags(ArchSpec::eRISCV_rvc);51 std::unique_ptr<UnwindAssemblyInstEmulation> engine(52 static_cast<UnwindAssemblyInstEmulation *>(53 UnwindAssemblyInstEmulation::CreateInstance(arch)));54 ASSERT_NE(nullptr, engine);55 56 // RISC-V function with compressed and uncompressed instructions57 // 0x0000: 1141 addi sp, sp, -0x1058 // 0x0002: e406 sd ra, 0x8(sp)59 // 0x0004: e022 sd s0, 0x0(sp)60 // 0x0006: 0800 addi s0, sp, 0x1061 // 0x0008: 00000537 lui a0, 0x062 // 0x000C: 00050513 mv a0, a063 // 0x0010: 00000097 auipc ra, 0x064 // 0x0014: 000080e7 jalr ra <main+0x10>65 // 0x0018: 4501 li a0, 0x066 // 0x001A: ff040113 addi sp, s0, -0x1067 // 0x001E: 60a2 ld ra, 0x8(sp)68 // 0x0020: 6402 ld s0, 0x0(sp)69 // 0x0022: 0141 addi sp, sp, 0x1070 // 0x0024: 8082 ret71 uint8_t data[] = {// 0x0000: 1141 addi sp, sp, -0x1072 0x41, 0x11,73 // 0x0002: e406 sd ra, 0x8(sp)74 0x06, 0xE4,75 // 0x0004: e022 sd s0, 0x0(sp)76 0x22, 0xE0,77 // 0x0006: 0800 addi s0, sp, 0x1078 0x00, 0x08,79 // 0x0008: 00000537 lui a0, 0x080 0x37, 0x05, 0x00, 0x00,81 // 0x000C: 00050513 mv a0, a082 0x13, 0x05, 0x05, 0x00,83 // 0x0010: 00000097 auipc ra, 0x084 0x97, 0x00, 0x00, 0x00,85 // 0x0014: 000080e7 jalr ra <main+0x10>86 0xE7, 0x80, 0x00, 0x00,87 // 0x0018: 4501 li a0, 0x088 0x01, 0x45,89 // 0x001A: ff040113 addi sp, s0, -0x1090 0x13, 0x01, 0x04, 0xFF,91 // 0x001E: 60a2 ld ra, 0x8(sp)92 0xA2, 0x60,93 // 0x0020: 6402 ld s0, 0x0(sp)94 0x02, 0x64,95 // 0x0022: 0141 addi sp, sp, 0x1096 0x41, 0x01,97 // 0x0024: 8082 ret98 0x82, 0x80};99 100 // Expected UnwindPlan (prologue only - emulation stops after frame setup):101 // row[0]: 0: CFA=sp+0 => fp= <same> ra= <same>102 // row[1]: 2: CFA=sp+16 => fp= <same> ra= <same> (after stack103 // allocation) row[2]: 4: CFA=sp+16 => fp= <same> ra=[CFA-8]104 // (after saving ra) row[3]: 6: CFA=sp+16 => fp=[CFA-16] ra=[CFA-8]105 // (after saving s0/fp) row[4]: 8: CFA=s0+0 => fp=[CFA-16] ra=[CFA-8]106 // (after setting frame pointer: s0=sp+16)107 108 const UnwindPlan::Row *row;109 AddressRange sample_range;110 UnwindPlan unwind_plan(eRegisterKindLLDB);111 UnwindPlan::Row::AbstractRegisterLocation regloc;112 sample_range = AddressRange(0x1000, sizeof(data));113 114 EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(115 sample_range, data, sizeof(data), unwind_plan));116 117 // CFA=sp+0 => fp=<same> ra=<same>.118 row = unwind_plan.GetRowForFunctionOffset(0);119 EXPECT_EQ(0, row->GetOffset());120 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);121 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);122 EXPECT_EQ(0, row->GetCFAValue().GetOffset());123 124 EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));125 EXPECT_TRUE(regloc.IsSame());126 127 EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));128 EXPECT_TRUE(regloc.IsSame());129 130 // CFA=sp+16 => fp=<same> ra=<same>.131 row = unwind_plan.GetRowForFunctionOffset(2);132 EXPECT_EQ(2, row->GetOffset());133 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);134 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);135 EXPECT_EQ(16, row->GetCFAValue().GetOffset());136 137 EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));138 EXPECT_TRUE(regloc.IsSame());139 140 EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));141 EXPECT_TRUE(regloc.IsSame());142 143 // CFA=sp+16 => fp=<same> ra=[CFA-8].144 row = unwind_plan.GetRowForFunctionOffset(4);145 EXPECT_EQ(4, row->GetOffset());146 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);147 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);148 EXPECT_EQ(16, row->GetCFAValue().GetOffset());149 150 EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));151 EXPECT_TRUE(regloc.IsSame());152 153 EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));154 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());155 EXPECT_EQ(-8, regloc.GetOffset());156 157 // CFA=sp+16 => fp=[CFA-16] ra=[CFA-8]158 row = unwind_plan.GetRowForFunctionOffset(6);159 EXPECT_EQ(6, row->GetOffset());160 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_sp_riscv);161 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);162 EXPECT_EQ(16, row->GetCFAValue().GetOffset());163 164 EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));165 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());166 EXPECT_EQ(-16, regloc.GetOffset());167 168 EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));169 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());170 EXPECT_EQ(-8, regloc.GetOffset());171 172 // CFA=s0+0 => fp=[CFA-16] ra=[CFA-8]173 // s0 = sp + 16, so switching CFA to s0 does not change the effective174 // locations.175 row = unwind_plan.GetRowForFunctionOffset(8);176 EXPECT_EQ(8, row->GetOffset());177 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_fp_riscv);178 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);179 EXPECT_EQ(0, row->GetCFAValue().GetOffset());180 181 EXPECT_TRUE(row->GetRegisterInfo(gpr_fp_riscv, regloc));182 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());183 EXPECT_EQ(-16, regloc.GetOffset());184 185 EXPECT_TRUE(row->GetRegisterInfo(gpr_ra_riscv, regloc));186 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());187 EXPECT_EQ(-8, regloc.GetOffset());188}189