808 changes: 808 additions & 0 deletions lldb/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp

Large diffs are not rendered by default.

120 changes: 120 additions & 0 deletions lldb/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//===-- ABISysV_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_ABISysV_s390x_h_
#define liblldb_ABISysV_s390x_h_

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"

class ABISysV_s390x : public lldb_private::ABI
{
public:
~ABISysV_s390x() 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<lldb::addr_t> args) const override;

bool
GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override;

lldb_private::Error
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
GetFallbackRegisterLocation (const lldb_private::RegisterInfo *reg_info,
lldb_private::UnwindPlan::Row::RegisterLocation &unwind_regloc) override;

bool
CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
return false; // Not 8 byte aligned
if (cfa == 0)
return false; // Zero is not a valid stack address
return true;
}

bool
CodeAddressIsValid(lldb::addr_t pc) override
{
// Code addressed must be 2 byte aligned
if (pc & 1ull)
return false;
return true;
}

const lldb_private::RegisterInfo *
GetRegisterInfoArray(uint32_t &count) override;

//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------

static void
Initialize();

static void
Terminate();

static lldb::ABISP
CreateInstance(const lldb_private::ArchSpec &arch);

static lldb_private::ConstString
GetPluginNameStatic();

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------

lldb_private::ConstString
GetPluginName() override;

uint32_t
GetPluginVersion() override;

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:
ABISysV_s390x() : lldb_private::ABI()
{
// Call CreateInstance instead.
}
};

#endif // liblldb_ABISysV_s390x_h_
3 changes: 3 additions & 0 deletions lldb/source/Plugins/ABI/SysV-s390x/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
add_lldb_library(lldbPluginABISysV_s390x
ABISysV_s390x.cpp
)
3 changes: 3 additions & 0 deletions lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ ELFHeader::GetRelocationJumpSlotType() const
case EM_MIPS:
slot = R_MIPS_JUMP_SLOT;
break;
case EM_S390:
slot = R_390_JMP_SLOT;
break;
}

return slot;
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
case 6: triple.setArchName("mips"); break;
case 7: triple.setArchName("mips64el"); break;
case 8: triple.setArchName("mipsel"); break;
case 9: triple.setArchName("s390x"); break;
default: return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/Linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_lldb_library(lldbPluginProcessLinux
NativeRegisterContextLinux_arm64.cpp
NativeRegisterContextLinux_x86_64.cpp
NativeRegisterContextLinux_mips64.cpp
NativeRegisterContextLinux_s390x.cpp
NativeThreadLinux.cpp
ProcFileReader.cpp
SingleStepCheck.cpp
Expand Down
11 changes: 11 additions & 0 deletions lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,7 @@ NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size)
// FIXME put this behind a breakpoint protocol class that can be
// set per architecture. Need ARM, MIPS support here.
static const uint8_t g_i386_opcode [] = { 0xCC };
static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 };

switch (m_arch.GetMachine ())
{
Expand All @@ -2255,6 +2256,10 @@ NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size)
actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode));
return Error ();

case llvm::Triple::systemz:
actual_opcode_size = static_cast<uint32_t> (sizeof(g_s390x_opcode));
return Error ();

case llvm::Triple::arm:
case llvm::Triple::aarch64:
case llvm::Triple::mips64:
Expand Down Expand Up @@ -2294,6 +2299,7 @@ NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hin
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_s390x_opcode[] = { 0x00, 0x01 };
static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };

switch (m_arch.GetMachine ())
Expand Down Expand Up @@ -2337,6 +2343,11 @@ NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hin
actual_opcode_size = sizeof(g_mips64el_opcode);
return Error ();

case llvm::Triple::systemz:
trap_opcode_bytes = g_s390x_opcode;
actual_opcode_size = sizeof(g_s390x_opcode);
return Error ();

default:
assert(false && "CPU type not supported!");
return Error ("CPU type not supported");
Expand Down
716 changes: 716 additions & 0 deletions lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp

Large diffs are not rendered by default.

