[Lldb-commits] [lldb] r326224 - [LLDB] Initial version of PPC64 InstEmulation
Pavel Labath via lldb-commits
lldb-commits at lists.llvm.org
Tue Feb 27 10:42:46 PST 2018
Author: labath
Date: Tue Feb 27 10:42:46 2018
New Revision: 326224
URL: http://llvm.org/viewvc/llvm-project?rev=326224&view=rev
Log:
[LLDB] Initial version of PPC64 InstEmulation
Summary: Supports common prologue/epilogue instructions.
Reviewers: clayborg, labath
Reviewed By: clayborg, labath
Subscribers: davide, anajuliapc, alexandreyy, lbianc, nemanjai, mgorny, kbarton
Differential Revision: https://reviews.llvm.org/D43345
Author: Leandro Lupori <leandro.lupori at gmail.com>
Added:
lldb/trunk/source/Plugins/Instruction/PPC64/
lldb/trunk/source/Plugins/Instruction/PPC64/CMakeLists.txt
lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
lldb/trunk/unittests/UnwindAssembly/ARM64/
lldb/trunk/unittests/UnwindAssembly/ARM64/CMakeLists.txt
lldb/trunk/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp
- copied, changed from r326218, lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp
lldb/trunk/unittests/UnwindAssembly/PPC64/
lldb/trunk/unittests/UnwindAssembly/PPC64/CMakeLists.txt
lldb/trunk/unittests/UnwindAssembly/PPC64/TestPPC64InstEmulation.cpp
Removed:
lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt
lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp
Modified:
lldb/trunk/source/API/SystemInitializerFull.cpp
lldb/trunk/source/Plugins/Instruction/CMakeLists.txt
lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp
lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt
Modified: lldb/trunk/source/API/SystemInitializerFull.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SystemInitializerFull.cpp?rev=326224&r1=326223&r2=326224&view=diff
==============================================================================
--- lldb/trunk/source/API/SystemInitializerFull.cpp (original)
+++ lldb/trunk/source/API/SystemInitializerFull.cpp Tue Feb 27 10:42:46 2018
@@ -50,6 +50,7 @@
#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
+#include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h"
#include "Plugins/InstrumentationRuntime/ASan/ASanRuntime.h"
#include "Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.h"
#include "Plugins/InstrumentationRuntime/TSan/TSanRuntime.h"
@@ -326,6 +327,7 @@ void SystemInitializerFull::Initialize()
UnwindAssemblyInstEmulation::Initialize();
UnwindAssembly_x86::Initialize();
EmulateInstructionARM64::Initialize();
+ EmulateInstructionPPC64::Initialize();
SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
AppleObjCRuntimeV2::Initialize();
@@ -451,6 +453,7 @@ void SystemInitializerFull::Terminate()
UnwindAssembly_x86::Terminate();
UnwindAssemblyInstEmulation::Terminate();
EmulateInstructionARM64::Terminate();
+ EmulateInstructionPPC64::Terminate();
SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
AppleObjCRuntimeV2::Terminate();
Modified: lldb/trunk/source/Plugins/Instruction/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/CMakeLists.txt?rev=326224&r1=326223&r2=326224&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Instruction/CMakeLists.txt Tue Feb 27 10:42:46 2018
@@ -2,3 +2,4 @@ add_subdirectory(ARM)
add_subdirectory(ARM64)
add_subdirectory(MIPS)
add_subdirectory(MIPS64)
+add_subdirectory(PPC64)
Added: lldb/trunk/source/Plugins/Instruction/PPC64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/PPC64/CMakeLists.txt?rev=326224&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/PPC64/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/Instruction/PPC64/CMakeLists.txt Tue Feb 27 10:42:46 2018
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginInstructionPPC64 PLUGIN
+ EmulateInstructionPPC64.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbInterpreter
+ lldbSymbol
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
+ )
Added: lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp?rev=326224&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp (added)
+++ lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp Tue Feb 27 10:42:46 2018
@@ -0,0 +1,406 @@
+//===-- EmulateInstructionPPC64.cpp ------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulateInstructionPPC64.h"
+
+#include <stdlib.h>
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/ConstString.h"
+
+#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
+
+#define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+EmulateInstructionPPC64::EmulateInstructionPPC64(const ArchSpec &arch)
+ : EmulateInstruction(arch) {}
+
+void EmulateInstructionPPC64::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+}
+
+void EmulateInstructionPPC64::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString EmulateInstructionPPC64::GetPluginNameStatic() {
+ ConstString g_plugin_name("lldb.emulate-instruction.ppc64");
+ return g_plugin_name;
+}
+
+ConstString EmulateInstructionPPC64::GetPluginName() {
+ static ConstString g_plugin_name("EmulateInstructionPPC64");
+ return g_plugin_name;
+}
+
+const char *EmulateInstructionPPC64::GetPluginDescriptionStatic() {
+ return "Emulate instructions for the PPC64 architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch,
+ InstructionType inst_type) {
+ if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic(
+ inst_type)) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64 ||
+ arch.GetTriple().getArch() == llvm::Triple::ppc64le) {
+ return new EmulateInstructionPPC64(arch);
+ }
+ }
+
+ return nullptr;
+}
+
+bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) {
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64)
+ return true;
+ else if (arch.GetTriple().getArch() == llvm::Triple::ppc64le)
+ return true;
+
+ return false;
+}
+
+static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo ®_info) {
+ if (reg_num >= llvm::array_lengthof(g_register_infos_ppc64le))
+ return false;
+ reg_info = g_register_infos_ppc64le[reg_num];
+ return true;
+}
+
+bool EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind,
+ uint32_t reg_num,
+ RegisterInfo ®_info) {
+ if (reg_kind == eRegisterKindGeneric) {
+ switch (reg_num) {
+ case LLDB_REGNUM_GENERIC_PC:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_pc_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_SP:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_r1_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_RA:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_lr_ppc64le;
+ break;
+ case LLDB_REGNUM_GENERIC_FLAGS:
+ reg_kind = eRegisterKindLLDB;
+ reg_num = gpr_cr_ppc64le;
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ if (reg_kind == eRegisterKindLLDB)
+ return LLDBTableGetRegisterInfo(reg_num, reg_info);
+ return false;
+}
+
+bool EmulateInstructionPPC64::ReadInstruction() {
+ bool success = false;
+ m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
+ LLDB_INVALID_ADDRESS, &success);
+ if (success) {
+ Context ctx;
+ ctx.type = eContextReadOpcode;
+ ctx.SetNoArgs();
+ m_opcode.SetOpcode32(ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success),
+ GetByteOrder());
+ }
+ if (!success)
+ m_addr = LLDB_INVALID_ADDRESS;
+ return success;
+}
+
+bool EmulateInstructionPPC64::CreateFunctionEntryUnwind(
+ UnwindPlan &unwind_plan) {
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind(eRegisterKindLLDB);
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our previous Call Frame Address is the stack pointer
+ row->GetCFAValue().SetIsRegisterPlusOffset(gpr_r1_ppc64le, 0);
+
+ unwind_plan.AppendRow(row);
+ unwind_plan.SetSourceName("EmulateInstructionPPC64");
+ unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le);
+ return true;
+}
+
+EmulateInstructionPPC64::Opcode *
+EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) {
+ static EmulateInstructionPPC64::Opcode g_opcodes[] = {
+ {0xfc0007ff, 0x7c0002a6, &EmulateInstructionPPC64::EmulateMFSPR,
+ "mfspr RT, SPR"},
+ {0xfc000003, 0xf8000000, &EmulateInstructionPPC64::EmulateSTD,
+ "std RS, DS(RA)"},
+ {0xfc000003, 0xf8000001, &EmulateInstructionPPC64::EmulateSTD,
+ "stdu RS, DS(RA)"},
+ {0xfc0007fe, 0x7c000378, &EmulateInstructionPPC64::EmulateOR,
+ "or RA, RS, RB"},
+ {0xfc000000, 0x38000000, &EmulateInstructionPPC64::EmulateADDI,
+ "addi RT, RA, SI"},
+ {0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD,
+ "ld RT, DS(RA)"}};
+ static const size_t k_num_ppc_opcodes = llvm::array_lengthof(g_opcodes);
+
+ for (size_t i = 0; i < k_num_ppc_opcodes; ++i) {
+ if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
+ return &g_opcodes[i];
+ }
+ return nullptr;
+}
+
+bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) {
+ const uint32_t opcode = m_opcode.GetOpcode32();
+ // LLDB_LOG(log, "PPC64::EvaluateInstruction: opcode={0:X+8}", opcode);
+ Opcode *opcode_data = GetOpcodeForInstruction(opcode);
+ if (!opcode_data)
+ return false;
+
+ // LLDB_LOG(log, "PPC64::EvaluateInstruction: {0}", opcode_data->name);
+ const bool auto_advance_pc =
+ evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+
+ bool success = false;
+
+ uint32_t orig_pc_value = 0;
+ if (auto_advance_pc) {
+ orig_pc_value =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ }
+
+ // Call the Emulate... function.
+ success = (this->*opcode_data->callback)(opcode);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc) {
+ uint32_t new_pc_value =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc && (new_pc_value == orig_pc_value)) {
+ EmulateInstruction::Context context;
+ context.type = eContextAdvancePC;
+ context.SetNoArgs();
+ if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_ppc64le,
+ orig_pc_value + 4))
+ return false;
+ }
+ }
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateMFSPR(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t spr = Bits32(opcode, 20, 11);
+
+ enum { SPR_LR = 0x100 };
+
+ // For now, we're only insterested in 'mfspr r0, lr'
+ if (rt != gpr_r0_ppc64le || spr != SPR_LR)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateMFSPR: {0:X+8}: mfspr r0, lr", m_addr);
+
+ bool success;
+ uint64_t lr =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ Context context;
+ context.type = eContextWriteRegisterRandomBits;
+ WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_r0_ppc64le, lr);
+ LLDB_LOG(log, "EmulateMFSPR: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateLD(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t ds = Bits32(opcode, 15, 2);
+
+ int32_t ids = llvm::SignExtend32<16>(ds << 2);
+
+ // For now, tracking only loads from 0(r1) to r1
+ // (0(r1) is the ABI defined location to save previous SP)
+ if (ra != gpr_r1_ppc64le || rt != gpr_r1_ppc64le || ids != 0)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateLD: {0:X+8}: ld r{1}, {2}(r{3})", m_addr, rt, ids, ra);
+
+ RegisterInfo r1_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
+ return false;
+
+ // restore SP
+ Context ctx;
+ ctx.type = eContextRestoreStackPointer;
+ ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
+
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0);
+ LLDB_LOG(log, "EmulateLD: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) {
+ uint32_t rs = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t ds = Bits32(opcode, 15, 2);
+ uint32_t u = Bits32(opcode, 1, 0);
+
+ // For now, tracking only stores to r1
+ if (ra != gpr_r1_ppc64le)
+ return false;
+ // ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr)
+ if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le &&
+ rs != gpr_r0_ppc64le)
+ return false;
+
+ bool success;
+ uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success);
+ if (!success)
+ return false;
+
+ int32_t ids = llvm::SignExtend32<16>(ds << 2);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr,
+ u ? "u" : "", rs, ids, ra);
+
+ // Make sure that r0 is really holding LR value
+ // (this won't catch unlikely cases, such as r0 being overwritten after mfspr)
+ uint32_t rs_num = rs;
+ if (rs == gpr_r0_ppc64le) {
+ uint64_t lr =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
+ if (!success || lr != rs_val)
+ return false;
+ rs_num = gpr_lr_ppc64le;
+ }
+
+ // set context
+ RegisterInfo rs_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, rs_num, rs_info))
+ return false;
+ RegisterInfo ra_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextPushRegisterOnStack;
+ ctx.SetRegisterToRegisterPlusOffset(rs_info, ra_info, ids);
+
+ // store
+ uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success);
+ if (!success)
+ return false;
+
+ lldb::addr_t addr = ra_val + ids;
+ WriteMemory(ctx, addr, &rs_val, sizeof(rs_val));
+
+ // update RA?
+ if (u) {
+ Context ctx;
+ // NOTE Currently, RA will always be equal to SP(r1)
+ ctx.type = eContextAdjustStackPointer;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr);
+ }
+
+ LLDB_LOG(log, "EmulateSTD: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) {
+ uint32_t rs = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t rb = Bits32(opcode, 15, 11);
+
+ // to be safe, process only the known 'mr r31/r30, r1' prologue instructions
+ if (m_fp != LLDB_INVALID_REGNUM || rs != rb ||
+ (ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le)
+ return false;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb);
+
+ // set context
+ RegisterInfo ra_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextSetFramePointer;
+ ctx.SetRegister(ra_info);
+
+ // move
+ bool success;
+ uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success);
+ if (!success)
+ return false;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val);
+ m_fp = ra;
+ LLDB_LOG(log, "EmulateOR: success!");
+ return true;
+}
+
+bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) {
+ uint32_t rt = Bits32(opcode, 25, 21);
+ uint32_t ra = Bits32(opcode, 20, 16);
+ uint32_t si = Bits32(opcode, 15, 0);
+
+ // handle stack adjustments only
+ // (this is a typical epilogue operation, with ra == r1. If it's
+ // something else, then we won't know the correct value of ra)
+ if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le)
+ return false;
+
+ int32_t si_val = llvm::SignExtend32<16>(si);
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
+ LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val);
+
+ // set context
+ RegisterInfo r1_info;
+ if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
+ return false;
+
+ Context ctx;
+ ctx.type = eContextRestoreStackPointer;
+ ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
+
+ // adjust SP
+ bool success;
+ uint64_t r1 =
+ ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success);
+ if (!success)
+ return false;
+ WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val);
+ LLDB_LOG(log, "EmulateADDI: success!");
+ return true;
+}
Added: lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h?rev=326224&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h (added)
+++ lldb/trunk/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h Tue Feb 27 10:42:46 2018
@@ -0,0 +1,97 @@
+//===-- EmulateInstructionPPC64.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EmulateInstructionPPC64_h_
+#define EmulateInstructionPPC64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Interpreter/OptionValue.h"
+#include "lldb/Utility/Log.h"
+
+namespace lldb_private {
+
+class EmulateInstructionPPC64 : public EmulateInstruction {
+public:
+ EmulateInstructionPPC64(const ArchSpec &arch);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static EmulateInstruction *CreateInstance(const ArchSpec &arch,
+ InstructionType inst_type);
+
+ static bool
+ SupportsEmulatingInstructionsOfTypeStatic(InstructionType inst_type) {
+ switch (inst_type) {
+ case eInstructionTypeAny:
+ case eInstructionTypePrologueEpilogue:
+ return true;
+
+ case eInstructionTypePCModifying:
+ case eInstructionTypeAll:
+ return false;
+ }
+ return false;
+ }
+
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override { return 1; }
+
+ bool SetTargetTriple(const ArchSpec &arch) override;
+
+ bool SupportsEmulatingInstructionsOfType(InstructionType inst_type) override {
+ return SupportsEmulatingInstructionsOfTypeStatic(inst_type);
+ }
+
+ bool ReadInstruction() override;
+
+ bool EvaluateInstruction(uint32_t evaluate_options) override;
+
+ bool TestEmulation(Stream *out_stream, ArchSpec &arch,
+ OptionValueDictionary *test_data) override {
+ return false;
+ }
+
+ bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num,
+ RegisterInfo ®_info) override;
+
+ bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) override;
+
+private:
+ struct Opcode {
+ uint32_t mask;
+ uint32_t value;
+ bool (EmulateInstructionPPC64::*callback)(uint32_t opcode);
+ const char *name;
+ };
+
+ uint32_t m_fp = LLDB_INVALID_REGNUM;
+
+ Opcode *GetOpcodeForInstruction(uint32_t opcode);
+
+ bool EmulateMFSPR(uint32_t opcode);
+ bool EmulateLD(uint32_t opcode);
+ bool EmulateSTD(uint32_t opcode);
+ bool EmulateOR(uint32_t opcode);
+ bool EmulateADDI(uint32_t opcode);
+};
+
+} // namespace lldb_private
+
+#endif // EmulateInstructionPPC64_h_
Modified: lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp?rev=326224&r1=326223&r2=326224&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp (original)
+++ lldb/trunk/tools/lldb-test/SystemInitializerTest.cpp Tue Feb 27 10:42:46 2018
@@ -40,6 +40,7 @@
#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
#include "Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h"
#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
+#include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h"
#include "Plugins/InstrumentationRuntime/ASan/ASanRuntime.h"
#include "Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.h"
#include "Plugins/InstrumentationRuntime/TSan/TSanRuntime.h"
@@ -180,6 +181,7 @@ void SystemInitializerTest::Initialize()
UnwindAssemblyInstEmulation::Initialize();
UnwindAssembly_x86::Initialize();
EmulateInstructionARM64::Initialize();
+ EmulateInstructionPPC64::Initialize();
SymbolFileDWARFDebugMap::Initialize();
ItaniumABILanguageRuntime::Initialize();
AppleObjCRuntimeV2::Initialize();
@@ -283,6 +285,7 @@ void SystemInitializerTest::Terminate()
UnwindAssembly_x86::Terminate();
UnwindAssemblyInstEmulation::Terminate();
EmulateInstructionARM64::Terminate();
+ EmulateInstructionPPC64::Terminate();
SymbolFileDWARFDebugMap::Terminate();
ItaniumABILanguageRuntime::Terminate();
AppleObjCRuntimeV2::Terminate();
Added: lldb/trunk/unittests/UnwindAssembly/ARM64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/ARM64/CMakeLists.txt?rev=326224&view=auto
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/ARM64/CMakeLists.txt (added)
+++ lldb/trunk/unittests/UnwindAssembly/ARM64/CMakeLists.txt Tue Feb 27 10:42:46 2018
@@ -0,0 +1,13 @@
+add_lldb_unittest(Arm64InstEmulationTests
+ TestArm64InstEmulation.cpp
+ LINK_LIBS
+ lldbCore
+ lldbSymbol
+ lldbTarget
+ lldbPluginUnwindAssemblyInstEmulation
+ lldbPluginDisassemblerLLVM
+ lldbPluginInstructionARM64
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
+ ${LLVM_TARGETS_TO_BUILD})
Copied: lldb/trunk/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp (from r326218, lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp?p2=lldb/trunk/unittests/UnwindAssembly/ARM64/TestArm64InstEmulation.cpp&p1=lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp&r1=326218&r2=326224&rev=326224&view=diff
==============================================================================
(empty)
Modified: lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt?rev=326224&r1=326223&r2=326224&view=diff
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt (original)
+++ lldb/trunk/unittests/UnwindAssembly/CMakeLists.txt Tue Feb 27 10:42:46 2018
@@ -1,5 +1,11 @@
+if ("AArch64" IN_LIST LLVM_TARGETS_TO_BUILD)
+ add_subdirectory(ARM64)
+endif()
+
+if ("PowerPC" IN_LIST LLVM_TARGETS_TO_BUILD)
+ add_subdirectory(PPC64)
+endif()
+
if ("X86" IN_LIST LLVM_TARGETS_TO_BUILD)
add_subdirectory(x86)
endif()
-
-add_subdirectory(InstEmulation)
Removed: lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt?rev=326223&view=auto
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt (original)
+++ lldb/trunk/unittests/UnwindAssembly/InstEmulation/CMakeLists.txt (removed)
@@ -1,15 +0,0 @@
-if ("AArch64" IN_LIST LLVM_TARGETS_TO_BUILD)
- add_lldb_unittest(InstEmulationTests
- TestArm64InstEmulation.cpp
- LINK_LIBS
- lldbCore
- lldbSymbol
- lldbTarget
- lldbPluginUnwindAssemblyInstEmulation
- lldbPluginDisassemblerLLVM
- lldbPluginInstructionARM64
- lldbPluginProcessUtility
- LINK_COMPONENTS
- Support
- ${LLVM_TARGETS_TO_BUILD})
-endif()
Removed: lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp?rev=326223&view=auto
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp (original)
+++ lldb/trunk/unittests/UnwindAssembly/InstEmulation/TestArm64InstEmulation.cpp (removed)
@@ -1,672 +0,0 @@
-//===-- TestArm64InstEmulation.cpp ------------------------------------*- C++
-//-*-===//
-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-
-#include <vector>
-
-#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
-
-#include "lldb/Core/Address.h"
-#include "lldb/Core/AddressRange.h"
-#include "lldb/Symbol/UnwindPlan.h"
-#include "lldb/Target/UnwindAssembly.h"
-#include "lldb/Utility/ArchSpec.h"
-
-#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
-#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
-#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
-#include "llvm/Support/TargetSelect.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-class TestArm64InstEmulation : public testing::Test {
-public:
- static void SetUpTestCase();
- static void TearDownTestCase();
-
- // virtual void SetUp() override { }
- // virtual void TearDown() override { }
-
-protected:
-};
-
-void TestArm64InstEmulation::SetUpTestCase() {
- llvm::InitializeAllTargets();
- llvm::InitializeAllAsmPrinters();
- llvm::InitializeAllTargetMCs();
- llvm::InitializeAllDisassemblers();
- DisassemblerLLVMC::Initialize();
- EmulateInstructionARM64::Initialize();
-}
-
-void TestArm64InstEmulation::TearDownTestCase() {
- DisassemblerLLVMC::Terminate();
- EmulateInstructionARM64::Terminate();
-}
-
-TEST_F(TestArm64InstEmulation, TestSimpleDarwinFunction) {
- ArchSpec arch("arm64-apple-ios10");
- std::unique_ptr<UnwindAssemblyInstEmulation> engine(
- static_cast<UnwindAssemblyInstEmulation *>(
- UnwindAssemblyInstEmulation::CreateInstance(arch)));
- ASSERT_NE(nullptr, engine);
-
- UnwindPlan::RowSP row_sp;
- AddressRange sample_range;
- UnwindPlan unwind_plan(eRegisterKindLLDB);
- UnwindPlan::Row::RegisterLocation regloc;
-
- // 'int main() { }' compiled for arm64-apple-ios with clang
- uint8_t data[] = {
- 0xfd, 0x7b, 0xbf, 0xa9, // 0xa9bf7bfd : stp x29, x30, [sp, #-0x10]!
- 0xfd, 0x03, 0x00, 0x91, // 0x910003fd : mov x29, sp
- 0xff, 0x43, 0x00, 0xd1, // 0xd10043ff : sub sp, sp, #0x10
-
- 0xbf, 0x03, 0x00, 0x91, // 0x910003bf : mov sp, x29
- 0xfd, 0x7b, 0xc1, 0xa8, // 0xa8c17bfd : ldp x29, x30, [sp], #16
- 0xc0, 0x03, 0x5f, 0xd6, // 0xd65f03c0 : ret
- };
-
- // UnwindPlan we expect:
-
- // row[0]: 0: CFA=sp +0 =>
- // row[1]: 4: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
- // row[2]: 8: CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
- // row[2]: 16: CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
- // row[3]: 20: CFA=sp +0 => fp= <same> lr= <same>
-
- sample_range = AddressRange(0x1000, sizeof(data));
-
- EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
- sample_range, data, sizeof(data), unwind_plan));
-
- // CFA=sp +0
- row_sp = unwind_plan.GetRowForFunctionOffset(0);
- EXPECT_EQ(0ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
- row_sp = unwind_plan.GetRowForFunctionOffset(4);
- EXPECT_EQ(4ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-16, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-8, regloc.GetOffset());
-
- // CFA=fp+16 => fp=[CFA-16] lr=[CFA-8]
- row_sp = unwind_plan.GetRowForFunctionOffset(8);
- EXPECT_EQ(8ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-16, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-8, regloc.GetOffset());
-
- // CFA=sp+16 => fp=[CFA-16] lr=[CFA-8]
- row_sp = unwind_plan.GetRowForFunctionOffset(16);
- EXPECT_EQ(16ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-16, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-8, regloc.GetOffset());
-
- // CFA=sp +0 => fp= <same> lr= <same>
- row_sp = unwind_plan.GetRowForFunctionOffset(20);
- EXPECT_EQ(20ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-}
-
-TEST_F(TestArm64InstEmulation, TestMediumDarwinFunction) {
- ArchSpec arch("arm64-apple-ios10");
- std::unique_ptr<UnwindAssemblyInstEmulation> engine(
- static_cast<UnwindAssemblyInstEmulation *>(
- UnwindAssemblyInstEmulation::CreateInstance(arch)));
- ASSERT_NE(nullptr, engine);
-
- UnwindPlan::RowSP row_sp;
- AddressRange sample_range;
- UnwindPlan unwind_plan(eRegisterKindLLDB);
- UnwindPlan::Row::RegisterLocation regloc;
-
- // disassembly of -[NSPlaceholderString initWithBytes:length:encoding:]
- // from Foundation for iOS.
- uint8_t data[] = {
- 0xf6, 0x57, 0xbd, 0xa9, // 0: 0xa9bd57f6 stp x22, x21, [sp, #-48]!
- 0xf4, 0x4f, 0x01, 0xa9, // 4: 0xa9014ff4 stp x20, x19, [sp, #16]
- 0xfd, 0x7b, 0x02, 0xa9, // 8: 0xa9027bfd stp x29, x30, [sp, #32]
- 0xfd, 0x83, 0x00, 0x91, // 12: 0x910083fd add x29, sp, #32
- 0xff, 0x43, 0x00, 0xd1, // 16: 0xd10043ff sub sp, sp, #16
-
- // [... function body ...]
- 0x1f, 0x20, 0x03, 0xd5, // 20: 0xd503201f nop
-
- 0xbf, 0x83, 0x00, 0xd1, // 24: 0xd10083bf sub sp, x29, #32
- 0xfd, 0x7b, 0x42, 0xa9, // 28: 0xa9427bfd ldp x29, x30, [sp, #32]
- 0xf4, 0x4f, 0x41, 0xa9, // 32: 0xa9414ff4 ldp x20, x19, [sp, #16]
- 0xf6, 0x57, 0xc3, 0xa8, // 36: 0xa8c357f6 ldp x22, x21, [sp], #48
- 0x01, 0x16, 0x09, 0x14, // 40: 0x14091601 b 0x18f640524 ; symbol stub
- // for: CFStringCreateWithBytes
- };
-
- // UnwindPlan we expect:
- // 0: CFA=sp +0 =>
- // 4: CFA=sp+48 => x21=[CFA-40] x22=[CFA-48]
- // 8: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // 12: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // fp=[CFA-16] lr=[CFA-8]
- // 16: CFA=fp+16 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // fp=[CFA-16] lr=[CFA-8]
-
- // [... function body ...]
-
- // 28: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // fp=[CFA-16] lr=[CFA-8]
- // 32: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] fp=
- // <same> lr= <same>
- // 36: CFA=sp+48 => x19= <same> x20= <same> x21=[CFA-40] x22=[CFA-48] fp=
- // <same> lr= <same>
- // 40: CFA=sp +0 => x19= <same> x20= <same> x21= <same> x22= <same> fp= <same>
- // lr= <same>
-
- sample_range = AddressRange(0x1000, sizeof(data));
-
- EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
- sample_range, data, sizeof(data), unwind_plan));
-
- // 0: CFA=sp +0 =>
- row_sp = unwind_plan.GetRowForFunctionOffset(0);
- EXPECT_EQ(0ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- // 4: CFA=sp+48 => x21=[CFA-40] x22=[CFA-48]
- row_sp = unwind_plan.GetRowForFunctionOffset(4);
- EXPECT_EQ(4ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-40, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-48, regloc.GetOffset());
-
- // 8: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- row_sp = unwind_plan.GetRowForFunctionOffset(8);
- EXPECT_EQ(8ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-24, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-32, regloc.GetOffset());
-
- // 12: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // fp=[CFA-16] lr=[CFA-8]
- row_sp = unwind_plan.GetRowForFunctionOffset(12);
- EXPECT_EQ(12ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-16, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-8, regloc.GetOffset());
-
- // 16: CFA=fp+16 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // fp=[CFA-16] lr=[CFA-8]
- row_sp = unwind_plan.GetRowForFunctionOffset(16);
- EXPECT_EQ(16ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
-
- // 28: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // fp=[CFA-16] lr=[CFA-8]
- row_sp = unwind_plan.GetRowForFunctionOffset(28);
- EXPECT_EQ(28ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(48, row_sp->GetCFAValue().GetOffset());
-
- // 32: CFA=sp+48 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48] fp=
- // <same> lr= <same>
- row_sp = unwind_plan.GetRowForFunctionOffset(32);
- EXPECT_EQ(32ull, row_sp->GetOffset());
-
- // I'd prefer if these restored registers were cleared entirely instead of set
- // to IsSame...
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
- EXPECT_TRUE(regloc.IsSame());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
- EXPECT_TRUE(regloc.IsSame());
-
- // 36: CFA=sp+48 => x19= <same> x20= <same> x21=[CFA-40] x22=[CFA-48] fp=
- // <same> lr= <same>
- row_sp = unwind_plan.GetRowForFunctionOffset(36);
- EXPECT_EQ(36ull, row_sp->GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc));
- EXPECT_TRUE(regloc.IsSame());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
- EXPECT_TRUE(regloc.IsSame());
-
- // 40: CFA=sp +0 => x19= <same> x20= <same> x21= <same> x22= <same> fp= <same>
- // lr= <same>
- row_sp = unwind_plan.GetRowForFunctionOffset(40);
- EXPECT_EQ(40ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc));
- EXPECT_TRUE(regloc.IsSame());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc));
- EXPECT_TRUE(regloc.IsSame());
-}
-
-TEST_F(TestArm64InstEmulation, TestFramelessThreeEpilogueFunction) {
- ArchSpec arch("arm64-apple-ios10");
- std::unique_ptr<UnwindAssemblyInstEmulation> engine(
- static_cast<UnwindAssemblyInstEmulation *>(
- UnwindAssemblyInstEmulation::CreateInstance(arch)));
- ASSERT_NE(nullptr, engine);
-
- UnwindPlan::RowSP row_sp;
- AddressRange sample_range;
- UnwindPlan unwind_plan(eRegisterKindLLDB);
- UnwindPlan::Row::RegisterLocation regloc;
-
- // disassembly of JSC::ARM64LogicalImmediate::findBitRange<16u>
- // from JavaScriptcore for iOS.
- uint8_t data[] = {
- 0x08, 0x3c, 0x0f, 0x53, // 0: 0x530f3c08 ubfx w8, w0, #15, #1
- 0x68, 0x00, 0x00, 0x39, // 4: 0x39000068 strb w8, [x3]
- 0x08, 0x3c, 0x40, 0xd2, // 8: 0xd2403c08 eor x8, x0, #0xffff
- 0x1f, 0x00, 0x71, 0xf2, // 12: 0xf271001f tst x0, #0x8000
-
- // [...]
-
- 0x3f, 0x01, 0x0c, 0xeb, // 16: 0xeb0c013f cmp x9, x12
- 0x81, 0x00, 0x00, 0x54, // 20: 0x54000081 b.ne +34
- 0x5f, 0x00, 0x00, 0xb9, // 24: 0xb900005f str wzr, [x2]
- 0xe0, 0x03, 0x00, 0x32, // 28: 0x320003e0 orr w0, wzr, #0x1
- 0xc0, 0x03, 0x5f, 0xd6, // 32: 0xd65f03c0 ret
- 0x89, 0x01, 0x09, 0xca, // 36: 0xca090189 eor x9, x12, x9
-
- // [...]
-
- 0x08, 0x05, 0x00, 0x11, // 40: 0x11000508 add w8, w8, #0x1
- 0x48, 0x00, 0x00, 0xb9, // 44: 0xb9000048 str w8, [x2]
- 0xe0, 0x03, 0x00, 0x32, // 48: 0x320003e0 orr w0, wzr, #0x1
- 0xc0, 0x03, 0x5f, 0xd6, // 52: 0xd65f03c0 ret
- 0x00, 0x00, 0x80, 0x52, // 56: 0x52800000 mov w0, #0x0
- 0xc0, 0x03, 0x5f, 0xd6, // 60: 0xd65f03c0 ret
-
- };
-
- // UnwindPlan we expect:
- // 0: CFA=sp +0 =>
- // (possibly with additional rows at offsets 36 and 56 saying the same thing)
-
- sample_range = AddressRange(0x1000, sizeof(data));
-
- EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
- sample_range, data, sizeof(data), unwind_plan));
-
- // 0: CFA=sp +0 =>
- row_sp = unwind_plan.GetRowForFunctionOffset(0);
- EXPECT_EQ(0ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- row_sp = unwind_plan.GetRowForFunctionOffset(32);
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x19_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x21_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x22_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x23_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x24_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x25_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x26_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x27_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_x28_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_fp_arm64, regloc));
- EXPECT_FALSE(row_sp->GetRegisterInfo(gpr_lr_arm64, regloc));
-
- row_sp = unwind_plan.GetRowForFunctionOffset(36);
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- row_sp = unwind_plan.GetRowForFunctionOffset(52);
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- row_sp = unwind_plan.GetRowForFunctionOffset(56);
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- row_sp = unwind_plan.GetRowForFunctionOffset(60);
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-}
-
-TEST_F(TestArm64InstEmulation, TestRegisterSavedTwice) {
- ArchSpec arch("arm64-apple-ios10");
- std::unique_ptr<UnwindAssemblyInstEmulation> engine(
- static_cast<UnwindAssemblyInstEmulation *>(
- UnwindAssemblyInstEmulation::CreateInstance(arch)));
- ASSERT_NE(nullptr, engine);
-
- UnwindPlan::RowSP row_sp;
- AddressRange sample_range;
- UnwindPlan unwind_plan(eRegisterKindLLDB);
- UnwindPlan::Row::RegisterLocation regloc;
-
- // disassembly of mach_msg_sever_once from libsystem_kernel.dylib for iOS.
- uint8_t data[] = {
-
- 0xfc, 0x6f, 0xba, 0xa9, // 0: 0xa9ba6ffc stp x28, x27, [sp, #-0x60]!
- 0xfa, 0x67, 0x01, 0xa9, // 4: 0xa90167fa stp x26, x25, [sp, #0x10]
- 0xf8, 0x5f, 0x02, 0xa9, // 8: 0xa9025ff8 stp x24, x23, [sp, #0x20]
- 0xf6, 0x57, 0x03, 0xa9, // 12: 0xa90357f6 stp x22, x21, [sp, #0x30]
- 0xf4, 0x4f, 0x04, 0xa9, // 16: 0xa9044ff4 stp x20, x19, [sp, #0x40]
- 0xfd, 0x7b, 0x05, 0xa9, // 20: 0xa9057bfd stp x29, x30, [sp, #0x50]
- 0xfd, 0x43, 0x01, 0x91, // 24: 0x910143fd add x29, sp, #0x50
- 0xff, 0xc3, 0x00, 0xd1, // 28: 0xd100c3ff sub sp, sp, #0x30
-
- // mid-function, store x20 & x24 on the stack at a different location.
- // this should not show up in the unwind plan; caller's values are not
- // being saved to stack.
- 0xf8, 0x53, 0x01, 0xa9, // 32: 0xa90153f8 stp x24, x20, [sp, #0x10]
-
- // mid-function, copy x20 and x19 off of the stack -- but not from
- // their original locations. unwind plan should ignore this.
- 0xf4, 0x4f, 0x41, 0xa9, // 36: 0xa9414ff4 ldp x20, x19, [sp, #0x10]
-
- // epilogue
- 0xbf, 0x43, 0x01, 0xd1, // 40: 0xd10143bf sub sp, x29, #0x50
- 0xfd, 0x7b, 0x45, 0xa9, // 44: 0xa9457bfd ldp x29, x30, [sp, #0x50]
- 0xf4, 0x4f, 0x44, 0xa9, // 48: 0xa9444ff4 ldp x20, x19, [sp, #0x40]
- 0xf6, 0x57, 0x43, 0xa9, // 52: 0xa94357f6 ldp x22, x21, [sp, #0x30]
- 0xf8, 0x5f, 0x42, 0xa9, // 56: 0xa9425ff8 ldp x24, x23, [sp, #0x20]
- 0xfa, 0x67, 0x41, 0xa9, // 60: 0xa94167fa ldp x26, x25, [sp, #0x10]
- 0xfc, 0x6f, 0xc6, 0xa8, // 64: 0xa8c66ffc ldp x28, x27, [sp], #0x60
- 0xc0, 0x03, 0x5f, 0xd6, // 68: 0xd65f03c0 ret
- };
-
- // UnwindPlan we expect:
- // 0: CFA=sp +0 =>
- // 4: CFA=sp+96 => x27=[CFA-88] x28=[CFA-96]
- // 8: CFA=sp+96 => x25=[CFA-72] x26=[CFA-80] x27=[CFA-88] x28=[CFA-96]
- // 12: CFA=sp+96 => x23=[CFA-56] x24=[CFA-64] x25=[CFA-72] x26=[CFA-80]
- // x27=[CFA-88] x28=[CFA-96]
- // 16: CFA=sp+96 => x21=[CFA-40] x22=[CFA-48] x23=[CFA-56] x24=[CFA-64]
- // x25=[CFA-72] x26=[CFA-80] x27=[CFA-88] x28=[CFA-96]
- // 20: CFA=sp+96 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // x23=[CFA-56] x24=[CFA-64] x25=[CFA-72] x26=[CFA-80] x27=[CFA-88]
- // x28=[CFA-96]
- // 24: CFA=sp+96 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // x23=[CFA-56] x24=[CFA-64] x25=[CFA-72] x26=[CFA-80] x27=[CFA-88]
- // x28=[CFA-96] fp=[CFA-16] lr=[CFA-8]
- // 28: CFA=fp+16 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // x23=[CFA-56] x24=[CFA-64] x25=[CFA-72] x26=[CFA-80] x27=[CFA-88]
- // x28=[CFA-96] fp=[CFA-16] lr=[CFA-8]
-
- // 44: CFA=sp+96 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // x23=[CFA-56] x24=[CFA-64] x25=[CFA-72] x26=[CFA-80] x27=[CFA-88]
- // x28=[CFA-96] fp=[CFA-16] lr=[CFA-8]
- // 48: CFA=sp+96 => x19=[CFA-24] x20=[CFA-32] x21=[CFA-40] x22=[CFA-48]
- // x23=[CFA-56] x24=[CFA-64] x25=[CFA-72] x26=[CFA-80] x27=[CFA-88]
- // x28=[CFA-96]
- // 52: CFA=sp+96 => x21=[CFA-40] x22=[CFA-48] x23=[CFA-56] x24=[CFA-64]
- // x25=[CFA-72] x26=[CFA-80] x27=[CFA-88] x28=[CFA-96]
- // 56: CFA=sp+96 => x23=[CFA-56] x24=[CFA-64] x25=[CFA-72] x26=[CFA-80]
- // x27=[CFA-88] x28=[CFA-96]
- // 60: CFA=sp+96 => x25=[CFA-72] x26=[CFA-80] x27=[CFA-88] x28=[CFA-96]
- // 64: CFA=sp+96 => x27=[CFA-88] x28=[CFA-96]
- // 68: CFA=sp +0 =>
-
- sample_range = AddressRange(0x1000, sizeof(data));
-
- EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
- sample_range, data, sizeof(data), unwind_plan));
-
- row_sp = unwind_plan.GetRowForFunctionOffset(36);
- EXPECT_EQ(28ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-32, regloc.GetOffset());
-
- row_sp = unwind_plan.GetRowForFunctionOffset(40);
- EXPECT_EQ(28ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_x20_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-32, regloc.GetOffset());
-}
-
-TEST_F(TestArm64InstEmulation, TestRegisterDoubleSpills) {
- ArchSpec arch("arm64-apple-ios10");
- std::unique_ptr<UnwindAssemblyInstEmulation> engine(
- static_cast<UnwindAssemblyInstEmulation *>(
- UnwindAssemblyInstEmulation::CreateInstance(arch)));
- ASSERT_NE(nullptr, engine);
-
- UnwindPlan::RowSP row_sp;
- AddressRange sample_range;
- UnwindPlan unwind_plan(eRegisterKindLLDB);
- UnwindPlan::Row::RegisterLocation regloc;
-
- // this file built with clang for iOS arch arm64 optimization -Os
- // #include <stdio.h>
- // double foo(double in) {
- // double arr[32];
- // for (int i = 0; i < 32; i++)
- // arr[i] = in + i;
- // for (int i = 2; i < 30; i++)
- // arr[i] = ((((arr[i - 1] * arr[i - 2] * 0.2) + (0.7 * arr[i])) /
- // ((((arr[i] * 0.73) + 0.65) * (arr[i - 1] + 0.2)) - ((arr[i + 1] + (arr[i]
- // * 0.32) + 0.52) / 0.3) + (0.531 * arr[i - 2]))) + ((arr[i - 1] + 5) /
- // ((arr[i + 2] + 0.4) / arr[i])) + (arr[5] * (0.17 + arr[7] * arr[i])) +
- // ((i > 5 ? (arr[i - 3]) : arr[i - 1]) * 0.263) + (((arr[i - 2] + arr[i -
- // 1]) * 0.3252) + 3.56) - (arr[i + 1] * 0.852311)) * ((arr[i] * 85234.1345)
- // + (77342.451324 / (arr[i - 2] + arr[i - 1] - 73425341.33455))) + (arr[i]
- // * 875712013.55) - (arr[i - 1] * 0.5555) - ((arr[i] * (arr[i + 1] +
- // 17342834.44) / 8688200123.555)) + (arr[i - 2] + 8888.888);
- // return arr[16];
- //}
- // int main(int argc, char **argv) { printf("%g\n", foo(argc)); }
-
- // so function foo() uses enough registers that it spills the callee-saved
- // floating point registers.
- uint8_t data[] = {
- // prologue
- 0xef, 0x3b, 0xba, 0x6d, // 0: 0x6dba3bef stp d15, d14, [sp, #-0x60]!
- 0xed, 0x33, 0x01, 0x6d, // 4: 0x6d0133ed stp d13, d12, [sp, #0x10]
- 0xeb, 0x2b, 0x02, 0x6d, // 8: 0x6d022beb stp d11, d10, [sp, #0x20]
- 0xe9, 0x23, 0x03, 0x6d, // 12: 0x6d0323e9 stp d9, d8, [sp, #0x30]
- 0xfc, 0x6f, 0x04, 0xa9, // 16: 0xa9046ffc stp x28, x27, [sp, #0x40]
- 0xfd, 0x7b, 0x05, 0xa9, // 20: 0xa9057bfd stp x29, x30, [sp, #0x50]
- 0xfd, 0x43, 0x01, 0x91, // 24: 0x910143fd add x29, sp, #0x50
- 0xff, 0x43, 0x04, 0xd1, // 28: 0xd10443ff sub sp, sp, #0x110
-
- // epilogue
- 0xbf, 0x43, 0x01, 0xd1, // 32: 0xd10143bf sub sp, x29, #0x50
- 0xfd, 0x7b, 0x45, 0xa9, // 36: 0xa9457bfd ldp x29, x30, [sp, #0x50]
- 0xfc, 0x6f, 0x44, 0xa9, // 40: 0xa9446ffc ldp x28, x27, [sp, #0x40]
- 0xe9, 0x23, 0x43, 0x6d, // 44: 0x6d4323e9 ldp d9, d8, [sp, #0x30]
- 0xeb, 0x2b, 0x42, 0x6d, // 48: 0x6d422beb ldp d11, d10, [sp, #0x20]
- 0xed, 0x33, 0x41, 0x6d, // 52: 0x6d4133ed ldp d13, d12, [sp, #0x10]
- 0xef, 0x3b, 0xc6, 0x6c, // 56: 0x6cc63bef ldp d15, d14, [sp], #0x60
- 0xc0, 0x03, 0x5f, 0xd6, // 60: 0xd65f03c0 ret
- };
-
- // UnwindPlan we expect:
- // 0: CFA=sp +0 =>
- // 4: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96]
- // 8: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- // 12: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80]
- // d14=[CFA-88] d15=[CFA-96]
- // 16: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64]
- // d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- // 20: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48]
- // d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88]
- // d15=[CFA-96]
- // 24: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
- // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
- // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- // 28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
- // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
- // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- // 36: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
- // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
- // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- // 40: CFA=sp+96 => x27=[CFA-24] x28=[CFA-32] d8=[CFA-40] d9=[CFA-48]
- // d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80] d14=[CFA-88]
- // d15=[CFA-96]
- // 44: CFA=sp+96 => d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64]
- // d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- // 48: CFA=sp+96 => d10=[CFA-56] d11=[CFA-64] d12=[CFA-72] d13=[CFA-80]
- // d14=[CFA-88] d15=[CFA-96]
- // 52: CFA=sp+96 => d12=[CFA-72] d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- // 56: CFA=sp+96 => d14=[CFA-88] d15=[CFA-96]
- // 60: CFA=sp +0 =>
-
- sample_range = AddressRange(0x1000, sizeof(data));
-
- EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
- sample_range, data, sizeof(data), unwind_plan));
-
- // 28: CFA=fp+16 => x27=[CFA-24] x28=[CFA-32] fp=[CFA-16] lr=[CFA-8]
- // d8=[CFA-40] d9=[CFA-48] d10=[CFA-56] d11=[CFA-64] d12=[CFA-72]
- // d13=[CFA-80] d14=[CFA-88] d15=[CFA-96]
- row_sp = unwind_plan.GetRowForFunctionOffset(28);
- EXPECT_EQ(28ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_fp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(16, row_sp->GetCFAValue().GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d15_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-96, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d14_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-88, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d13_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-80, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d12_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-72, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d11_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-64, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d10_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-56, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d9_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-48, regloc.GetOffset());
-
- EXPECT_TRUE(row_sp->GetRegisterInfo(fpu_d8_arm64, regloc));
- EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
- EXPECT_EQ(-40, regloc.GetOffset());
-
- // 60: CFA=sp +0 =>
- row_sp = unwind_plan.GetRowForFunctionOffset(60);
- EXPECT_EQ(60ull, row_sp->GetOffset());
- EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_sp_arm64);
- EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
- EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
-
- if (row_sp->GetRegisterInfo(fpu_d8_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(fpu_d9_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(fpu_d10_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(fpu_d11_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(fpu_d12_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(fpu_d13_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(fpu_d14_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(fpu_d15_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(gpr_x27_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
- if (row_sp->GetRegisterInfo(gpr_x28_arm64, regloc))
- EXPECT_TRUE(regloc.IsSame());
-}
Added: lldb/trunk/unittests/UnwindAssembly/PPC64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/PPC64/CMakeLists.txt?rev=326224&view=auto
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/PPC64/CMakeLists.txt (added)
+++ lldb/trunk/unittests/UnwindAssembly/PPC64/CMakeLists.txt Tue Feb 27 10:42:46 2018
@@ -0,0 +1,13 @@
+add_lldb_unittest(PPC64InstEmulationTests
+ TestPPC64InstEmulation.cpp
+ LINK_LIBS
+ lldbCore
+ lldbSymbol
+ lldbTarget
+ lldbPluginUnwindAssemblyInstEmulation
+ lldbPluginDisassemblerLLVM
+ lldbPluginInstructionPPC64
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
+ ${LLVM_TARGETS_TO_BUILD})
Added: lldb/trunk/unittests/UnwindAssembly/PPC64/TestPPC64InstEmulation.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/UnwindAssembly/PPC64/TestPPC64InstEmulation.cpp?rev=326224&view=auto
==============================================================================
--- lldb/trunk/unittests/UnwindAssembly/PPC64/TestPPC64InstEmulation.cpp (added)
+++ lldb/trunk/unittests/UnwindAssembly/PPC64/TestPPC64InstEmulation.cpp Tue Feb 27 10:42:46 2018
@@ -0,0 +1,259 @@
+//===-- TestPPC64InstEmulation.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include <vector>
+
+#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/UnwindAssembly.h"
+#include "lldb/Utility/ArchSpec.h"
+
+#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
+#include "Plugins/Instruction/PPC64/EmulateInstructionPPC64.h"
+#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
+#include "llvm/Support/TargetSelect.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class TestPPC64InstEmulation : public testing::Test {
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ // virtual void SetUp() override { }
+ // virtual void TearDown() override { }
+
+protected:
+};
+
+void TestPPC64InstEmulation::SetUpTestCase() {
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllDisassemblers();
+ DisassemblerLLVMC::Initialize();
+ EmulateInstructionPPC64::Initialize();
+}
+
+void TestPPC64InstEmulation::TearDownTestCase() {
+ DisassemblerLLVMC::Terminate();
+ EmulateInstructionPPC64::Terminate();
+}
+
+TEST_F(TestPPC64InstEmulation, TestSimpleFunction) {
+ ArchSpec arch("powerpc64le-linux-gnu");
+ std::unique_ptr<UnwindAssemblyInstEmulation> engine(
+ static_cast<UnwindAssemblyInstEmulation *>(
+ UnwindAssemblyInstEmulation::CreateInstance(arch)));
+ ASSERT_NE(nullptr, engine);
+
+ UnwindPlan::RowSP row_sp;
+ AddressRange sample_range;
+ UnwindPlan unwind_plan(eRegisterKindLLDB);
+ UnwindPlan::Row::RegisterLocation regloc;
+
+ // prologue and epilogue of:
+ // int main() {
+ // int i = test();
+ // return i;
+ // }
+ //
+ // compiled with clang -O0 -g
+ uint8_t data[] = {
+ // prologue
+ 0x02, 0x10, 0x40, 0x3c, // 0: lis r2, 4098
+ 0x00, 0x7f, 0x42, 0x38, // 4: addi r2, r2, 32512
+ 0xa6, 0x02, 0x08, 0x7c, // 8: mflr r0
+ 0xf8, 0xff, 0xe1, 0xfb, // 12: std r31, -8(r1)
+ 0x10, 0x00, 0x01, 0xf8, // 16: std r0, 16(r1)
+ 0x91, 0xff, 0x21, 0xf8, // 20: stdu r1, -112(r1)
+ 0x78, 0x0b, 0x3f, 0x7c, // 24: mr r31, r1
+ 0x00, 0x00, 0x60, 0x38, // 28: li r3, 0
+ 0x64, 0x00, 0x7f, 0x90, // 32: stw r3, 100(r31)
+
+ // epilogue
+ 0x70, 0x00, 0x21, 0x38, // 36: addi r1, r1, 112
+ 0x10, 0x00, 0x01, 0xe8, // 40: ld r0, 16(r1)
+ 0xf8, 0xff, 0xe1, 0xeb, // 44: ld r31, -8(r1)
+ 0xa6, 0x03, 0x08, 0x7c, // 48: mtlr r0
+ 0x20, 0x00, 0x80, 0x4e // 52: blr
+ };
+
+ sample_range = AddressRange(0x1000, sizeof(data));
+
+ EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+ sample_range, data, sizeof(data), unwind_plan));
+
+ // 0: CFA=sp+0
+ row_sp = unwind_plan.GetRowForFunctionOffset(0);
+ EXPECT_EQ(0ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ // 1: CFA=sp+0 => fp=[CFA-8]
+ row_sp = unwind_plan.GetRowForFunctionOffset(16);
+ EXPECT_EQ(16ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_r31_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-8, regloc.GetOffset());
+
+ // 2: CFA=sp+0 => fp=[CFA-8] lr=[CFA+16]
+ row_sp = unwind_plan.GetRowForFunctionOffset(20);
+ EXPECT_EQ(20ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(16, regloc.GetOffset());
+
+ // 3: CFA=sp+112 => fp=[CFA-8] lr=[CFA+16]
+ row_sp = unwind_plan.GetRowForFunctionOffset(24);
+ EXPECT_EQ(24ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(112, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_r31_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-8, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(16, regloc.GetOffset());
+
+ // 4: CFA=r31+112 => fp=[CFA-8] lr=[CFA+16]
+ row_sp = unwind_plan.GetRowForFunctionOffset(28);
+ EXPECT_EQ(28ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r31_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(112, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_r31_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-8, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(16, regloc.GetOffset());
+
+ // 5: CFA=sp+0 => fp=[CFA-8] lr=[CFA+16]
+ row_sp = unwind_plan.GetRowForFunctionOffset(40);
+ EXPECT_EQ(40ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_r31_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-8, regloc.GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(16, regloc.GetOffset());
+}
+
+TEST_F(TestPPC64InstEmulation, TestMediumFunction) {
+ ArchSpec arch("powerpc64le-linux-gnu");
+ std::unique_ptr<UnwindAssemblyInstEmulation> engine(
+ static_cast<UnwindAssemblyInstEmulation *>(
+ UnwindAssemblyInstEmulation::CreateInstance(arch)));
+ ASSERT_NE(nullptr, engine);
+
+ UnwindPlan::RowSP row_sp;
+ AddressRange sample_range;
+ UnwindPlan unwind_plan(eRegisterKindLLDB);
+ UnwindPlan::Row::RegisterLocation regloc;
+
+ // prologue and epilogue of main() (call-func.c),
+ // with several calls and stack variables.
+ //
+ // compiled with clang -O0 -g
+ uint8_t data[] = {
+ // prologue
+ 0xa6, 0x02, 0x08, 0x7c, // 0: mflr r0
+ 0xf8, 0xff, 0xe1, 0xfb, // 4: std r31, -8(r1)
+ 0x10, 0x00, 0x01, 0xf8, // 8: std r0, 16(r1)
+ 0x78, 0x0b, 0x3e, 0x7c, // 12: mr r30, r1
+ 0xe0, 0x06, 0x20, 0x78, // 16: clrldi r0, r1, 59
+ 0xa0, 0xfa, 0x00, 0x20, // 20: subfic r0, r0, -1376
+ 0x6a, 0x01, 0x21, 0x7c, // 24: stdux r1, r1, r0
+ 0x78, 0x0b, 0x3f, 0x7c, // 28: mr r31, r1
+
+ // epilogue
+ 0x00, 0x00, 0x21, 0xe8, // 32: ld r1, 0(r1)
+ 0x20, 0x00, 0x80, 0x4e // 36: blr
+ };
+
+ sample_range = AddressRange(0x1000, sizeof(data));
+
+ EXPECT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(
+ sample_range, data, sizeof(data), unwind_plan));
+
+ // 0: CFA=sp+0
+ row_sp = unwind_plan.GetRowForFunctionOffset(0);
+ EXPECT_EQ(0ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ // 1: CFA=sp+0 => fp=[CFA-8]
+ row_sp = unwind_plan.GetRowForFunctionOffset(8);
+ EXPECT_EQ(8ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_r31_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(-8, regloc.GetOffset());
+
+ // 2: CFA=sp+0 => fp=[CFA-8] lr=[CFA+16]
+ row_sp = unwind_plan.GetRowForFunctionOffset(12);
+ EXPECT_EQ(12ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ EXPECT_TRUE(row_sp->GetRegisterInfo(gpr_lr_ppc64le, regloc));
+ EXPECT_TRUE(regloc.IsAtCFAPlusOffset());
+ EXPECT_EQ(16, regloc.GetOffset());
+
+ // 3: CFA=r30
+ row_sp = unwind_plan.GetRowForFunctionOffset(16);
+ EXPECT_EQ(16ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r30_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ row_sp = unwind_plan.GetRowForFunctionOffset(32);
+ EXPECT_EQ(16ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r30_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+
+ // 4: CFA=sp+0
+ row_sp = unwind_plan.GetRowForFunctionOffset(36);
+ EXPECT_EQ(36ull, row_sp->GetOffset());
+ EXPECT_TRUE(row_sp->GetCFAValue().GetRegisterNumber() == gpr_r1_ppc64le);
+ EXPECT_TRUE(row_sp->GetCFAValue().IsRegisterPlusOffset() == true);
+ EXPECT_EQ(0, row_sp->GetCFAValue().GetOffset());
+}
More information about the lldb-commits
mailing list