diff options
| author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2016-04-14 14:28:34 +0000 |
|---|---|---|
| committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2016-04-14 14:28:34 +0000 |
| commit | bb00d0b6b29a2ab1c59d3040a21f14156d8779df (patch) | |
| tree | cbe5c64120aa89abbfd4cfc9e6d54b958f0e85bd /lldb/source/Plugins/Process/elf-core | |
| parent | 7311bb34f63df58edb4819e5b483b49932b371bd (diff) | |
| download | bcm5719-llvm-bb00d0b6b29a2ab1c59d3040a21f14156d8779df.tar.gz bcm5719-llvm-bb00d0b6b29a2ab1c59d3040a21f14156d8779df.zip | |
Support Linux on SystemZ as platform
This patch adds support for Linux on SystemZ:
- A new ArchSpec value of eCore_s390x_generic
- A new directory Plugins/ABI/SysV-s390x providing an ABI implementation
- Register context support
- Native Linux support including watchpoint support
- ELF core file support
- Misc. support throughout the code base (e.g. breakpoint opcodes)
- Test case updates to support the platform
This should provide complete support for debugging the SystemZ platform.
Not yet supported are optional features like transaction support (zEC12)
or SIMD vector support (z13).
There is no instruction emulation, since our ABI requires that all code
provide correct DWARF CFI at all PC locations in .eh_frame to support
unwinding (i.e. -fasynchronous-unwind-tables is on by default).
The implementation follows existing platforms in a mostly straightforward
manner. A couple of things that are different:
- We do not use PTRACE_PEEKUSER / PTRACE_POKEUSER to access single registers,
since some registers (access register) reside at offsets in the user area
that are multiples of 4, but the PTRACE_PEEKUSER interface only allows
accessing aligned 8-byte blocks in the user area. Instead, we use a s390
specific ptrace interface PTRACE_PEEKUSR_AREA / PTRACE_POKEUSR_AREA that
allows accessing a whole block of the user area in one go, so in effect
allowing to treat parts of the user area as register sets.
- SystemZ hardware does not provide any means to implement read watchpoints,
only write watchpoints. In fact, we can only support a *single* write
watchpoint (but this can span a range of arbitrary size). In LLDB this
means we support only a single watchpoint. I've set all test cases that
require read watchpoints (or multiple watchpoints) to expected failure
on the platform. [ Note that there were two test cases that install
a read/write watchpoint even though they nowhere rely on the "read"
property. I've changed those to simply use plain write watchpoints. ]
Differential Revision: http://reviews.llvm.org/D18978
llvm-svn: 266308
Diffstat (limited to 'lldb/source/Plugins/Process/elf-core')
5 files changed, 193 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt index 1a4dd7e9d33..b9f0b6cdfb7 100644 --- a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt +++ b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt @@ -7,5 +7,6 @@ add_lldb_library(lldbPluginProcessElfCore RegisterContextPOSIXCore_arm64.cpp RegisterContextPOSIXCore_mips64.cpp RegisterContextPOSIXCore_powerpc.cpp + RegisterContextPOSIXCore_s390x.cpp RegisterContextPOSIXCore_x86_64.cpp ) diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp new file mode 100644 index 00000000000..d2f0a8dd367 --- /dev/null +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -0,0 +1,115 @@ +//===-- RegisterContextCorePOSIX_s390x.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Target/Thread.h" +#include "RegisterContextPOSIXCore_s390x.h" + +using namespace lldb_private; + +RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x(Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, + const DataExtractor &fpregset) + : RegisterContextPOSIX_s390x(thread, 0, register_info) +{ + m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); +} + +RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() +{ +} + +bool +RegisterContextCorePOSIX_s390x::ReadGPR() +{ + return true; +} + +bool +RegisterContextCorePOSIX_s390x::ReadFPR() +{ + return true; +} + +bool +RegisterContextCorePOSIX_s390x::WriteGPR() +{ + assert(0); + return false; +} + +bool +RegisterContextCorePOSIX_s390x::WriteFPR() +{ + assert(0); + return false; +} + +bool +RegisterContextCorePOSIX_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return false; + + if (IsGPR(reg)) + { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) + { + value.SetUInt(v, reg_info->byte_size); + return true; + } + } + + if (IsFPR(reg)) + { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) + { + value.SetUInt(v, reg_info->byte_size); + return true; + } + } + + return false; +} + +bool +RegisterContextCorePOSIX_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) +{ + return false; +} + +bool +RegisterContextCorePOSIX_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) +{ + return false; +} + +bool +RegisterContextCorePOSIX_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) +{ + return false; +} + +bool +RegisterContextCorePOSIX_s390x::HardwareSingleStep(bool enable) +{ + return false; +} diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h new file mode 100644 index 00000000000..8bb6fe1771e --- /dev/null +++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h @@ -0,0 +1,65 @@ +//===-- RegisterContextCorePOSIX_s390x.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterContextCorePOSIX_s390x_h_ +#define liblldb_RegisterContextCorePOSIX_s390x_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/DataBufferHeap.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h" + +class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x +{ +public: + RegisterContextCorePOSIX_s390x(lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); + + ~RegisterContextCorePOSIX_s390x() override; + + bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override; + + bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override; + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + bool + HardwareSingleStep(bool enable) override; + +protected: + bool + ReadGPR() override; + + bool + ReadFPR() override; + + bool + WriteGPR() override; + + bool + WriteFPR() override; + +private: + lldb::DataBufferSP m_gpr_buffer; + lldb_private::DataExtractor m_gpr; + + lldb::DataBufferSP m_fpr_buffer; + lldb_private::DataExtractor m_fpr; +}; + +#endif // liblldb_RegisterContextCorePOSIX_s390x_h_ diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 9cc7829fc39..e4cfa68044f 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -18,6 +18,7 @@ #include "ProcessElfCore.h" #include "Plugins/Process/Utility/RegisterContextLinux_arm.h" #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" +#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h" @@ -29,6 +30,7 @@ #include "RegisterContextPOSIXCore_arm64.h" #include "RegisterContextPOSIXCore_mips64.h" #include "RegisterContextPOSIXCore_powerpc.h" +#include "RegisterContextPOSIXCore_s390x.h" #include "RegisterContextPOSIXCore_x86_64.h" using namespace lldb; @@ -139,6 +141,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) case llvm::Triple::aarch64: reg_interface = new RegisterContextLinux_arm64(arch); break; + case llvm::Triple::systemz: + reg_interface = new RegisterContextLinux_s390x(arch); + break; case llvm::Triple::x86_64: reg_interface = new RegisterContextLinux_x86_64(arch); break; @@ -174,6 +179,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) case llvm::Triple::ppc64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data)); break; + case llvm::Triple::systemz: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x (*this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; case llvm::Triple::x86: case llvm::Triple::x86_64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data)); @@ -218,6 +226,7 @@ ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) size_t len; switch(arch.GetCore()) { + case ArchSpec::eCore_s390x_generic: case ArchSpec::eCore_x86_64_x86_64: len = data.ExtractBytes(0, ELFLINUXPRSTATUS64_SIZE, byteorder, this); return len == ELFLINUXPRSTATUS64_SIZE; @@ -241,6 +250,7 @@ ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) size_t len; switch(arch.GetCore()) { + case ArchSpec::eCore_s390x_generic: case ArchSpec::eCore_x86_64_x86_64: len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this); return len == ELFLINUXPRPSINFO64_SIZE; diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h index d3a42e0eb54..b4e99014067 100644 --- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -68,6 +68,7 @@ struct ELFLinuxPrStatus { switch(arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: case lldb_private::ArchSpec::eCore_x86_64_x86_64: return ELFLINUXPRSTATUS64_SIZE; default: @@ -102,6 +103,7 @@ struct ELFLinuxPrPsInfo { switch(arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: case lldb_private::ArchSpec::eCore_x86_64_x86_64: return ELFLINUXPRPSINFO64_SIZE; default: |

