Skip to contentSkip to conversation

powerpc: Fix 64 bits vDSO dwarf info for CR register

PATCH In review Benjamin Herrenschmidt 3 participants 3 messages Oct 17, 2007 PowerPC

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 powerpc: Fix 64 bits vDSO dwarf info for CR register

The current DWARF info for CR are incorrect causing the gcc unwinder to go to lunch if taking a segfault in the vdso. This patch fixes it.

Problem identified by Andrew Haley, and fix provided by Jakub Jelinek (thanks !).

Unfortunately, a bug in gcc cause it to not quite work either, but that is being fixed separately with something around the lines of:

linux-unwind.h:

     fs->regs.reg[R_CR2].loc.offset = (long) &regs->ccr - new_cfa;

+ /* CR? regs are just 32-bit and PPC is big-endian. */
+ fs->regs.reg[R_CR2].loc.offset += sizeof (long) - 4;

(According to Jakub)

---

arch/powerpc/kernel/vdso64/sigtramp.S +7 -4
Index: linux-work/arch/powerpc/kernel/vdso64/sigtramp.S
===================================================================
@@ -134,13 +134,16 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
 9:
 
 /* This is where the pt_regs pointer can be found on the stack.  */
-#define PTREGS 128+168+56
+#define PTREGS	128+168+56
 
 /* Size of regs.  */
-#define RSIZE 8
+#define RSIZE	8
+
+/* Size of CR reg in DWARF unwind info. */
+#define CRSIZE	4
 
 /* This is the offset of the VMX reg pointer.  */
-#define VREGS 48*RSIZE+33*8
+#define VREGS	48*RSIZE+33*8
 
 /* Describe where general purpose regs are saved.  */
 #define EH_FRAME_GEN \
@@ -178,7 +181,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt64)
   rsave (31, 31*RSIZE);							\
   rsave (67, 32*RSIZE);		/* ap, used as temp for nip */		\
   rsave (65, 36*RSIZE);		/* lr */				\
-  rsave (70, 38*RSIZE)		/* cr */
+  rsave (70, 38*RSIZE + (RSIZE - CRSIZE)) /* cr */
 
 /* Describe where the FP regs are saved.  */
 #define EH_FRAME_FP \
#1 lore raw

Review

Quoted 8 lines · Benjamin Herrenschmidt

Unfortunately, a bug in gcc cause it to not quite work either, but that is being fixed separately with something around the lines of:

linux-unwind.h:

     fs->regs.reg[R_CR2].loc.offset = (long) &regs->ccr - new_cfa;
(quoted diff) +2 -0
+    /* CR? regs are just 32-bit and PPC is big-endian.  */
+    fs->regs.reg[R_CR2].loc.offset += sizeof (long) - 4;

Small correction. If vdso is present, then fixing the vdso is all that is needed, the above mentioned code is used only if the vdso is not present (or if glibc doesn't support the vdso).

Jakub

#2 lore raw
Quoted 6 lines · Jakub Jelinek
Quoted 5 lines · Benjamin Herrenschmidt

Unfortunately, a bug in gcc cause it to not quite work either, but that is being fixed separately with something around the lines of:

linux-unwind.h:

Quoted 7 lines

Review

Quoted 3 lines
     fs->regs.reg[R_CR2].loc.offset = (long) &regs->ccr - new_cfa;
(quoted diff) +2 -0
+    /* CR? regs are just 32-bit and PPC is big-endian.  */
+    fs->regs.reg[R_CR2].loc.offset += sizeof (long) - 4;

Small correction. If vdso is present, then fixing the vdso is all that is needed, the above mentioned code is used only if the vdso is not present (or if glibc doesn't support the vdso).

Perhaps we should test this change with a hacked libgcc, just to make sure it fixes the bug.

Andrew.

Signature · 2 lines
Red Hat UK Ltd, Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SL4 1TE, UK
Registered in England and Wales No. 3798903