]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-149202: Fix frame pointer unwinding on ppc64le and armv7/clang (#149409)
authorPetr Viktorin <encukou@gmail.com>
Thu, 7 May 2026 08:37:00 +0000 (10:37 +0200)
committerGitHub <noreply@github.com>
Thu, 7 May 2026 08:37:00 +0000 (10:37 +0200)
- ppc64's backchain format is also different from x86
- On 32-bit ARM, clang needs `-mno-thumb`, not `-marm` like GCC

Doc/using/configure.rst
Modules/_testinternalcapi.c
configure
configure.ac

index 62c53c283825c8f6530a5e3ad81fa3d05ea864ea..a0e46ff4e375b6a9d191fc575e76bf9d525fcf72 100644 (file)
@@ -789,14 +789,13 @@ also be used to improve performance.
 
    - ``-fno-omit-frame-pointer`` and/or ``-mno-omit-leaf-frame-pointer``
      are added when the compiler supports them.
-   - ``-marm`` is added on 32-bit ARM when supported,
+   - ``-marm`` and/or ``-mno-thumb`` is added on 32-bit ARM when supported,
    - on s390x platforms, when supported, ``-mbackchain`` is added *instead*.
      of the above frame pointer flags.
 
    Frame pointers enable profilers, debuggers, and system tracing tools
    (``perf``, ``eBPF``, ``dtrace``, ``gdb``) to walk the C call stack
-   without DWARF metadata.
-   The flags propagate to third-party C
+   without DWARF metadata. The flags propagate to third-party C
    extensions through :mod:`sysconfig`. On compilers that do not
    understand them, the build silently skips them.
 
index c0a7680388e4a7f784f213e9f8fd7710cb8dbaf1..b8a22c439e853d931f5f2ceb019577fc2e00c1ef 100644 (file)
@@ -92,6 +92,12 @@ static const uintptr_t min_frame_pointer_addr = 0x1000;
 #  define FRAME_POINTER_NEXT_OFFSET 0
 #  define FRAME_POINTER_RETURN_OFFSET \
     (S390X_FRAME_RETURN_ADDRESS_OFFSET / (Py_ssize_t)sizeof(uintptr_t))
+#elif defined(__powerpc64__) || defined(__ppc64__)
+// ppc64le puts the return address at fp[2]; it saves the Condition Register
+// in fp[1]. See:
+// https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
+#  define FRAME_POINTER_NEXT_OFFSET 0
+#  define FRAME_POINTER_RETURN_OFFSET 2
 #else
 #  define FRAME_POINTER_NEXT_OFFSET 0
 #  define FRAME_POINTER_RETURN_OFFSET 1
index f970bf9b7ba3c74393e9d25b6215c1c1950ddd0e..3377bf7516ebd21e2556a026fb66a328bb4b7b4a 100755 (executable)
--- a/configure
+++ b/configure
@@ -10346,7 +10346,7 @@ fi
       case $host_cpu in #(
   arm|armv*) :
 
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -marm" >&5
+                { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -marm" >&5
 printf %s "checking whether C compiler accepts -marm... " >&6; }
 if test ${ax_cv_check_cflags__Werror__marm+y}
 then :
@@ -10384,6 +10384,49 @@ then :
 
           frame_pointer_cflags="$frame_pointer_cflags -marm"
 
+else case e in #(
+  e) : ;;
+esac
+fi
+
+        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -mno-thumb" >&5
+printf %s "checking whether C compiler accepts -mno-thumb... " >&6; }
+if test ${ax_cv_check_cflags__Werror__mno_thumb+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e)
+  ax_check_save_flags=$CFLAGS
+  CFLAGS="$CFLAGS -Werror -mno-thumb"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main (void)
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+  ax_cv_check_cflags__Werror__mno_thumb=yes
+else case e in #(
+  e) ax_cv_check_cflags__Werror__mno_thumb=no ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+  CFLAGS=$ax_check_save_flags ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags__Werror__mno_thumb" >&5
+printf "%s\n" "$ax_cv_check_cflags__Werror__mno_thumb" >&6; }
+if test "x$ax_cv_check_cflags__Werror__mno_thumb" = xyes
+then :
+
+          frame_pointer_cflags="$frame_pointer_cflags -mno-thumb"
+
 else case e in #(
   e) : ;;
 esac
index 9f91a10c2918cf7d1eb2893532b8f0bbf5451838..fc2db4d5e8aebba74f4f408c58e190a71559c972 100644 (file)
@@ -2549,9 +2549,13 @@ AS_VAR_IF([ac_cv_gcc_compat], [yes], [
         frame_pointer_cflags="$frame_pointer_cflags -mno-omit-leaf-frame-pointer"
       ], [], [-Werror])
       AS_CASE([$host_cpu], [arm|armv*], [
+        dnl GCC uses "-marm"; clang uses "-mno-thumb"
         AX_CHECK_COMPILE_FLAG([-marm], [
           frame_pointer_cflags="$frame_pointer_cflags -marm"
         ], [], [-Werror])
+        AX_CHECK_COMPILE_FLAG([-mno-thumb], [
+          frame_pointer_cflags="$frame_pointer_cflags -mno-thumb"
+        ], [], [-Werror])
       ])
       AS_CASE([$host_cpu], [s390*], [
         AX_CHECK_COMPILE_FLAG([-mbackchain], [