On 64-bit PPC builds configured --with-tsc, Python segfaults within the first function call in the bytecode interpreter.
Upon investigation this is due to this code in Python/ceval.c:
32 typedef unsigned long long uint64;
33
34 /* PowerPC support.
35 "__ppc__" appears to be the preprocessor definition to detect on OS
X, whereas
36 "__powerpc__" appears to be the correct one for Linux with GCC
37 */
38 #if defined(__ppc__) || defined (__powerpc__)
39
40 #define READ_TIMESTAMP(var) ppc_getcounter(&var)
41
42 static void
43 ppc_getcounter(uint64 *v)
44 {
45 register unsigned long tbu, tb, tbu2;
46
47 loop:
48 asm volatile ("mftbu %0" : "=r" (tbu) );
49 asm volatile ("mftb %0" : "=r" (tb) );
50 asm volatile ("mftbu %0" : "=r" (tbu2));
51 if (__builtin_expect(tbu != tbu2, 0)) goto loop;
52
53 /* The slightly peculiar way of writing the next lines is
54 compiled better by GCC than any other way I tried. */
55 ((long*)(v))[0] = tbu;
56 /*((long*)(v))[1] = tb; */ /* <==== this is the bug */
57 }
58
59 #elif defined(__i386__)
(gdb) p sizeof(long)
$44 = 8
(gdb) p sizeof(uint64)
$45 = 8
Looks like lines 55 and 56 are erroneously assuming that a long is 4 bytes on
this arch: line 56 above is trashing the next value beyond the timer value, which is on the machine's stack, corrupting local variables within PyEval_EvalFrameEx.
The code has been this way since ppc_getcounter was added, in:
http://hg.python.org/cpython/rev/f455bbe7ea7e
I may have broken this in:
http://hg.python.org/cpython/rev/419ca089d365/
which was for:
http://bugs.python.org/issue10655
by (perhaps) generalizing support from ppc to (ppc and ppc64) (not sure about
this).
I'm attaching a patch which splits the ppc tsc support into 32-bit and 64-bit parts, and which also removes an aliasing violation on 32-bit ppc.
(I'm tracking this downstream in Fedora's bug tracker as https://bugzilla.redhat.com/show_bug.cgi?id=698726 )
|