forked from OSchip/llvm-project
Initial Assembly profiler for mips64
Summary: This is initial implementation of assembly profiler which only scans prologue/epilogue assembly instructions to create CFI instructions. Reviewers: clayborg, jasonmolenda Differential Revision: http://reviews.llvm.org/D7696 llvm-svn: 232619
This commit is contained in:
parent
41c56755be
commit
29e5937cd9
|
@ -49,6 +49,7 @@ set( LLDB_USED_LIBS
|
|||
lldbPluginABISysV_ppc64
|
||||
lldbPluginInstructionARM
|
||||
lldbPluginInstructionARM64
|
||||
lldbPluginInstructionMIPS64
|
||||
lldbPluginObjectFilePECOFF
|
||||
lldbPluginOSPython
|
||||
lldbPluginMemoryHistoryASan
|
||||
|
|
|
@ -45,6 +45,7 @@ USEDLIBS = lldbAPI.a \
|
|||
lldbPluginDynamicLoaderMacOSX.a \
|
||||
lldbPluginEmulateInstructionARM.a \
|
||||
lldbPluginEmulateInstructionARM64.a \
|
||||
lldbPluginEmulateInstructionMIPS64.a \
|
||||
lldbPluginInstrumentationRuntimeAddressSanitizer.a \
|
||||
lldbPluginLanguageRuntimeCPlusPlusItaniumABI.a \
|
||||
lldbPluginLanguageRuntimeObjCAppleObjCRuntime.a \
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
add_subdirectory(ARM)
|
||||
add_subdirectory(ARM64)
|
||||
add_subdirectory(MIPS64)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
add_lldb_library(lldbPluginInstructionMIPS64
|
||||
EmulateInstructionMIPS64.cpp
|
||||
)
|
|
@ -0,0 +1,444 @@
|
|||
//===-- EmulateInstructionMIPS64.cpp -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "EmulateInstructionMIPS64.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/Address.h"
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
#include "lldb/Symbol/UnwindPlan.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
//#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
|
||||
|
||||
#include "Plugins/Process/Utility/InstructionUtils.h"
|
||||
#include "Plugins/Process/Utility/RegisterContext_mips64.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
#define UInt(x) ((uint64_t)x)
|
||||
#define integer int64_t
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// EmulateInstructionMIPS64 implementation
|
||||
//
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
EmulateInstructionMIPS64::Initialize ()
|
||||
{
|
||||
PluginManager::RegisterPlugin (GetPluginNameStatic (),
|
||||
GetPluginDescriptionStatic (),
|
||||
CreateInstance);
|
||||
}
|
||||
|
||||
void
|
||||
EmulateInstructionMIPS64::Terminate ()
|
||||
{
|
||||
PluginManager::UnregisterPlugin (CreateInstance);
|
||||
}
|
||||
|
||||
ConstString
|
||||
EmulateInstructionMIPS64::GetPluginNameStatic ()
|
||||
{
|
||||
ConstString g_plugin_name ("lldb.emulate-instruction.mips64");
|
||||
return g_plugin_name;
|
||||
}
|
||||
|
||||
lldb_private::ConstString
|
||||
EmulateInstructionMIPS64::GetPluginName()
|
||||
{
|
||||
static ConstString g_plugin_name ("EmulateInstructionMIPS64");
|
||||
return g_plugin_name;
|
||||
}
|
||||
|
||||
const char *
|
||||
EmulateInstructionMIPS64::GetPluginDescriptionStatic ()
|
||||
{
|
||||
return "Emulate instructions for the MIPS64 architecture.";
|
||||
}
|
||||
|
||||
EmulateInstruction *
|
||||
EmulateInstructionMIPS64::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
|
||||
{
|
||||
if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
|
||||
{
|
||||
if (arch.GetTriple().getArch() == llvm::Triple::mips64)
|
||||
{
|
||||
std::auto_ptr<EmulateInstructionMIPS64> emulate_insn_ap (new EmulateInstructionMIPS64 (arch));
|
||||
if (emulate_insn_ap.get())
|
||||
return emulate_insn_ap.release();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::SetTargetTriple (const ArchSpec &arch)
|
||||
{
|
||||
if (arch.GetTriple().getArch () == llvm::Triple::mips64)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *
|
||||
EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name)
|
||||
{
|
||||
if (alternate_name)
|
||||
{
|
||||
switch (reg_num)
|
||||
{
|
||||
case gcc_dwarf_sp_mips64: return "r29";
|
||||
case gcc_dwarf_r30_mips64: return "r30";
|
||||
case gcc_dwarf_ra_mips64: return "r31";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (reg_num)
|
||||
{
|
||||
case gcc_dwarf_zero_mips64: return "r0";
|
||||
case gcc_dwarf_r1_mips64: return "r1";
|
||||
case gcc_dwarf_r2_mips64: return "r2";
|
||||
case gcc_dwarf_r3_mips64: return "r3";
|
||||
case gcc_dwarf_r4_mips64: return "r4";
|
||||
case gcc_dwarf_r5_mips64: return "r5";
|
||||
case gcc_dwarf_r6_mips64: return "r6";
|
||||
case gcc_dwarf_r7_mips64: return "r7";
|
||||
case gcc_dwarf_r8_mips64: return "r8";
|
||||
case gcc_dwarf_r9_mips64: return "r9";
|
||||
case gcc_dwarf_r10_mips64: return "r10";
|
||||
case gcc_dwarf_r11_mips64: return "r11";
|
||||
case gcc_dwarf_r12_mips64: return "r12";
|
||||
case gcc_dwarf_r13_mips64: return "r13";
|
||||
case gcc_dwarf_r14_mips64: return "r14";
|
||||
case gcc_dwarf_r15_mips64: return "r15";
|
||||
case gcc_dwarf_r16_mips64: return "r16";
|
||||
case gcc_dwarf_r17_mips64: return "r17";
|
||||
case gcc_dwarf_r18_mips64: return "r18";
|
||||
case gcc_dwarf_r19_mips64: return "r19";
|
||||
case gcc_dwarf_r20_mips64: return "r20";
|
||||
case gcc_dwarf_r21_mips64: return "r21";
|
||||
case gcc_dwarf_r22_mips64: return "r22";
|
||||
case gcc_dwarf_r23_mips64: return "r23";
|
||||
case gcc_dwarf_r24_mips64: return "r24";
|
||||
case gcc_dwarf_r25_mips64: return "r25";
|
||||
case gcc_dwarf_r26_mips64: return "r26";
|
||||
case gcc_dwarf_r27_mips64: return "r27";
|
||||
case gcc_dwarf_gp_mips64: return "gp";
|
||||
case gcc_dwarf_sp_mips64: return "sp";
|
||||
case gcc_dwarf_r30_mips64: return "fp";
|
||||
case gcc_dwarf_ra_mips64: return "ra";
|
||||
case gcc_dwarf_sr_mips64: return "sr";
|
||||
case gcc_dwarf_lo_mips64: return "lo";
|
||||
case gcc_dwarf_hi_mips64: return "hi";
|
||||
case gcc_dwarf_bad_mips64: return "bad";
|
||||
case gcc_dwarf_cause_mips64: return "cause";
|
||||
case gcc_dwarf_pc_mips64: return "pc";
|
||||
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info)
|
||||
{
|
||||
if (reg_kind == eRegisterKindGeneric)
|
||||
{
|
||||
switch (reg_num)
|
||||
{
|
||||
case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips64; break;
|
||||
case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips64; break;
|
||||
case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips64; break;
|
||||
case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips64; break;
|
||||
case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips64; break;
|
||||
return true;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (reg_kind == eRegisterKindDWARF)
|
||||
{
|
||||
::memset (®_info, 0, sizeof(RegisterInfo));
|
||||
::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
|
||||
|
||||
if (reg_num == gcc_dwarf_sr_mips64)
|
||||
{
|
||||
reg_info.byte_size = 4;
|
||||
reg_info.format = eFormatHex;
|
||||
reg_info.encoding = eEncodingUint;
|
||||
}
|
||||
else if (reg_num >= gcc_dwarf_zero_mips64 && reg_num <= gcc_dwarf_pc_mips64)
|
||||
{
|
||||
reg_info.byte_size = 8;
|
||||
reg_info.format = eFormatHex;
|
||||
reg_info.encoding = eEncodingUint;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
reg_info.name = GetRegisterName (reg_num, false);
|
||||
reg_info.alt_name = GetRegisterName (reg_num, true);
|
||||
reg_info.kinds[eRegisterKindDWARF] = reg_num;
|
||||
|
||||
switch (reg_num)
|
||||
{
|
||||
case gcc_dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
|
||||
case gcc_dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
|
||||
case gcc_dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
|
||||
case gcc_dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
|
||||
case gcc_dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
EmulateInstructionMIPS64::Opcode*
|
||||
EmulateInstructionMIPS64::GetOpcodeForInstruction (const uint32_t opcode)
|
||||
{
|
||||
static EmulateInstructionMIPS64::Opcode
|
||||
g_opcodes[] =
|
||||
{
|
||||
//----------------------------------------------------------------------
|
||||
// Prologue/Epilogue instructions
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// stack adjustment
|
||||
{ 0xffff0000, 0x67bd0000, &EmulateInstructionMIPS64::Emulate_addsp_imm, "DADDIU rt, rs, immediate" },
|
||||
|
||||
// store register
|
||||
{ 0xfc000000, 0xfc000000, &EmulateInstructionMIPS64::Emulate_store, "SD rt, offset(Rn)" },
|
||||
|
||||
// Load register
|
||||
{ 0xfc000000, 0xdc000000, &EmulateInstructionMIPS64::Emulate_load, "LD rt, offset(base)" },
|
||||
|
||||
};
|
||||
static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
|
||||
|
||||
for (size_t i=0; i<k_num_mips_opcodes; ++i)
|
||||
{
|
||||
if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
|
||||
return &g_opcodes[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::ReadInstruction ()
|
||||
{
|
||||
bool success = false;
|
||||
m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
|
||||
if (success)
|
||||
{
|
||||
Context read_inst_context;
|
||||
read_inst_context.type = eContextReadOpcode;
|
||||
read_inst_context.SetNoArgs ();
|
||||
m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder());
|
||||
}
|
||||
if (!success)
|
||||
m_addr = LLDB_INVALID_ADDRESS;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
|
||||
{
|
||||
uint32_t opcode = m_opcode.GetOpcode32();
|
||||
|
||||
if (GetByteOrder() == eByteOrderBig)
|
||||
opcode = llvm::ByteSwap_32(opcode);
|
||||
|
||||
Opcode *opcode_data = GetOpcodeForInstruction(opcode);
|
||||
bool success = false;
|
||||
|
||||
if (opcode_data == NULL)
|
||||
return false;
|
||||
|
||||
// Call the Emulate... function.
|
||||
success = (this->*opcode_data->callback) (opcode);
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
|
||||
{
|
||||
unwind_plan.Clear();
|
||||
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
|
||||
|
||||
UnwindPlan::RowSP row(new UnwindPlan::Row);
|
||||
const bool can_replace = false;
|
||||
|
||||
// Our previous Call Frame Address is the stack pointer
|
||||
row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips64, 0);
|
||||
|
||||
// Our previous PC is in the RA
|
||||
row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips64, gcc_dwarf_ra_mips64, can_replace);
|
||||
|
||||
unwind_plan.AppendRow (row);
|
||||
|
||||
// All other registers are the same.
|
||||
|
||||
unwind_plan.SetSourceName ("EmulateInstructionMIPS64");
|
||||
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
|
||||
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum)
|
||||
{
|
||||
switch (regnum)
|
||||
{
|
||||
case gcc_dwarf_r16_mips64:
|
||||
case gcc_dwarf_r17_mips64:
|
||||
case gcc_dwarf_r18_mips64:
|
||||
case gcc_dwarf_r19_mips64:
|
||||
case gcc_dwarf_r20_mips64:
|
||||
case gcc_dwarf_r21_mips64:
|
||||
case gcc_dwarf_r22_mips64:
|
||||
case gcc_dwarf_r23_mips64:
|
||||
case gcc_dwarf_sp_mips64:
|
||||
case gcc_dwarf_r30_mips64:
|
||||
case gcc_dwarf_ra_mips64:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::Emulate_addsp_imm (const uint32_t opcode)
|
||||
{
|
||||
|
||||
/* Get immediate operand */
|
||||
const uint32_t imm16 = Bits32(opcode, 15, 0);
|
||||
|
||||
bool success = false;
|
||||
uint64_t result;
|
||||
uint64_t imm = SignedBits(imm16, 15, 0);
|
||||
|
||||
uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_sp_mips64, 0, &success);
|
||||
uint64_t operand2 = imm;
|
||||
|
||||
result = operand1 + operand2;
|
||||
|
||||
Context context;
|
||||
RegisterInfo reg_info_Rn;
|
||||
if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_Rn))
|
||||
context.SetRegisterPlusOffset (reg_info_Rn, imm);
|
||||
|
||||
/* We are allocating bytes on stack */
|
||||
context.type = eContextAdjustStackPointer;
|
||||
|
||||
WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::Emulate_store (const uint32_t opcode)
|
||||
{
|
||||
uint32_t imm16 = Bits32(opcode, 15, 0);
|
||||
uint32_t Rt = Bits32(opcode, 20, 16);
|
||||
uint32_t base = Bits32(opcode, 25, 21);
|
||||
uint64_t imm = SignedBits(imm16, 15, 0);
|
||||
uint64_t address;
|
||||
|
||||
integer n = UInt(base);
|
||||
integer t = UInt(Rt);
|
||||
|
||||
RegisterValue data_Rt;
|
||||
|
||||
RegisterInfo reg_info_base;
|
||||
RegisterInfo reg_info_Rt;
|
||||
|
||||
if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + n, reg_info_base))
|
||||
return false;
|
||||
|
||||
if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + t, reg_info_Rt))
|
||||
return false;
|
||||
|
||||
bool success = false;
|
||||
Context context_t;
|
||||
|
||||
/* We look for sp based non-volatile register stores */
|
||||
if (n == 29 && nonvolatile_reg_p(t))
|
||||
address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_sp_mips64, 0, &success);
|
||||
else
|
||||
return false;
|
||||
|
||||
/* Calculate address to store */
|
||||
address = address + imm;
|
||||
|
||||
context_t.type = eContextPushRegisterOnStack;
|
||||
context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
|
||||
|
||||
uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
|
||||
Error error;
|
||||
|
||||
if (!ReadRegister (®_info_Rt, data_Rt))
|
||||
return false;
|
||||
|
||||
if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0)
|
||||
return false;
|
||||
|
||||
if (!WriteMemory(context_t, address, buffer, reg_info_Rt.byte_size))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EmulateInstructionMIPS64::Emulate_load (const uint32_t opcode)
|
||||
{
|
||||
uint32_t Rt = Bits32(opcode, 20, 16);
|
||||
uint32_t base = Bits32(opcode, 25, 21);
|
||||
|
||||
integer n = UInt(base);
|
||||
integer t = UInt(Rt);
|
||||
|
||||
RegisterValue data_Rt;
|
||||
RegisterInfo reg_info_Rt;
|
||||
|
||||
if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + t, reg_info_Rt))
|
||||
return false;
|
||||
|
||||
Context context_t;
|
||||
|
||||
/* We are looking for "saved register" being restored from stack */
|
||||
if (!n == 29 || !nonvolatile_reg_p(t))
|
||||
return false;
|
||||
|
||||
context_t.type = eContextRegisterLoad;
|
||||
|
||||
if (!WriteRegister (context_t, ®_info_Rt, data_Rt))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
//===-- EmulateInstructionMIPS64.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef EmulateInstructionMIPS64_h_
|
||||
#define EmulateInstructionMIPS64_h_
|
||||
|
||||
#include "lldb/Core/EmulateInstruction.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Interpreter/OptionValue.h"
|
||||
|
||||
class EmulateInstructionMIPS64 : public lldb_private::EmulateInstruction
|
||||
{
|
||||
public:
|
||||
static void
|
||||
Initialize ();
|
||||
|
||||
static void
|
||||
Terminate ();
|
||||
|
||||
static lldb_private::ConstString
|
||||
GetPluginNameStatic ();
|
||||
|
||||
static const char *
|
||||
GetPluginDescriptionStatic ();
|
||||
|
||||
static lldb_private::EmulateInstruction *
|
||||
CreateInstance (const lldb_private::ArchSpec &arch,
|
||||
lldb_private::InstructionType inst_type);
|
||||
|
||||
static bool
|
||||
SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type)
|
||||
{
|
||||
switch (inst_type)
|
||||
{
|
||||
case lldb_private::eInstructionTypeAny:
|
||||
case lldb_private::eInstructionTypePrologueEpilogue:
|
||||
return true;
|
||||
|
||||
case lldb_private::eInstructionTypePCModifying:
|
||||
case lldb_private::eInstructionTypeAll:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual lldb_private::ConstString
|
||||
GetPluginName();
|
||||
|
||||
virtual lldb_private::ConstString
|
||||
GetShortPluginName()
|
||||
{
|
||||
return GetPluginNameStatic();
|
||||
}
|
||||
|
||||
virtual uint32_t
|
||||
GetPluginVersion()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool
|
||||
SetTargetTriple (const lldb_private::ArchSpec &arch);
|
||||
|
||||
EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch) :
|
||||
EmulateInstruction (arch)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool
|
||||
SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
|
||||
{
|
||||
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
ReadInstruction ();
|
||||
|
||||
virtual bool
|
||||
EvaluateInstruction (uint32_t evaluate_options);
|
||||
|
||||
virtual bool
|
||||
TestEmulation (lldb_private::Stream *out_stream,
|
||||
lldb_private::ArchSpec &arch,
|
||||
lldb_private::OptionValueDictionary *test_data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
GetRegisterInfo (lldb::RegisterKind reg_kind,
|
||||
uint32_t reg_num,
|
||||
lldb_private::RegisterInfo ®_info);
|
||||
|
||||
virtual bool
|
||||
CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t mask;
|
||||
uint32_t value;
|
||||
bool (EmulateInstructionMIPS64::*callback) (const uint32_t opcode);
|
||||
const char *name;
|
||||
} Opcode;
|
||||
|
||||
static Opcode*
|
||||
GetOpcodeForInstruction (const uint32_t opcode);
|
||||
|
||||
bool
|
||||
Emulate_addsp_imm (const uint32_t opcode);
|
||||
|
||||
bool
|
||||
Emulate_store (const uint32_t opcode);
|
||||
|
||||
bool
|
||||
Emulate_load (const uint32_t opcode);
|
||||
|
||||
bool
|
||||
nonvolatile_reg_p (uint64_t regnum);
|
||||
|
||||
const char *
|
||||
GetRegisterName (unsigned reg_num, bool altnernate_name);
|
||||
|
||||
};
|
||||
|
||||
#endif // EmulateInstructionMIPS64_h_
|
|
@ -0,0 +1,14 @@
|
|||
##===- source/Plugins/Instruction/MIPS64/Makefile -------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LLDB_LEVEL := ../../../..
|
||||
LIBRARYNAME := lldbPluginEmulateInstructionMIPS64
|
||||
BUILD_ARCHIVE = 1
|
||||
|
||||
include $(LLDB_LEVEL)/Makefile
|
|
@ -19,7 +19,7 @@ PARALLEL_DIRS := ABI/MacOSX-arm ABI/MacOSX-arm64 ABI/MacOSX-i386 ABI/SysV-x86_64
|
|||
ObjectContainer/Universal-Mach-O ObjectFile/Mach-O \
|
||||
ObjectFile/JIT SymbolFile/DWARF SymbolFile/Symtab Process/Utility \
|
||||
DynamicLoader/Static Platform Process/gdb-remote \
|
||||
Instruction/ARM Instruction/ARM64 \
|
||||
Instruction/ARM Instruction/ARM64 Instruction/MIPS64 \
|
||||
UnwindAssembly/InstEmulation UnwindAssembly/x86 \
|
||||
LanguageRuntime/CPlusPlus/ItaniumABI \
|
||||
LanguageRuntime/ObjC/AppleObjCRuntime \
|
||||
|
|
|
@ -610,7 +610,6 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
|
|||
case EmulateInstruction::eContextRegisterPlusOffset:
|
||||
case EmulateInstruction::eContextAdjustPC:
|
||||
case EmulateInstruction::eContextRegisterStore:
|
||||
case EmulateInstruction::eContextRegisterLoad:
|
||||
case EmulateInstruction::eContextAbsoluteBranchRegister:
|
||||
case EmulateInstruction::eContextSupervisorCall:
|
||||
case EmulateInstruction::eContextTableBranchReadMemory:
|
||||
|
@ -634,6 +633,35 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
|
|||
// }
|
||||
break;
|
||||
|
||||
case EmulateInstruction::eContextRegisterLoad:
|
||||
{
|
||||
const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
|
||||
const uint32_t reg_num = reg_info->kinds[unwind_reg_kind];
|
||||
if (reg_num != LLDB_INVALID_REGNUM)
|
||||
{
|
||||
m_curr_row->SetRegisterLocationToRegister (reg_num, reg_num, must_replace);
|
||||
m_curr_row_modified = true;
|
||||
m_curr_insn_restored_a_register = true;
|
||||
|
||||
if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA)
|
||||
{
|
||||
// This load was restoring the return address register,
|
||||
// so this is also how we will unwind the PC...
|
||||
RegisterInfo pc_reg_info;
|
||||
if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
|
||||
{
|
||||
uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind];
|
||||
if (pc_reg_num != LLDB_INVALID_REGNUM)
|
||||
{
|
||||
m_curr_row->SetRegisterLocationToRegister (pc_reg_num, reg_num, must_replace);
|
||||
m_curr_row_modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EmulateInstruction::eContextRelativeBranchImmediate:
|
||||
{
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
|
||||
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
|
||||
#include "Plugins/Instruction/ARM64/EmulateInstructionARM64.h"
|
||||
#include "Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h"
|
||||
#include "Plugins/JITLoader/GDB/JITLoaderGDB.h"
|
||||
#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h"
|
||||
#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
|
||||
|
@ -224,6 +225,7 @@ lldb_private::Initialize ()
|
|||
UnwindAssembly_x86::Initialize();
|
||||
EmulateInstructionARM::Initialize();
|
||||
EmulateInstructionARM64::Initialize();
|
||||
EmulateInstructionMIPS64::Initialize();
|
||||
SymbolFileDWARFDebugMap::Initialize();
|
||||
ItaniumABILanguageRuntime::Initialize();
|
||||
AppleObjCRuntimeV2::Initialize();
|
||||
|
@ -339,6 +341,7 @@ lldb_private::Terminate ()
|
|||
UnwindAssemblyInstEmulation::Terminate();
|
||||
EmulateInstructionARM::Terminate();
|
||||
EmulateInstructionARM64::Terminate();
|
||||
EmulateInstructionMIPS64::Terminate();
|
||||
SymbolFileDWARFDebugMap::Terminate();
|
||||
ItaniumABILanguageRuntime::Terminate();
|
||||
AppleObjCRuntimeV2::Terminate();
|
||||
|
|
Loading…
Reference in New Issue