141 changes: 141 additions & 0 deletions lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//===-- NativeRegisterContextLinux_s390x.h ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#if defined(__s390x__) && defined(__linux__)

#ifndef lldb_NativeRegisterContextLinux_s390x_h
#define lldb_NativeRegisterContextLinux_s390x_h

#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
#include "Plugins/Process/Utility/RegisterContext_s390x.h"
#include "Plugins/Process/Utility/lldb-s390x-register-enums.h"

namespace lldb_private
{
namespace process_linux
{

class NativeProcessLinux;

class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux
{
public:
NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
uint32_t concrete_frame_idx);

uint32_t
GetRegisterSetCount() const override;

const RegisterSet *
GetRegisterSet(uint32_t set_index) const override;

uint32_t
GetUserRegisterCount() const override;

Error
ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override;

Error
WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override;

Error
ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;

Error
WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;

Error
IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;

Error
GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;

Error
IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;

bool
ClearHardwareWatchpoint(uint32_t wp_index) override;

Error
ClearAllHardwareWatchpoints() override;

uint32_t
SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) override;

lldb::addr_t
GetWatchpointAddress(uint32_t wp_index) override;

uint32_t
NumSupportedHardwareWatchpoints() override;

protected:
Error
DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, RegisterValue &value) override;

Error
DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override;

Error
DoReadGPR(void *buf, size_t buf_size) override;

Error
DoWriteGPR(void *buf, size_t buf_size) override;

Error
DoReadFPR(void *buf, size_t buf_size) override;

Error
DoWriteFPR(void *buf, size_t buf_size) override;

private:
// Info about register ranges.
struct RegInfo
{
uint32_t num_registers;
uint32_t num_gpr_registers;
uint32_t num_fpr_registers;

uint32_t last_gpr;
uint32_t first_fpr;
uint32_t last_fpr;
};

// Private member variables.
RegInfo m_reg_info;
lldb::addr_t m_watchpoint_addr;

// Private member methods.
bool
IsRegisterSetAvailable(uint32_t set_index) const;

bool
IsGPR(uint32_t reg_index) const;

bool
IsFPR(uint32_t reg_index) const;

Error
PeekUserArea(uint32_t offset, void *buf, size_t buf_size);

Error
PokeUserArea(uint32_t offset, const void *buf, size_t buf_size);

Error
DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size);

Error
DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size);
};

} // namespace process_linux
} // namespace lldb_private

#endif // #ifndef lldb_NativeRegisterContextLinux_s390x_h

#endif // defined(__s390x__) && defined(__linux__)
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/Utility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextLinux_x86_64.cpp
RegisterContextLinux_mips64.cpp
RegisterContextLinux_mips.cpp
RegisterContextLinux_s390x.cpp
RegisterContextLLDB.cpp
RegisterContextMacOSXFrameBackchain.cpp
RegisterContextMach_arm.cpp
Expand All @@ -39,6 +40,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextPOSIX_arm64.cpp
RegisterContextPOSIX_mips64.cpp
RegisterContextPOSIX_powerpc.cpp
RegisterContextPOSIX_s390x.cpp
RegisterContextPOSIX_x86.cpp
RegisterContextThreadMemory.cpp
StopInfoMachException.cpp
Expand Down
98 changes: 98 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//===-- RegisterContextLinux_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 "RegisterContextPOSIX_s390x.h"
#include "RegisterContextLinux_s390x.h"

using namespace lldb_private;
using namespace lldb;

//---------------------------------------------------------------------------
// Include RegisterInfos_s390x to declare our g_register_infos_s390x structure.
//---------------------------------------------------------------------------
#define DECLARE_REGISTER_INFOS_S390X_STRUCT
#include "RegisterInfos_s390x.h"
#undef DECLARE_REGISTER_INFOS_S390X_STRUCT

static const RegisterInfo *
GetRegisterInfoPtr(const ArchSpec &target_arch)
{
switch (target_arch.GetMachine())
{
case llvm::Triple::systemz:
return g_register_infos_s390x;
default:
assert(false && "Unhandled target architecture.");
return nullptr;
}
}

