Index: include/lldb/Core/Architecture.h =================================================================== --- include/lldb/Core/Architecture.h +++ include/lldb/Core/Architecture.h @@ -12,6 +12,9 @@ #include "lldb/Core/PluginInterface.h" +#include +#include + namespace lldb_private { class Architecture : public PluginInterface { @@ -112,6 +115,17 @@ return addr; } + static constexpr uint8_t max_features_count = 32u; + virtual std::bitset GetFeatures() const { return 0; } + + using ReadRegister = std::function( + ConstString /*name*/, bool /*case_sensitive*/)>; + virtual bool SetFeatures(const ReadRegister &func) { return true; } + + virtual bool MatchFeatures(const ArchSpec &spec) const { return true; } + + virtual bool SupportsFeatures() const { return false; } + private: Architecture(const Architecture &) = delete; void operator=(const Architecture &) = delete; Index: include/lldb/Utility/ArchSpec.h =================================================================== --- include/lldb/Utility/ArchSpec.h +++ include/lldb/Utility/ArchSpec.h @@ -190,6 +190,8 @@ eCore_kalimba4, eCore_kalimba5, + eCore_arc, // little endian ARC + kNumCores, kCore_invalid, Index: source/API/SystemInitializerFull.cpp =================================================================== --- source/API/SystemInitializerFull.cpp +++ source/API/SystemInitializerFull.cpp @@ -39,6 +39,7 @@ #include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h" #include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h" #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h" +#include "Plugins/Architecture/Arc/ArchitectureArc.h" #include "Plugins/Architecture/Arm/ArchitectureArm.h" #include "Plugins/Architecture/Mips/ArchitectureMips.h" #include "Plugins/Architecture/PPC64/ArchitecturePPC64.h" @@ -327,6 +328,7 @@ ABISysV_mips64::Initialize(); ABISysV_s390x::Initialize(); + ArchitectureArc::Initialize(); ArchitectureArm::Initialize(); ArchitectureMips::Initialize(); ArchitecturePPC64::Initialize(); @@ -444,6 +446,7 @@ ClangASTContext::Terminate(); + ArchitectureArc::Terminate(); ArchitectureArm::Terminate(); ArchitectureMips::Terminate(); ArchitecturePPC64::Terminate(); Index: source/Plugins/Architecture/Arc/ArchitectureArc.h =================================================================== --- source/Plugins/Architecture/Arc/ArchitectureArc.h +++ source/Plugins/Architecture/Arc/ArchitectureArc.h @@ -0,0 +1,50 @@ +//===-- ArchitectureArc.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGIN_ARCHITECTURE_ARC_H +#define LLDB_PLUGIN_ARCHITECTURE_ARC_H + +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +namespace arc_features { +enum { reduced_register_file, big_endian, address_size_32 }; +} + +class ArchitectureArc : public Architecture { +public: + static ConstString GetPluginNameStatic(); + static void Initialize(); + static void Terminate(); + + ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + + void OverrideStopInfo(Thread &thread) const override {} + + std::bitset GetFeatures() const override { + return m_features; + } + + bool SetFeatures(const ReadRegister &func) override; + + bool MatchFeatures(const ArchSpec &spec) const override; + + bool SupportsFeatures() const override { return true; } + +private: + static std::unique_ptr Create(const ArchSpec &arch); + ArchitectureArc() = default; + std::bitset m_features; +}; + +} // namespace lldb_private + +#endif // LLDB_PLUGIN_ARCHITECTURE_ARC_H Index: source/Plugins/Architecture/Arc/ArchitectureArc.cpp =================================================================== --- source/Plugins/Architecture/Arc/ArchitectureArc.cpp +++ source/Plugins/Architecture/Arc/ArchitectureArc.cpp @@ -0,0 +1,85 @@ +//===-- ArchitectureArc.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Architecture/Arc/ArchitectureArc.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/RegisterValue.h" + +#include + +using namespace lldb_private; +using namespace lldb; + +ConstString ArchitectureArc::GetPluginNameStatic() { + return ConstString("arc"); +} + +void ArchitectureArc::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "ARC-specific algorithms", + &ArchitectureArc::Create); +} + +void ArchitectureArc::Terminate() { + PluginManager::UnregisterPlugin(&ArchitectureArc::Create); +} + +std::unique_ptr ArchitectureArc::Create(const ArchSpec &arch) { + if (arch.GetMachine() != llvm::Triple::arc) + return nullptr; + return std::unique_ptr(new ArchitectureArc()); +} + +ConstString ArchitectureArc::GetPluginName() { return GetPluginNameStatic(); } +uint32_t ArchitectureArc::GetPluginVersion() { return 1; } + +bool ArchitectureArc::SetFeatures(const ReadRegister &func) { + + auto set_feature = [&func, this]( + ConstString reg_name, uint_least32_t field_mask, size_t feature_position) + -> llvm::Optional { + const bool case_sensitive = false; + auto opt_value = func(reg_name, case_sensitive); + if (!opt_value) + return llvm::None; + + auto reg_value = opt_value.getValue().GetAsUInt64(0); + m_features.set(feature_position, reg_value & field_mask); + return reg_value; + }; + + ConstString rf_build("rf_build"); + // RF_BUILD "Number of Entries" bit. + const uint_least16_t rf_entries = 1 << 9; + if (!set_feature(rf_build, rf_entries, arc_features::reduced_register_file)) + return false; + + ConstString isa_config("isa_config"); + // ISA_CONFIG "Byte Order" bit. + const uint_least32_t byte_order = 1 << 20; + auto result = set_feature(isa_config, byte_order, arc_features::big_endian); + if (!result) + return false; + + // ISA_CONFIG "Address Size" field. + const uint_least32_t addr_size = 4 << 16; + m_features.set(arc_features::address_size_32, result.getValue() & addr_size); + return true; +} + +bool ArchitectureArc::MatchFeatures(const ArchSpec &spec) const { + return ((spec.GetByteOrder() == eByteOrderBig) == + m_features.test(arc_features::big_endian)) && + ((spec.GetAddressByteSize() == 4) == + m_features.test(arc_features::address_size_32)); +} Index: source/Plugins/Architecture/Arc/CMakeLists.txt =================================================================== --- source/Plugins/Architecture/Arc/CMakeLists.txt +++ source/Plugins/Architecture/Arc/CMakeLists.txt @@ -0,0 +1,10 @@ +add_lldb_library(lldbPluginArchitectureArc PLUGIN + ArchitectureArc.cpp + + LINK_LIBS + lldbCore + lldbTarget + lldbUtility + LINK_COMPONENTS + Support + ) Index: source/Plugins/Architecture/CMakeLists.txt =================================================================== --- source/Plugins/Architecture/CMakeLists.txt +++ source/Plugins/Architecture/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(Arc) add_subdirectory(Arm) add_subdirectory(Mips) add_subdirectory(PPC64) Index: source/Plugins/Process/Utility/DynamicRegisterInfo.h =================================================================== --- source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -52,6 +52,9 @@ lldb_private::RegisterInfo *GetRegisterInfoAtIndex(uint32_t i); + const lldb_private::RegisterInfo *GetRegisterInfo( + const lldb_private::ConstString ®_name, bool case_sensitive = true) const; + const lldb_private::RegisterSet *GetRegisterSet(uint32_t i) const; uint32_t GetRegisterSetIndexByName(lldb_private::ConstString &set_name, @@ -77,9 +80,6 @@ typedef std::vector dwarf_opcode; typedef std::map dynamic_reg_size_map; - const lldb_private::RegisterInfo * - GetRegisterInfo(const lldb_private::ConstString ®_name) const; - void MoveFrom(DynamicRegisterInfo &&info); reg_collection m_regs; Index: source/Plugins/Process/Utility/DynamicRegisterInfo.cpp =================================================================== --- source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -622,6 +622,55 @@ } break; + case llvm::Triple::arc: + { + for (auto ® : m_regs) { + if (strcmp(reg.name, "pc") == 0) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + else if ((strcmp(reg.name, "fp") == 0) || + (strcmp(reg.name, "r27") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + else if ((strcmp(reg.name, "sp") == 0) || + (strcmp(reg.name, "r28") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; + else if ((strcmp(reg.name, "blink") == 0) || + (strcmp(reg.name, "r31") == 0)) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; + else if (strcmp(reg.name, "status32") == 0) + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; + + switch (reg.kinds[eRegisterKindDWARF]) { + case 0: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG1; + break; + case 1: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG2; + break; + case 2: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG3; + break; + case 3: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG4; + break; + case 4: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG5; + break; + case 5: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG6; + break; + case 6: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG7; + break; + case 7: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG8; + break; + default: + break; + } + } + } + break; + default: break; } @@ -747,13 +796,10 @@ } const lldb_private::RegisterInfo *DynamicRegisterInfo::GetRegisterInfo( - const lldb_private::ConstString ®_name) const { - for (auto ®_info : m_regs) { - // We can use pointer comparison since we used a ConstString to set the - // "name" member in AddRegister() - if (reg_info.name == reg_name.GetCString()) { + const lldb_private::ConstString ®_name, bool case_sensitive) const { + for (const auto ®_info : m_regs) { + if (ConstString::Equals(ConstString(reg_info.name), reg_name, case_sensitive)) return ®_info; - } } - return NULL; + return nullptr; } Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -345,7 +345,7 @@ // not, we assume no limit // build the qSupported packet - std::vector features = {"xmlRegisters=i386,arm,mips"}; + std::vector features = {"xmlRegisters=i386,arm,mips,arc"}; StreamString packet; packet.PutCString("qSupported"); for (uint32_t i = 0; i < features.size(); ++i) { Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1198,6 +1198,34 @@ } } + auto arch_plugin = GetTarget().GetArchitecturePlugin(); + if (nullptr != arch_plugin && arch_plugin->SupportsFeatures()) { + auto reg_reader = [this](ConstString reg_name, bool case_sensitive) + -> llvm::Optional { + auto reg_info = m_register_info.GetRegisterInfo(reg_name, + case_sensitive); + if(nullptr == reg_info) + return llvm::None; + + // Feature registers are not context-dependent. + const auto tid = LLDB_INVALID_THREAD_ID; + // Cannot use GDBRemoteRegisterContext here, it is not created yet. + DataBufferSP buffer_sp = GetGDBRemote().ReadRegister(tid, + reg_info->kinds[eRegisterKindProcessPlugin]); + if (!buffer_sp || buffer_sp->GetByteSize() < reg_info->byte_size) + return llvm::None; + + return RegisterValue(buffer_sp->GetBytes(), buffer_sp->GetByteSize(), + GetByteOrder()); + }; + + if (!arch_plugin->SetFeatures(reg_reader) && log) + log->PutCString("Failed to set architecture features"); + + if (!arch_plugin->MatchFeatures(GetTarget().GetArchitecture())) + log->PutCString("The architecture has incompatible features"); + } + // Find out which StructuredDataPlugins are supported by the debug monitor. // These plugins transmit data over async $J packets. auto supported_packets_array = Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp +++ source/Target/Platform.cpp @@ -1869,6 +1869,12 @@ size_t trap_opcode_size = 0; switch (arch.GetMachine()) { + case llvm::Triple::arc: { + static const uint8_t g_hex_opcode[] = { 0xff, 0x7f }; + trap_opcode = g_hex_opcode; + trap_opcode_size = sizeof(g_hex_opcode); + } break; + case llvm::Triple::aarch64: { static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4}; trap_opcode = g_aarch64_opcode; Index: source/Target/Thread.cpp =================================================================== --- source/Target/Thread.cpp +++ source/Target/Thread.cpp @@ -2061,6 +2061,7 @@ switch (machine) { case llvm::Triple::x86_64: case llvm::Triple::x86: + case llvm::Triple::arc: case llvm::Triple::arm: case llvm::Triple::aarch64: case llvm::Triple::thumb: Index: source/Utility/ArchSpec.cpp =================================================================== --- source/Utility/ArchSpec.cpp +++ source/Utility/ArchSpec.cpp @@ -221,7 +221,8 @@ {eByteOrderLittle, 4, 1, 1, llvm::Triple::kalimba, ArchSpec::eCore_kalimba4, "kalimba4"}, {eByteOrderLittle, 4, 1, 1, llvm::Triple::kalimba, ArchSpec::eCore_kalimba5, - "kalimba5"}}; + "kalimba5"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arc, ArchSpec::eCore_arc, "arc"}}; // Ensure that we have an entry in the g_core_definitions for each core. If you // comment out an entry above, you will need to comment out the corresponding @@ -458,7 +459,9 @@ {ArchSpec::eCore_kalimba4, llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v4, 0xFFFFFFFFu, 0xFFFFFFFFu}, // KALIMBA {ArchSpec::eCore_kalimba5, llvm::ELF::EM_CSR_KALIMBA, - llvm::Triple::KalimbaSubArch_v5, 0xFFFFFFFFu, 0xFFFFFFFFu} // KALIMBA + llvm::Triple::KalimbaSubArch_v5, 0xFFFFFFFFu, 0xFFFFFFFFu}, // KALIMBA + {ArchSpec::eCore_arc, llvm::ELF::EM_ARC_COMPACT2, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu } // ARC }; static const ArchDefinition g_elf_arch_def = {