Index: include/lldb/Core/Architecture.h =================================================================== --- include/lldb/Core/Architecture.h +++ include/lldb/Core/Architecture.h @@ -11,6 +11,10 @@ #define LLDB_CORE_ARCHITECTURE_H #include "lldb/Core/PluginInterface.h" +#include "lldb/Utility/Flags.h" + +#include +#include namespace lldb_private { @@ -112,6 +116,16 @@ return addr; } + virtual std::vector + ConfigurationRegisterNames() const { return {}; } + + using ConfigurationRegisterValues = std::map; + virtual bool SetFlagsFrom(const ConfigurationRegisterValues &) { return true; } + + virtual bool TestFlag(Flags::ValueType bit) const { return false; } + + virtual bool MatchFlags(const ArchSpec &spec) const { return true; } + 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/Plugins/Architecture/Arc/ArchitectureArc.h =================================================================== --- source/Plugins/Architecture/Arc/ArchitectureArc.h +++ source/Plugins/Architecture/Arc/ArchitectureArc.h @@ -0,0 +1,53 @@ +//===-- 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 = 1u << 0, + big_endian = 1u << 1, + address_size_32 = 1u << 2 +}; +} + +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::vector ConfigurationRegisterNames() const override; + + bool SetFlagsFrom(const ConfigurationRegisterValues &) override; + + bool TestFlag(Flags::ValueType bit) const override; + + bool MatchFlags(const ArchSpec &spec) const override; + +private: + static std::unique_ptr Create(const ArchSpec &arch); + ArchitectureArc() = default; + + lldb_private::Flags m_flags; +}; + +} // 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,86 @@ +//===-- 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" + +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::SetFlagsFrom(const ConfigurationRegisterValues ®s) { + ConstString rf_build("rf_build"); + auto it = regs.find(rf_build); + if (it == regs.end()) + return false; + + // RF_BUILD "Number of Entries" bit. + const uint32_t rf_entries = 1 << 9; + if (it->second & rf_entries) + m_flags.Set(arc_features::reduced_register_file); + + ConstString isa_config("isa_config"); + it = regs.find(isa_config); + if (it == regs.end()) + return false; + + // ISA_CONFIG "Byte Order" bit. + const uint_least32_t byte_order = 1 << 20; + if (it->second & byte_order) + m_flags.Set(arc_features::big_endian); + + // ISA_CONFIG "Address Size" field. + const uint_least32_t addr_size = 4 << 16; + if (it->second & addr_size) + m_flags.Set(arc_features::address_size_32); + + return true; +} + +bool ArchitectureArc::TestFlag(Flags::ValueType bit) const { + return m_flags.Test(bit); +} + +std::vector ArchitectureArc::ConfigurationRegisterNames() const { + return { ConstString("rf_build"), ConstString("isa_config") }; +} + +bool ArchitectureArc::MatchFlags(const ArchSpec &spec) const { + return ((spec.GetByteOrder() == eByteOrderBig) == + m_flags.Test(arc_features::big_endian)) && + ((spec.GetAddressByteSize() == 4) == + m_flags.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,57 @@ } break; + case llvm::Triple::arc: + { + enum ArgumentRegisters { + eArg1 = 0, eArg2, eArg3, eArg4, eArg5, eArg6, eArg7, eArg8 }; + 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 eArg1: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG1; + break; + case eArg2: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG2; + break; + case eArg3: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG3; + break; + case eArg4: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG4; + break; + case eArg5: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG5; + break; + case eArg6: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG6; + break; + case eArg7: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG7; + break; + case eArg8: + reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_ARG8; + break; + default: + break; + } + } + } + break; + default: break; } @@ -747,13 +798,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,44 @@ } } + auto arch_plugin = GetTarget().GetArchitecturePlugin(); + if (nullptr != arch_plugin) { + Architecture::ConfigurationRegisterValues reg_values; + + for (const auto ®_name : arch_plugin->ConfigurationRegisterNames()) { + bool case_sensitive = false; + auto reg_info = m_register_info.GetRegisterInfo(reg_name, case_sensitive); + if (!reg_info) { + if (log) + log->Printf("Cannot find register info for \"%s\"", + reg_name.AsCString()); + continue; + } + + // Configuration 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){ + if (log) + log->Printf("Failed to read configuration register \"%s\"", + reg_name.AsCString()); + continue; + } + + reg_values[reg_name] = RegisterValue(buffer_sp->GetBytes(), + buffer_sp->GetByteSize(), + GetByteOrder()).GetAsUInt32(); + } + + if (!arch_plugin->SetFlagsFrom(reg_values) && log) + log->PutCString("Failed to set architechture's features"); + + if (!arch_plugin->MatchFlags(GetTarget().GetArchitecture()) && log) + 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 = {