static uint32_t
GetRegisterInfoCount(const ArchSpec &target_arch)
{
switch (target_arch.GetMachine())
{
case llvm::Triple::systemz:
return k_num_registers_s390x;
default:
assert(false && "Unhandled target architecture.");
return 0;
}
}

static uint32_t
GetUserRegisterInfoCount(const ArchSpec &target_arch)
{
switch (target_arch.GetMachine())
{
case llvm::Triple::systemz:
return k_num_user_registers_s390x + k_num_linux_registers_s390x;
default:
assert(false && "Unhandled target architecture.");
return 0;
}
}

RegisterContextLinux_s390x::RegisterContextLinux_s390x(const ArchSpec &target_arch)
: lldb_private::RegisterInfoInterface(target_arch),
m_register_info_p(GetRegisterInfoPtr(target_arch)),
m_register_info_count(GetRegisterInfoCount(target_arch)),
m_user_register_count(GetUserRegisterInfoCount(target_arch))
{
}

const std::vector<lldb_private::RegisterInfo> *
RegisterContextLinux_s390x::GetDynamicRegisterInfoP() const
{
return &d_register_infos;
}

const RegisterInfo *
RegisterContextLinux_s390x::GetRegisterInfo() const
{
return m_register_info_p;
}

uint32_t
RegisterContextLinux_s390x::GetRegisterCount() const
{
return m_register_info_count;
}

uint32_t
RegisterContextLinux_s390x::GetUserRegisterCount() const
{
return m_user_register_count;
}

size_t
RegisterContextLinux_s390x::GetGPRSize() const
{
return 0;
}
42 changes: 42 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//===-- RegisterContextLinux_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_RegisterContextLinux_s390x_h_
#define liblldb_RegisterContextLinux_s390x_h_

#include "RegisterInfoInterface.h"

class RegisterContextLinux_s390x : public lldb_private::RegisterInfoInterface
{
public:
RegisterContextLinux_s390x(const lldb_private::ArchSpec &target_arch);

size_t
GetGPRSize() const override;

const lldb_private::RegisterInfo *
GetRegisterInfo() const override;

uint32_t
GetRegisterCount() const override;

uint32_t
GetUserRegisterCount() const override;

const std::vector<lldb_private::RegisterInfo> *
GetDynamicRegisterInfoP() const override;

private:
const lldb_private::RegisterInfo *m_register_info_p;
uint32_t m_register_info_count;
uint32_t m_user_register_count;
std::vector<lldb_private::RegisterInfo> d_register_infos;
};

#endif
265 changes: 265 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
//===-- RegisterContextPOSIX_x86.cpp ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <cstring>
#include <errno.h>
#include <stdint.h>

#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Host/Endian.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "llvm/Support/Compiler.h"

#include "RegisterContext_s390x.h"
#include "RegisterContextPOSIX_s390x.h"

using namespace lldb_private;
using namespace lldb;

// s390x 64-bit general purpose registers.
static const uint32_t g_gpr_regnums_s390x[] =
{
lldb_r0_s390x,
lldb_r1_s390x,
lldb_r2_s390x,
lldb_r3_s390x,
lldb_r4_s390x,
lldb_r5_s390x,
lldb_r6_s390x,
lldb_r7_s390x,
lldb_r8_s390x,
lldb_r9_s390x,
lldb_r10_s390x,
lldb_r11_s390x,
lldb_r12_s390x,
lldb_r13_s390x,
lldb_r14_s390x,
lldb_r15_s390x,
lldb_acr0_s390x,
lldb_acr1_s390x,
lldb_acr2_s390x,
lldb_acr3_s390x,
lldb_acr4_s390x,
lldb_acr5_s390x,
lldb_acr6_s390x,
lldb_acr7_s390x,
lldb_acr8_s390x,
lldb_acr9_s390x,
lldb_acr10_s390x,
lldb_acr11_s390x,
lldb_acr12_s390x,
lldb_acr13_s390x,
lldb_acr14_s390x,
lldb_acr15_s390x,
lldb_pswm_s390x,
lldb_pswa_s390x,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x,
"g_gpr_regnums_s390x has wrong number of register infos");

