Index: lldb/trunk/cmake/LLDBDependencies.cmake =================================================================== --- lldb/trunk/cmake/LLDBDependencies.cmake +++ lldb/trunk/cmake/LLDBDependencies.cmake @@ -49,6 +49,7 @@ lldbPluginABISysV_ppc64 lldbPluginInstructionARM lldbPluginInstructionARM64 + lldbPluginInstructionMIPS64 lldbPluginObjectFilePECOFF lldbPluginOSPython lldbPluginMemoryHistoryASan Index: lldb/trunk/lib/Makefile =================================================================== --- lldb/trunk/lib/Makefile +++ lldb/trunk/lib/Makefile @@ -45,6 +45,7 @@ lldbPluginDynamicLoaderMacOSX.a \ lldbPluginEmulateInstructionARM.a \ lldbPluginEmulateInstructionARM64.a \ + lldbPluginEmulateInstructionMIPS64.a \ lldbPluginInstrumentationRuntimeAddressSanitizer.a \ lldbPluginLanguageRuntimeCPlusPlusItaniumABI.a \ lldbPluginLanguageRuntimeObjCAppleObjCRuntime.a \ Index: lldb/trunk/source/Plugins/Instruction/CMakeLists.txt =================================================================== --- lldb/trunk/source/Plugins/Instruction/CMakeLists.txt +++ lldb/trunk/source/Plugins/Instruction/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(ARM) add_subdirectory(ARM64) +add_subdirectory(MIPS64) Index: lldb/trunk/source/Plugins/Instruction/MIPS64/CMakeLists.txt =================================================================== --- lldb/trunk/source/Plugins/Instruction/MIPS64/CMakeLists.txt +++ lldb/trunk/source/Plugins/Instruction/MIPS64/CMakeLists.txt @@ -0,0 +1,5 @@ +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginInstructionMIPS64 + EmulateInstructionMIPS64.cpp + ) Index: lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h =================================================================== --- lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h +++ lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h @@ -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_ Index: lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp =================================================================== --- lldb/trunk/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ lldb/trunk/source/Plugins/Instruction/MIPS64/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 + +#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 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*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; +} Index: lldb/trunk/source/Plugins/Instruction/MIPS64/Makefile =================================================================== --- lldb/trunk/source/Plugins/Instruction/MIPS64/Makefile +++ lldb/trunk/source/Plugins/Instruction/MIPS64/Makefile @@ -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 Index: lldb/trunk/source/Plugins/Makefile =================================================================== --- lldb/trunk/source/Plugins/Makefile +++ lldb/trunk/source/Plugins/Makefile @@ -19,7 +19,7 @@ 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 \ Index: lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp =================================================================== --- lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -610,7 +610,6 @@ 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 @@ // } 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: { Index: lldb/trunk/source/lldb.cpp =================================================================== --- lldb/trunk/source/lldb.cpp +++ lldb/trunk/source/lldb.cpp @@ -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 @@ UnwindAssembly_x86::Initialize(); EmulateInstructionARM::Initialize(); EmulateInstructionARM64::Initialize(); + EmulateInstructionMIPS64::Initialize(); SymbolFileDWARFDebugMap::Initialize(); ItaniumABILanguageRuntime::Initialize(); AppleObjCRuntimeV2::Initialize(); @@ -339,6 +341,7 @@ UnwindAssemblyInstEmulation::Terminate(); EmulateInstructionARM::Terminate(); EmulateInstructionARM64::Terminate(); + EmulateInstructionMIPS64::Terminate(); SymbolFileDWARFDebugMap::Terminate(); ItaniumABILanguageRuntime::Terminate(); AppleObjCRuntimeV2::Terminate();