[Lldb-commits] [lldb] r220944 - First cut of PowerPC(64) support in LLDB.
Justin Hibbits
jrh29 at alumni.cwru.edu
Thu Oct 30 19:34:29 PDT 2014
Author: jhibbits
Date: Thu Oct 30 21:34:28 2014
New Revision: 220944
URL: http://llvm.org/viewvc/llvm-project?rev=220944&view=rev
Log:
First cut of PowerPC(64) support in LLDB.
Summary:
This adds preliminary support for PowerPC/PowerPC64, for FreeBSD. There are
some issues still:
* Breakpoints don't work well on powerpc64.
* Shared libraries don't yet get loaded for a 32-bit process on powerpc64 host.
* Backtraces don't work. This is due to PowerPC ABI using a backchain pointer
in memory, instead of a dedicated frame pointer register for the backchain.
* Breakpoints on functions without debug info may not work correctly for 32-bit
powerpc.
Reviewers: emaste, tfiala, jingham, clayborg
Reviewed By: clayborg
Subscribers: emaste, lldb-commits
Differential Revision: http://reviews.llvm.org/D5988
Added:
lldb/trunk/source/Plugins/ABI/SysV-ppc/
lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
lldb/trunk/source/Plugins/ABI/SysV-ppc/CMakeLists.txt
lldb/trunk/source/Plugins/ABI/SysV-ppc/Makefile
lldb/trunk/source/Plugins/ABI/SysV-ppc64/
lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
lldb/trunk/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt
lldb/trunk/source/Plugins/ABI/SysV-ppc64/Makefile
lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h
lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
lldb/trunk/source/Plugins/Process/Utility/RegisterContext_powerpc.h
lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
Modified:
lldb/trunk/lib/Makefile
lldb/trunk/source/CMakeLists.txt
lldb/trunk/source/Core/ArchSpec.cpp
lldb/trunk/source/Host/freebsd/Host.cpp
lldb/trunk/source/Plugins/ABI/CMakeLists.txt
lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
lldb/trunk/source/Plugins/Makefile
lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt
lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt
lldb/trunk/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt
lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp
lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp
lldb/trunk/source/Target/Thread.cpp
lldb/trunk/source/lldb.cpp
Modified: lldb/trunk/lib/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lib/Makefile?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/lib/Makefile (original)
+++ lldb/trunk/lib/Makefile Thu Oct 30 21:34:28 2014
@@ -34,6 +34,7 @@ USEDLIBS = lldbAPI.a \
lldbPluginABIMacOSX_arm.a \
lldbPluginABIMacOSX_arm64.a \
lldbPluginABIMacOSX_i386.a \
+ lldbPluginABISysV_ppc64.a \
lldbPluginABISysV_x86_64.a \
lldbPluginABISysV_hexagon.a \
lldbPluginDisassemblerLLVM.a \
Modified: lldb/trunk/source/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/CMakeLists.txt?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/CMakeLists.txt (original)
+++ lldb/trunk/source/CMakeLists.txt Thu Oct 30 21:34:28 2014
@@ -80,6 +80,8 @@ set( LLDB_USED_LIBS
lldbPluginABIMacOSX_i386
lldbPluginABISysV_x86_64
lldbPluginABISysV_hexagon
+ lldbPluginABISysV_ppc
+ lldbPluginABISysV_ppc64
lldbPluginInstructionARM
lldbPluginInstructionARM64
lldbPluginObjectFilePECOFF
Modified: lldb/trunk/source/Core/ArchSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ArchSpec.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Core/ArchSpec.cpp (original)
+++ lldb/trunk/source/Core/ArchSpec.cpp Thu Oct 30 21:34:28 2014
@@ -19,6 +19,7 @@
#include "llvm/Support/ELF.h"
#include "llvm/Support/Host.h"
#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/StringList.h"
#include "lldb/Host/Endian.h"
@@ -84,7 +85,7 @@ static const CoreDefinition g_core_defin
{ eByteOrderBig , 8, 4, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" },
- { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "ppc" },
+ { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "powerpc" },
{ eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc601 , "ppc601" },
{ eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc602 , "ppc602" },
{ eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc603 , "ppc603" },
@@ -98,7 +99,7 @@ static const CoreDefinition g_core_defin
{ eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc7450 , "ppc7450" },
{ eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc970 , "ppc970" },
- { eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_generic , "ppc64" },
+ { eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_generic , "powerpc64" },
{ eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_ppc970_64 , "ppc970-64" },
{ eByteOrderLittle, 4, 4, 4, llvm::Triple::sparc , ArchSpec::eCore_sparc_generic , "sparc" },
Modified: lldb/trunk/source/Host/freebsd/Host.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/freebsd/Host.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Host/freebsd/Host.cpp (original)
+++ lldb/trunk/source/Host/freebsd/Host.cpp Thu Oct 30 21:34:28 2014
@@ -286,6 +286,49 @@ Host::GetProcessInfo (lldb::pid_t pid, P
return false;
}
+static lldb::DataBufferSP
+GetAuxvData32(lldb_private::Process *process)
+{
+ struct {
+ uint32_t ps_argvstr;
+ int ps_nargvstr;
+ uint32_t ps_envstr;
+ int ps_nenvstr;
+ } ps_strings;
+ void *ps_strings_addr, *auxv_addr;
+ struct privElf32_Auxinfo { int a_type; unsigned int a_val; } aux_info32[AT_COUNT];
+ struct ptrace_io_desc pid;
+ DataBufferSP buf_sp;
+ std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
+
+ ps_strings_addr = (void *)0xffffdff0;
+ pid.piod_op = PIOD_READ_D;
+ pid.piod_addr = &ps_strings;
+ pid.piod_offs = ps_strings_addr;
+ pid.piod_len = sizeof(ps_strings);
+ if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
+ perror("failed to fetch ps_strings");
+ buf_ap.release();
+ goto done;
+ }
+
+ auxv_addr = (void *)(ps_strings.ps_envstr + sizeof(uint32_t) * (ps_strings.ps_nenvstr + 1));
+
+ pid.piod_addr = aux_info32;
+ pid.piod_offs = auxv_addr;
+ pid.piod_len = sizeof(aux_info32);
+ if (::ptrace(PT_IO, process->GetID(), (caddr_t)&pid, 0)) {
+ perror("failed to fetch aux_info");
+ buf_ap.release();
+ goto done;
+ }
+ memcpy(buf_ap->GetBytes(), aux_info32, pid.piod_len);
+ buf_sp.reset(buf_ap.release());
+
+ done:
+ return buf_sp;
+}
+
lldb::DataBufferSP
Host::GetAuxvData(lldb_private::Process *process)
{
@@ -296,6 +339,10 @@ Host::GetAuxvData(lldb_private::Process
struct ps_strings ps_strings;
struct ptrace_io_desc pid;
DataBufferSP buf_sp;
+
+ if (process->GetAddressByteSize() < HostInfo::GetArchitecture().GetAddressByteSize())
+ return GetAuxvData32(process);
+
std::unique_ptr<DataBufferHeap> buf_ap(new DataBufferHeap(1024, 0));
if (::sysctl(mib, 2, &ps_strings_addr, &ps_strings_size, NULL, 0) == 0) {
Modified: lldb/trunk/source/Plugins/ABI/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/CMakeLists.txt?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/ABI/CMakeLists.txt Thu Oct 30 21:34:28 2014
@@ -1,4 +1,6 @@
add_subdirectory(SysV-hexagon)
+add_subdirectory(SysV-ppc64)
+add_subdirectory(SysV-ppc)
add_subdirectory(SysV-x86_64)
add_subdirectory(MacOSX-i386)
add_subdirectory(MacOSX-arm)
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp Thu Oct 30 21:34:28 2014
@@ -0,0 +1,1097 @@
+//===-- ABISysV_ppc.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_ppc.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_r0 = 0,
+ gcc_dwarf_r1,
+ gcc_dwarf_r2,
+ gcc_dwarf_r3,
+ gcc_dwarf_r4,
+ gcc_dwarf_r5,
+ gcc_dwarf_r6,
+ gcc_dwarf_r7,
+ gcc_dwarf_r8,
+ gcc_dwarf_r9,
+ gcc_dwarf_r10,
+ gcc_dwarf_r11,
+ gcc_dwarf_r12,
+ gcc_dwarf_r13,
+ gcc_dwarf_r14,
+ gcc_dwarf_r15,
+ gcc_dwarf_r16,
+ gcc_dwarf_r17,
+ gcc_dwarf_r18,
+ gcc_dwarf_r19,
+ gcc_dwarf_r20,
+ gcc_dwarf_r21,
+ gcc_dwarf_r22,
+ gcc_dwarf_r23,
+ gcc_dwarf_r24,
+ gcc_dwarf_r25,
+ gcc_dwarf_r26,
+ gcc_dwarf_r27,
+ gcc_dwarf_r28,
+ gcc_dwarf_r29,
+ gcc_dwarf_r30,
+ gcc_dwarf_r31,
+ gcc_dwarf_f0,
+ gcc_dwarf_f1,
+ gcc_dwarf_f2,
+ gcc_dwarf_f3,
+ gcc_dwarf_f4,
+ gcc_dwarf_f5,
+ gcc_dwarf_f6,
+ gcc_dwarf_f7,
+ gcc_dwarf_f8,
+ gcc_dwarf_f9,
+ gcc_dwarf_f10,
+ gcc_dwarf_f11,
+ gcc_dwarf_f12,
+ gcc_dwarf_f13,
+ gcc_dwarf_f14,
+ gcc_dwarf_f15,
+ gcc_dwarf_f16,
+ gcc_dwarf_f17,
+ gcc_dwarf_f18,
+ gcc_dwarf_f19,
+ gcc_dwarf_f20,
+ gcc_dwarf_f21,
+ gcc_dwarf_f22,
+ gcc_dwarf_f23,
+ gcc_dwarf_f24,
+ gcc_dwarf_f25,
+ gcc_dwarf_f26,
+ gcc_dwarf_f27,
+ gcc_dwarf_f28,
+ gcc_dwarf_f29,
+ gcc_dwarf_f30,
+ gcc_dwarf_f31,
+ gcc_dwarf_cr,
+ gcc_dwarf_fpscr,
+ gcc_dwarf_xer = 101,
+ gcc_dwarf_lr = 108,
+ gcc_dwarf_ctr,
+ gcc_dwarf_pc,
+ gcc_dwarf_cfa,
+};
+
+enum gdb_regnums
+{
+ gdb_r0 = 0,
+ gdb_r1,
+ gdb_r2,
+ gdb_r3,
+ gdb_r4,
+ gdb_r5,
+ gdb_r6,
+ gdb_r7,
+ gdb_r8,
+ gdb_r9,
+ gdb_r10,
+ gdb_r11,
+ gdb_r12,
+ gdb_r13,
+ gdb_r14,
+ gdb_r15,
+ gdb_r16,
+ gdb_r17,
+ gdb_r18,
+ gdb_r19,
+ gdb_r20,
+ gdb_r21,
+ gdb_r22,
+ gdb_r23,
+ gdb_r24,
+ gdb_r25,
+ gdb_r26,
+ gdb_r27,
+ gdb_r28,
+ gdb_r29,
+ gdb_r30,
+ gdb_r31,
+ gdb_lr,
+ gdb_cr,
+ gdb_xer,
+ gdb_ctr,
+ gdb_pc,
+};
+
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, 8, 0, eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL }
+static const RegisterInfo
+g_register_infos[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
+ DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
+ DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
+ DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
+ DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
+ DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
+ DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
+ DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
+ DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
+ DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
+ DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
+ DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
+ DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
+ DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
+ DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
+ DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
+ DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
+ DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
+ DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
+ DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
+ DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
+ DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
+ DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
+ DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
+ DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
+ DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
+ DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
+ DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
+ DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+
+const lldb_private::RegisterInfo *
+ABISysV_ppc::GetRegisterInfoArray (uint32_t &count)
+{
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+
+size_t
+ABISysV_ppc::GetRedZoneSize () const
+{
+ return 224;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_ppc::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_ppc);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_ppc::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_ppc::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+ thread.GetID(),
+ (uint64_t)sp,
+ (uint64_t)func_addr,
+ (uint64_t)return_addr);
+
+ for (size_t i = 0; i < args.size(); ++i)
+ s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ const RegisterInfo *reg_info = NULL;
+
+ if (args.size() > 8) // TODO handle more than 8 arguments
+ return false;
+
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+ }
+
+ // First, align the SP
+
+ if (log)
+ log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull));
+
+ sp &= ~(0xfull); // 16-byte alignment
+
+ sp -= 8;
+
+ Error error;
+ const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ ProcessSP process_sp (thread.GetProcess());
+
+ RegisterValue reg_value;
+
+#if 0
+ // This code adds an extra frame so that we don't lose the function that we came from
+ // by pushing the PC and the FP and then writing the current FP to point to the FP value
+ // we just pushed. It is disabled for now until the stack backtracing code can be debugged.
+
+ // Save current PC
+ const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+ if (reg_ctx->ReadRegister(pc_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+
+ sp -= 8;
+
+ // Save current FP
+ if (reg_ctx->ReadRegister(fp_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+ }
+ // Setup FP backchain
+ reg_value.SetUInt64 (sp);
+
+ if (log)
+ log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64());
+
+ if (!reg_ctx->WriteRegister(fp_reg_info, reg_value))
+ {
+ return false;
+ }
+
+ sp -= 8;
+ }
+#endif
+
+ if (log)
+ log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
+
+ // Save return address onto the stack
+ if (!process_sp->WritePointerToMemory(sp, return_addr, error))
+ return false;
+
+ // %r1 is set to the actual stack value.
+
+ if (log)
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
+ return false;
+
+ // %pc is set to the address of the called function.
+
+ if (log)
+ log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
+ return false;
+
+ return true;
+}
+
+static bool ReadIntegerArgument(Scalar &scalar,
+ unsigned int bit_width,
+ bool is_signed,
+ Thread &thread,
+ uint32_t *argument_register_ids,
+ unsigned int ¤t_argument_register,
+ addr_t ¤t_stack_argument)
+{
+ if (bit_width > 64)
+ return false; // Scalar can't hold large integer arguments
+
+ if (current_argument_register < 6)
+ {
+ scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
+ current_argument_register++;
+ if (is_signed)
+ scalar.SignExtend (bit_width);
+ }
+ else
+ {
+ uint32_t byte_size = (bit_width + (8-1))/8;
+ Error error;
+ if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
+ {
+ current_stack_argument += byte_size;
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+bool
+ABISysV_ppc::GetArgumentValues (Thread &thread,
+ ValueList &values) const
+{
+ unsigned int num_values = values.GetSize();
+ unsigned int value_index;
+
+ // Extract the register context so we can read arguments from registers
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ // Get the pointer to the first stack argument so we have a place to start
+ // when reading data
+
+ addr_t sp = reg_ctx->GetSP(0);
+
+ if (!sp)
+ return false;
+
+ addr_t current_stack_argument = sp + 48; // jump over return address
+
+ uint32_t argument_register_ids[8];
+
+ argument_register_ids[0] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB];
+ argument_register_ids[1] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB];
+ argument_register_ids[2] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB];
+ argument_register_ids[3] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB];
+ argument_register_ids[4] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB];
+ argument_register_ids[5] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)->kinds[eRegisterKindLLDB];
+ argument_register_ids[6] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)->kinds[eRegisterKindLLDB];
+ argument_register_ids[7] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)->kinds[eRegisterKindLLDB];
+
+ unsigned int current_argument_register = 0;
+
+ for (value_index = 0;
+ value_index < num_values;
+ ++value_index)
+ {
+ Value *value = values.GetValueAtIndex(value_index);
+
+ if (!value)
+ return false;
+
+ // We currently only support extracting values with Clang QualTypes.
+ // Do we care about others?
+ ClangASTType clang_type = value->GetClangType();
+ if (!clang_type)
+ return false;
+ bool is_signed;
+
+ if (clang_type.IsIntegerType (is_signed))
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ is_signed,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ else if (clang_type.IsPointerType ())
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ false,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ }
+
+ return true;
+}
+
+Error
+ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType clang_type = new_value_sp->GetClangType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+
+ }
+ else if (clang_type.IsFloatingPointType (count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ {
+ size_t bit_width = clang_type.GetBitSize();
+ if (bit_width <= 64)
+ {
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ unsigned char buffer[16];
+ ByteOrder byte_order = data.GetByteOrder();
+
+ data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order);
+ set_it_simple = true;
+ }
+ else
+ {
+ // FIXME - don't know how to do 80 bit long doubles yet.
+ error.SetErrorString ("We don't support returning float values > 64 bits at present");
+ }
+ }
+ }
+
+ if (!set_it_simple)
+ {
+ // Okay we've got a structure or something that doesn't fit in a simple register.
+ // We should figure out where it really goes, but we don't support this yet.
+ error.SetErrorString ("We only support setting simple integer and float return types at present.");
+ }
+
+ return error;
+}
+
+
+ValueObjectSP
+ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
+ ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ //value.SetContext (Value::eContextTypeClangType, return_value_type);
+ value.SetClangType (return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ if (type_flags & eTypeIsScalar)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & eTypeIsInteger)
+ {
+ // Extract the register context so we can read arguments from registers
+
+ const size_t byte_size = return_clang_type.GetByteSize();
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+
+ case sizeof(uint64_t):
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
+ }
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+
+ }
+ else if (type_flags & eTypeIsPointer)
+ {
+ unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ value.SetValueType(Value::eValueTypeScalar);
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ const size_t byte_size = return_clang_type.GetByteSize();
+ if (byte_size > 0)
+ {
+
+ const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0);
+ if (altivec_reg == NULL)
+ altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
+ if (altivec_reg)
+ {
+ if (byte_size <= altivec_reg->byte_size)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(altivec_reg, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (altivec_reg,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ if (return_valobj_sp)
+ return return_valobj_sp;
+
+ RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+ if (!reg_ctx_sp)
+ return return_valobj_sp;
+
+ const size_t bit_width = return_clang_type.GetBitSize();
+ if (return_clang_type.IsAggregateType())
+ {
+ Target *target = exe_ctx.GetTargetPtr();
+ bool is_memory = true;
+ if (bit_width <= 128)
+ {
+ ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0);
+ const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
+
+ RegisterValue r3_value, rdx_value;
+ reg_ctx_sp->ReadRegister (r3_info, r3_value);
+ reg_ctx_sp->ReadRegister (rdx_info, rdx_value);
+
+ DataExtractor r3_data, rdx_data;
+
+ r3_value.GetData(r3_data);
+ rdx_value.GetData(rdx_data);
+
+ uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
+ uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
+
+ const uint32_t num_children = return_clang_type.GetNumFields ();
+
+ // Since we are in the small struct regime, assume we are not in memory.
+ is_memory = false;
+
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ std::string name;
+ uint64_t field_bit_offset = 0;
+ bool is_signed;
+ bool is_complex;
+ uint32_t count;
+
+ ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_clang_type.GetBitSize();
+
+ // If there are any unaligned fields, this is stored in memory.
+ if (field_bit_offset % field_bit_width != 0)
+ {
+ is_memory = true;
+ break;
+ }
+
+ uint32_t field_byte_width = field_bit_width/8;
+ uint32_t field_byte_offset = field_bit_offset/8;
+
+
+ DataExtractor *copy_from_extractor = NULL;
+ uint32_t copy_from_offset = 0;
+
+ if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ {
+ if (integer_bytes < 8)
+ {
+ if (integer_bytes + field_byte_width <= 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The next field wouldn't fit in the remaining space, so we pushed it to rdx.
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = 0;
+ integer_bytes = 8 + field_byte_width;
+
+ }
+ }
+ else if (integer_bytes + field_byte_width <= 16)
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The last field didn't fit. I can't see how that would happen w/o the overall size being
+ // greater than 16 bytes. For now, return a NULL return value object.
+ return return_valobj_sp;
+ }
+ }
+ else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ {
+ // Structs with long doubles are always passed in memory.
+ if (field_bit_width == 128)
+ {
+ is_memory = true;
+ break;
+ }
+ else if (field_bit_width == 64)
+ {
+ copy_from_offset = 0;
+ fp_bytes += field_byte_width;
+ }
+ else if (field_bit_width == 32)
+ {
+ // This one is kind of complicated. If we are in an "eightbyte" with another float, we'll
+ // be stuffed into an xmm register with it. If we are in an "eightbyte" with one or more ints,
+ // then we will be stuffed into the appropriate GPR with them.
+ bool in_gpr;
+ if (field_byte_offset % 8 == 0)
+ {
+ // We are at the beginning of one of the eightbytes, so check the next element (if any)
+ if (idx == num_children - 1)
+ in_gpr = false;
+ else
+ {
+ uint64_t next_field_bit_offset = 0;
+ ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ name,
+ &next_field_bit_offset,
+ NULL,
+ NULL);
+ if (next_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 0;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else if (field_byte_offset % 4 == 0)
+ {
+ // We are inside of an eightbyte, so see if the field before us is floating point:
+ // This could happen if somebody put padding in the structure.
+ if (idx == 0)
+ in_gpr = false;
+ else
+ {
+ uint64_t prev_field_bit_offset = 0;
+ ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ name,
+ &prev_field_bit_offset,
+ NULL,
+ NULL);
+ if (prev_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 4;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else
+ {
+ is_memory = true;
+ continue;
+ }
+
+ // Okay, we've figured out whether we are in GPR or XMM, now figure out which one.
+ if (in_gpr)
+ {
+ if (integer_bytes < 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ }
+ else
+ {
+ fp_bytes += field_byte_width;
+ }
+ }
+ }
+
+ // These two tests are just sanity checks. If I somehow get the
+ // type calculation wrong above it is better to just return nothing
+ // than to assert or crash.
+ if (!copy_from_extractor)
+ return return_valobj_sp;
+ if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize())
+ return return_valobj_sp;
+
+ copy_from_extractor->CopyByteOrderedData (copy_from_offset,
+ field_byte_width,
+ data_sp->GetBytes() + field_byte_offset,
+ field_byte_width,
+ target_byte_order);
+ }
+
+ if (!is_memory)
+ {
+ // The result is in our data buffer. Let's make a variable object out of it:
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ return_ext);
+ }
+ }
+
+
+ // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location.
+ // If we are going to do this right, when we make a new frame we should check to see if it uses a memory
+ // return, and if we are at the first instruction and if so stash away the return location. Then we would
+ // only return the memory return value if we know it is valid.
+
+ if (is_memory)
+ {
+ unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (storage_addr, NULL),
+ return_clang_type);
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+bool
+ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t lr_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->SetCFARegister (sp_reg_num);
+
+ // The previous PC is in the LR
+ row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("ppc at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+ return true;
+}
+
+bool
+ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_lr;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ const int32_t ptr_size = 8;
+ row->SetCFARegister (LLDB_REGNUM_GENERIC_SP);
+ row->SetCFAOffset (8);
+ row->SetOffset (0);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * -2, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("ppc default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ return true;
+}
+
+bool
+ABISysV_ppc::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return !RegisterIsCalleeSaved (reg_info);
+}
+
+
+
+// See "Register Usage" in the
+// "System V Application Binary Interface"
+// "64-bit PowerPC ELF Application Binary Interface Supplement"
+// current version is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc/PPC-elf64abi-1.9.pdf
+
+bool
+ABISysV_ppc::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Preserved registers are :
+ // r1,r2,r13-r31
+ // f14-f31 (not yet)
+ // v20-v31 (not yet)
+ // vrsave (not yet)
+
+ const char *name = reg_info->name;
+ if (name[0] == 'r')
+ {
+ if ((name[1] == '1' || name[1] == '2') && name[2] == '\0')
+ return true;
+ if (name[1] == '1' && name[2] > '2')
+ return true;
+ if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')
+ return true;
+ }
+
+ if (name[0] == 'f' && name[1] >= '0' && name[1] <= '9')
+ {
+ if (name[3] == '1' && name[4] >= '4')
+ return true;
+ if ((name[3] == '2' || name[3] == '3') && name[4] != '\0')
+ return true;
+ }
+
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
+ return true;
+ if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
+ return true;
+ }
+ return false;
+}
+
+
+
+void
+ABISysV_ppc::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for ppc targets",
+ CreateInstance);
+}
+
+void
+ABISysV_ppc::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_ppc::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-ppc");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_ppc::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_ppc::GetPluginVersion()
+{
+ return 1;
+}
+
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h Thu Oct 30 21:34:28 2014
@@ -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_
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc/CMakeLists.txt?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc/CMakeLists.txt Thu Oct 30 21:34:28 2014
@@ -0,0 +1,5 @@
+set(LLVM_NO_RTTI 1)
+
+add_lldb_library(lldbPluginABISysV_ppc
+ ABISysV_ppc.cpp
+ )
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc/Makefile?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc/Makefile (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc/Makefile Thu Oct 30 21:34:28 2014
@@ -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
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp Thu Oct 30 21:34:28 2014
@@ -0,0 +1,1101 @@
+//===-- ABISysV_ppc64.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_ppc64.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum gcc_dwarf_regnums
+{
+ gcc_dwarf_r0 = 0,
+ gcc_dwarf_r1,
+ gcc_dwarf_r2,
+ gcc_dwarf_r3,
+ gcc_dwarf_r4,
+ gcc_dwarf_r5,
+ gcc_dwarf_r6,
+ gcc_dwarf_r7,
+ gcc_dwarf_r8,
+ gcc_dwarf_r9,
+ gcc_dwarf_r10,
+ gcc_dwarf_r11,
+ gcc_dwarf_r12,
+ gcc_dwarf_r13,
+ gcc_dwarf_r14,
+ gcc_dwarf_r15,
+ gcc_dwarf_r16,
+ gcc_dwarf_r17,
+ gcc_dwarf_r18,
+ gcc_dwarf_r19,
+ gcc_dwarf_r20,
+ gcc_dwarf_r21,
+ gcc_dwarf_r22,
+ gcc_dwarf_r23,
+ gcc_dwarf_r24,
+ gcc_dwarf_r25,
+ gcc_dwarf_r26,
+ gcc_dwarf_r27,
+ gcc_dwarf_r28,
+ gcc_dwarf_r29,
+ gcc_dwarf_r30,
+ gcc_dwarf_r31,
+ gcc_dwarf_f0,
+ gcc_dwarf_f1,
+ gcc_dwarf_f2,
+ gcc_dwarf_f3,
+ gcc_dwarf_f4,
+ gcc_dwarf_f5,
+ gcc_dwarf_f6,
+ gcc_dwarf_f7,
+ gcc_dwarf_f8,
+ gcc_dwarf_f9,
+ gcc_dwarf_f10,
+ gcc_dwarf_f11,
+ gcc_dwarf_f12,
+ gcc_dwarf_f13,
+ gcc_dwarf_f14,
+ gcc_dwarf_f15,
+ gcc_dwarf_f16,
+ gcc_dwarf_f17,
+ gcc_dwarf_f18,
+ gcc_dwarf_f19,
+ gcc_dwarf_f20,
+ gcc_dwarf_f21,
+ gcc_dwarf_f22,
+ gcc_dwarf_f23,
+ gcc_dwarf_f24,
+ gcc_dwarf_f25,
+ gcc_dwarf_f26,
+ gcc_dwarf_f27,
+ gcc_dwarf_f28,
+ gcc_dwarf_f29,
+ gcc_dwarf_f30,
+ gcc_dwarf_f31,
+ gcc_dwarf_cr,
+ gcc_dwarf_fpscr,
+ gcc_dwarf_xer = 101,
+ gcc_dwarf_lr = 108,
+ gcc_dwarf_ctr,
+ gcc_dwarf_pc,
+ gcc_dwarf_cfa,
+};
+
+enum gdb_regnums
+{
+ gdb_r0 = 0,
+ gdb_r1,
+ gdb_r2,
+ gdb_r3,
+ gdb_r4,
+ gdb_r5,
+ gdb_r6,
+ gdb_r7,
+ gdb_r8,
+ gdb_r9,
+ gdb_r10,
+ gdb_r11,
+ gdb_r12,
+ gdb_r13,
+ gdb_r14,
+ gdb_r15,
+ gdb_r16,
+ gdb_r17,
+ gdb_r18,
+ gdb_r19,
+ gdb_r20,
+ gdb_r21,
+ gdb_r22,
+ gdb_r23,
+ gdb_r24,
+ gdb_r25,
+ gdb_r26,
+ gdb_r27,
+ gdb_r28,
+ gdb_r29,
+ gdb_r30,
+ gdb_r31,
+ gdb_lr,
+ gdb_cr,
+ gdb_xer,
+ gdb_ctr,
+ gdb_pc,
+};
+
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
+ { #reg, alt, 8, 0, eEncodingUint, \
+ eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL }
+static const RegisterInfo
+g_register_infos[] =
+{
+ // General purpose registers. GCC, DWARF, Generic, GDB
+ DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
+ DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
+ DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
+ DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
+ DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
+ DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
+ DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
+ DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
+ DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
+ DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
+ DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
+ DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
+ DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
+ DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
+ DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
+ DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
+ DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
+ DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
+ DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
+ DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
+ DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
+ DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
+ DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
+ DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
+ DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
+ DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
+ DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
+ DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
+ DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
+ DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
+ DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
+ DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
+ DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
+ DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+
+const lldb_private::RegisterInfo *
+ABISysV_ppc64::GetRegisterInfoArray (uint32_t &count)
+{
+ count = k_num_register_infos;
+ return g_register_infos;
+}
+
+
+size_t
+ABISysV_ppc64::GetRedZoneSize () const
+{
+ return 224;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_ppc64::CreateInstance (const ArchSpec &arch)
+{
+ static ABISP g_abi_sp;
+ if (arch.GetTriple().getArch() == llvm::Triple::ppc64)
+ {
+ if (!g_abi_sp)
+ g_abi_sp.reset (new ABISysV_ppc64);
+ return g_abi_sp;
+ }
+ return ABISP();
+}
+
+bool
+ABISysV_ppc64::PrepareTrivialCall (Thread &thread,
+ addr_t sp,
+ addr_t func_addr,
+ addr_t return_addr,
+ llvm::ArrayRef<addr_t> args) const
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ StreamString s;
+ s.Printf("ABISysV_ppc64::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+ thread.GetID(),
+ (uint64_t)sp,
+ (uint64_t)func_addr,
+ (uint64_t)return_addr);
+
+ for (size_t i = 0; i < args.size(); ++i)
+ s.Printf (", arg%zd = 0x%" PRIx64, i + 1, args[i]);
+ s.PutCString (")");
+ log->PutCString(s.GetString().c_str());
+ }
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ const RegisterInfo *reg_info = NULL;
+
+ if (args.size() > 8) // TODO handle more than 8 arguments
+ return false;
+
+ for (size_t i = 0; i < args.size(); ++i)
+ {
+ reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ if (log)
+ log->Printf("About to write arg%zd (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+ return false;
+ }
+
+ // First, align the SP
+
+ if (log)
+ log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull));
+
+ sp &= ~(0xfull); // 16-byte alignment
+
+ sp -= 8;
+
+ Error error;
+ const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ ProcessSP process_sp (thread.GetProcess());
+
+ RegisterValue reg_value;
+
+#if 0
+ // This code adds an extra frame so that we don't lose the function that we came from
+ // by pushing the PC and the FP and then writing the current FP to point to the FP value
+ // we just pushed. It is disabled for now until the stack backtracing code can be debugged.
+
+ // Save current PC
+ const RegisterInfo *fp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+ if (reg_ctx->ReadRegister(pc_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current PC onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+
+ sp -= 8;
+
+ // Save current FP
+ if (reg_ctx->ReadRegister(fp_reg_info, reg_value))
+ {
+ if (log)
+ log->Printf("Pushing the current FP onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, reg_value.GetAsUInt64());
+
+ if (!process_sp->WritePointerToMemory(sp, reg_value.GetAsUInt64(), error))
+ return false;
+ }
+ // Setup FP backchain
+ reg_value.SetUInt64 (sp);
+
+ if (log)
+ log->Printf("Writing FP: 0x%" PRIx64 " (for FP backchain)", reg_value.GetAsUInt64());
+
+ if (!reg_ctx->WriteRegister(fp_reg_info, reg_value))
+ {
+ return false;
+ }
+
+ sp -= 8;
+ }
+#endif
+
+ if (log)
+ log->Printf("Pushing the return address onto the stack: 0x%" PRIx64 ": 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
+
+ // Save return address onto the stack
+ if (!process_sp->WritePointerToMemory(sp, return_addr, error))
+ return false;
+
+ // %r1 is set to the actual stack value.
+
+ if (log)
+ log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_info, sp))
+ return false;
+
+ // %pc is set to the address of the called function.
+
+ if (log)
+ log->Printf("Writing IP: 0x%" PRIx64, (uint64_t)func_addr);
+
+ if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
+ return false;
+
+ return true;
+}
+
+static bool ReadIntegerArgument(Scalar &scalar,
+ unsigned int bit_width,
+ bool is_signed,
+ Thread &thread,
+ uint32_t *argument_register_ids,
+ unsigned int ¤t_argument_register,
+ addr_t ¤t_stack_argument)
+{
+ if (bit_width > 64)
+ return false; // Scalar can't hold large integer arguments
+
+ if (current_argument_register < 6)
+ {
+ scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
+ current_argument_register++;
+ if (is_signed)
+ scalar.SignExtend (bit_width);
+ }
+ else
+ {
+ uint32_t byte_size = (bit_width + (8-1))/8;
+ Error error;
+ if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
+ {
+ current_stack_argument += byte_size;
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+bool
+ABISysV_ppc64::GetArgumentValues (Thread &thread,
+ ValueList &values) const
+{
+ unsigned int num_values = values.GetSize();
+ unsigned int value_index;
+
+ // Extract the register context so we can read arguments from registers
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+
+ if (!reg_ctx)
+ return false;
+
+ // Get the pointer to the first stack argument so we have a place to start
+ // when reading data
+
+ addr_t sp = reg_ctx->GetSP(0);
+
+ if (!sp)
+ return false;
+
+ addr_t current_stack_argument = sp + 48; // jump over return address
+
+ uint32_t argument_register_ids[8];
+
+ argument_register_ids[0] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB];
+ argument_register_ids[1] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB];
+ argument_register_ids[2] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB];
+ argument_register_ids[3] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB];
+ argument_register_ids[4] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB];
+ argument_register_ids[5] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6)->kinds[eRegisterKindLLDB];
+ argument_register_ids[6] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG7)->kinds[eRegisterKindLLDB];
+ argument_register_ids[7] = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG8)->kinds[eRegisterKindLLDB];
+
+ unsigned int current_argument_register = 0;
+
+ for (value_index = 0;
+ value_index < num_values;
+ ++value_index)
+ {
+ Value *value = values.GetValueAtIndex(value_index);
+
+ if (!value)
+ return false;
+
+ // We currently only support extracting values with Clang QualTypes.
+ // Do we care about others?
+ ClangASTType clang_type = value->GetClangType();
+ if (!clang_type)
+ return false;
+ bool is_signed;
+
+ if (clang_type.IsIntegerType (is_signed))
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ is_signed,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ else if (clang_type.IsPointerType ())
+ {
+ ReadIntegerArgument(value->GetScalar(),
+ clang_type.GetBitSize(),
+ false,
+ thread,
+ argument_register_ids,
+ current_argument_register,
+ current_stack_argument);
+ }
+ }
+
+ return true;
+}
+
+Error
+ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+ Error error;
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ ClangASTType clang_type = new_value_sp->GetClangType();
+ if (!clang_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ Thread *thread = frame_sp->GetThread().get();
+
+ bool is_signed;
+ uint32_t count;
+ bool is_complex;
+
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+ bool set_it_simple = false;
+ if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ if (num_bytes <= 8)
+ {
+ uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+
+ if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value))
+ set_it_simple = true;
+ }
+ else
+ {
+ error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+ }
+
+ }
+ else if (clang_type.IsFloatingPointType (count, is_complex))
+ {
+ if (is_complex)
+ error.SetErrorString ("We don't support returning complex values at present");
+ else
+ {
+ size_t bit_width = clang_type.GetBitSize();
+ if (bit_width <= 64)
+ {
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ unsigned char buffer[16];
+ ByteOrder byte_order = data.GetByteOrder();
+
+ data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order);
+ set_it_simple = true;
+ }
+ else
+ {
+ // FIXME - don't know how to do 80 bit long doubles yet.
+ error.SetErrorString ("We don't support returning float values > 64 bits at present");
+ }
+ }
+ }
+
+ if (!set_it_simple)
+ {
+ // Okay we've got a structure or something that doesn't fit in a simple register.
+ // We should figure out where it really goes, but we don't support this yet.
+ error.SetErrorString ("We only support setting simple integer and float return types at present.");
+ }
+
+ return error;
+}
+
+
+ValueObjectSP
+ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
+ ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+ Value value;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ //value.SetContext (Value::eContextTypeClangType, return_value_type);
+ value.SetClangType (return_clang_type);
+
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return return_valobj_sp;
+
+ const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ if (type_flags & eTypeIsScalar)
+ {
+ value.SetValueType(Value::eValueTypeScalar);
+
+ bool success = false;
+ if (type_flags & eTypeIsInteger)
+ {
+ // Extract the register context so we can read arguments from registers
+
+ const size_t byte_size = return_clang_type.GetByteSize();
+ uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
+ const bool is_signed = (type_flags & eTypeIsSigned) != 0;
+ switch (byte_size)
+ {
+ default:
+ break;
+
+ case sizeof(uint64_t):
+ if (is_signed)
+ value.GetScalar() = (int64_t)(raw_value);
+ else
+ value.GetScalar() = (uint64_t)(raw_value);
+ success = true;
+ break;
+
+ case sizeof(uint32_t):
+ if (is_signed)
+ value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+ else
+ value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint16_t):
+ if (is_signed)
+ value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+ else
+ value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+ success = true;
+ break;
+
+ case sizeof(uint8_t):
+ if (is_signed)
+ value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+ else
+ value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+ success = true;
+ break;
+ }
+ }
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ }
+ }
+
+ if (success)
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+
+ }
+ else if (type_flags & eTypeIsPointer)
+ {
+ unsigned r3_id = reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ value.SetValueType(Value::eValueTypeScalar);
+ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+ value,
+ ConstString(""));
+ }
+ else if (type_flags & eTypeIsVector)
+ {
+ const size_t byte_size = return_clang_type.GetByteSize();
+ if (byte_size > 0)
+ {
+
+ const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v0", 0);
+ if (altivec_reg == NULL)
+ altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
+ if (altivec_reg)
+ {
+ if (byte_size <= altivec_reg->byte_size)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ if (reg_ctx->ReadRegister(altivec_reg, reg_value))
+ {
+ Error error;
+ if (reg_value.GetAsMemoryData (altivec_reg,
+ heap_data_ap->GetBytes(),
+ heap_data_ap->GetByteSize(),
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+ ValueObjectSP return_valobj_sp;
+
+ if (!return_clang_type)
+ return return_valobj_sp;
+
+ ExecutionContext exe_ctx (thread.shared_from_this());
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ if (return_valobj_sp)
+ return return_valobj_sp;
+
+ RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+ if (!reg_ctx_sp)
+ return return_valobj_sp;
+
+ const size_t bit_width = return_clang_type.GetBitSize();
+ if (return_clang_type.IsAggregateType())
+ {
+ Target *target = exe_ctx.GetTargetPtr();
+ bool is_memory = true;
+ if (bit_width <= 128)
+ {
+ ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ const RegisterInfo *r3_info = reg_ctx_sp->GetRegisterInfoByName("r3", 0);
+ const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
+
+ RegisterValue r3_value, rdx_value;
+ reg_ctx_sp->ReadRegister (r3_info, r3_value);
+ reg_ctx_sp->ReadRegister (rdx_info, rdx_value);
+
+ DataExtractor r3_data, rdx_data;
+
+ r3_value.GetData(r3_data);
+ rdx_value.GetData(rdx_data);
+
+ uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
+ uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
+
+ const uint32_t num_children = return_clang_type.GetNumFields ();
+
+ // Since we are in the small struct regime, assume we are not in memory.
+ is_memory = false;
+
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ std::string name;
+ uint64_t field_bit_offset = 0;
+ bool is_signed;
+ bool is_complex;
+ uint32_t count;
+
+ ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_clang_type.GetBitSize();
+
+ // If there are any unaligned fields, this is stored in memory.
+ if (field_bit_offset % field_bit_width != 0)
+ {
+ is_memory = true;
+ break;
+ }
+
+ uint32_t field_byte_width = field_bit_width/8;
+ uint32_t field_byte_offset = field_bit_offset/8;
+
+
+ DataExtractor *copy_from_extractor = NULL;
+ uint32_t copy_from_offset = 0;
+
+ if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ {
+ if (integer_bytes < 8)
+ {
+ if (integer_bytes + field_byte_width <= 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The next field wouldn't fit in the remaining space, so we pushed it to rdx.
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = 0;
+ integer_bytes = 8 + field_byte_width;
+
+ }
+ }
+ else if (integer_bytes + field_byte_width <= 16)
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ // The last field didn't fit. I can't see how that would happen w/o the overall size being
+ // greater than 16 bytes. For now, return a NULL return value object.
+ return return_valobj_sp;
+ }
+ }
+ else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ {
+ // Structs with long doubles are always passed in memory.
+ if (field_bit_width == 128)
+ {
+ is_memory = true;
+ break;
+ }
+ else if (field_bit_width == 64)
+ {
+ copy_from_offset = 0;
+ fp_bytes += field_byte_width;
+ }
+ else if (field_bit_width == 32)
+ {
+ // This one is kind of complicated. If we are in an "eightbyte" with another float, we'll
+ // be stuffed into an xmm register with it. If we are in an "eightbyte" with one or more ints,
+ // then we will be stuffed into the appropriate GPR with them.
+ bool in_gpr;
+ if (field_byte_offset % 8 == 0)
+ {
+ // We are at the beginning of one of the eightbytes, so check the next element (if any)
+ if (idx == num_children - 1)
+ in_gpr = false;
+ else
+ {
+ uint64_t next_field_bit_offset = 0;
+ ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ name,
+ &next_field_bit_offset,
+ NULL,
+ NULL);
+ if (next_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 0;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else if (field_byte_offset % 4 == 0)
+ {
+ // We are inside of an eightbyte, so see if the field before us is floating point:
+ // This could happen if somebody put padding in the structure.
+ if (idx == 0)
+ in_gpr = false;
+ else
+ {
+ uint64_t prev_field_bit_offset = 0;
+ ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ name,
+ &prev_field_bit_offset,
+ NULL,
+ NULL);
+ if (prev_field_clang_type.IsIntegerType (is_signed))
+ in_gpr = true;
+ else
+ {
+ copy_from_offset = 4;
+ in_gpr = false;
+ }
+ }
+
+ }
+ else
+ {
+ is_memory = true;
+ continue;
+ }
+
+ // Okay, we've figured out whether we are in GPR or XMM, now figure out which one.
+ if (in_gpr)
+ {
+ if (integer_bytes < 8)
+ {
+ // This is in RAX, copy from register to our result structure:
+ copy_from_extractor = &r3_data;
+ copy_from_offset = integer_bytes;
+ integer_bytes += field_byte_width;
+ }
+ else
+ {
+ copy_from_extractor = &rdx_data;
+ copy_from_offset = integer_bytes - 8;
+ integer_bytes += field_byte_width;
+ }
+ }
+ else
+ {
+ fp_bytes += field_byte_width;
+ }
+ }
+ }
+
+ // These two tests are just sanity checks. If I somehow get the
+ // type calculation wrong above it is better to just return nothing
+ // than to assert or crash.
+ if (!copy_from_extractor)
+ return return_valobj_sp;
+ if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize())
+ return return_valobj_sp;
+
+ copy_from_extractor->CopyByteOrderedData (copy_from_offset,
+ field_byte_width,
+ data_sp->GetBytes() + field_byte_offset,
+ field_byte_width,
+ target_byte_order);
+ }
+
+ if (!is_memory)
+ {
+ // The result is in our data buffer. Let's make a variable object out of it:
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_clang_type,
+ ConstString(""),
+ return_ext);
+ }
+ }
+
+
+ // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location.
+ // If we are going to do this right, when we make a new frame we should check to see if it uses a memory
+ // return, and if we are at the first instruction and if so stash away the return location. Then we would
+ // only return the memory return value if we know it is valid.
+
+ if (is_memory)
+ {
+ unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
+ lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (storage_addr, NULL),
+ return_clang_type);
+ }
+ }
+
+ return return_valobj_sp;
+}
+
+bool
+ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t lr_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_pc;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ // Our Call Frame Address is the stack pointer value
+ row->SetCFARegister (sp_reg_num);
+
+ // The previous PC is in the LR
+ row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+ unwind_plan.AppendRow (row);
+
+ // All other registers are the same.
+
+ unwind_plan.SetSourceName ("ppc64 at-func-entry default");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+ return true;
+}
+
+bool
+ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+ unwind_plan.Clear();
+ unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+ uint32_t sp_reg_num = gcc_dwarf_r1;
+ uint32_t pc_reg_num = gcc_dwarf_lr;
+
+ UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+ const int32_t ptr_size = 8;
+ row->SetCFARegister (LLDB_REGNUM_GENERIC_SP);
+ row->SetCFAOffset (48);
+ row->SetOffset (0);
+
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -4, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * -6, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size * -5, true);
+
+ unwind_plan.AppendRow (row);
+ unwind_plan.SetSourceName ("ppc64 default unwind plan");
+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+ unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ return true;
+}
+
+bool
+ABISysV_ppc64::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+ return !RegisterIsCalleeSaved (reg_info);
+}
+
+
+
+// See "Register Usage" in the
+// "System V Application Binary Interface"
+// "64-bit PowerPC ELF Application Binary Interface Supplement"
+// current version is 1.9 released 2004 at http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.pdf
+
+bool
+ABISysV_ppc64::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+ if (reg_info)
+ {
+ // Preserved registers are :
+ // r1,r2,r13-r31
+ // cr2-cr4 (partially preserved)
+ // f14-f31 (not yet)
+ // v20-v31 (not yet)
+ // vrsave (not yet)
+
+ const char *name = reg_info->name;
+ if (name[0] == 'r')
+ {
+ if ((name[1] == '1' || name[1] == '2') && name[2] == '\0')
+ return true;
+ if (name[1] == '1' && name[2] > '2')
+ return true;
+ if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')
+ return true;
+ }
+
+ if (name[0] == 'f' && name[1] >= '0' && name[2] <= '9')
+ {
+ if (name[2] == '\0')
+ return false;
+ if (name[1] == '1' && name[2] >= '4')
+ return true;
+ if ((name[1] == '2' || name[1] == '3') && name[2] != '\0')
+ return true;
+ }
+
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp
+ return true;
+ if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc
+ return true;
+ }
+ return false;
+}
+
+
+
+void
+ABISysV_ppc64::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "System V ABI for ppc64 targets",
+ CreateInstance);
+}
+
+void
+ABISysV_ppc64::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_ppc64::GetPluginNameStatic()
+{
+ static ConstString g_name("sysv-ppc64");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_ppc64::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_ppc64::GetPluginVersion()
+{
+ return 1;
+}
+
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h Thu Oct 30 21:34:28 2014
@@ -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_
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc64/CMakeLists.txt Thu Oct 30 21:34:28 2014
@@ -0,0 +1,5 @@
+set(LLVM_NO_RTTI 1)
+
+add_lldb_library(lldbPluginABISysV_ppc64
+ ABISysV_ppc64.cpp
+ )
Added: lldb/trunk/source/Plugins/ABI/SysV-ppc64/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-ppc64/Makefile?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-ppc64/Makefile (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-ppc64/Makefile Thu Oct 30 21:34:28 2014
@@ -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
Modified: lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp (original)
+++ lldb/trunk/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp Thu Oct 30 21:34:28 2014
@@ -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;
}
Modified: lldb/trunk/source/Plugins/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Makefile?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Makefile (original)
+++ lldb/trunk/source/Plugins/Makefile Thu Oct 30 21:34:28 2014
@@ -13,7 +13,7 @@ include $(LLDB_LEVEL)/../../Makefile.con
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 \
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp Thu Oct 30 21:34:28 2014
@@ -173,6 +173,12 @@ ELFHeader::GetRelocationJumpSlotType() c
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;
Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Thu Oct 30 21:34:28 2014
@@ -1724,6 +1724,7 @@ ObjectFileELF::ParseSymbols (Symtab *sym
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;
Modified: lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp Thu Oct 30 21:34:28 2014
@@ -326,6 +326,13 @@ PlatformFreeBSD::GetSoftwareBreakpointTr
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))
Modified: lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp Thu Oct 30 21:34:28 2014
@@ -113,6 +113,7 @@ PtraceWrapper(int req, lldb::pid_t pid,
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';
@@ -120,6 +121,7 @@ PtraceWrapper(int req, lldb::pid_t pid,
for (int i = 0; i <= 7; i++)
log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]);
}
+#endif
}
return result;
Modified: lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/CMakeLists.txt Thu Oct 30 21:34:28 2014
@@ -12,5 +12,6 @@ add_lldb_library(lldbPluginProcessPOSIX
ProcessPOSIXLog.cpp
RegisterContextPOSIXProcessMonitor_arm64.cpp
RegisterContextPOSIXProcessMonitor_mips64.cpp
+ RegisterContextPOSIXProcessMonitor_powerpc.cpp
RegisterContextPOSIXProcessMonitor_x86.cpp
)
Modified: lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/POSIX/POSIXThread.cpp Thu Oct 30 21:34:28 2014
@@ -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"
@@ -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;
@@ -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:
{
@@ -624,6 +642,8 @@ POSIXThread::GetRegisterIndexFromOffset(
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:
{
@@ -655,6 +675,8 @@ POSIXThread::GetRegisterName(unsigned re
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);
Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp (added)
+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp Thu Oct 30 21:34:28 2014
@@ -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;
+}
+
Added: lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h (added)
+++ lldb/trunk/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h Thu Oct 30 21:34:28 2014
@@ -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
Modified: lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt Thu Oct 30 21:34:28 2014
@@ -16,6 +16,7 @@ add_lldb_library(lldbPluginProcessUtilit
RegisterContextDummy.cpp
RegisterContextFreeBSD_i386.cpp
RegisterContextFreeBSD_mips64.cpp
+ RegisterContextFreeBSD_powerpc.cpp
RegisterContextFreeBSD_x86_64.cpp
RegisterContextHistory.cpp
RegisterContextLinux_arm64.cpp
@@ -29,6 +30,7 @@ add_lldb_library(lldbPluginProcessUtilit
RegisterContextMemory.cpp
RegisterContextPOSIX_arm64.cpp
RegisterContextPOSIX_mips64.cpp
+ RegisterContextPOSIX_powerpc.cpp
RegisterContextPOSIX_x86.cpp
RegisterContextThreadMemory.cpp
StopInfoMachException.cpp
Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp Thu Oct 30 21:34:28 2014
@@ -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]));
+}
Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h Thu Oct 30 21:34:28 2014
@@ -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
Modified: lldb/trunk/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp Thu Oct 30 21:34:28 2014
@@ -149,7 +149,8 @@ RegisterContextMacOSXFrameBackchain::Rea
// 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))
{
Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp Thu Oct 30 21:34:28 2014
@@ -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;
+}
+
Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h Thu Oct 30 21:34:28 2014
@@ -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_
Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContext_powerpc.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContext_powerpc.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContext_powerpc.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContext_powerpc.h Thu Oct 30 21:34:28 2014
@@ -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_
Added: lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_powerpc.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_powerpc.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_powerpc.h Thu Oct 30 21:34:28 2014
@@ -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
+
Modified: lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt Thu Oct 30 21:34:28 2014
@@ -6,5 +6,6 @@ add_lldb_library(lldbPluginProcessElfCor
ProcessElfCore.cpp
ThreadElfCore.cpp
RegisterContextPOSIXCore_mips64.cpp
+ RegisterContextPOSIXCore_powerpc.cpp
RegisterContextPOSIXCore_x86_64.cpp
)
Modified: lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ProcessElfCore.cpp Thu Oct 30 21:34:28 2014
@@ -420,6 +420,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_
{
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);
Added: lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp (added)
+++ lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp Thu Oct 30 21:34:28 2014
@@ -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;
+}
Added: lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h?rev=220944&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h (added)
+++ lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h Thu Oct 30 21:34:28 2014
@@ -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_
Modified: lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp Thu Oct 30 21:34:28 2014
@@ -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;
@@ -94,6 +96,12 @@ ThreadElfCore::CreateRegisterContextForF
{
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;
@@ -138,6 +146,10 @@ ThreadElfCore::CreateRegisterContextForF
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));
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Thu Oct 30 21:34:28 2014
@@ -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;
Modified: lldb/trunk/source/lldb.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/lldb.cpp?rev=220944&r1=220943&r2=220944&view=diff
==============================================================================
--- lldb/trunk/source/lldb.cpp (original)
+++ lldb/trunk/source/lldb.cpp Thu Oct 30 21:34:28 2014
@@ -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"
@@ -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();
@@ -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();
More information about the lldb-commits
mailing list