// s390x 64-bit floating point registers.
static const uint32_t g_fpu_regnums_s390x[] =
{
lldb_f0_s390x,
lldb_f1_s390x,
lldb_f2_s390x,
lldb_f3_s390x,
lldb_f4_s390x,
lldb_f5_s390x,
lldb_f6_s390x,
lldb_f7_s390x,
lldb_f8_s390x,
lldb_f9_s390x,
lldb_f10_s390x,
lldb_f11_s390x,
lldb_f12_s390x,
lldb_f13_s390x,
lldb_f14_s390x,
lldb_f15_s390x,
lldb_fpc_s390x,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x,
"g_fpu_regnums_s390x has wrong number of register infos");

// Number of register sets provided by this context.
enum
{
k_num_register_sets = 2
};

// Register sets for s390x 64-bit.
static const RegisterSet g_reg_sets_s390x[k_num_register_sets] =
{
{ "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x },
{ "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x },
};

bool
RegisterContextPOSIX_s390x::IsGPR(unsigned reg)
{
return reg <= m_reg_info.last_gpr; // GPRs come first.
}

bool
RegisterContextPOSIX_s390x::IsFPR(unsigned reg)
{
return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
}

RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x(Thread &thread, uint32_t concrete_frame_idx,
RegisterInfoInterface *register_info)
: RegisterContext(thread, concrete_frame_idx)
{
m_register_info_ap.reset(register_info);

switch (register_info->m_target_arch.GetMachine())
{
case llvm::Triple::systemz:
m_reg_info.num_registers = k_num_registers_s390x;
m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x;
m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x;
m_reg_info.last_gpr = k_last_gpr_s390x;
m_reg_info.first_fpr = k_first_fpr_s390x;
m_reg_info.last_fpr = k_last_fpr_s390x;
break;
default:
assert(false && "Unhandled target architecture.");
break;
}
}

RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x()
{
}

void
RegisterContextPOSIX_s390x::Invalidate()
{
}

void
RegisterContextPOSIX_s390x::InvalidateAllRegisters()
{
}

const RegisterInfo *
RegisterContextPOSIX_s390x::GetRegisterInfo()
{
return m_register_info_ap->GetRegisterInfo();
}

const RegisterInfo *
RegisterContextPOSIX_s390x::GetRegisterInfoAtIndex(size_t reg)
{
if (reg < m_reg_info.num_registers)
return &GetRegisterInfo()[reg];
else
return NULL;
}

size_t
RegisterContextPOSIX_s390x::GetRegisterCount()
{
return m_reg_info.num_registers;
}

unsigned
RegisterContextPOSIX_s390x::GetRegisterOffset(unsigned reg)
{
assert(reg < m_reg_info.num_registers && "Invalid register number.");
return GetRegisterInfo()[reg].byte_offset;
}

unsigned
RegisterContextPOSIX_s390x::GetRegisterSize(unsigned reg)
{
assert(reg < m_reg_info.num_registers && "Invalid register number.");
return GetRegisterInfo()[reg].byte_size;
}

const char *
RegisterContextPOSIX_s390x::GetRegisterName(unsigned reg)
{
assert(reg < m_reg_info.num_registers && "Invalid register offset.");
return GetRegisterInfo()[reg].name;
}

bool
RegisterContextPOSIX_s390x::IsRegisterSetAvailable(size_t set_index)
{
return set_index < k_num_register_sets;
}

size_t
RegisterContextPOSIX_s390x::GetRegisterSetCount()
{
size_t sets = 0;
for (size_t set = 0; set < k_num_register_sets; ++set)
{
if (IsRegisterSetAvailable(set))
++sets;
}

return sets;
}

const RegisterSet *
RegisterContextPOSIX_s390x::GetRegisterSet(size_t set)
{
if (IsRegisterSetAvailable(set))
{
switch (m_register_info_ap->m_target_arch.GetMachine())
{
case llvm::Triple::systemz:
return &g_reg_sets_s390x[set];
default:
assert(false && "Unhandled target architecture.");
return NULL;
}
}
return NULL;
}

lldb::ByteOrder
RegisterContextPOSIX_s390x::GetByteOrder()
{
// Get the target process whose privileged thread was used for the register read.
lldb::ByteOrder byte_order = eByteOrderInvalid;
Process *process = CalculateProcess().get();

if (process)
byte_order = process->GetByteOrder();
return byte_order;
}

// Used when parsing DWARF and EH frame information and any other
// object file sections that contain register numbers in them.
uint32_t
RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)
{
const uint32_t num_regs = GetRegisterCount();

assert(kind < kNumRegisterKinds);
for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
{
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);

if (reg_info->kinds[kind] == num)
return reg_idx;
}

return LLDB_INVALID_REGNUM;
}
103 changes: 103 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//===-- RegisterContextPOSIX_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_RegisterContextPOSIX_s390x_h_
#define liblldb_RegisterContextPOSIX_s390x_h_

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Log.h"
#include "lldb/Target/RegisterContext.h"
#include "RegisterInfoInterface.h"
#include "RegisterContext_s390x.h"
#include "lldb-s390x-register-enums.h"

