Hi emaste, jasonmolenda,
Taking advantage of the new 'CFAIsRegisterDereferenced' CFA register type, add
full stack unwind support to the PowerPC/PowerPC64 ABI. Also, add a new
register set for powerpc32-on-64, so the register sizes are correct. This also
requires modifying the ProcessMonitor to add support for non-uintptr_t-sized
register values.
http://reviews.llvm.org/D6183
Files:
source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
source/Plugins/Process/Utility/RegisterInfos_powerpc.h
Index: source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
===================================================================
--- source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
+++ source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -1012,13 +1012,14 @@
UnwindPlan::RowSP row(new UnwindPlan::Row);
- const int32_t ptr_size = 8;
- row->SetCFARegister (LLDB_REGNUM_GENERIC_SP);
- row->SetCFAOffset (8);
+ const int32_t ptr_size = 4;
+ row->SetCFARegister (sp_reg_num);
+ row->SetCFAOffset (0);
row->SetOffset (0);
+ row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
- row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
- row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size * -2, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 1, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("ppc default unwind plan");
Index: source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
===================================================================
--- source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
+++ source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -1013,13 +1013,13 @@
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->SetCFARegister (LLDB_REGNUM_GENERIC_SP);
- row->SetCFAOffset (48);
+ row->SetCFARegister (sp_reg_num);
row->SetOffset (0);
+ row->SetCFAType(lldb_private::UnwindPlan::Row::CFAIsRegisterDereferenced);
- 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);
+ row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
+ row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("ppc64 default unwind plan");
Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
===================================================================
--- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -312,9 +312,16 @@
if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)®s, 0)) < 0) {
m_result = false;
} else {
+ // 'struct reg' contains only 32- or 64-bit register values. Punt on
+ // others. Also, not all entries may be uintptr_t sized, such as 32-bit
+ // processes on powerpc64 (probably the same for i386 on amd64)
if (m_size == sizeof(uintptr_t))
m_value = *(uintptr_t *)(((caddr_t)®s) + m_offset);
- else
+ else if (m_size == sizeof(uint32_t))
+ m_value = *(uint32_t *)(((caddr_t)®s) + m_offset);
+ else if (m_size == sizeof(uint64_t))
+ m_value = *(uint64_t *)(((caddr_t)®s) + m_offset);
+ else
memcpy(&m_value, (((caddr_t)®s) + m_offset), m_size);
m_result = true;
}
Index: source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
===================================================================
--- source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -123,8 +123,13 @@
}
ProcessMonitor &monitor = GetMonitor();
+ // Account for the fact that 32-bit targets on powerpc64 really use 64-bit
+ // registers in ptrace, but expose here 32-bit registers with a higher
+ // offset.
+ uint64_t offset = GetRegisterOffset(reg_to_write);
+ offset &= ~(sizeof(uintptr_t) - 1);
return monitor.WriteRegisterValue(m_thread.GetID(),
- GetRegisterOffset(reg_to_write),
+ offset,
GetRegisterName(reg_to_write),
value_to_write);
}
Index: source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
===================================================================
--- source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
+++ source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
@@ -56,6 +56,86 @@
uint64_t pc;
} GPR64;
+typedef struct _GPR32_on_64
+{
+ uint32_t unused0;
+ uint32_t r0;
+ uint32_t unused1;
+ uint32_t r1;
+ uint32_t unused2;
+ uint32_t r2;
+ uint32_t unused3;
+ uint32_t r3;
+ uint32_t unused4;
+ uint32_t r4;
+ uint32_t unused5;
+ uint32_t r5;
+ uint32_t unused6;
+ uint32_t r6;
+ uint32_t unused7;
+ uint32_t r7;
+ uint32_t unused8;
+ uint32_t r8;
+ uint32_t unused9;
+ uint32_t r9;
+ uint32_t unused10;
+ uint32_t r10;
+ uint32_t unused11;
+ uint32_t r11;
+ uint32_t unused12;
+ uint32_t r12;
+ uint32_t unused13;
+ uint32_t r13;
+ uint32_t unused14;
+ uint32_t r14;
+ uint32_t unused15;
+ uint32_t r15;
+ uint32_t unused16;
+ uint32_t r16;
+ uint32_t unused17;
+ uint32_t r17;
+ uint32_t unused18;
+ uint32_t r18;
+ uint32_t unused19;
+ uint32_t r19;
+ uint32_t unused20;
+ uint32_t r20;
+ uint32_t unused21;
+ uint32_t r21;
+ uint32_t unused22;
+ uint32_t r22;
+ uint32_t unused23;
+ uint32_t r23;
+ uint32_t unused24;
+ uint32_t r24;
+ uint32_t unused25;
+ uint32_t r25;
+ uint32_t unused26;
+ uint32_t r26;
+ uint32_t unused27;
+ uint32_t r27;
+ uint32_t unused28;
+ uint32_t r28;
+ uint32_t unused29;
+ uint32_t r29;
+ uint32_t unused30;
+ uint32_t r30;
+ uint32_t unused31;
+ uint32_t r31;
+ uint32_t unused32;
+ uint32_t lr;
+ uint32_t unused33;
+ uint32_t cr;
+ uint32_t unused34;
+ uint32_t xer;
+ uint32_t unused35;
+ uint32_t ctr;
+ uint32_t unused36;
+ uint32_t pc;
+} GPR32_on_64;
+
+static_assert(sizeof(GPR32_on_64) == sizeof(GPR64), "Size mismatch");
+
typedef struct _GPR32
{
uint32_t r0;
@@ -153,7 +233,7 @@
size_t
RegisterContextFreeBSD_powerpc::GetGPRSize() const
{
- return sizeof(GPR64);
+ return 0;
}
const RegisterInfo *
@@ -217,6 +297,8 @@
RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const
{
//assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
+ if (m_target_arch.GetMachine() == llvm::Triple::ppc)
+ return g_register_infos_powerpc64_32;
return g_register_infos_powerpc64;
}
Index: source/Plugins/Process/Utility/RegisterInfos_powerpc.h
===================================================================
--- source/Plugins/Process/Utility/RegisterInfos_powerpc.h
+++ source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -97,7 +97,6 @@
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[] =
{
@@ -107,6 +106,14 @@
};
static RegisterInfo
+g_register_infos_powerpc64_32[] =
+{
+#define GPR GPR32_on_64
+ POWERPC_REGS
+#undef GPR
+};
+
+static RegisterInfo
g_register_infos_powerpc32[] =
{
#define GPR GPR32
@@ -117,6 +124,8 @@
"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");
+static_assert(sizeof(g_register_infos_powerpc64_32) == sizeof(g_register_infos_powerpc64),
+ "g_register_infos_powerpc64_32 doesn't match size of g_register_infos_powerpc64");
#undef DEFINE_FPR
#undef DEFINE_GPR
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits