[Lldb-commits] [lldb] r237420 - Assembly profiler for mips32
Bhushan D. Attarde
Bhushan.Attarde at imgtec.com
Thu May 14 23:53:30 PDT 2015
Author: bhushan.attarde
Date: Fri May 15 01:53:30 2015
New Revision: 237420
URL: http://llvm.org/viewvc/llvm-project?rev=237420&view=rev
Log:
Assembly profiler for mips32
Summary:
Implementation of assembly profiler for MIPS32 using EmulateInstruction which currently scans only prologue/epilogue assembly instructions. It uses llvm::MCDisassembler to decode assembly instructions.
Reviewers: clayborg, jasonmolenda
Differential Revision: http://reviews.llvm.org/D9769
Added:
lldb/trunk/source/Plugins/Instruction/MIPS/
lldb/trunk/source/Plugins/Instruction/MIPS/CMakeLists.txt
lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
lldb/trunk/source/Plugins/Instruction/MIPS/Makefile
Modified:
lldb/trunk/cmake/LLDBDependencies.cmake
lldb/trunk/lib/Makefile
lldb/trunk/source/Initialization/SystemInitializerCommon.cpp
lldb/trunk/source/Plugins/Instruction/CMakeLists.txt
lldb/trunk/source/Plugins/Makefile
lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp
lldb/trunk/source/Target/Thread.cpp
Modified: lldb/trunk/cmake/LLDBDependencies.cmake
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/LLDBDependencies.cmake?rev=237420&r1=237419&r2=237420&view=diff
==============================================================================
--- lldb/trunk/cmake/LLDBDependencies.cmake (original)
+++ lldb/trunk/cmake/LLDBDependencies.cmake Fri May 15 01:53:30 2015
@@ -54,6 +54,7 @@ set( LLDB_USED_LIBS
lldbPluginABISysV_ppc64
lldbPluginInstructionARM
lldbPluginInstructionARM64
+ lldbPluginInstructionMIPS
lldbPluginInstructionMIPS64
lldbPluginObjectFilePECOFF
lldbPluginOSPython
Modified: lldb/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lib/Makefile?rev=237420&r1=237419&r2=237420&view=diff
==============================================================================
--- lldb/trunk/lib/Makefile (original)
+++ lldb/trunk/lib/Makefile Fri May 15 01:53:30 2015
@@ -48,6 +48,7 @@ USEDLIBS = lldbAPI.a \
lldbPluginDynamicLoaderMacOSX.a \
lldbPluginEmulateInstructionARM.a \
lldbPluginEmulateInstructionARM64.a \
+ lldbPluginEmulateInstructionMIPS.a \
lldbPluginEmulateInstructionMIPS64.a \
lldbPluginInstrumentationRuntimeAddressSanitizer.a \
lldbPluginLanguageRuntimeCPlusPlusItaniumABI.a \
Modified: lldb/trunk/source/Initialization/SystemInitializerCommon.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Initialization/SystemInitializerCommon.cpp?rev=237420&r1=237419&r2=237420&view=diff
==============================================================================
--- lldb/trunk/source/Initialization/SystemInitializerCommon.cpp (original)
+++ lldb/trunk/source/Initialization/SystemInitializerCommon.cpp Fri May 15 01:53:30 2015
@@ -18,6 +18,7 @@
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
+#include "Plugins/Instruction/MIPS/EmulateInstructionMIPS.h"
#include "Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h"
#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
#include "Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h"
@@ -113,6 +114,7 @@ SystemInitializerCommon::Initialize()
platform_android::PlatformAndroid::Initialize();
EmulateInstructionARM::Initialize();
+ EmulateInstructionMIPS::Initialize();
EmulateInstructionMIPS64::Initialize();
//----------------------------------------------------------------------
@@ -163,6 +165,7 @@ SystemInitializerCommon::Terminate()
PlatformiOSSimulator::Terminate();
EmulateInstructionARM::Terminate();
+ EmulateInstructionMIPS::Terminate();
EmulateInstructionMIPS64::Terminate();
#if defined(__APPLE__)
Modified: lldb/trunk/source/Plugins/Instruction/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/CMakeLists.txt?rev=237420&r1=237419&r2=237420&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Instruction/CMakeLists.txt Fri May 15 01:53:30 2015
@@ -1,3 +1,4 @@
add_subdirectory(ARM)
add_subdirectory(ARM64)
+add_subdirectory(MIPS)
add_subdirectory(MIPS64)
Added: lldb/trunk/source/Plugins/Instruction/MIPS/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/MIPS/CMakeLists.txt?rev=237420&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/MIPS/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/Instruction/MIPS/CMakeLists.txt Fri May 15 01:53:30 2015
@@ -0,0 +1,5 @@
+set(LLVM_NO_RTTI 1)
+
+add_lldb_library(lldbPluginInstructionMIPS
+ EmulateInstructionMIPS.cpp
+ )
Added: lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp?rev=237420&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp (added)
+++ lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp Fri May 15 01:53:30 2015
@@ -0,0 +1,591 @@
+//===-- EmulateInstructionMIPS.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulateInstructionMIPS.h"
+
+#include <stdlib.h>
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Opcode.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/UnwindPlan.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+#include "Plugins/Process/Utility/RegisterContext_mips64.h" //mips32 has same registers nos as mips64
+
+using namespace lldb;
+using namespace lldb_private;
+
+#define UInt(x) ((uint64_t)x)
+#define integer int64_t
+
+
+//----------------------------------------------------------------------
+//
+// EmulateInstructionMIPS implementation
+//
+//----------------------------------------------------------------------
+
+#ifdef __mips__
+extern "C" {
+ void LLVMInitializeMipsTargetInfo ();
+ void LLVMInitializeMipsTarget ();
+ void LLVMInitializeMipsAsmPrinter ();
+ void LLVMInitializeMipsTargetMC ();
+ void LLVMInitializeMipsDisassembler ();
+}
+#endif
+
+EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &arch) :
+ EmulateInstruction (arch)
+{
+ /* Create instance of llvm::MCDisassembler */
+ std::string Error;
+ llvm::Triple triple = arch.GetTriple();
+ const llvm::Target *target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error);
+
+ /*
+ * If we fail to get the target then we haven't registered it. The SystemInitializerCommon
+ * does not initialize targets, MCs and disassemblers. However we need the MCDisassembler
+ * to decode the instructions so that the decoding complexity stays with LLVM.
+ * Initialize the MIPS targets and disassemblers.
+ */
+#ifdef __mips__
+ if (!target)
+ {
+ LLVMInitializeMipsTargetInfo ();
+ LLVMInitializeMipsTarget ();
+ LLVMInitializeMipsAsmPrinter ();
+ LLVMInitializeMipsTargetMC ();
+ LLVMInitializeMipsDisassembler ();
+ target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error);
+ }
+#endif
+
+ assert (target);
+
+ llvm::StringRef cpu;
+
+ switch (arch.GetCore())
+ {
+ case ArchSpec::eCore_mips32:
+ case ArchSpec::eCore_mips32el:
+ cpu = "mips32"; break;
+ case ArchSpec::eCore_mips32r2:
+ case ArchSpec::eCore_mips32r2el:
+ cpu = "mips32r2"; break;
+ case ArchSpec::eCore_mips32r3:
+ case ArchSpec::eCore_mips32r3el:
+ cpu = "mips32r3"; break;
+ case ArchSpec::eCore_mips32r5:
+ case ArchSpec::eCore_mips32r5el:
+ cpu = "mips32r5"; break;
+ case ArchSpec::eCore_mips32r6:
+ case ArchSpec::eCore_mips32r6el:
+ cpu = "mips32r6"; break;
+ case ArchSpec::eCore_mips64:
+ case ArchSpec::eCore_mips64el:
+ cpu = "mips64"; break;
+ case ArchSpec::eCore_mips64r2:
+ case ArchSpec::eCore_mips64r2el:
+ cpu = "mips64r2"; break;
+ case ArchSpec::eCore_mips64r3:
+ case ArchSpec::eCore_mips64r3el:
+ cpu = "mips64r3"; break;
+ case ArchSpec::eCore_mips64r5:
+ case ArchSpec::eCore_mips64r5el:
+ cpu = "mips64r5"; break;
+ case ArchSpec::eCore_mips64r6:
+ case ArchSpec::eCore_mips64r6el:
+ cpu = "mips64r6"; break;
+ default:
+ cpu = "generic"; break;
+ }
+
+ m_reg_info.reset (target->createMCRegInfo (triple.getTriple()));
+ assert (m_reg_info.get());
+
+ m_insn_info.reset (target->createMCInstrInfo());
+ assert (m_insn_info.get());
+
+ m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple()));
+ m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, ""));
+ assert (m_asm_info.get() && m_subtype_info.get());
+
+ m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr));
+ assert (m_context.get());
+
+ m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context));
+ assert (m_disasm.get());
+}
+
+void
+EmulateInstructionMIPS::Initialize ()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic (),
+ GetPluginDescriptionStatic (),
+ CreateInstance);
+}
+
+void
+EmulateInstructionMIPS::Terminate ()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+ConstString
+EmulateInstructionMIPS::GetPluginNameStatic ()
+{
+ ConstString g_plugin_name ("lldb.emulate-instruction.mips32");
+ return g_plugin_name;
+}
+
+lldb_private::ConstString
+EmulateInstructionMIPS::GetPluginName()
+{
+ static ConstString g_plugin_name ("EmulateInstructionMIPS");
+ return g_plugin_name;
+}
+
+const char *
+EmulateInstructionMIPS::GetPluginDescriptionStatic ()
+{
+ return "Emulate instructions for the MIPS32 architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionMIPS::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
+{
+ if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic(inst_type))
+ {
+ if (arch.GetTriple().getArch() == llvm::Triple::mips
+ || arch.GetTriple().getArch() == llvm::Triple::mipsel)
+ {
+ std::auto_ptr<EmulateInstructionMIPS> emulate_insn_ap (new EmulateInstructionMIPS (arch));
+ if (emulate_insn_ap.get())
+ return emulate_insn_ap.release();
+ }
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionMIPS::SetTargetTriple (const ArchSpec &arch)
+{
+ if (arch.GetTriple().getArch () == llvm::Triple::mips
+ || arch.GetTriple().getArch () == llvm::Triple::mipsel)
+ return true;
+ return false;
+}
+
+const char *
+EmulateInstructionMIPS::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
+EmulateInstructionMIPS::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;
+ default:
+ return false;
+ }
+ }
+
+ if (reg_kind == eRegisterKindDWARF)
+ {
+ ::memset (®_info, 0, sizeof(RegisterInfo));
+ ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
+
+ if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_pc_mips64)
+ {
+ reg_info.byte_size = 4;
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ reg_info.name = GetRegisterName (reg_num, false);
+ reg_info.alt_name = GetRegisterName (reg_num, true);
+ reg_info.kinds[eRegisterKindDWARF] = reg_num;
+ }
+ else
+ {
+ return false;
+ }
+
+ 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;
+}
+
+EmulateInstructionMIPS::MipsOpcode*
+EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
+{
+ static EmulateInstructionMIPS::MipsOpcode
+ g_opcodes[] =
+ {
+ //----------------------------------------------------------------------
+ // Prologue/Epilogue instructions
+ //----------------------------------------------------------------------
+ { "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt,rs,immediate" },
+ { "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt,offset(rs)" },
+ { "LW", &EmulateInstructionMIPS::Emulate_LW, "LW 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 (! strcasecmp (g_opcodes[i].op_name, op_name))
+ return &g_opcodes[i];
+ }
+
+ return NULL;
+}
+
+bool
+EmulateInstructionMIPS::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
+EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
+{
+ bool success = false;
+ llvm::MCInst mc_insn;
+ uint64_t insn_size;
+ DataExtractor data;
+
+ /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */
+ if (m_opcode.GetData (data))
+ {
+ llvm::MCDisassembler::DecodeStatus decode_status;
+ llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize());
+ decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ if (decode_status != llvm::MCDisassembler::Success)
+ return false;
+ }
+
+ /*
+ * mc_insn.getOpcode() returns decoded opcode. However to make use
+ * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc".
+ */
+ const char *op_name = m_insn_info->getName (mc_insn.getOpcode ());
+
+ if (op_name == NULL)
+ return false;
+
+ /*
+ * Decoding has been done already. Just get the call-back function
+ * and emulate the instruction.
+ */
+ MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name);
+
+ if (opcode_data == NULL)
+ return false;
+
+ uint64_t old_pc = 0, new_pc = 0;
+ const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+
+ if (auto_advance_pc)
+ {
+ old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+ }
+
+ /* emulate instruction */
+ success = (this->*opcode_data->callback) (mc_insn);
+ if (!success)
+ return false;
+
+ if (auto_advance_pc)
+ {
+ new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ /* If we haven't changed the PC, change it here */
+ if (old_pc == new_pc)
+ {
+ new_pc += 4;
+ Context context;
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, new_pc))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::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 ("EmulateInstructionMIPS");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::nonvolatile_reg_p (uint32_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_gp_mips64:
+ case gcc_dwarf_sp_mips64:
+ case gcc_dwarf_r30_mips64:
+ case gcc_dwarf_ra_mips64:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
+{
+ bool success = false;
+ const uint32_t imm16 = insn.getOperand(2).getImm();
+ uint32_t imm = SignedBits(imm16, 15, 0);
+ uint64_t result;
+ uint32_t src, dst;
+
+ dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ /* Check if this is addiu sp,<src>,imm16 */
+ if (dst == gcc_dwarf_sp_mips64)
+ {
+ /* read <src> register */
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success);
+ if (!success)
+ return false;
+
+ result = src_opd_val + imm;
+
+ Context context;
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm);
+
+ /* We are allocating bytes on stack */
+ context.type = eContextAdjustStackPointer;
+
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result);
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t imm16 = insn.getOperand(2).getImm();
+ uint32_t imm = SignedBits(imm16, 15, 0);
+ uint32_t src, base;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ /* We look for sp based non-volatile register stores */
+ if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ {
+ uint32_t address;
+ RegisterInfo reg_info_base;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
+ || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ return false;
+
+ /* read SP */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ Context context;
+ RegisterValue data_src;
+ context.type = eContextPushRegisterOnStack;
+ context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
+
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
+
+ if (!ReadRegister (®_info_base, data_src))
+ return false;
+
+ if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
+{
+ uint32_t src, base;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ {
+ RegisterValue data_src;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ return false;
+
+ Context context;
+ context.type = eContextRegisterLoad;
+
+ if (!WriteRegister (context, ®_info_src, data_src))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
Added: lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h?rev=237420&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h (added)
+++ lldb/trunk/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h Fri May 15 01:53:30 2015
@@ -0,0 +1,148 @@
+//===-- EmulateInstructionMIPS.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EmulateInstructionMIPS_h_
+#define EmulateInstructionMIPS_h_
+
+namespace llvm
+{
+ class MCDisassembler;
+ class MCSubtargetInfo;
+ class MCRegisterInfo;
+ class MCAsmInfo;
+ class MCContext;
+ class MCInstrInfo;
+ class MCInst;
+}
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+class EmulateInstructionMIPS : 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:
+ case lldb_private::eInstructionTypePCModifying:
+ return true;
+
+ 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);
+
+ EmulateInstructionMIPS (const lldb_private::ArchSpec &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
+ {
+ const char *op_name;
+ bool (EmulateInstructionMIPS::*callback) (llvm::MCInst& insn);
+ const char *insn_name;
+ } MipsOpcode;
+
+ static MipsOpcode*
+ GetOpcodeForInstruction (const char *op_name);
+
+ bool
+ Emulate_ADDiu (llvm::MCInst& insn);
+
+ bool
+ Emulate_SW (llvm::MCInst& insn);
+
+ bool
+ Emulate_LW (llvm::MCInst& insn);
+
+ bool
+ nonvolatile_reg_p (uint32_t regnum);
+
+ const char *
+ GetRegisterName (unsigned reg_num, bool altnernate_name);
+
+private:
+ std::unique_ptr<llvm::MCDisassembler> m_disasm;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info;
+ std::unique_ptr<llvm::MCRegisterInfo> m_reg_info;
+ std::unique_ptr<llvm::MCAsmInfo> m_asm_info;
+ std::unique_ptr<llvm::MCContext> m_context;
+ std::unique_ptr<llvm::MCInstrInfo> m_insn_info;
+};
+
+#endif // EmulateInstructionMIPS_h_
Added: lldb/trunk/source/Plugins/Instruction/MIPS/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/MIPS/Makefile?rev=237420&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Instruction/MIPS/Makefile (added)
+++ lldb/trunk/source/Plugins/Instruction/MIPS/Makefile Fri May 15 01:53:30 2015
@@ -0,0 +1,14 @@
+##===- source/Plugins/Instruction/MIPS/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 := lldbPluginEmulateInstructionMIPS
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
Modified: lldb/trunk/source/Plugins/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Makefile?rev=237420&r1=237419&r2=237420&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Makefile (original)
+++ lldb/trunk/source/Plugins/Makefile Fri May 15 01:53:30 2015
@@ -19,7 +19,7 @@ PARALLEL_DIRS := ABI/MacOSX-arm ABI/MacO
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/MIPS64 \
+ Instruction/ARM Instruction/ARM64 Instruction/MIPS Instruction/MIPS64 \
UnwindAssembly/InstEmulation UnwindAssembly/x86 \
LanguageRuntime/CPlusPlus/ItaniumABI \
LanguageRuntime/ObjC/AppleObjCRuntime \
Modified: lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp?rev=237420&r1=237419&r2=237420&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp Fri May 15 01:53:30 2015
@@ -614,6 +614,7 @@ PlatformLinux::GetSoftwareBreakpointTrap
}
}
break;
+ case llvm::Triple::mips:
case llvm::Triple::mips64:
{
static const uint8_t g_hex_opcode[] = { 0x00, 0x00, 0x00, 0x0d };
@@ -621,6 +622,7 @@ PlatformLinux::GetSoftwareBreakpointTrap
trap_opcode_size = sizeof(g_hex_opcode);
}
break;
+ case llvm::Triple::mipsel:
case llvm::Triple::mips64el:
{
static const uint8_t g_hex_opcode[] = { 0x0d, 0x00, 0x00, 0x00 };
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=237420&r1=237419&r2=237420&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Fri May 15 01:53:30 2015
@@ -2320,6 +2320,8 @@ Thread::GetUnwinder ()
case llvm::Triple::arm:
case llvm::Triple::aarch64:
case llvm::Triple::thumb:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::ppc:
More information about the lldb-commits
mailing list