class ProcessMonitor;

class RegisterContextPOSIX_s390x : public lldb_private::RegisterContext
{
public:
RegisterContextPOSIX_s390x(lldb_private::Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);

~RegisterContextPOSIX_s390x() override;

void
Invalidate();

void
InvalidateAllRegisters() override;

size_t
GetRegisterCount() override;

virtual unsigned
GetRegisterSize(unsigned reg);

virtual unsigned
GetRegisterOffset(unsigned reg);

const lldb_private::RegisterInfo *
GetRegisterInfoAtIndex(size_t reg) override;

size_t
GetRegisterSetCount() override;

const lldb_private::RegisterSet *
GetRegisterSet(size_t set) override;

const char *
GetRegisterName(unsigned reg);

uint32_t
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;

protected:
struct RegInfo
{
uint32_t num_registers;
uint32_t num_gpr_registers;
uint32_t num_fpr_registers;

uint32_t last_gpr;
uint32_t first_fpr;
uint32_t last_fpr;
};

RegInfo m_reg_info;
std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap;

virtual bool
IsRegisterSetAvailable(size_t set_index);

virtual const lldb_private::RegisterInfo *
GetRegisterInfo();

bool
IsGPR(unsigned reg);

bool
IsFPR(unsigned reg);

lldb::ByteOrder
GetByteOrder();

virtual bool
ReadGPR() = 0;
virtual bool
ReadFPR() = 0;
virtual bool
WriteGPR() = 0;
virtual bool
WriteFPR() = 0;
};

#endif // liblldb_RegisterContextPOSIX_s390x_h_
93 changes: 93 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContext_s390x.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//===-- RegisterContext_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_RegisterContext_s390x_h_
#define liblldb_RegisterContext_s390x_h_

//---------------------------------------------------------------------------
// SystemZ ehframe, dwarf regnums
//---------------------------------------------------------------------------

// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)
enum
{
// General Purpose Registers
dwarf_r0_s390x = 0,
dwarf_r1_s390x,
dwarf_r2_s390x,
dwarf_r3_s390x,
dwarf_r4_s390x,
dwarf_r5_s390x,
dwarf_r6_s390x,
dwarf_r7_s390x,
dwarf_r8_s390x,
dwarf_r9_s390x,
dwarf_r10_s390x,
dwarf_r11_s390x,
dwarf_r12_s390x,
dwarf_r13_s390x,
dwarf_r14_s390x,
dwarf_r15_s390x,
// Floating Point Registers / Vector Registers 0-15
dwarf_f0_s390x = 16,
dwarf_f2_s390x,
dwarf_f4_s390x,
dwarf_f6_s390x,
dwarf_f1_s390x,
dwarf_f3_s390x,
dwarf_f5_s390x,
dwarf_f7_s390x,
dwarf_f8_s390x,
dwarf_f10_s390x,
dwarf_f12_s390x,
dwarf_f14_s390x,
dwarf_f9_s390x,
dwarf_f11_s390x,
dwarf_f13_s390x,
dwarf_f15_s390x,
// Access Registers
dwarf_acr0_s390x = 48,
dwarf_acr1_s390x,
dwarf_acr2_s390x,
dwarf_acr3_s390x,
dwarf_acr4_s390x,
dwarf_acr5_s390x,
dwarf_acr6_s390x,
dwarf_acr7_s390x,
dwarf_acr8_s390x,
dwarf_acr9_s390x,
dwarf_acr10_s390x,
dwarf_acr11_s390x,
dwarf_acr12_s390x,
dwarf_acr13_s390x,
dwarf_acr14_s390x,
dwarf_acr15_s390x,
// Program Status Word
dwarf_pswm_s390x = 64,
dwarf_pswa_s390x,
// Vector Registers 16-31
dwarf_v16_s390x = 68,
dwarf_v18_s390x,
dwarf_v20_s390x,
dwarf_v22_s390x,
dwarf_v17_s390x,
dwarf_v19_s390x,
dwarf_v21_s390x,
dwarf_v23_s390x,
dwarf_v24_s390x,
dwarf_v26_s390x,
dwarf_v28_s390x,
dwarf_v30_s390x,
dwarf_v25_s390x,
dwarf_v27_s390x,
dwarf_v29_s390x,
dwarf_v31_s390x,
};

#endif
132 changes: 132 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterInfos_s390x.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//===-- RegisterInfos_s390x.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <stddef.h>

// C++ Includes
// Other libraries and framework includes
#include "llvm/Support/Compiler.h"

// Project includes

#ifdef DECLARE_REGISTER_INFOS_S390X_STRUCT

// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(num) (16 + 8 * num)
// Computes the offset of the given ACR in the user data area.
#define ACR_OFFSET(num) (16 + 8 * 16 + 4 * num)
// Computes the offset of the given FPR in the extended data area.
#define FPR_OFFSET(num) (8 + 8 * num)

// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB

