@@ -5,13 +5,15 @@ Author: Pablo Galindo Salgado <pablogsal@python.org>,
55 Savannah Ostrowski <savannah@python.org>,
66 Diego Russo <diego.russo@arm.com>,
77Discussions-To: https://discuss.python.org/t/106958
8- Status: Accepted
8+ Status: Final
99Type: Standards Track
1010Created: 14-Mar-2026
1111Python-Version: 3.15
1212Post-History: `13-Apr-2026 <https://discuss.python.org/t/106958 >`__
1313Resolution: `30-Apr-2026 <https://discuss.python.org/t/106958/6 >`__
1414
15+ .. canonical-doc :: :external+py3.15:option:`--without-frame-pointers`
16+
1517Abstract
1618========
1719
@@ -470,11 +472,12 @@ Build System Changes
470472The following changes are made to ``configure.ac ``::
471473
472474 AX_CHECK_COMPILE_FLAG([-fno-omit-frame-pointer],
473- [CFLAGS ="$CFLAGS -fno-omit-frame-pointer"])
475+ [BASECFLAGS ="$BASECFLAGS -fno-omit-frame-pointer"])
474476 AX_CHECK_COMPILE_FLAG([-mno-omit-leaf-frame-pointer],
475- [CFLAGS ="$CFLAGS -mno-omit-leaf-frame-pointer"])
477+ [BASECFLAGS ="$BASECFLAGS -mno-omit-leaf-frame-pointer"])
476478
477- Using ``CFLAGS `` ensures:
479+ The flags are prepended to ``BASECFLAGS `` (rather than ``CFLAGS_NODIST ``) so
480+ they propagate to third-party builds via ``sysconfig ``. This ensures:
478481
4794821. The flags apply to all ``*.c `` files compiled as part of the interpreter:
480483 the ``python `` binary, ``libpython ``, and built-in extension modules under
@@ -483,6 +486,18 @@ Using ``CFLAGS`` ensures:
483486 extensions built against this Python (via ``pip ``, Setuptools, or direct
484487 ``sysconfig `` queries) inherit frame pointers by default.
485488
489+ Several architectures need adjustments to produce a walkable frame-pointer
490+ chain:
491+
492+ * On 32-bit ARM, ``-marm `` (GCC) or ``-mno-thumb `` (Clang) is added to force
493+ ARM mode, since GCC's default Thumb prologue does not preserve the
494+ ``fp[0] ``/``fp[1] `` layout the simple unwinder expects.
495+ * On s390x, ``-mbackchain `` is added *instead * of the frame-pointer flags;
496+ GCC and Clang do not emit a usable backchain on s390x without it.
497+ * On ppc64le, no compiler flags are added: the Power ABI already requires
498+ compilers to maintain a back chain by default, so unwinding works without
499+ ``-fno-omit-frame-pointer ``.
500+
486501This is an intentional design choice. For profiling data to be useful, the
487502frame-pointer chain must be continuous through the entire call stack. A gap at
488503any C extension boundary is as harmful as a gap in the interpreter itself. By
@@ -502,7 +517,7 @@ A new ``configure`` option is added::
502517
503518 --without-frame-pointers
504519
505- When specified, neither flag is added to ``CFLAGS ``. This is appropriate for
520+ When specified, neither flag is added to ``BASECFLAGS ``. This is appropriate for
506521deployments that have measured an unacceptable regression on their specific
507522workload, or for distributions that inject frame-pointer flags at a higher
508523level and wish to avoid double-specification, analogous to Fedora's per-package
@@ -550,9 +565,10 @@ recommendation for earlier versions.
550565Platform Scope
551566--------------
552567
553- Both flags are accepted by GCC and Clang on all supported Linux architectures
554- (x86-64, AArch64, s390x, RISC-V, ARM). On macOS with Apple Silicon, the ARM64
555- ABI mandates frame pointers; the flags are redundant but harmless.
568+ Both flags are accepted by GCC and Clang on x86-64, AArch64, RISC-V, and
569+ 32-bit ARM. s390x and ppc64le require different handling (see above). On
570+ macOS with Apple Silicon, the ARM64 ABI mandates frame pointers; the flags
571+ are redundant but harmless.
556572
557573On Windows x64, MSVC does not use frame pointers for stack unwinding. Instead,
558574the Windows x64 ABI mandates ``.pdata `` / ``.xdata `` unwind metadata for every
@@ -746,15 +762,15 @@ formalised by GCC 4.6 in 2011. The industry has since broadly reversed course:
746762
747763CPython has not yet adopted this change.
748764
749- Why Not Use ``CFLAGS_NODIST `` Instead of ``CFLAGS ``
750- ---------------------------------------------------
765+ Why Not Use ``CFLAGS_NODIST `` Instead of ``BASECFLAGS ``
766+ -------------------------------------------------------
751767
752768CPython's build system provides ``CFLAGS_NODIST `` specifically for flags that
753769should apply to the interpreter but not propagate to extension module builds
754770via ``sysconfig ``. Using ``CFLAGS_NODIST `` would confine the overhead to the
755771interpreter itself.
756772
757- This PEP deliberately chooses ``CFLAGS `` over ``CFLAGS_NODIST `` because frame
773+ This PEP deliberately chooses ``BASECFLAGS `` over ``CFLAGS_NODIST `` because frame
758774pointers are only useful when the chain is continuous. Unlike debugging aids
759775such as sanitizers or assertions, which are useful even when applied to a
760776single component, a frame-pointer chain with a gap at a C extension boundary
@@ -772,7 +788,7 @@ not exhibit the same call density and sees negligible overhead.
772788As Gregory Szorc (``python-build-standalone `` creator) noted: "Turning the
773789corner on the long tail of compiled extensions having frame pointers will take
774790years. So the sooner we start..." [#pbs992 ]_ Propagating the flags via
775- ``CFLAGS `` is how CPython starts that process.
791+ ``BASECFLAGS `` is how CPython starts that process.
776792
777793Alternatives to Frame-Pointer Unwinding
778794---------------------------------------
0 commit comments