1,097 changes: 1,097 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp

Large diffs are not rendered by default.

143 changes: 143 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//===-- ABISysV_ppc.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_ppc_h_
#define liblldb_ABISysV_ppc_h_

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

class ABISysV_ppc :
public lldb_private::ABI
{
public:

~ABISysV_ppc()
{
}

virtual size_t
GetRedZoneSize () const;

virtual 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;

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

virtual lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);

protected:
lldb::ValueObjectSP
GetReturnValueObjectSimple (lldb_private::Thread &thread,
lldb_private::ClangASTType &ast_type) const;

public:
virtual lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
lldb_private::ClangASTType &type) const;

virtual bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);

virtual bool
CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);

virtual bool
RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);

virtual bool
StackUsesFrames ()
{
return true;
}

// The SysV ppc ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
// code, we've seen that the stack pointer is often not aligned properly
// before the handler is invoked. This means that lldb will stop the unwind
// early -- before the function which caused the trap.
//
// To work around this, we relax that alignment to be just word-size (8-bytes).
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
virtual bool
CallFrameAddressIsValid (lldb::addr_t cfa)
{
// 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;
}

virtual bool
CodeAddressIsValid (lldb::addr_t pc)
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}

virtual bool
FunctionCallsChangeCFA ()
{
return true;
}

virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
Initialize();

static void
Terminate();

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

static lldb_private::ConstString
GetPluginNameStatic();

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
GetPluginName();

virtual uint32_t
GetPluginVersion();

protected:
void
CreateRegisterMapIfNeeded ();

bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);

private:
ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead.
};

#endif // liblldb_ABI_h_
5 changes: 5 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(LLVM_NO_RTTI 1)

add_lldb_library(lldbPluginABISysV_ppc
ABISysV_ppc.cpp
)
14 changes: 14 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
##===- source/Plugins/ABI/SysV-hexagon/Makefile -------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##

LLDB_LEVEL := ../../../..
LIBRARYNAME := lldbPluginABISysV_ppc
BUILD_ARCHIVE = 1

include $(LLDB_LEVEL)/Makefile
1,101 changes: 1,101 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp

Large diffs are not rendered by default.

143 changes: 143 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//===-- ABISysV_ppc64.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_ppc64_h_
#define liblldb_ABISysV_ppc64_h_

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

class ABISysV_ppc64 :
public lldb_private::ABI
{
public:

~ABISysV_ppc64()
{
}

virtual size_t
GetRedZoneSize () const;

virtual 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;

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

virtual lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);

protected:
lldb::ValueObjectSP
GetReturnValueObjectSimple (lldb_private::Thread &thread,
lldb_private::ClangASTType &ast_type) const;

public:
virtual lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
lldb_private::ClangASTType &type) const;

virtual bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);

virtual bool
CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);

virtual bool
RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);

virtual bool
StackUsesFrames ()
{
return true;
}

// The SysV ppc64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
// code, we've seen that the stack pointer is often not aligned properly
// before the handler is invoked. This means that lldb will stop the unwind
// early -- before the function which caused the trap.
//
// To work around this, we relax that alignment to be just word-size (8-bytes).
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
virtual bool
CallFrameAddressIsValid (lldb::addr_t cfa)
{
// 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;
}

virtual bool
CodeAddressIsValid (lldb::addr_t pc)
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}

virtual bool
FunctionCallsChangeCFA ()
{
return true;
}

virtual const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
Initialize();

static void
Terminate();

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

static lldb_private::ConstString
GetPluginNameStatic();

//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
GetPluginName();

virtual uint32_t
GetPluginVersion();

protected:
void
CreateRegisterMapIfNeeded ();

bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);

private:
ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead.
};

#endif // liblldb_ABI_h_
5 changes: 5 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
set(LLVM_NO_RTTI 1)

add_lldb_library(lldbPluginABISysV_ppc64
ABISysV_ppc64.cpp
)
14 changes: 14 additions & 0 deletions lldb/source/Plugins/ABI/SysV-ppc64/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
##===- source/Plugins/ABI/SysV-hexagon/Makefile -------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##

LLDB_LEVEL := ../../../..
LIBRARYNAME := lldbPluginABISysV_ppc64
BUILD_ARCHIVE = 1

include $(LLDB_LEVEL)/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,13 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint()
return LLDB_INVALID_ADDRESS;

m_entry_point = static_cast<addr_t>(I->value);

const ArchSpec &arch = m_process->GetTarget().GetArchitecture();

// On ppc64, the entry point is actually a descriptor. Dereference it.
if (arch.GetMachine() == llvm::Triple::ppc64)
m_entry_point = ReadUnsignedIntWithSizeInBytes(m_entry_point, 8);

return m_entry_point;
}

Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ include $(LLDB_LEVEL)/../../Makefile.config


PARALLEL_DIRS := ABI/MacOSX-arm ABI/MacOSX-arm64 ABI/MacOSX-i386 ABI/SysV-x86_64 \
ABI/SysV-hexagon \
ABI/SysV-hexagon ABI/SysV-ppc64 \
Disassembler/llvm \
ObjectContainer/BSD-Archive ObjectFile/ELF ObjectFile/PECOFF \
ObjectFile/JIT SymbolFile/DWARF SymbolFile/Symtab Process/Utility \
Expand Down
6 changes: 6 additions & 0 deletions lldb/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@ ELFHeader::GetRelocationJumpSlotType() const
default:
assert(false && "architecture not supported");
break;
case EM_PPC:
slot = R_PPC_JMP_SLOT;
break;
case EM_PPC64:
slot = R_PPC64_JMP_SLOT;
break;
case EM_386:
case EM_486:
slot = R_386_JUMP_SLOT;
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
static ConstString rodata1_section_name(".rodata1");
static ConstString data2_section_name(".data1");
static ConstString bss_section_name(".bss");
static ConstString opd_section_name(".opd"); // For ppc64