#define DEFINE_GPR(name, size, offset, alt, generic) \
{ \
#name, alt, size, offset, eEncodingUint, eFormatHex, \
{ dwarf_##name##_s390x, dwarf_##name##_s390x, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \
NULL, NULL, \
}

#define DEFINE_GPR_NODWARF(name, size, offset, alt, generic) \
{ \
#name, alt, size, offset, eEncodingUint, eFormatHex, \
{ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \
NULL, NULL, \
}

#define DEFINE_FPR(name, size, offset) \
{ \
#name, NULL, size, offset, eEncodingUint, eFormatHex, \
{ dwarf_##name##_s390x, dwarf_##name##_s390x, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \
NULL, NULL, \
}

#define DEFINE_FPR_NODWARF(name, size, offset) \
{ \
#name, NULL, size, offset, eEncodingUint, eFormatHex, \
{ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \
NULL, NULL, \
}

static RegisterInfo g_register_infos_s390x[] =
{
// General purpose registers.
DEFINE_GPR(r0, 8, GPR_OFFSET(0), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r1, 8, GPR_OFFSET(1), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r2, 8, GPR_OFFSET(2), "arg1", LLDB_REGNUM_GENERIC_ARG1),
DEFINE_GPR(r3, 8, GPR_OFFSET(3), "arg2", LLDB_REGNUM_GENERIC_ARG2),
DEFINE_GPR(r4, 8, GPR_OFFSET(4), "arg3", LLDB_REGNUM_GENERIC_ARG3),
DEFINE_GPR(r5, 8, GPR_OFFSET(5), "arg4", LLDB_REGNUM_GENERIC_ARG4),
DEFINE_GPR(r6, 8, GPR_OFFSET(6), "arg5", LLDB_REGNUM_GENERIC_ARG5),
DEFINE_GPR(r7, 8, GPR_OFFSET(7), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r8, 8, GPR_OFFSET(8), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r9, 8, GPR_OFFSET(9), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r10, 8, GPR_OFFSET(10), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r11, 8, GPR_OFFSET(11), "fp", LLDB_REGNUM_GENERIC_FP),
DEFINE_GPR(r12, 8, GPR_OFFSET(12), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r13, 8, GPR_OFFSET(13), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r14, 8, GPR_OFFSET(14), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(r15, 8, GPR_OFFSET(15), "sp", LLDB_REGNUM_GENERIC_SP),
DEFINE_GPR(acr0, 4, ACR_OFFSET(0), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr1, 4, ACR_OFFSET(1), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr2, 4, ACR_OFFSET(2), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr3, 4, ACR_OFFSET(3), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr4, 4, ACR_OFFSET(4), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr5, 4, ACR_OFFSET(5), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr6, 4, ACR_OFFSET(6), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr7, 4, ACR_OFFSET(7), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr8, 4, ACR_OFFSET(8), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr9, 4, ACR_OFFSET(9), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr10, 4, ACR_OFFSET(10), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr11, 4, ACR_OFFSET(11), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr12, 4, ACR_OFFSET(12), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr13, 4, ACR_OFFSET(13), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr14, 4, ACR_OFFSET(14), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(acr15, 4, ACR_OFFSET(15), nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR(pswm, 8, 0, "flags", LLDB_REGNUM_GENERIC_FLAGS),
DEFINE_GPR(pswa, 8, 8, "pc", LLDB_REGNUM_GENERIC_PC),

// Floating point registers.
DEFINE_FPR(f0, 8, FPR_OFFSET(0)),
DEFINE_FPR(f1, 8, FPR_OFFSET(1)),
DEFINE_FPR(f2, 8, FPR_OFFSET(2)),
DEFINE_FPR(f3, 8, FPR_OFFSET(3)),
DEFINE_FPR(f4, 8, FPR_OFFSET(4)),
DEFINE_FPR(f5, 8, FPR_OFFSET(5)),
DEFINE_FPR(f6, 8, FPR_OFFSET(6)),
DEFINE_FPR(f7, 8, FPR_OFFSET(7)),
DEFINE_FPR(f8, 8, FPR_OFFSET(8)),
DEFINE_FPR(f9, 8, FPR_OFFSET(9)),
DEFINE_FPR(f10, 8, FPR_OFFSET(10)),
DEFINE_FPR(f11, 8, FPR_OFFSET(11)),
DEFINE_FPR(f12, 8, FPR_OFFSET(12)),
DEFINE_FPR(f13, 8, FPR_OFFSET(13)),
DEFINE_FPR(f14, 8, FPR_OFFSET(14)),
DEFINE_FPR(f15, 8, FPR_OFFSET(15)),
DEFINE_FPR_NODWARF(fpc, 4, 0),

// Linux operating-specific info.
DEFINE_GPR_NODWARF(orig_r2, 8, 16 + 16 * 8 + 16 * 4, nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR_NODWARF(last_break, 8, 0, nullptr, LLDB_INVALID_REGNUM),
DEFINE_GPR_NODWARF(system_call, 4, 0, nullptr, LLDB_INVALID_REGNUM),
};

static_assert((sizeof(g_register_infos_s390x) / sizeof(g_register_infos_s390x[0])) == k_num_registers_s390x,
"g_register_infos_s390x has wrong number of register infos");

#undef GPR_OFFSET
#undef ACR_OFFSET
#undef FPR_OFFSET
#undef DEFINE_GPR
#undef DEFINE_GPR_NODWARF
#undef DEFINE_FPR
#undef DEFINE_FPR_NODWARF

#endif // DECLARE_REGISTER_INFOS_S390X_STRUCT
94 changes: 94 additions & 0 deletions lldb/source/Plugins/Process/Utility/lldb-s390x-register-enums.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//===-- lldb-s390x-register-enums.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_s390x_register_enums_h
#define lldb_s390x_register_enums_h

namespace lldb_private
{
// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)

//---------------------------------------------------------------------------
// Internal codes for all s390x registers.
//---------------------------------------------------------------------------
enum
{
k_first_gpr_s390x,
lldb_r0_s390x = k_first_gpr_s390x,
lldb_r1_s390x,
lldb_r2_s390x,
lldb_r3_s390x,
lldb_r4_s390x,
lldb_r5_s390x,
lldb_r6_s390x,
lldb_r7_s390x,
lldb_r8_s390x,
lldb_r9_s390x,
lldb_r10_s390x,
lldb_r11_s390x,
lldb_r12_s390x,
lldb_r13_s390x,
lldb_r14_s390x,
lldb_r15_s390x,
lldb_acr0_s390x,
lldb_acr1_s390x,
lldb_acr2_s390x,
lldb_acr3_s390x,
lldb_acr4_s390x,
lldb_acr5_s390x,
lldb_acr6_s390x,
lldb_acr7_s390x,
lldb_acr8_s390x,
lldb_acr9_s390x,
lldb_acr10_s390x,
lldb_acr11_s390x,
lldb_acr12_s390x,
lldb_acr13_s390x,
lldb_acr14_s390x,
lldb_acr15_s390x,
lldb_pswm_s390x,
lldb_pswa_s390x,
k_last_gpr_s390x = lldb_pswa_s390x,

k_first_fpr_s390x,
lldb_f0_s390x = k_first_fpr_s390x,
lldb_f1_s390x,
lldb_f2_s390x,
lldb_f3_s390x,
lldb_f4_s390x,
lldb_f5_s390x,
lldb_f6_s390x,
lldb_f7_s390x,
lldb_f8_s390x,
lldb_f9_s390x,
lldb_f10_s390x,
lldb_f11_s390x,
lldb_f12_s390x,
lldb_f13_s390x,
lldb_f14_s390x,
lldb_f15_s390x,
lldb_fpc_s390x,
k_last_fpr_s390x = lldb_fpc_s390x,

// These are only available on Linux.
k_first_linux_s390x,
lldb_orig_r2_s390x = k_first_linux_s390x,
lldb_last_break_s390x,
lldb_system_call_s390x,
k_last_linux_s390x = lldb_system_call_s390x,

k_num_registers_s390x,
k_num_gpr_registers_s390x = k_last_gpr_s390x - k_first_gpr_s390x + 1,
k_num_fpr_registers_s390x = k_last_fpr_s390x - k_first_fpr_s390x + 1,
k_num_linux_registers_s390x = k_last_linux_s390x - k_first_linux_s390x + 1,
k_num_user_registers_s390x = k_num_gpr_registers_s390x + k_num_fpr_registers_s390x,
};
}

#endif // #ifndef lldb_s390x_register_enums_h
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/elf-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ add_lldb_library(lldbPluginProcessElfCore
RegisterContextPOSIXCore_arm64.cpp
RegisterContextPOSIXCore_mips64.cpp
RegisterContextPOSIXCore_powerpc.cpp
RegisterContextPOSIXCore_s390x.cpp
RegisterContextPOSIXCore_x86_64.cpp
)
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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_
10 changes: 10 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
8 changes: 8 additions & 0 deletions lldb/source/Target/Platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2118,6 +2118,14 @@ Platform::GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_sit
}
break;

case llvm::Triple::systemz:
{
static const uint8_t g_hex_opcode[] = {0x00, 0x01};
trap_opcode = g_hex_opcode;
trap_opcode_size = sizeof(g_hex_opcode);
}
break;

case llvm::Triple::hexagon:
{
static const uint8_t g_hex_opcode[] = {0x0c, 0xdb, 0x00, 0x54};
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Target/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2340,6 +2340,7 @@ Thread::GetUnwinder ()
case llvm::Triple::mips64el:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::systemz:
case llvm::Triple::hexagon:
m_unwinder_ap.reset (new UnwindLLDB (*this));
break;
Expand Down