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)&regs, 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)&regs) + m_offset);
-        else 
+        else if (m_size == sizeof(uint32_t))
+            m_value = *(uint32_t *)(((caddr_t)&regs) + m_offset);
+        else if (m_size == sizeof(uint64_t))
+            m_value = *(uint64_t *)(((caddr_t)&regs) + m_offset);
+        else
             memcpy(&m_value, (((caddr_t)&regs) + 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

Reply via email to