//StreamFile strm(stdout, false);
unsigned i;
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,13 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite
trap_opcode_size = sizeof(g_i386_opcode);
}
break;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
{
static const uint8_t g_ppc_opcode[] = { 0x7f, 0xe0, 0x00, 0x08 };
trap_opcode = g_ppc_opcode;
trap_opcode_size = sizeof(g_ppc_opcode);
}
}

if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,15 @@ PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax);
}
#endif
#ifndef __powerpc__
if (req == PT_GETDBREGS || req == PT_SETDBREGS) {
struct dbreg *r = (struct dbreg *) addr;
char setget = (req == PT_GETDBREGS) ? 'G' : 'S';

for (int i = 0; i <= 7; i++)
log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]);
}
#endif
}

return result;
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/POSIX/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ add_lldb_library(lldbPluginProcessPOSIX
ProcessPOSIXLog.cpp
RegisterContextPOSIXProcessMonitor_arm64.cpp
RegisterContextPOSIXProcessMonitor_mips64.cpp
RegisterContextPOSIXProcessMonitor_powerpc.cpp
RegisterContextPOSIXProcessMonitor_x86.cpp
)
22 changes: 22 additions & 0 deletions lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@
#include "Plugins/Process/Linux/ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
#include "RegisterContextPOSIXProcessMonitor_x86.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
#include "Plugins/Process/Utility/UnwindLLDB.h"

