Index: include/lldb/Core/Architecture.h =================================================================== --- include/lldb/Core/Architecture.h +++ include/lldb/Core/Architecture.h @@ -10,6 +10,7 @@ #define LLDB_CORE_ARCHITECTURE_H #include "lldb/Core/PluginInterface.h" +#include "lldb/Utility/Flags.h" namespace lldb_private { @@ -30,7 +31,7 @@ /// stopped at the current PC. The code is generic and applies to all /// ARM CPUs. //------------------------------------------------------------------ - virtual void OverrideStopInfo(Thread &thread) const = 0; + virtual void OverrideStopInfo(Thread &thread) const {} //------------------------------------------------------------------ /// This method is used to get the number of bytes that should be @@ -111,9 +112,14 @@ return addr; } + const Flags &GetFlags() const { return m_flags; } + Flags &GetFlags() { return m_flags; } + private: Architecture(const Architecture &) = delete; void operator=(const Architecture &) = delete; + + Flags m_flags; }; } // namespace lldb_private Index: include/lldb/Utility/ArchSpec.h =================================================================== --- include/lldb/Utility/ArchSpec.h +++ include/lldb/Utility/ArchSpec.h @@ -189,6 +189,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 @@ -38,6 +38,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" @@ -326,6 +327,7 @@ ABISysV_mips64::Initialize(); ABISysV_s390x::Initialize(); + ArchitectureArc::Initialize(); ArchitectureArm::Initialize(); ArchitectureMips::Initialize(); ArchitecturePPC64::Initialize(); @@ -443,6 +445,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,38 @@ +//===-- ArchitectureArc.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGIN_ARCHITECTURE_ARC_H +#define LLDB_PLUGIN_ARCHITECTURE_ARC_H + +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +class ArchitectureArc : public Architecture { +public: + FLAGS_ANONYMOUS_ENUM() { + eReducedRegisterFile = (1u << 0), + eBigEndian = (1u << 1), + eAddressSize32 = (1u << 2) + }; + + static ConstString GetPluginNameStatic(); + static void Initialize(); + static void Terminate(); + + ConstString GetPluginName() override; + uint32_t GetPluginVersion() override; + +private: + static std::unique_ptr Create(const ArchSpec &arch); + ArchitectureArc() = default; +}; + +} // 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,37 @@ +//===-- ArchitectureArc.cpp -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Architecture/Arc/ArchitectureArc.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Utility/ArchSpec.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; } 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/Architecture/Mips/ArchitectureMips.h =================================================================== --- source/Plugins/Architecture/Mips/ArchitectureMips.h +++ source/Plugins/Architecture/Mips/ArchitectureMips.h @@ -23,8 +23,6 @@ ConstString GetPluginName() override; uint32_t GetPluginVersion() override; - void OverrideStopInfo(Thread &thread) const override {} - lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr, Target &) const override; Index: source/Plugins/Architecture/PPC64/ArchitecturePPC64.h =================================================================== --- source/Plugins/Architecture/PPC64/ArchitecturePPC64.h +++ source/Plugins/Architecture/PPC64/ArchitecturePPC64.h @@ -22,8 +22,6 @@ ConstString GetPluginName() override; uint32_t GetPluginVersion() override; - void OverrideStopInfo(Thread &thread) const override {} - //------------------------------------------------------------------ /// This method compares current address with current function's /// local entry point, returning the bytes to skip if they match. Index: source/Plugins/Process/Utility/DynamicRegisterInfo.h =================================================================== --- source/Plugins/Process/Utility/DynamicRegisterInfo.h +++ source/Plugins/Process/Utility/DynamicRegisterInfo.h @@ -51,6 +51,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, @@ -76,9 +79,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 @@ -621,6 +621,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; } @@ -746,13 +797,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 @@ -344,7 +344,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 @@ -70,6 +70,7 @@ #include "lldb/Utility/Timer.h" #include "GDBRemoteRegisterContext.h" +#include "Plugins/Architecture/Arc/ArchitectureArc.h" #include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" @@ -81,6 +82,8 @@ #include "lldb/Utility/StringExtractorGDBRemote.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Threading.h" #include "llvm/Support/raw_ostream.h" @@ -1090,6 +1093,77 @@ return error; } +namespace arc { +bool CheckArchitectureCompatibility(const ArchSpec &arch_spec, + Flags arch_features) { + return ((arch_spec.GetByteOrder() == eByteOrderBig) == + arch_features.Test(ArchitectureArc::eBigEndian)) && + ((arch_spec.GetAddressByteSize() == 4) == + arch_features.Test(ArchitectureArc::eAddressSize32)); +} + +Status SetArchitectureFlags(ProcessGDBRemote &process, + const DynamicRegisterInfo ®isters, + Architecture &arch) { + auto read_register_value = [®isters, &process] (ConstString reg_name) + -> llvm::Expected { + bool case_sensitive = false; + auto reg_info = registers.GetRegisterInfo(reg_name, case_sensitive); + if (!reg_info) + return llvm::createStringError(llvm::errc::result_out_of_range, + "Cannot find register info for \"%s\"", reg_name.AsCString()); + + // 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 = process.GetGDBRemote().ReadRegister(tid, + reg_info->kinds[eRegisterKindProcessPlugin]); + if (!buffer_sp || buffer_sp->GetByteSize() < reg_info->byte_size) + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Failed to read configuration register \"%s\"", reg_name.AsCString()); + + return RegisterValue(buffer_sp->GetBytes(), buffer_sp->GetByteSize(), + process.GetByteOrder()).GetAsUInt32(); + }; + + ConstString rf_build("rf_build"); + auto expected_reg_value = read_register_value(rf_build); + if (!expected_reg_value) + return Status(expected_reg_value.takeError()); + + Flags flags_to_set; + + // RF_BUILD "Number of Entries" bit. + const uint32_t rf_entries = 1 << 9; + if (expected_reg_value.get() & rf_entries) + flags_to_set.Set(ArchitectureArc::eReducedRegisterFile); + + ConstString isa_config("isa_config"); + expected_reg_value = read_register_value(isa_config); + if (!expected_reg_value) + return Status(expected_reg_value.takeError()); + + // ISA_CONFIG "Byte Order" bit. + const uint_least32_t byte_order = 1 << 20; + if (expected_reg_value.get() & byte_order) + flags_to_set.Set(ArchitectureArc::eBigEndian); + + // ISA_CONFIG "Address Size" field. + const uint_least32_t addr_size = 4 << 16; + if (expected_reg_value.get() & addr_size) + flags_to_set.Set(ArchitectureArc::eAddressSize32); + + if (CheckArchitectureCompatibility(process.GetTarget().GetArchitecture(), + flags_to_set)) + arch.GetFlags().Set(flags_to_set.Get()); + else + return Status("The architecture has incompatible features"); + + return Status(); +} +} // namespace arc + void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); if (log) @@ -1210,6 +1284,16 @@ m_gdb_comm.GetSupportedStructuredDataPlugins(); if (supported_packets_array) MapSupportedStructuredDataPlugins(*supported_packets_array); + + if (llvm::Triple::arc == GetTarget().GetArchitecture().GetMachine()) { + auto arch_plugin = GetTarget().GetArchitecturePlugin(); + if (nullptr != arch_plugin) { + auto status = arc::SetArchitectureFlags(*this, m_register_info, + *arch_plugin); + if (status.Fail() && log) + log->PutCString(status.AsCString()); + } + } } } Index: source/Target/Platform.cpp =================================================================== --- source/Target/Platform.cpp +++ source/Target/Platform.cpp @@ -1868,6 +1868,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 @@ -2060,6 +2060,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 @@ -220,7 +220,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 @@ -457,7 +458,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 = {