259 lines · cpp
1//===-- TestPPC64InstEmulation.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 <vector>12 13#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"14 15#include "lldb/Core/Address.h"16#include "lldb/Core/AddressRange.h"17#include "lldb/Symbol/UnwindPlan.h"18#include "lldb/Target/UnwindAssembly.h"19#include "lldb/Utility/ArchSpec.h"20 21#include "Plugins/Disassembler/LLVMC/DisassemblerLLVMC.h"22#include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h"23#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"24#include "llvm/Support/TargetSelect.h"25 26using namespace lldb;27using namespace lldb_private;28 29class TestPPC64InstEmulation : public testing::Test {30public:31 static void SetUpTestCase();32 static void TearDownTestCase();33 34 // virtual void SetUp() override { }35 // virtual void TearDown() override { }36 37protected:38};39 40void TestPPC64InstEmulation::SetUpTestCase() {41 llvm::InitializeAllTargets();42 llvm::InitializeAllAsmPrinters();43 llvm::InitializeAllTargetMCs();44 llvm::InitializeAllDisassemblers();45 DisassemblerLLVMC::Initialize();46 EmulateInstructionPPC64::Initialize();47}48 49void TestPPC64InstEmulation::TearDownTestCase() {50 DisassemblerLLVMC::Terminate();51 EmulateInstructionPPC64::Terminate();52}53 54TEST_F(TestPPC64InstEmulation, TestSimpleFunction) {55 ArchSpec arch("powerpc64le-linux-gnu");56 std::unique_ptr<UnwindAssemblyInstEmulation> engine(57 static_cast<UnwindAssemblyInstEmulation *>(58 UnwindAssemblyInstEmulation::CreateInstance(arch)));59 ASSERT_NE(nullptr, engine);60 61 const UnwindPlan::Row *row;62 AddressRange sample_range;63 UnwindPlan unwind_plan(eRegisterKindLLDB);64 UnwindPlan::Row::AbstractRegisterLocation regloc;65 66 // prologue and epilogue of:67 // int main() {68 // int i = test();69 // return i;70 // }71 //72 // compiled with clang -O0 -g73 uint8_t data[] = {74 // prologue75 0x02, 0x10, 0x40, 0x3c, // 0: lis r2, 409876 0x00, 0x7f, 0x42, 0x38, // 4: addi r2, r2, 3251277 0xa6, 0x02, 0x08, 0x7c, // 8: mflr r078 0xf8, 0xff, 0xe1, 0xfb, // 12: std r31, -8(r1)79 0x10, 0x00, 0x01, 0xf8, // 16: std r0, 16(r1)80 0x91, 0xff, 0x21, 0xf8, // 20: stdu r1, -112(r1)81 0x78, 0x0b, 0x3f, 0x7c, // 24: mr r31, r182 0x00, 0x00, 0x60, 0x38, // 28: li r3, 083 0x64, 0x00, 0x7f, 0x90, // 32: stw r3, 100(r31)84 85 // epilogue86 0x70, 0x00, 0x21, 0x38, // 36: addi r1, r1, 11287 0x10, 0x00, 0x01, 0xe8, // 40: ld r0, 16(r1)88 0xf8, 0xff, 0xe1, 0xeb, // 44: ld r31, -8(r1)89 0xa6, 0x03, 0x08, 0x7c, // 48: mtlr r090 0x20, 0x00, 0x80, 0x4e // 52: blr91 };92 93 sample_range = AddressRange(0x1000, sizeof(data));94 95 EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(96 sample_range, data, sizeof(data), unwind_plan));97 98 // 0: CFA=sp+099 row = unwind_plan.GetRowForFunctionOffset(0);100 EXPECT_EQ(0, row->GetOffset());101 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);102 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);103 EXPECT_EQ(0, row->GetCFAValue().GetOffset());104 105 // 1: CFA=sp+0 => fp=[CFA-8]106 row = unwind_plan.GetRowForFunctionOffset(16);107 EXPECT_EQ(16, row->GetOffset());108 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);109 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);110 EXPECT_EQ(0, row->GetCFAValue().GetOffset());111 112 EXPECT_TRUE(row->GetRegisterInfo(gpr_r31_ppc64le, regloc));113 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());114 EXPECT_EQ(-8, regloc.GetOffset());115 116 // 2: CFA=sp+0 => fp=[CFA-8] lr=[CFA+16]117 row = unwind_plan.GetRowForFunctionOffset(20);118 EXPECT_EQ(20, row->GetOffset());119 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);120 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);121 EXPECT_EQ(0, row->GetCFAValue().GetOffset());122 123 EXPECT_TRUE(row->GetRegisterInfo(gpr_lr_ppc64le, regloc));124 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());125 EXPECT_EQ(16, regloc.GetOffset());126 127 // 3: CFA=sp+112 => fp=[CFA-8] lr=[CFA+16]128 row = unwind_plan.GetRowForFunctionOffset(24);129 EXPECT_EQ(24, row->GetOffset());130 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);131 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);132 EXPECT_EQ(112, row->GetCFAValue().GetOffset());133 134 EXPECT_TRUE(row->GetRegisterInfo(gpr_r31_ppc64le, regloc));135 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());136 EXPECT_EQ(-8, regloc.GetOffset());137 138 EXPECT_TRUE(row->GetRegisterInfo(gpr_lr_ppc64le, regloc));139 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());140 EXPECT_EQ(16, regloc.GetOffset());141 142 // 4: CFA=r31+112 => fp=[CFA-8] lr=[CFA+16]143 row = unwind_plan.GetRowForFunctionOffset(28);144 EXPECT_EQ(28, row->GetOffset());145 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r31_ppc64le);146 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);147 EXPECT_EQ(112, row->GetCFAValue().GetOffset());148 149 EXPECT_TRUE(row->GetRegisterInfo(gpr_r31_ppc64le, regloc));150 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());151 EXPECT_EQ(-8, regloc.GetOffset());152 153 EXPECT_TRUE(row->GetRegisterInfo(gpr_lr_ppc64le, regloc));154 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());155 EXPECT_EQ(16, regloc.GetOffset());156 157 // 5: CFA=sp+0 => fp=[CFA-8] lr=[CFA+16]158 row = unwind_plan.GetRowForFunctionOffset(40);159 EXPECT_EQ(40, row->GetOffset());160 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);161 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);162 EXPECT_EQ(0, row->GetCFAValue().GetOffset());163 164 EXPECT_TRUE(row->GetRegisterInfo(gpr_r31_ppc64le, regloc));165 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());166 EXPECT_EQ(-8, regloc.GetOffset());167 168 EXPECT_TRUE(row->GetRegisterInfo(gpr_lr_ppc64le, regloc));169 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());170 EXPECT_EQ(16, regloc.GetOffset());171}172 173TEST_F(TestPPC64InstEmulation, TestMediumFunction) {174 ArchSpec arch("powerpc64le-linux-gnu");175 std::unique_ptr<UnwindAssemblyInstEmulation> engine(176 static_cast<UnwindAssemblyInstEmulation *>(177 UnwindAssemblyInstEmulation::CreateInstance(arch)));178 ASSERT_NE(nullptr, engine);179 180 const UnwindPlan::Row *row;181 AddressRange sample_range;182 UnwindPlan unwind_plan(eRegisterKindLLDB);183 UnwindPlan::Row::AbstractRegisterLocation regloc;184 185 // prologue and epilogue of main() (call-func.c),186 // with several calls and stack variables.187 //188 // compiled with clang -O0 -g189 uint8_t data[] = {190 // prologue191 0xa6, 0x02, 0x08, 0x7c, // 0: mflr r0192 0xf8, 0xff, 0xe1, 0xfb, // 4: std r31, -8(r1)193 0x10, 0x00, 0x01, 0xf8, // 8: std r0, 16(r1)194 0x78, 0x0b, 0x3e, 0x7c, // 12: mr r30, r1195 0xe0, 0x06, 0x20, 0x78, // 16: clrldi r0, r1, 59196 0xa0, 0xfa, 0x00, 0x20, // 20: subfic r0, r0, -1376197 0x6a, 0x01, 0x21, 0x7c, // 24: stdux r1, r1, r0198 0x78, 0x0b, 0x3f, 0x7c, // 28: mr r31, r1199 200 // epilogue201 0x00, 0x00, 0x21, 0xe8, // 32: ld r1, 0(r1)202 0x20, 0x00, 0x80, 0x4e // 36: blr203 };204 205 sample_range = AddressRange(0x1000, sizeof(data));206 207 EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(208 sample_range, data, sizeof(data), unwind_plan));209 210 // 0: CFA=sp+0211 row = unwind_plan.GetRowForFunctionOffset(0);212 EXPECT_EQ(0, row->GetOffset());213 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);214 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);215 EXPECT_EQ(0, row->GetCFAValue().GetOffset());216 217 // 1: CFA=sp+0 => fp=[CFA-8]218 row = unwind_plan.GetRowForFunctionOffset(8);219 EXPECT_EQ(8, row->GetOffset());220 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);221 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);222 EXPECT_EQ(0, row->GetCFAValue().GetOffset());223 224 EXPECT_TRUE(row->GetRegisterInfo(gpr_r31_ppc64le, regloc));225 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());226 EXPECT_EQ(-8, regloc.GetOffset());227 228 // 2: CFA=sp+0 => fp=[CFA-8] lr=[CFA+16]229 row = unwind_plan.GetRowForFunctionOffset(12);230 EXPECT_EQ(12, row->GetOffset());231 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);232 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);233 EXPECT_EQ(0, row->GetCFAValue().GetOffset());234 235 EXPECT_TRUE(row->GetRegisterInfo(gpr_lr_ppc64le, regloc));236 EXPECT_TRUE(regloc.IsAtCFAPlusOffset());237 EXPECT_EQ(16, regloc.GetOffset());238 239 // 3: CFA=r30240 row = unwind_plan.GetRowForFunctionOffset(16);241 EXPECT_EQ(16, row->GetOffset());242 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r30_ppc64le);243 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);244 EXPECT_EQ(0, row->GetCFAValue().GetOffset());245 246 row = unwind_plan.GetRowForFunctionOffset(32);247 EXPECT_EQ(16, row->GetOffset());248 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r30_ppc64le);249 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);250 EXPECT_EQ(0, row->GetCFAValue().GetOffset());251 252 // 4: CFA=sp+0253 row = unwind_plan.GetRowForFunctionOffset(36);254 EXPECT_EQ(36, row->GetOffset());255 EXPECT_TRUE(row->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);256 EXPECT_TRUE(row->GetCFAValue().IsRegisterPlusOffset() == true);257 EXPECT_EQ(0, row->GetCFAValue().GetOffset());258}259