1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
From a173b50b22b2f884853fcde45fec9bffb0fc5aae Mon Sep 17 00:00:00 2001
From: Finn Thain <fthain@linux-m68k.org>
Date: Tue, 3 Dec 2024 11:32:55 +1100
Subject: [PATCH] Specify minimum PyGC_Head and PyObject alignment to fix build
failure
As documented in InternalDocs/garbage_collector.md, the garbage collector
stores flags in the least significant two bits of the _gc_prev pointer
in struct PyGC_Head. Consequently, this pointer is only capable of storing
a location that's aligned to a 4-byte boundary.
This alignment requirement is documented but it's not actually encoded.
The code only works when python happens to run on a platform that has a
sufficiently large minimum alignment for the structs in question.
The same problem arises with PyObject pointers because the least
significant bits get used for PyStackRef tags.
Since we know that 2 bits are needed, we also know the minimum alignment
that's needed. Let's make that explicit, so the compiler can then make
those bits available.
This patch fixes a segfault in _bootstrap_python. In 3.14.0 beta 2
this fixes the "Assertion `!PyStackRef_IsTaggedInt(ref)' failed" when
built with --config-pydebug.
Also, making the requirements explicit improves clarity.
This bug was previously investigated by Adrian Glaubitz here:
https://lists.debian.org/debian-68k/2024/11/msg00020.html
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1087600
Although Adrian's patch isn't really correct (because natural alignment
is not needed), he deserves full credit for finding the root cause.
Origin: Backported from upstream, https://github.com/fthain/cpython/commit/a173b50b22b2f884853fcde45fec9bffb0fc5aae
Bug-Upstream: https://github.com/python/cpython/issues/127545
Bug-Debian: https://bugs.debian.org/1105110
---
Include/internal/pycore_gc.h | 5 +++--
Include/object.h | 9 +++++++--
.../Build/2024-12-04-10-00-35.gh-issue-127545.t0THjE.rst | 1 +
3 files changed, 11 insertions(+), 4 deletions(-)
create mode 100644 Misc/NEWS.d/next/Build/2024-12-04-10-00-35.gh-issue-127545.t0THjE.rst
--- a/Include/internal/pycore_gc.h
+++ b/Include/internal/pycore_gc.h
@@ -18,8 +18,9 @@
// Pointer to previous object in the list.
// Lowest two bits are used for flags documented later.
+ // Those bits are made available by the struct's minimum alignment.
uintptr_t _gc_prev;
-} PyGC_Head;
+} PyGC_Head Py_ALIGNED(1 << _PyObject_ALIGNMENT_SHIFT);
#define _PyGC_Head_UNUSED PyGC_Head
@@ -146,7 +147,7 @@
/* Bit 1 is set when the object is in generation which is GCed currently. */
#define _PyGC_PREV_MASK_COLLECTING (2)
/* The (N-2) most significant bits contain the real address. */
-#define _PyGC_PREV_SHIFT (2)
+#define _PyGC_PREV_SHIFT _PyObject_ALIGNMENT_SHIFT
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
/* set for debugging information */
--- a/Include/object.h
+++ b/Include/object.h
@@ -154,6 +154,11 @@
#define PyObject_VAR_HEAD PyVarObject ob_base;
#define Py_INVALID_SIZE (Py_ssize_t)-1
+/* PyObjects are given a minimum alignment so that the least significant bits
+ * of an object pointer become available for other purposes.
+ */
+#define _PyObject_ALIGNMENT_SHIFT 2
+
/* Nothing is actually declared to be a PyObject, but every pointer to
* a Python object can be cast to a PyObject*. This is inheritance built
* by hand. Similarly every pointer to a variable-size Python object can,
@@ -183,7 +188,7 @@
#endif
PyTypeObject *ob_type;
-};
+} Py_ALIGNED(1 << _PyObject_ALIGNMENT_SHIFT);
#else
// Objects that are not owned by any thread use a thread id (tid) of zero.
// This includes both immortal objects and objects whose reference count
@@ -215,7 +220,7 @@
uint32_t ob_ref_local; // local reference count
Py_ssize_t ob_ref_shared; // shared (atomic) reference count
PyTypeObject *ob_type;
-};
+} Py_ALIGNED(1 << _PyObject_ALIGNMENT_SHIFT);
#endif
/* Cast argument to PyObject* type. */
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2024-12-04-10-00-35.gh-issue-127545.t0THjE.rst
@@ -0,0 +1 @@
+Fix crash when building on Linux/m68k.
|