From: Ilya Kuklin Date: Mon, 17 Apr 2023 22:26:48 +0000 (-0700) Subject: [lldb] Add support for MSP430 in LLDB. X-Git-Tag: upstream/17.0.6~11282 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=81beb15d7e54b16f4beba0bafd982d56c6b95222;p=platform%2Fupstream%2Fllvm.git [lldb] Add support for MSP430 in LLDB. Add MSP430 to the list of available targets, implement MSP430 ABI, add support for debugging targets with 16-bit address size. The update is intended for use with MSPDebug, a GDB server implementation for MSP430. Reviewed By: bulbazord, DavidSpickett Differential Revision: https://reviews.llvm.org/D146965 --- diff --git a/lldb/include/lldb/Utility/ArchSpec.h b/lldb/include/lldb/Utility/ArchSpec.h index 444d427..2de517d 100644 --- a/lldb/include/lldb/Utility/ArchSpec.h +++ b/lldb/include/lldb/Utility/ArchSpec.h @@ -172,6 +172,8 @@ public: eCore_mips64r5el, eCore_mips64r6el, + eCore_msp430, + eCore_ppc_generic, eCore_ppc_ppc601, eCore_ppc_ppc602, diff --git a/lldb/include/lldb/Utility/DataExtractor.h b/lldb/include/lldb/Utility/DataExtractor.h index dbf0bce..0b7e771 100644 --- a/lldb/include/lldb/Utility/DataExtractor.h +++ b/lldb/include/lldb/Utility/DataExtractor.h @@ -843,9 +843,7 @@ public: /// \param[in] addr_size /// The size in bytes to use when extracting addresses. void SetAddressByteSize(uint32_t addr_size) { -#ifdef LLDB_CONFIGURATION_DEBUG - assert(addr_size == 4 || addr_size == 8); -#endif + assert(addr_size == 2 || addr_size == 4 || addr_size == 8); m_addr_size = addr_size; } diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index 3c102dd4..951444d 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -96,12 +96,21 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) { // regions, walk forward through memory until a region is found that has // adequate space for our allocation. if (process_is_alive) { - const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8 - ? 0xffffffffffffffffull - : 0xffffffffull; - - lldbassert(process_sp->GetAddressByteSize() == 4 || - end_of_memory != 0xffffffffull); + uint64_t end_of_memory; + switch (process_sp->GetAddressByteSize()) { + case 2: + end_of_memory = 0xffffull; + break; + case 4: + end_of_memory = 0xffffffffull; + break; + case 8: + end_of_memory = 0xffffffffffffffffull; + break; + default: + lldbassert(false && "Invalid address size."); + return LLDB_INVALID_ADDRESS; + } MemoryRegionInfo region_info; Status err = process_sp->GetMemoryRegionInfo(ret, region_info); @@ -137,26 +146,31 @@ lldb::addr_t IRMemoryMap::FindSpace(size_t size) { // We've tried our algorithm, and it didn't work. Now we have to reset back // to the end of the allocations we've already reported, or use a 'sensible' // default if this is our first allocation. - if (m_allocations.empty()) { uint32_t address_byte_size = GetAddressByteSize(); if (address_byte_size != UINT32_MAX) { switch (address_byte_size) { - case 8: - ret = 0xdead0fff00000000ull; + case 2: + ret = 0x8000ull; break; case 4: ret = 0xee000000ull; break; - default: + case 8: + ret = 0xdead0fff00000000ull; break; + default: + lldbassert(false && "Invalid address size."); + return LLDB_INVALID_ADDRESS; } } } else { auto back = m_allocations.rbegin(); lldb::addr_t addr = back->first; size_t alloc_size = back->second.m_size; - ret = llvm::alignTo(addr + alloc_size, 4096); + auto arch = target_sp->GetArchitecture().GetTriple().getArch(); + auto align = arch == llvm::Triple::msp430 ? 512 : 4096; + ret = llvm::alignTo(addr + alloc_size, align); } return ret; diff --git a/lldb/source/Expression/LLVMUserExpression.cpp b/lldb/source/Expression/LLVMUserExpression.cpp index 6d11abb..af63a16 100644 --- a/lldb/source/Expression/LLVMUserExpression.cpp +++ b/lldb/source/Expression/LLVMUserExpression.cpp @@ -333,7 +333,9 @@ bool LLVMUserExpression::PrepareToExecuteJITExpression( if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) { Status alloc_error; - const size_t stack_frame_size = 512 * 1024; + auto arch = target->GetArchitecture().GetTriple().getArch(); + const size_t stack_frame_size = + arch == llvm::Triple::msp430 ? 512 : 512 * 1024; const bool zero_memory = false; diff --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp index 95258e1..b3ef8f0 100644 --- a/lldb/source/Host/common/NativeProcessProtocol.cpp +++ b/lldb/source/Host/common/NativeProcessProtocol.cpp @@ -503,6 +503,7 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { static const uint8_t g_i386_opcode[] = {0xCC}; static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d}; static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00}; + static const uint8_t g_msp430_opcode[] = {0x43, 0x43}; static const uint8_t g_s390x_opcode[] = {0x00, 0x01}; static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08}; // trap static const uint8_t g_ppcle_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap @@ -528,6 +529,9 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { case llvm::Triple::mips64el: return llvm::ArrayRef(g_mips64el_opcode); + case llvm::Triple::msp430: + return llvm::ArrayRef(g_msp430_opcode); + case llvm::Triple::systemz: return llvm::ArrayRef(g_s390x_opcode); diff --git a/lldb/source/Plugins/ABI/CMakeLists.txt b/lldb/source/Plugins/ABI/CMakeLists.txt index d7cc39b..828aea6 100644 --- a/lldb/source/Plugins/ABI/CMakeLists.txt +++ b/lldb/source/Plugins/ABI/CMakeLists.txt @@ -1,4 +1,4 @@ -foreach(target AArch64 ARM ARC Hexagon Mips PowerPC SystemZ X86) +foreach(target AArch64 ARM ARC Hexagon Mips MSP430 PowerPC SystemZ X86) if (${target} IN_LIST LLVM_TARGETS_TO_BUILD) add_subdirectory(${target}) endif() diff --git a/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.cpp b/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.cpp new file mode 100644 index 0000000..7fb651a --- /dev/null +++ b/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.cpp @@ -0,0 +1,365 @@ +//===-- ABISysV_msp430.cpp --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ABISysV_msp430.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" + +#include "llvm/IR/DerivedTypes.h" +#include "llvm/TargetParser/Triple.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE_ADV(ABISysV_msp430, ABIMSP430) + +enum dwarf_regnums { + dwarf_pc = 0, + dwarf_sp, + dwarf_r2, + dwarf_r3, + dwarf_fp, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, +}; + +static const RegisterInfo g_register_infos[] = { + {"r0", + "pc", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r1", + "sp", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r2", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r3", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r4", + "fp", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_fp, dwarf_fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r5", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r6", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r7", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r8", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r9", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r10", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r11", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r12", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r13", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r14", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }, + {"r15", + "", + 2, + 0, + eEncodingUint, + eFormatHex, + {dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM}, + nullptr, + nullptr, + nullptr, + }}; + +static const uint32_t k_num_register_infos = + sizeof(g_register_infos) / sizeof(RegisterInfo); + +const lldb_private::RegisterInfo * +ABISysV_msp430::GetRegisterInfoArray(uint32_t &count) { + // Make the C-string names and alt_names for the register infos into const + // C-string values by having the ConstString unique the names in the global + // constant C-string pool. + count = k_num_register_infos; + return g_register_infos; +} + +size_t ABISysV_msp430::GetRedZoneSize() const { return 0; } + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ + +ABISP +ABISysV_msp430::CreateInstance(lldb::ProcessSP process_sp, + const ArchSpec &arch) { + if (arch.GetTriple().getArch() == llvm::Triple::msp430) { + return ABISP( + new ABISysV_msp430(std::move(process_sp), MakeMCRegisterInfo(arch))); + } + return ABISP(); +} + +bool ABISysV_msp430::PrepareTrivialCall(Thread &thread, lldb::addr_t sp, + lldb::addr_t pc, lldb::addr_t ra, + llvm::ArrayRef args) const { + // we don't use the traditional trivial call specialized for jit + return false; +} + +bool ABISysV_msp430::GetArgumentValues(Thread &thread, + ValueList &values) const { + return false; +} + +Status ABISysV_msp430::SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value_sp) { + return Status(); +} + +ValueObjectSP ABISysV_msp430::GetReturnValueObjectSimple( + Thread &thread, CompilerType &return_compiler_type) const { + ValueObjectSP return_valobj_sp; + return return_valobj_sp; +} + +ValueObjectSP ABISysV_msp430::GetReturnValueObjectImpl( + Thread &thread, CompilerType &return_compiler_type) const { + ValueObjectSP return_valobj_sp; + return return_valobj_sp; +} + +// called when we are on the first instruction of a new function +bool ABISysV_msp430::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + uint32_t sp_reg_num = dwarf_sp; + uint32_t pc_reg_num = dwarf_pc; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 2); + row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -2, true); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); + + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("msp430 at-func-entry default"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + return true; +} + +bool ABISysV_msp430::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + uint32_t fp_reg_num = dwarf_fp; + uint32_t sp_reg_num = dwarf_sp; + uint32_t pc_reg_num = dwarf_pc; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 2); + row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -2, true); + row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); + row->SetRegisterLocationToUnspecified(fp_reg_num, true); + + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("msp430 default unwind plan"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + return true; +} + +bool ABISysV_msp430::RegisterIsVolatile(const RegisterInfo *reg_info) { + return !RegisterIsCalleeSaved(reg_info); +} + +bool ABISysV_msp430::RegisterIsCalleeSaved(const RegisterInfo *reg_info) { + int reg = ((reg_info->byte_offset) / 2); + + bool save = (reg >= 4) && (reg <= 10); + return save; +} + +void ABISysV_msp430::Initialize(void) { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), "System V ABI for msp430 targets", CreateInstance); +} + +void ABISysV_msp430::Terminate(void) { + PluginManager::UnregisterPlugin(CreateInstance); +} diff --git a/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h b/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h new file mode 100644 index 0000000..91f48a8 --- /dev/null +++ b/lldb/source/Plugins/ABI/MSP430/ABISysV_msp430.h @@ -0,0 +1,88 @@ +//===-- ABISysV_msp430.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_SOURCE_PLUGINS_ABI_MSP430_ABISYSV_MSP430_H +#define LLDB_SOURCE_PLUGINS_ABI_MSP430_ABISYSV_MSP430_H + +#include "lldb/Target/ABI.h" +#include "lldb/lldb-private.h" + +class ABISysV_msp430 : public lldb_private::RegInfoBasedABI { +public: + ~ABISysV_msp430() override = default; + + size_t GetRedZoneSize() const override; + + bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; + + bool GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; + + lldb_private::Status + SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value) override; + + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; + + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + + bool CallFrameAddressIsValid(lldb::addr_t cfa) override { + // Make sure the stack call frame addresses are 2 byte aligned + // and not zero + if (cfa & 0x01 || cfa == 0) + return false; + return true; + } + + bool CodeAddressIsValid(lldb::addr_t pc) override { return true; } + + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + + static void Initialize(); + + static void Terminate(); + + static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, + const lldb_private::ArchSpec &arch); + + static llvm::StringRef GetPluginNameStatic() { return "sysv-msp430"; } + + // PluginInterface protocol + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + +protected: + void CreateRegisterMapIfNeeded(); + + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + + bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); + +private: + using lldb_private::RegInfoBasedABI::RegInfoBasedABI; +}; + +#endif // LLDB_SOURCE_PLUGINS_ABI_MSP430_ABISYSV_MSP430_H diff --git a/lldb/source/Plugins/ABI/MSP430/CMakeLists.txt b/lldb/source/Plugins/ABI/MSP430/CMakeLists.txt new file mode 100644 index 0000000..81abb2d --- /dev/null +++ b/lldb/source/Plugins/ABI/MSP430/CMakeLists.txt @@ -0,0 +1,12 @@ +add_lldb_library(lldbPluginABIMSP430 PLUGIN + ABISysV_msp430.cpp + + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + LINK_COMPONENTS + Support + TargetParser + ) + diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp index f26d6df..b0afe03 100644 --- a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp +++ b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp @@ -71,6 +71,7 @@ llvm::Triple::ArchType stringTo(llvm::StringRef Str) { .Case("arm", Triple::arm) .Cases("arm64", "arm64e", Triple::aarch64) .Case("mips", Triple::mips) + .Case("msp430", Triple::msp430) .Case("ppc", Triple::ppc) .Case("ppc64", Triple::ppc64) .Case("s390", Triple::systemz) diff --git a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp index bf226fa..755c13d 100644 --- a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -123,7 +123,7 @@ PlatformLinux::PlatformLinux(bool is_host) {llvm::Triple::x86_64, llvm::Triple::x86, llvm::Triple::arm, llvm::Triple::aarch64, llvm::Triple::mips64, llvm::Triple::mips64, llvm::Triple::hexagon, llvm::Triple::mips, llvm::Triple::mips64el, - llvm::Triple::mipsel, llvm::Triple::systemz}, + llvm::Triple::mipsel, llvm::Triple::msp430, llvm::Triple::systemz}, llvm::Triple::Linux); } } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp index b391edc..8068614 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterFallback.cpp @@ -19,6 +19,7 @@ namespace process_gdb_remote { } #define R64(name) REG(name, 8) #define R32(name) REG(name, 4) +#define R16(name) REG(name, 2) static std::vector GetRegisters_aarch64() { ConstString empty_alt_name; @@ -35,6 +36,18 @@ static std::vector GetRegisters_aarch64() { return registers; } +static std::vector GetRegisters_msp430() { + ConstString empty_alt_name; + ConstString reg_set{"general purpose registers"}; + + std::vector registers{ + R16(pc), R16(sp), R16(r2), R16(r3), R16(fp), R16(r5), + R16(r6), R16(r7), R16(r8), R16(r9), R16(r10), R16(r11), + R16(r12), R16(r13), R16(r14), R16(r15)}; + + return registers; +} + static std::vector GetRegisters_x86() { ConstString empty_alt_name; ConstString reg_set{"general purpose registers"}; @@ -71,6 +84,8 @@ GetFallbackRegisters(const ArchSpec &arch_to_use) { switch (arch_to_use.GetMachine()) { case llvm::Triple::aarch64: return GetRegisters_aarch64(); + case llvm::Triple::msp430: + return GetRegisters_msp430(); case llvm::Triple::x86: return GetRegisters_x86(); case llvm::Triple::x86_64: diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index cbe9f49..bff24b1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -940,7 +940,8 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); bool version_OK = SymbolFileDWARF::SupportedVersion(header.m_version); - bool addr_size_OK = (header.m_addr_size == 4) || (header.m_addr_size == 8); + bool addr_size_OK = (header.m_addr_size == 2) || (header.m_addr_size == 4) || + (header.m_addr_size == 8); bool type_offset_OK = !header.IsTypeUnit() || (header.m_type_offset <= header.GetLength()); diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 1ddd759..50b54fb 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1895,6 +1895,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, trap_opcode_size = sizeof(g_hex_opcode); } break; + case llvm::Triple::msp430: { + static const uint8_t g_msp430_opcode[] = {0x43, 0x43}; + trap_opcode = g_msp430_opcode; + trap_opcode_size = sizeof(g_msp430_opcode); + } break; + case llvm::Triple::systemz: { static const uint8_t g_hex_opcode[] = {0x00, 0x01}; trap_opcode = g_hex_opcode; diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp index c82097a..475d0c8 100644 --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -154,6 +154,10 @@ static const CoreDefinition g_core_definitions[] = { {eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r6el, "mips64r6el"}, + // MSP430 + {eByteOrderLittle, 2, 2, 4, llvm::Triple::msp430, ArchSpec::eCore_msp430, + "msp430"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_generic, "powerpc"}, {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc601, @@ -402,6 +406,8 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { ArchSpec::eMIPSSubType_mips64r2el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r2el {ArchSpec::eCore_mips64r6el, llvm::ELF::EM_MIPS, ArchSpec::eMIPSSubType_mips64r6el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r6el + {ArchSpec::eCore_msp430, llvm::ELF::EM_MSP430, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // MSP430 {ArchSpec::eCore_hexagon_generic, llvm::ELF::EM_HEXAGON, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // HEXAGON {ArchSpec::eCore_arc, llvm::ELF::EM_ARC_COMPACT2, LLDB_INVALID_CPUTYPE, @@ -899,6 +905,9 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, case llvm::ELF::ELFOSABI_SOLARIS: m_triple.setOS(llvm::Triple::OSType::Solaris); break; + case llvm::ELF::ELFOSABI_STANDALONE: + m_triple.setOS(llvm::Triple::OSType::UnknownOS); + break; } } else if (arch_type == eArchTypeCOFF && os == llvm::Triple::Win32) { m_triple.setVendor(llvm::Triple::PC); diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestMSP430MSPDebug.py b/lldb/test/API/functionalities/gdb_remote_client/TestMSP430MSPDebug.py new file mode 100644 index 0000000..067bb08 --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/TestMSP430MSPDebug.py @@ -0,0 +1,110 @@ +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from lldbsuite.test.gdbclientutils import * +from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase + +# This test ensures that LLDB correctly handles packets sent by MSPDebug. +# https://github.com/dlbeer/mspdebug + +class MyResponder(MockGDBServerResponder): + def qSupported(self, client_supported): + return "PacketSize=4000" + + def setBreakpoint(self, packet): + return "OK" + + def stopPackets(): + # Registers 3 to 15 are empty + regs3to15 = "".join('%02x:%s;' % (i, "00000000") for i in range(3, 16)) + yield "T0500:00050000;01:00000000;02:00000000;" + regs3to15 + yield "T0500:10050000;01:baff0000;02:05000000;" + regs3to15 + yield "T0500:16050000;01:baff0000;02:05000000;" + regs3to15 + + stopPacket = stopPackets() + def haltReason(self): + return next(self.stopPacket) + + def cont(self): + return self.haltReason() + + # Memory dump + def readMemory(self, addr, length): + # Program memory + if (addr == 0x0400): + return ("ff"*256) + "3140c0ff0c43b0121c05b01281010000b240d2043c051c423c0530413180020081430000b01210053150020030411c4330413c402a0030410c433041" + ("ff"*196) + # Stack contents + if (addr == 0xfe00): + return ("ff"*442) + "280500000a05" + ("ff"*62) + "0005" + +class TestMSP430MSPDebug(GDBRemoteTestBase): + + @skipIfLLVMTargetMissing("MSP430") + def test(self): + """ + Test LLDB's MSP430 functionality. + """ + target = self.createTarget("msp430.yaml") + self.server.responder = MyResponder() + + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + process = self.connect(target) + lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, + [lldb.eStateStopped]) + num_threads = len(process.threads) + self.assertEqual(num_threads, 1, "Only one thread") + thread = process.GetThreadAtIndex(0) + + # Test if a breakpoint can be set + bp = target.BreakpointCreateByName("func") + self.assertTrue(bp.IsValid()) + bp.SetEnabled(True) + self.assertTrue(bp.IsEnabled()) + + # Test if the breakpoint address is resolved correctly + self.assertEqual(bp.GetNumLocations(), 1, "Only one location") + bp_loc = bp.GetLocationAtIndex(0); + self.assertTrue(bp_loc.GetAddress().GetLoadAddress(target) == 0x510, + "Address of main") + + # Test if the process stops at the breakpoint + process.Continue() + self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonBreakpoint, + "Hit a breakpoint") + + # Check if disassembler works and the current function is "func" + func = thread.GetFrameAtIndex(0).GetFunction() + insts = func.GetInstructions(target) + inst = insts.GetInstructionAtIndex(0) + self.assertEqual(inst.GetMnemonic(target), "mov") + self.assertEqual(inst.GetOperands(target), "#1234, &1340") + + # Test if thread can step a single instruction + thread.StepInstruction(False) + self.assertTrue(thread.GetFrameAtIndex(0).GetPCAddress().GetLoadAddress(target) == 0x516, + "Address of the next instruction") + + # Test if registers are being set correctly + registerSet = thread.GetFrameAtIndex(0).GetRegisters().GetValueAtIndex(0) + reg_val_dict = { + "pc": 0x0516, "sp": 0xffba, "r2": 0x0005, + "r3": 0x0000, "fp": 0x0000, "r5": 0x0000, + "r6": 0x0000, "r7": 0x0000, "r8": 0x0000, + "r9": 0x0000, "r10": 0x0000, "r11": 0x0000, + "r12": 0x0000, "r13": 0x0000, "r14": 0x0000, + "r15": 0x0000 + } + for reg in registerSet: + self.assertEqual(reg.GetValueAsUnsigned(), + reg_val_dict[reg.GetName()]) + + # Check if backtracing works: + self.assertTrue(len(thread.frames) >= 3) + crt0_addr = thread.GetFrameAtIndex(2).GetPCAddress().GetLoadAddress(target) + self.assertEqual(crt0_addr, 0x50a) + + diff --git a/lldb/test/API/functionalities/gdb_remote_client/msp430.yaml b/lldb/test/API/functionalities/gdb_remote_client/msp430.yaml new file mode 100644 index 0000000..ef61b66 --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/msp430.yaml @@ -0,0 +1,426 @@ +# File test.c, compiled with flags "-O0 -g" +# Source code: +# +# int foo = 0; +# +# int func() { +# foo = 1234; +# return foo; +# } +# +# int main() { +# return func(); +# } +# + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + OSABI: ELFOSABI_STANDALONE + Type: ET_EXEC + Machine: EM_MSP430 + Flags: [ ] + Entry: 0x500 +ProgramHeaders: + - Type: PT_LOAD + Flags: [ PF_X, PF_R ] + FirstSec: .text + LastSec: .bss + VAddr: 0x46C + Align: 0x4 + - Type: PT_LOAD + Flags: [ PF_W, PF_R ] + FirstSec: .data + LastSec: .bss + VAddr: 0x53C + Align: 0x4 + - Type: PT_LOAD + Flags: [ PF_R ] + FirstSec: __interrupt_vector_31 + LastSec: __interrupt_vector_31 + VAddr: 0xFFFE + Align: 0x4 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Address: 0x500 + AddressAlign: 0x4 + Content: 3140C0FF0C43B0121C05B01281010000B240D2043C051C423C0530413180020081430000B01210053150020030411C4330413C402A0030410C433041 + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x53C + AddressAlign: 0x1 + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x53C + AddressAlign: 0x2 + Size: 0x2 + - Name: __interrupt_vector_31 + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + Address: 0xFFFE + AddressAlign: 0x1 + Offset: 0xD2 + Content: '0005' + - Name: .rodata + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + Address: 0x500 + AddressAlign: 0x1 + - Name: .rodata2 + Type: SHT_PROGBITS + Flags: [ SHF_WRITE ] + Address: 0x500 + AddressAlign: 0x1 + - Name: .noinit + Type: SHT_PROGBITS + Flags: [ SHF_WRITE ] + Address: 0x53E + AddressAlign: 0x1 + - Name: .persistent + Type: SHT_PROGBITS + Flags: [ SHF_WRITE ] + Address: 0x53E + AddressAlign: 0x1 + - Name: .MSP430.attributes + Type: SHT_MSP430_ATTRIBUTES + AddressAlign: 0x1 + Content: 41160000006D737061626900010B000000040106010801 + - Name: .comment + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 4743433A20284D6974746F2053797374656D73204C696D69746564202D206D73703433302D67636320392E332E312E31312920392E332E3100636C616E672076657273696F6E2031362E302E30202868747470733A2F2F6769746875622E636F6D2F6163636573732D736F6674656B2F6C6C766D2D70726F6A6563742E67697420373634363331663864643330353231386339613938656165373535353464303436303236343032322900 + - Name: .debug_info + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 4D000000050001040000000001001D0001080000000000000002011E0000000800000002032E000000000202A1000304050204010C00000001510500042E00000004021200000001510600092E00000000 + - Name: .debug_abbrev + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 011101252513050325721710171B25111B120673170000023400032549133F193A0B3B0B0218000003240003253E0B0B0B0000042E00111B1206401803253A0B3B0B49133F19000000 + - Name: .debug_line + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 660000000500040037000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E011E000000002C97BF5F43C79BB948A69660B684FF4A0400000502100500001505060A130509670502064A0500063105090A830502060B4A0206000101 + - Name: .debug_frame + Type: SHT_PROGBITS + AddressAlign: 0x4 + Content: 10000000FFFFFFFF04000400017E000C010280010C00000000000000100500000C00000014000000000000001C05000012000000440E044C0E020000 + - Name: .debug_str_offsets + Type: SHT_PROGBITS + AddressAlign: 0x1 + Content: 2000000005000000000000007200000079000000970000009B0000009F000000A4000000 + - Name: .debug_line_str + Type: SHT_PROGBITS + Flags: [ SHF_MERGE, SHF_STRINGS ] + AddressAlign: 0x1 + EntSize: 0x1 + Content: 2F686F6D652F757365722F6465762F746573742F6D737034333000746573742E6300 + - Type: SectionHeaderTable + Sections: + - Name: __interrupt_vector_31 + - Name: .rodata + - Name: .rodata2 + - Name: .text + - Name: .data + - Name: .bss + - Name: .noinit + - Name: .persistent + - Name: .MSP430.attributes + - Name: .comment + - Name: .debug_info + - Name: .debug_abbrev + - Name: .debug_line + - Name: .debug_frame + - Name: .debug_str + - Name: .debug_str_offsets + - Name: .debug_addr + - Name: .debug_line_str + - Name: .symtab + - Name: .strtab + - Name: .shstrtab +Symbols: + - Name: __interrupt_vector_31 + Type: STT_SECTION + Section: __interrupt_vector_31 + Value: 0xFFFE + - Name: .rodata + Type: STT_SECTION + Section: .rodata + Value: 0x500 + - Name: .rodata2 + Type: STT_SECTION + Section: .rodata2 + Value: 0x500 + - Name: .text + Type: STT_SECTION + Section: .text + Value: 0x500 + - Name: .data + Type: STT_SECTION + Section: .data + Value: 0x53C + - Name: .bss + Type: STT_SECTION + Section: .bss + Value: 0x53C + - Name: .noinit + Type: STT_SECTION + Section: .noinit + Value: 0x53E + - Name: .persistent + Type: STT_SECTION + Section: .persistent + Value: 0x53E + - Name: .MSP430.attributes + Type: STT_SECTION + Section: .MSP430.attributes + - Name: .comment + Type: STT_SECTION + Section: .comment + - Name: .debug_info + Type: STT_SECTION + Section: .debug_info + - Name: .debug_abbrev + Type: STT_SECTION + Section: .debug_abbrev + - Name: .debug_line + Type: STT_SECTION + Section: .debug_line + - Name: .debug_frame + Type: STT_SECTION + Section: .debug_frame + - Name: .debug_str + Type: STT_SECTION + Section: .debug_str + - Name: .debug_str_offsets + Type: STT_SECTION + Section: .debug_str_offsets + - Name: .debug_addr + Type: STT_SECTION + Section: .debug_addr + - Name: .debug_line_str + Type: STT_SECTION + Section: .debug_line_str + - Name: __msp430_resetvec_hook + Section: __interrupt_vector_31 + Value: 0xFFFE + - Name: .Loc.58.1 + Section: .text + Value: 0x500 + - Name: "L0\x01" + Section: .text + Value: 0x504 + - Name: "L0\x01 (1)" + Section: .text + Value: 0x500 + - Name: "L0\x01 (2)" + Section: .text + Value: 0x504 + - Name: crt_main.o + Type: STT_FILE + Index: SHN_ABS + - Name: .Loc.253.1 + Section: .text + Value: 0x504 + - Name: .Loc.254.1 + Section: .text + Value: 0x506 + - Name: "L0\x01 (3)" + Section: .text + Value: 0x50A + - Name: "L0\x01 (4)" + Section: .text + Value: 0x504 + - Name: "L0\x01 (5)" + Section: .text + Value: 0x50A + - Name: crt_callexit.o + Type: STT_FILE + Index: SHN_ABS + - Name: .Loc.267.1 + Section: .text + Value: 0x50A + - Name: "L0\x01 (6)" + Section: .text + Value: 0x50E + - Name: "L0\x01 (7)" + Section: .text + Value: 0x50A + - Name: "L0\x01 (8)" + Section: .text + Value: 0x50E + - Name: test.c + Type: STT_FILE + Index: SHN_ABS + - Name: syscalls.o + Type: STT_FILE + Index: SHN_ABS + - Name: .Loc.59.1 + Section: .text + Value: 0x52E + - Name: .Loc.60.1 + Section: .text + Value: 0x530 + - Name: .Loc.65.1 + Section: .text + Value: 0x532 + - Name: .Loc.66.1 + Section: .text + Value: 0x536 + - Name: .Loc.71.1 + Section: .text + Value: 0x538 + - Name: .Loc.72.1 + Section: .text + Value: 0x53A + - Name: "L0\x01 (9)" + Section: .text + Value: 0x53C + - Name: "L0\x01 (10)" + Section: .text + Value: 0x52E + - Name: "L0\x01 (11)" + Section: .text + Value: 0x53C + - Name: __crt0_call_exit + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x50A + Size: 0x4 + - Name: getpid + Section: .text + Binding: STB_WEAK + Value: 0x532 + - Name: isatty + Section: .text + Binding: STB_WEAK + Value: 0x52E + - Name: __crt0_start + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x500 + Size: 0x4 + - Name: lseek + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x186 + - Name: _isatty + Section: .text + Binding: STB_WEAK + Value: 0x52E + - Name: fstat + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x18A + - Name: kill + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x189 + - Name: _start + Section: .text + Binding: STB_GLOBAL + Value: 0x500 + - Name: read + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x184 + - Name: __rom_highdatacopysize + Index: SHN_ABS + Binding: STB_WEAK + - Name: gettimeofday + Section: .text + Binding: STB_WEAK + Value: 0x538 + Size: 0x4 + - Name: main + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x51C + Size: 0x12 + - Name: __high_bsssize + Index: SHN_ABS + Binding: STB_WEAK + - Name: __rom_highdatastart + Index: SHN_ABS + Binding: STB_WEAK + - Name: __high_datastart + Index: SHN_ABS + Binding: STB_WEAK + - Name: __upper_data_init + Index: SHN_ABS + Binding: STB_WEAK + - Name: func + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x510 + Size: 0xC + - Name: foo + Type: STT_OBJECT + Section: .bss + Binding: STB_GLOBAL + Value: 0x53C + Size: 0x2 + - Name: __stack + Section: .persistent + Binding: STB_GLOBAL + Value: 0xFFC0 + - Name: _edata + Section: .data + Binding: STB_GLOBAL + Value: 0x53C + - Name: _end + Section: .bss + Binding: STB_GLOBAL + Value: 0x53E + - Name: exit + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x181 + - Name: __high_bssstart + Index: SHN_ABS + Binding: STB_WEAK + - Name: __crt0_call_main + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Value: 0x504 + Size: 0x6 + - Name: _exit + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x181 + - Name: open + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x182 + - Name: close + Index: SHN_ABS + Binding: STB_WEAK + Value: 0x183 +DWARF: + debug_str: + - test.c + - foo + - int + - func + - main + debug_addr: + - Length: 0x10 + Version: 0x5 + AddressSize: 0x4 + Entries: + - Address: 0x53C + - Address: 0x510 + - Address: 0x51C +... diff --git a/lldb/unittests/Utility/ArchSpecTest.cpp b/lldb/unittests/Utility/ArchSpecTest.cpp index 43cec1f..de3590b 100644 --- a/lldb/unittests/Utility/ArchSpecTest.cpp +++ b/lldb/unittests/Utility/ArchSpecTest.cpp @@ -123,6 +123,12 @@ TEST(ArchSpecTest, TestSetTriple) { EXPECT_STREQ("i686", AS.GetArchitectureName()); EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore()); + AS = ArchSpec(); + EXPECT_TRUE(AS.SetTriple("msp430---elf")); + EXPECT_EQ(llvm::Triple::msp430, AS.GetTriple().getArch()); + EXPECT_STREQ("msp430", AS.GetArchitectureName()); + EXPECT_EQ(ArchSpec::eCore_msp430, AS.GetCore()); + // Various flavors of invalid triples. AS = ArchSpec(); EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));