Expand Down Expand Up @@ -167,6 +169,14 @@ POSIXThread::GetRegisterContext()
case llvm::Triple::FreeBSD:
switch (target_arch.GetMachine())
{
case llvm::Triple::ppc:
#ifndef __powerpc64__
reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
break;
#endif
case llvm::Triple::ppc64:
reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
break;
case llvm::Triple::mips64:
reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
break;
Expand Down Expand Up @@ -229,6 +239,14 @@ POSIXThread::GetRegisterContext()
m_reg_context_sp.reset(reg_ctx);
break;
}
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
{
RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface);
m_posix_thread = reg_ctx;
m_reg_context_sp.reset(reg_ctx);
break;
}
case llvm::Triple::x86:
case llvm::Triple::x86_64:
{
Expand Down Expand Up @@ -624,6 +642,8 @@ POSIXThread::GetRegisterIndexFromOffset(unsigned offset)

case llvm::Triple::aarch64:
case llvm::Triple::mips64:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
{
Expand Down Expand Up @@ -655,6 +675,8 @@ POSIXThread::GetRegisterName(unsigned reg)

case llvm::Triple::aarch64:
case llvm::Triple::mips64:
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
name = GetRegisterContext()->GetRegisterName(reg);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
//===-- RegisterContextPOSIXProcessMonitor_powerpc.h ------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//

#include "lldb/Target/Thread.h"
#include "lldb/Core/RegisterValue.h"

#include "RegisterContextPOSIX_powerpc.h"
#include "ProcessPOSIX.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
#include "ProcessMonitor.h"

using namespace lldb_private;
using namespace lldb;

#define REG_CONTEXT_SIZE (GetGPRSize())

RegisterContextPOSIXProcessMonitor_powerpc::RegisterContextPOSIXProcessMonitor_powerpc(Thread &thread,
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info)
{
}

ProcessMonitor &
RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()
{
ProcessSP base = CalculateProcess();
ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
return process->GetMonitor();
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR()
{
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR()
{
// XXX not yet implemented
return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR()
{
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR()
{
// XXX not yet implemented
return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const unsigned reg,
RegisterValue &value)
{
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadRegisterValue(m_thread.GetID(),
GetRegisterOffset(reg),
GetRegisterName(reg),
GetRegisterSize(reg),
value);
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const unsigned reg,
const RegisterValue &value)
{
unsigned reg_to_write = reg;
RegisterValue value_to_write = value;

// Check if this is a subregister of a full register.
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
{
RegisterValue full_value;
uint32_t full_reg = reg_info->invalidate_regs[0];
const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);

// Read the full register.
if (ReadRegister(full_reg_info, full_value))
{
Error error;
ByteOrder byte_order = GetByteOrder();
uint8_t dst[RegisterValue::kMaxRegisterByteSize];

// Get the bytes for the full register.
const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
dst,
sizeof(dst),
byte_order,
error);
if (error.Success() && dest_size)
{
uint8_t src[RegisterValue::kMaxRegisterByteSize];

// Get the bytes for the source data.
const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
if (error.Success() && src_size && (src_size < dest_size))
{
// Copy the src bytes to the destination.
memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
// Set this full register as the value to write.
value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
value_to_write.SetType(full_reg_info);
reg_to_write = full_reg;
}
}
}
}

ProcessMonitor &monitor = GetMonitor();
return monitor.WriteRegisterValue(m_thread.GetID(),
GetRegisterOffset(reg_to_write),
GetRegisterName(reg_to_write),
value_to_write);
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
{
if (!reg_info)
return false;

const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];

if (IsFPR(reg))
{
if (!ReadFPR())
return false;
}
else
{
uint32_t full_reg = reg;
bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);

if (is_subreg)
{
// Read the full aligned 64-bit register.
full_reg = reg_info->invalidate_regs[0];
}

bool success = ReadRegister(full_reg, value);

if (success)
{
// If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
value.SetUInt64(value.GetAsUInt64() >> 8);

// If our return byte size was greater than the return value reg size, then
// use the type specified by reg_info rather than the uint64_t default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
return success;
}

return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
{
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];

if (IsGPR(reg))
return WriteRegister(reg, value);

return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(DataBufferSP &data_sp)
{
bool success = false;
data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
if (data_sp && ReadGPR () && ReadFPR ())
{
uint8_t *dst = data_sp->GetBytes();
success = dst != 0;

if (success)
{
::memcpy (dst, &m_gpr_powerpc, GetGPRSize());
dst += GetGPRSize();
}
}
return success;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBufferSP &data_sp)
{
bool success = false;
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
{
uint8_t *src = data_sp->GetBytes();
if (src)
{
::memcpy (&m_gpr_powerpc, src, GetGPRSize());

if (WriteGPR())
{
src += GetGPRSize();
}
}
}
return success;
}

uint32_t
RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(addr_t addr, size_t size,
bool read, bool write)
{
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
uint32_t hw_index;

for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
{
if (IsWatchpointVacant(hw_index))
return SetHardwareWatchpointWithIndex(addr, size,
read, write,
hw_index);
}

return LLDB_INVALID_INDEX32;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(uint32_t hw_index)
{
return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(bool enable)
{
return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint()
{
lldb::addr_t pc;

if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
return false;

return true;
}

unsigned
RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(unsigned offset)
{
unsigned reg;
for (reg = 0; reg < k_num_registers_powerpc; reg++)
{
if (GetRegisterInfo()[reg].byte_offset == offset)
break;
}
assert(reg < k_num_registers_powerpc && "Invalid register offset.");
return reg;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(uint32_t hw_index)
{
return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits()
{
return false;
}

addr_t
RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(uint32_t hw_index)
{
return LLDB_INVALID_ADDRESS;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(uint32_t hw_index)
{
return false;
}

bool
RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
bool read, bool write,
uint32_t hw_index)
{
return false;
}

uint32_t
RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints()
{
return 0;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//===-- RegisterContextPOSIXProcessMonitor_powerpc.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_RegisterContextPOSIXProcessMonitor_powerpc_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_

#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"

class RegisterContextPOSIXProcessMonitor_powerpc:
public RegisterContextPOSIX_powerpc,
public POSIXBreakpointProtocol
{
public:
RegisterContextPOSIXProcessMonitor_powerpc(lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);

protected:
bool
ReadGPR();

bool
ReadFPR();

bool
WriteGPR();

bool
WriteFPR();

// lldb_private::RegisterContext
bool
ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);

bool
WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);

bool
ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);

bool
WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);

bool
ReadAllRegisterValues(lldb::DataBufferSP &data_sp);

bool
WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);

uint32_t
SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write);

bool
ClearHardwareWatchpoint(uint32_t hw_index);

bool
HardwareSingleStep(bool enable);

// POSIXBreakpointProtocol
bool
UpdateAfterBreakpoint();

unsigned
GetRegisterIndexFromOffset(unsigned offset);

bool
IsWatchpointHit(uint32_t hw_index);

bool
ClearWatchpointHits();

lldb::addr_t
GetWatchpointAddress(uint32_t hw_index);

bool
IsWatchpointVacant(uint32_t hw_index);

bool
SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index);

uint32_t
NumSupportedHardwareWatchpoints();

private:
ProcessMonitor &
GetMonitor();
};

#endif
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 @@ -16,6 +16,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextDummy.cpp
RegisterContextFreeBSD_i386.cpp
RegisterContextFreeBSD_mips64.cpp
RegisterContextFreeBSD_powerpc.cpp
RegisterContextFreeBSD_x86_64.cpp
RegisterContextHistory.cpp
RegisterContextLinux_arm64.cpp
Expand All @@ -29,6 +30,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextMemory.cpp
RegisterContextPOSIX_arm64.cpp
RegisterContextPOSIX_mips64.cpp
RegisterContextPOSIX_powerpc.cpp
RegisterContextPOSIX_x86.cpp
RegisterContextThreadMemory.cpp
StopInfoMachException.cpp
Expand Down
227 changes: 227 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
//===-- RegisterContextFreeBSD_powerpc.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//

#include <vector>
#include "RegisterContextPOSIX_powerpc.h"
#include "RegisterContextFreeBSD_powerpc.h"

using namespace lldb_private;
using namespace lldb;

// http://svnweb.freebsd.org/base/head/sys/powerpc/include/reg.h
typedef struct _GPR64
{
uint64_t r0;
uint64_t r1;
uint64_t r2;
uint64_t r3;
uint64_t r4;
uint64_t r5;
uint64_t r6;
uint64_t r7;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t r16;
uint64_t r17;
uint64_t r18;
uint64_t r19;
uint64_t r20;
uint64_t r21;
uint64_t r22;
uint64_t r23;
uint64_t r24;
uint64_t r25;
uint64_t r26;
uint64_t r27;
uint64_t r28;
uint64_t r29;
uint64_t r30;
uint64_t r31;
uint64_t lr;
uint64_t cr;
uint64_t xer;
uint64_t ctr;
uint64_t pc;
} GPR64;

typedef struct _GPR32
{
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r4;
uint32_t r5;
uint32_t r6;
uint32_t r7;
uint32_t r8;
uint32_t r9;
uint32_t r10;
uint32_t r11;
uint32_t r12;
uint32_t r13;
uint32_t r14;
uint32_t r15;
uint32_t r16;
uint32_t r17;
uint32_t r18;
uint32_t r19;
uint32_t r20;
uint32_t r21;
uint32_t r22;
uint32_t r23;
uint32_t r24;
uint32_t r25;
uint32_t r26;
uint32_t r27;
uint32_t r28;
uint32_t r29;
uint32_t r30;
uint32_t r31;
uint32_t lr;
uint32_t cr;
uint32_t xer;
uint32_t ctr;
uint32_t pc;
} GPR32;

typedef struct _FPR
{
uint64_t f0;
uint64_t f1;
uint64_t f2;
uint64_t f3;
uint64_t f4;
uint64_t f5;
uint64_t f6;
uint64_t f7;
uint64_t f8;
uint64_t f9;
uint64_t f10;
uint64_t f11;
uint64_t f12;
uint64_t f13;
uint64_t f14;
uint64_t f15;
uint64_t f16;
uint64_t f17;
uint64_t f18;
uint64_t f19;
uint64_t f20;
uint64_t f21;
uint64_t f22;
uint64_t f23;
uint64_t f24;
uint64_t f25;
uint64_t f26;
uint64_t f27;
uint64_t f28;
uint64_t f29;
uint64_t f30;
uint64_t f31;
uint64_t fpscr;
} FPR;

//---------------------------------------------------------------------------
// Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure.
//---------------------------------------------------------------------------
#define DECLARE_REGISTER_INFOS_POWERPC_STRUCT
#include "RegisterInfos_powerpc.h"
#undef DECLARE_REGISTER_INFOS_POWERPC_STRUCT

RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc(const ArchSpec &target_arch) :
RegisterInfoInterface(target_arch)
{
}

RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc()
{
}

size_t
RegisterContextFreeBSD_powerpc::GetGPRSize() const
{
return sizeof(GPR64);
}

const RegisterInfo *
RegisterContextFreeBSD_powerpc::GetRegisterInfo() const
{
//assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
llvm_unreachable("Abstract class!");
return NULL;
}

uint32_t
RegisterContextFreeBSD_powerpc::GetRegisterCount () const
{
return 0;
}

RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32(const ArchSpec &target_arch) :
RegisterContextFreeBSD_powerpc(target_arch)
{
}

RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32()
{
}

size_t
RegisterContextFreeBSD_powerpc32::GetGPRSize() const
{
return sizeof(GPR32);
}

const RegisterInfo *
RegisterContextFreeBSD_powerpc32::GetRegisterInfo() const
{
//assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
return g_register_infos_powerpc32;
}

uint32_t
RegisterContextFreeBSD_powerpc32::GetRegisterCount () const
{
return static_cast<uint32_t> (sizeof (g_register_infos_powerpc32) / sizeof (g_register_infos_powerpc32 [0]));
}

RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64(const ArchSpec &target_arch) :
RegisterContextFreeBSD_powerpc(target_arch)
{
}

RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64()
{
}

size_t
RegisterContextFreeBSD_powerpc64::GetGPRSize() const
{
return sizeof(GPR64);
}

const RegisterInfo *
RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const
{
//assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
return g_register_infos_powerpc64;
}

uint32_t
RegisterContextFreeBSD_powerpc64::GetRegisterCount () const
{
return static_cast<uint32_t> (sizeof (g_register_infos_powerpc64) / sizeof (g_register_infos_powerpc64 [0]));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===-- RegisterContextFreeBSD_powerpc.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_RegisterContextFreeBSD_powerpc_H_
#define liblldb_RegisterContextFreeBSD_powerpc_H_

#include "RegisterContextPOSIX.h"

class RegisterContextFreeBSD_powerpc:
public lldb_private::RegisterInfoInterface
{
public:
RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch);
virtual ~RegisterContextFreeBSD_powerpc();

size_t
GetGPRSize() const override;

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

uint32_t
GetRegisterCount() const override;
};

class RegisterContextFreeBSD_powerpc32:
public RegisterContextFreeBSD_powerpc
{
public:
RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch);
virtual ~RegisterContextFreeBSD_powerpc32();

size_t
GetGPRSize() const override;

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

uint32_t
GetRegisterCount() const override;
};

class RegisterContextFreeBSD_powerpc64:
public RegisterContextFreeBSD_powerpc
{
public:
RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch);
virtual ~RegisterContextFreeBSD_powerpc64();

size_t
GetGPRSize() const override;

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

uint32_t
GetRegisterCount() const override;
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,

// TOOD: need a better way to detect when "long double" types are
// the same bytes size as "double"
#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && !defined(__mips__)
#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && \
!defined(__mips__) && !defined(__powerpc__)
case sizeof (long double):
if (sizeof (long double) == sizeof(uint32_t))
{
Expand Down
273 changes: 273 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
//===-- RegisterContextPOSIX_powerpc.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/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Host/Endian.h"
#include "llvm/Support/Compiler.h"

#include "RegisterContextPOSIX_powerpc.h"
#include "Plugins/Process/elf-core/ProcessElfCore.h"

using namespace lldb_private;
using namespace lldb;

static const
uint32_t g_gpr_regnums[] =
{
gpr_r0_powerpc,
gpr_r1_powerpc,
gpr_r2_powerpc,
gpr_r3_powerpc,
gpr_r4_powerpc,
gpr_r5_powerpc,
gpr_r6_powerpc,
gpr_r7_powerpc,
gpr_r8_powerpc,
gpr_r9_powerpc,
gpr_r10_powerpc,
gpr_r11_powerpc,
gpr_r12_powerpc,
gpr_r13_powerpc,
gpr_r14_powerpc,
gpr_r15_powerpc,
gpr_r16_powerpc,
gpr_r17_powerpc,
gpr_r18_powerpc,
gpr_r19_powerpc,
gpr_r20_powerpc,
gpr_r21_powerpc,
gpr_r22_powerpc,
gpr_r23_powerpc,
gpr_r24_powerpc,
gpr_r25_powerpc,
gpr_r26_powerpc,
gpr_r27_powerpc,
gpr_r28_powerpc,
gpr_r29_powerpc,
gpr_r30_powerpc,
gpr_r31_powerpc,
gpr_lr_powerpc,
gpr_cr_powerpc,
gpr_xer_powerpc,
gpr_ctr_powerpc,
gpr_pc_powerpc,
};

static const
uint32_t g_fpr_regnums[] =
{
fpr_f0_powerpc,
fpr_f1_powerpc,
fpr_f2_powerpc,
fpr_f3_powerpc,
fpr_f4_powerpc,
fpr_f5_powerpc,
fpr_f6_powerpc,
fpr_f7_powerpc,
fpr_f8_powerpc,
fpr_f9_powerpc,
fpr_f10_powerpc,
fpr_f11_powerpc,
fpr_f12_powerpc,
fpr_f13_powerpc,
fpr_f14_powerpc,
fpr_f15_powerpc,
fpr_f16_powerpc,
fpr_f17_powerpc,
fpr_f18_powerpc,
fpr_f19_powerpc,
fpr_f20_powerpc,
fpr_f21_powerpc,
fpr_f22_powerpc,
fpr_f23_powerpc,
fpr_f24_powerpc,
fpr_f25_powerpc,
fpr_f26_powerpc,
fpr_f27_powerpc,
fpr_f28_powerpc,
fpr_f29_powerpc,
fpr_f30_powerpc,
fpr_f31_powerpc,
fpr_fpscr_powerpc,
};

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

static const RegisterSet
g_reg_sets_powerpc[k_num_register_sets] =
{
{ "General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, g_gpr_regnums },
{ "Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, g_fpr_regnums },
};

bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg)
{
return reg <= k_num_gpr_registers_powerpc; // GPR's come first.
}

bool
RegisterContextPOSIX_powerpc::IsFPR(unsigned reg)
{
// XXX
return (reg >= k_first_fpr) && (reg <= k_last_fpr);
}

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

// elf-core yet to support ReadFPR()
ProcessSP base = CalculateProcess();
if (base.get()->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
return;
}

RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc()
{
}

void
RegisterContextPOSIX_powerpc::Invalidate()
{
}

void
RegisterContextPOSIX_powerpc::InvalidateAllRegisters()
{
}

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

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

size_t
RegisterContextPOSIX_powerpc::GetRegisterCount()
{
size_t num_registers = k_num_registers_powerpc;
return num_registers;
}

size_t
RegisterContextPOSIX_powerpc::GetGPRSize()
{
return m_register_info_ap->GetGPRSize();
}

const RegisterInfo *
RegisterContextPOSIX_powerpc::GetRegisterInfo()
{
// Commonly, this method is overridden and g_register_infos is copied and specialized.
// So, use GetRegisterInfo() rather than g_register_infos in this scope.
return m_register_info_ap->GetRegisterInfo ();
}

const RegisterInfo *
RegisterContextPOSIX_powerpc::GetRegisterInfoAtIndex(size_t reg)
{
if (reg < k_num_registers_powerpc)
return &GetRegisterInfo()[reg];
else
return NULL;
}

size_t
RegisterContextPOSIX_powerpc::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_powerpc::GetRegisterSet(size_t set)
{
if (IsRegisterSetAvailable(set))
return &g_reg_sets_powerpc[set];
else
return NULL;
}

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

lldb::ByteOrder
RegisterContextPOSIX_powerpc::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;
}

bool
RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index)
{
size_t num_sets = k_num_register_sets;

return (set_index < num_sets);
}

// Used when parsing DWARF and EH frame information and any other
// object file sections that contain register numbers in them.
uint32_t
RegisterContextPOSIX_powerpc::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;
}

173 changes: 173 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
//===-- RegisterContextPOSIX_powerpc.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_powerpc_H_
#define liblldb_RegisterContextPOSIX_powerpc_H_

#include "lldb/Core/Log.h"
#include "RegisterContextPOSIX.h"
#include "RegisterContext_powerpc.h"

class ProcessMonitor;

// ---------------------------------------------------------------------------
// Internal codes for all powerpc registers.
// ---------------------------------------------------------------------------
enum
{
k_first_gpr_powerpc,
gpr_r0_powerpc = k_first_gpr_powerpc,
gpr_r1_powerpc,
gpr_r2_powerpc,
gpr_r3_powerpc,
gpr_r4_powerpc,
gpr_r5_powerpc,
gpr_r6_powerpc,
gpr_r7_powerpc,
gpr_r8_powerpc,
gpr_r9_powerpc,
gpr_r10_powerpc,
gpr_r11_powerpc,
gpr_r12_powerpc,
gpr_r13_powerpc,
gpr_r14_powerpc,
gpr_r15_powerpc,
gpr_r16_powerpc,
gpr_r17_powerpc,
gpr_r18_powerpc,
gpr_r19_powerpc,
gpr_r20_powerpc,
gpr_r21_powerpc,
gpr_r22_powerpc,
gpr_r23_powerpc,
gpr_r24_powerpc,
gpr_r25_powerpc,
gpr_r26_powerpc,
gpr_r27_powerpc,
gpr_r28_powerpc,
gpr_r29_powerpc,
gpr_r30_powerpc,
gpr_r31_powerpc,
gpr_lr_powerpc,
gpr_cr_powerpc,
gpr_xer_powerpc,
gpr_ctr_powerpc,
gpr_pc_powerpc,
k_last_gpr_powerpc = gpr_pc_powerpc,

k_first_fpr,
fpr_f0_powerpc = k_first_fpr,
fpr_f1_powerpc,
fpr_f2_powerpc,
fpr_f3_powerpc,
fpr_f4_powerpc,
fpr_f5_powerpc,
fpr_f6_powerpc,
fpr_f7_powerpc,
fpr_f8_powerpc,
fpr_f9_powerpc,
fpr_f10_powerpc,
fpr_f11_powerpc,
fpr_f12_powerpc,
fpr_f13_powerpc,
fpr_f14_powerpc,
fpr_f15_powerpc,
fpr_f16_powerpc,
fpr_f17_powerpc,
fpr_f18_powerpc,
fpr_f19_powerpc,
fpr_f20_powerpc,
fpr_f21_powerpc,
fpr_f22_powerpc,
fpr_f23_powerpc,
fpr_f24_powerpc,
fpr_f25_powerpc,
fpr_f26_powerpc,
fpr_f27_powerpc,
fpr_f28_powerpc,
fpr_f29_powerpc,
fpr_f30_powerpc,
fpr_f31_powerpc,
fpr_fpscr_powerpc,
k_last_fpr = fpr_fpscr_powerpc,

k_num_registers_powerpc,
k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1,
k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1,
};

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

~RegisterContextPOSIX_powerpc();

void
Invalidate();

void
InvalidateAllRegisters();

size_t
GetRegisterCount();

virtual size_t
GetGPRSize();

virtual unsigned
GetRegisterSize(unsigned reg);

virtual unsigned
GetRegisterOffset(unsigned reg);

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

size_t
GetRegisterSetCount();

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

const char *
GetRegisterName(unsigned reg);

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

protected:
uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers.
std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux)

// Determines if an extended register set is supported on the processor running the inferior process.
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 // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_
163 changes: 163 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//===-- RegisterContext_powerpc.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_powerpc_H_
#define liblldb_RegisterContext_powerpc_H_

// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
enum
{
gcc_dwarf_r0_powerpc = 0,
gcc_dwarf_r1_powerpc,
gcc_dwarf_r2_powerpc,
gcc_dwarf_r3_powerpc,
gcc_dwarf_r4_powerpc,
gcc_dwarf_r5_powerpc,
gcc_dwarf_r6_powerpc,
gcc_dwarf_r7_powerpc,
gcc_dwarf_r8_powerpc,
gcc_dwarf_r9_powerpc,
gcc_dwarf_r10_powerpc,
gcc_dwarf_r11_powerpc,
gcc_dwarf_r12_powerpc,
gcc_dwarf_r13_powerpc,
gcc_dwarf_r14_powerpc,
gcc_dwarf_r15_powerpc,
gcc_dwarf_r16_powerpc,
gcc_dwarf_r17_powerpc,
gcc_dwarf_r18_powerpc,
gcc_dwarf_r19_powerpc,
gcc_dwarf_r20_powerpc,
gcc_dwarf_r21_powerpc,
gcc_dwarf_r22_powerpc,
gcc_dwarf_r23_powerpc,
gcc_dwarf_r24_powerpc,
gcc_dwarf_r25_powerpc,
gcc_dwarf_r26_powerpc,
gcc_dwarf_r27_powerpc,
gcc_dwarf_r28_powerpc,
gcc_dwarf_r29_powerpc,
gcc_dwarf_r30_powerpc,
gcc_dwarf_r31_powerpc,
gcc_dwarf_f0_powerpc,
gcc_dwarf_f1_powerpc,
gcc_dwarf_f2_powerpc,
gcc_dwarf_f3_powerpc,
gcc_dwarf_f4_powerpc,
gcc_dwarf_f5_powerpc,
gcc_dwarf_f6_powerpc,
gcc_dwarf_f7_powerpc,
gcc_dwarf_f8_powerpc,
gcc_dwarf_f9_powerpc,
gcc_dwarf_f10_powerpc,
gcc_dwarf_f11_powerpc,
gcc_dwarf_f12_powerpc,
gcc_dwarf_f13_powerpc,
gcc_dwarf_f14_powerpc,
gcc_dwarf_f15_powerpc,
gcc_dwarf_f16_powerpc,
gcc_dwarf_f17_powerpc,
gcc_dwarf_f18_powerpc,
gcc_dwarf_f19_powerpc,
gcc_dwarf_f20_powerpc,
gcc_dwarf_f21_powerpc,
gcc_dwarf_f22_powerpc,
gcc_dwarf_f23_powerpc,
gcc_dwarf_f24_powerpc,
gcc_dwarf_f25_powerpc,
gcc_dwarf_f26_powerpc,
gcc_dwarf_f27_powerpc,
gcc_dwarf_f28_powerpc,
gcc_dwarf_f29_powerpc,
gcc_dwarf_f30_powerpc,
gcc_dwarf_f31_powerpc,
gcc_dwarf_cr_powerpc,
gcc_dwarf_fpscr_powerpc,
gcc_dwarf_xer_powerpc = 101,
gcc_dwarf_lr_powerpc = 108,
gcc_dwarf_ctr_powerpc,
gcc_dwarf_pc_powerpc,
};

// GDB Register numbers (eRegisterKindGDB)
enum
{
gdb_r0_powerpc = 0,
gdb_r1_powerpc,
gdb_r2_powerpc,
gdb_r3_powerpc,
gdb_r4_powerpc,
gdb_r5_powerpc,
gdb_r6_powerpc,
gdb_r7_powerpc,
gdb_r8_powerpc,
gdb_r9_powerpc,
gdb_r10_powerpc,
gdb_r11_powerpc,
gdb_r12_powerpc,
gdb_r13_powerpc,
gdb_r14_powerpc,
gdb_r15_powerpc,
gdb_r16_powerpc,
gdb_r17_powerpc,
gdb_r18_powerpc,
gdb_r19_powerpc,
gdb_r20_powerpc,
gdb_r21_powerpc,
gdb_r22_powerpc,
gdb_r23_powerpc,
gdb_r24_powerpc,
gdb_r25_powerpc,
gdb_r26_powerpc,
gdb_r27_powerpc,
gdb_r28_powerpc,
gdb_r29_powerpc,
gdb_r30_powerpc,
gdb_r31_powerpc,
gdb_f0_powerpc,
gdb_f1_powerpc,
gdb_f2_powerpc,
gdb_f3_powerpc,
gdb_f4_powerpc,
gdb_f5_powerpc,
gdb_f6_powerpc,
gdb_f7_powerpc,
gdb_f8_powerpc,
gdb_f9_powerpc,
gdb_f10_powerpc,
gdb_f11_powerpc,
gdb_f12_powerpc,
gdb_f13_powerpc,
gdb_f14_powerpc,
gdb_f15_powerpc,
gdb_f16_powerpc,
gdb_f17_powerpc,
gdb_f18_powerpc,
gdb_f19_powerpc,
gdb_f20_powerpc,
gdb_f21_powerpc,
gdb_f22_powerpc,
gdb_f23_powerpc,
gdb_f24_powerpc,
gdb_f25_powerpc,
gdb_f26_powerpc,
gdb_f27_powerpc,
gdb_f28_powerpc,
gdb_f29_powerpc,
gdb_f30_powerpc,
gdb_f31_powerpc,
gdb_cr_powerpc,
gdb_fpscr_powerpc,
gdb_xer_powerpc = 101,
gdb_lr_powerpc = 108,
gdb_ctr_powerpc,
gdb_pc_powerpc,
};

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

#include <stddef.h>

// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) \
(offsetof(GPR, regname))
#define FPR_OFFSET(regname) \
(offsetof(FPR, regname))

#ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT

// Note that the size and offset will be updated by platform-specific classes.
#define DEFINE_GPR(reg, alt, lldb_kind) \
{ #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \
eFormatHex, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, gpr_##reg##_powerpc }, NULL, NULL }
#define DEFINE_FPR(reg, lldb_kind) \
{ #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \
eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL }

// General purpose registers. GCC, DWARF, Generic, GDB
#define POWERPC_REGS \
DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \
DEFINE_GPR(r2, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r3, "arg1",LLDB_REGNUM_GENERIC_ARG1), \
DEFINE_GPR(r4, "arg2",LLDB_REGNUM_GENERIC_ARG2), \
DEFINE_GPR(r5, "arg3",LLDB_REGNUM_GENERIC_ARG3), \
DEFINE_GPR(r6, "arg4",LLDB_REGNUM_GENERIC_ARG4), \
DEFINE_GPR(r7, "arg5",LLDB_REGNUM_GENERIC_ARG5), \
DEFINE_GPR(r8, "arg6",LLDB_REGNUM_GENERIC_ARG6), \
DEFINE_GPR(r9, "arg7",LLDB_REGNUM_GENERIC_ARG7), \
DEFINE_GPR(r10, "arg8",LLDB_REGNUM_GENERIC_ARG8), \
DEFINE_GPR(r11, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r12, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r13, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r14, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r15, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r16, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r17, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r18, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r19, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r20, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r21, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r22, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r23, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r24, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r25, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r26, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r27, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r28, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r29, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r30, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r31, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(lr, "lr", LLDB_REGNUM_GENERIC_RA), \
DEFINE_GPR(cr, "cr", LLDB_REGNUM_GENERIC_FLAGS), \
DEFINE_GPR(xer, "xer", LLDB_INVALID_REGNUM), \
DEFINE_GPR(ctr, "ctr", LLDB_INVALID_REGNUM), \
DEFINE_GPR(pc, "pc", LLDB_REGNUM_GENERIC_PC), \
DEFINE_FPR(f0, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f1, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f2, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f3, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f4, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f5, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f6, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f7, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f8, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f9, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f10, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f11, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f12, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f13, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f14, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f15, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f16, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f17, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f18, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f19, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f20, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f21, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f22, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f23, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f24, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f25, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f26, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f27, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f28, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \
{ "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL },
//{ NULL, NULL, sizeof(((GPR*)NULL)->r0), 0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_cfa_powerpc}, NULL, NULL}
static RegisterInfo
g_register_infos_powerpc64[] =
{
#define GPR GPR64
POWERPC_REGS
#undef GPR
};

static RegisterInfo
g_register_infos_powerpc32[] =
{
#define GPR GPR32
POWERPC_REGS
#undef GPR
};
static_assert((sizeof(g_register_infos_powerpc32) / sizeof(g_register_infos_powerpc32[0])) == k_num_registers_powerpc,
"g_register_infos_powerpc32 has wrong number of register infos");
static_assert((sizeof(g_register_infos_powerpc64) / sizeof(g_register_infos_powerpc64[0])) == k_num_registers_powerpc,
"g_register_infos_powerpc64 has wrong number of register infos");

#undef DEFINE_FPR
#undef DEFINE_GPR

#endif // DECLARE_REGISTER_INFOS_POWERPC_STRUCT

#undef GPR_OFFSET

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 @@ -6,5 +6,6 @@ add_lldb_library(lldbPluginProcessElfCore
ProcessElfCore.cpp
ThreadElfCore.cpp
RegisterContextPOSIXCore_mips64.cpp
RegisterContextPOSIXCore_powerpc.cpp
RegisterContextPOSIXCore_x86_64.cpp
)
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
{
lldb::offset_t offset = 0;
bool lp64 = (arch.GetMachine() == llvm::Triple::mips64 ||
arch.GetMachine() == llvm::Triple::ppc64 ||
arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
//===-- RegisterContextCorePOSIX_powerpc.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 "RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_powerpc.h"

using namespace lldb_private;

RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread,
RegisterInfoInterface *register_info,
const DataExtractor &gpregset,
const DataExtractor &fpregset)
: RegisterContextPOSIX_powerpc(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_powerpc::~RegisterContextCorePOSIX_powerpc()
{
}

bool
RegisterContextCorePOSIX_powerpc::ReadGPR()
{
return true;
}

bool
RegisterContextCorePOSIX_powerpc::ReadFPR()
{
return true;
}

bool
RegisterContextCorePOSIX_powerpc::WriteGPR()
{
assert(0);
return false;
}

bool
RegisterContextCorePOSIX_powerpc::WriteFPR()
{
assert(0);
return false;
}

bool
RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
{
lldb::offset_t offset = reg_info->byte_offset;
if (reg_info->name[0] == 'f') {
uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size);
if (offset == reg_info->byte_offset + reg_info->byte_size)
{
value = v;
return true;
}
} else {
uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
if (offset == reg_info->byte_offset + reg_info->byte_size)
{
if (reg_info->byte_size < sizeof(v))
value = (uint32_t)v;
else
value = v;
return true;
}
}
return false;
}

bool
RegisterContextCorePOSIX_powerpc::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
{
return false;
}

bool
RegisterContextCorePOSIX_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
{
return false;
}

bool
RegisterContextCorePOSIX_powerpc::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
{
return false;
}

bool
RegisterContextCorePOSIX_powerpc::HardwareSingleStep(bool enable)
{
return false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===-- RegisterContextCorePOSIX_powerpc.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_powerpc_H_
#define liblldb_RegisterContextCorePOSIX_powerpc_H_

#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"

class RegisterContextCorePOSIX_powerpc :
public RegisterContextPOSIX_powerpc
{
public:
RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread,
lldb_private::RegisterInfoInterface *register_info,
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);

~RegisterContextCorePOSIX_powerpc();

virtual bool
ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);

virtual bool
WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);

bool
ReadAllRegisterValues(lldb::DataBufferSP &data_sp);

bool
WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);

bool
HardwareSingleStep(bool enable);

protected:
bool
ReadGPR();

bool
ReadFPR();

bool
WriteGPR();

bool
WriteFPR();

private:
lldb::DataBufferSP m_gpr_buffer;
lldb::DataBufferSP m_fpr_buffer;
lldb_private::DataExtractor m_gpr;
lldb_private::DataExtractor m_fpr;
};

#endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
12 changes: 12 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
#include "RegisterContextPOSIXCore_mips64.h"
#include "RegisterContextPOSIXCore_powerpc.h"
#include "RegisterContextPOSIXCore_x86_64.h"

using namespace lldb;
Expand Down Expand Up @@ -94,6 +96,12 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
{
switch (arch.GetMachine())
{
case llvm::Triple::ppc:
reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
break;
case llvm::Triple::ppc64:
reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
break;
case llvm::Triple::mips64:
reg_interface = new RegisterContextFreeBSD_mips64(arch);
break;
Expand Down Expand Up @@ -138,6 +146,10 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
case llvm::Triple::mips64:
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
break;
case llvm::Triple::ppc:
case llvm::Triple::ppc64:
m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*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
2 changes: 2 additions & 0 deletions lldb/source/Target/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2281,6 +2281,8 @@ Thread::GetUnwinder ()
case llvm::Triple::aarch64:
case llvm::Triple::thumb:
case llvm::Triple::mips64:
case llvm::Triple::ppc64:
case llvm::Triple::ppc:
case llvm::Triple::hexagon:
m_unwinder_ap.reset (new UnwindLLDB (*this));
break;
Expand Down
5 changes: 5 additions & 0 deletions lldb/source/lldb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h"
#include "Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h"
#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"
#include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h"
#include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h"
#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
#include "Plugins/Instruction/ARM/EmulateInstructionARM.h"
Expand Down Expand Up @@ -132,6 +134,8 @@ lldb_private::Initialize ()
ABIMacOSX_arm::Initialize();
ABIMacOSX_arm64::Initialize();
ABISysV_x86_64::Initialize();
ABISysV_ppc::Initialize();
ABISysV_ppc64::Initialize();
DisassemblerLLVMC::Initialize();
ObjectContainerBSDArchive::Initialize();
ObjectFileELF::Initialize();
Expand Down Expand Up @@ -225,6 +229,7 @@ lldb_private::Terminate ()
ABIMacOSX_arm::Terminate();
ABIMacOSX_arm64::Terminate();
ABISysV_x86_64::Terminate();
ABISysV_ppc64::Terminate();
DisassemblerLLVMC::Terminate();
ObjectContainerBSDArchive::Terminate();
ObjectFileELF::Terminate();
Expand Down