brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.3 KiB · c6bfe0f Raw
181 lines · cpp
1//===-- TestAArch64Emulator.cpp ------------------------------------------===//2 3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#include "gtest/gtest.h"11 12#include "lldb/Core/Address.h"13#include "lldb/Core/Disassembler.h"14#include "lldb/Target/ExecutionContext.h"15#include "lldb/Utility/ArchSpec.h"16#include "lldb/Utility/RegisterValue.h"17 18#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"19#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"20#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"21 22using namespace lldb;23using namespace lldb_private;24 25struct Arch64EmulatorTester : public EmulateInstructionARM64 {26  RegisterInfoPOSIX_arm64::GPR gpr;27  uint8_t memory[64] = {0};28  uint64_t memory_offset = 0;29 30  Arch64EmulatorTester()31      : EmulateInstructionARM64(ArchSpec("arm64-apple-ios")) {32    memset(&gpr, 0, sizeof(gpr));33    EmulateInstruction::SetCallbacks(ReadMemoryCallback, WriteMemoryCallback,34                                     ReadRegisterCallback,35                                     WriteRegisterCallback);36  }37 38  static bool ReadRegisterCallback(EmulateInstruction *instruction, void *baton,39                                   const RegisterInfo *reg_info,40                                   RegisterValue &reg_value) {41    auto *tester = static_cast<Arch64EmulatorTester *>(instruction);42    uint32_t reg = reg_info->kinds[eRegisterKindLLDB];43    if (reg >= gpr_x0_arm64 && reg <= gpr_x28_arm64) {44      reg_value.SetUInt64(tester->gpr.x[reg - gpr_x0_arm64]);45      return true;46    }47    if (reg >= gpr_w0_arm64 && reg <= gpr_w28_arm64) {48      reg_value.SetUInt32(tester->gpr.x[reg - gpr_w0_arm64]);49      return true;50    }51    switch (reg) {52    case gpr_fp_arm64:53      reg_value.SetUInt64(tester->gpr.fp);54      return true;55    case gpr_lr_arm64:56      reg_value.SetUInt64(tester->gpr.lr);57      return true;58    case gpr_sp_arm64:59      reg_value.SetUInt64(tester->gpr.sp);60      return true;61    case gpr_pc_arm64:62      reg_value.SetUInt64(tester->gpr.pc);63      return true;64    case gpr_cpsr_arm64:65      reg_value.SetUInt32(tester->gpr.cpsr);66      return true;67    default:68      return false;69    }70  }71 72  static bool WriteRegisterCallback(EmulateInstruction *instruction,73                                    void *baton, const Context &context,74                                    const RegisterInfo *reg_info,75                                    const RegisterValue &reg_value) {76    auto *tester = static_cast<Arch64EmulatorTester *>(instruction);77    uint32_t reg = reg_info->kinds[eRegisterKindLLDB];78    if (reg >= gpr_x0_arm64 && reg <= gpr_x28_arm64) {79      tester->gpr.x[reg - gpr_x0_arm64] = reg_value.GetAsUInt64();80      return true;81    }82    if (reg >= gpr_w0_arm64 && reg <= gpr_w28_arm64) {83      tester->gpr.x[reg - gpr_w0_arm64] = reg_value.GetAsUInt32();84      return true;85    }86    switch (reg) {87    case gpr_fp_arm64:88      tester->gpr.fp = reg_value.GetAsUInt64();89      return true;90    case gpr_lr_arm64:91      tester->gpr.lr = reg_value.GetAsUInt64();92      return true;93    case gpr_sp_arm64:94      tester->gpr.sp = reg_value.GetAsUInt64();95      return true;96    case gpr_pc_arm64:97      tester->gpr.pc = reg_value.GetAsUInt64();98      return true;99    case gpr_cpsr_arm64:100      tester->gpr.cpsr = reg_value.GetAsUInt32();101      return true;102    default:103      return false;104    }105  }106 107  static size_t ReadMemoryCallback(EmulateInstruction *instruction, void *baton,108                                   const Context &context, addr_t addr,109                                   void *dst, size_t length) {110    auto *tester = static_cast<Arch64EmulatorTester *>(instruction);111    assert(addr >= tester->memory_offset);112    assert(addr - tester->memory_offset + length <= sizeof(tester->memory));113    if (addr >= tester->memory_offset &&114        addr - tester->memory_offset + length <= sizeof(tester->memory)) {115      memcpy(dst, tester->memory + (addr - tester->memory_offset), length);116      return length;117    }118    return 0;119  };120 121  static size_t WriteMemoryCallback(EmulateInstruction *instruction,122                                    void *baton, const Context &context,123                                    addr_t addr, const void *dst,124                                    size_t length) {125    llvm_unreachable("implement when required");126    return 0;127  };128 129  static uint64_t AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bool carry_in,130                               EmulateInstructionARM64::ProcState &proc_state) {131    return EmulateInstructionARM64::AddWithCarry(N, x, y, carry_in, proc_state);132  }133};134 135class TestAArch64Emulator : public testing::Test {136public:137  static void SetUpTestCase();138  static void TearDownTestCase();139 140protected:141};142 143void TestAArch64Emulator::SetUpTestCase() {144  EmulateInstructionARM64::Initialize();145}146 147void TestAArch64Emulator::TearDownTestCase() {148  EmulateInstructionARM64::Terminate();149}150 151TEST_F(TestAArch64Emulator, TestOverflow) {152  EmulateInstructionARM64::ProcState pstate;153  memset(&pstate, 0, sizeof(pstate));154  uint64_t ll_max = std::numeric_limits<int64_t>::max();155  Arch64EmulatorTester emu;156  ASSERT_EQ(emu.AddWithCarry(64, ll_max, 0, 0, pstate), ll_max);157  ASSERT_EQ(pstate.V, 0ULL);158  ASSERT_EQ(pstate.C, 0ULL);159  ASSERT_EQ(emu.AddWithCarry(64, ll_max, 1, 0, pstate), (uint64_t)(ll_max + 1));160  ASSERT_EQ(pstate.V, 1ULL);161  ASSERT_EQ(pstate.C, 0ULL);162  ASSERT_EQ(emu.AddWithCarry(64, ll_max, 0, 1, pstate), (uint64_t)(ll_max + 1));163  ASSERT_EQ(pstate.V, 1ULL);164  ASSERT_EQ(pstate.C, 0ULL);165}166 167TEST_F(TestAArch64Emulator, TestAutoAdvancePC) {168  Arch64EmulatorTester emu;169  emu.memory_offset = 0x123456789abcde00;170  emu.gpr.pc = 0x123456789abcde00;171  emu.gpr.x[8] = 0x123456789abcde20;172  memcpy(emu.memory, "\x08\x01\x40\xb9", 4);        // ldr w8, [x8]173  memcpy(emu.memory + 0x20, "\x11\x22\x33\x44", 4); // 0x44332211174  ASSERT_TRUE(emu.ReadInstruction());175  ASSERT_TRUE(176      emu.EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC |177                              eEmulateInstructionOptionIgnoreConditions));178  ASSERT_EQ(emu.gpr.pc, (uint64_t)0x123456789abcde04);179  ASSERT_EQ(emu.gpr.x[8], (uint64_t)0x44332211);180}181