diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py index c90e1b8e056b92..2a7046280cdbf9 100644 --- a/Lib/test/test_perf_profiler.py +++ b/Lib/test/test_perf_profiler.py @@ -62,7 +62,6 @@ def tearDown(self) -> None: for file in files_to_delete: file.unlink() - @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_trampoline_works(self): code = """if 1: def foo(): @@ -113,7 +112,6 @@ def baz(): "Address should contain only hex characters", ) - @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_trampoline_with_unencodable_name(self): code = """if 1: import sys @@ -123,7 +121,6 @@ def test_trampoline_with_unencodable_name(self): """ assert_python_ok("-c", code, PYTHON_JIT="0") - @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_trampoline_works_with_forks(self): code = """if 1: import os, sys @@ -193,7 +190,6 @@ def baz(): self.assertNotIn(f"py::bar:{script}", child_perf_file_contents) self.assertNotIn(f"py::baz:{script}", child_perf_file_contents) - @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_trampoline_works_after_fork_with_many_code_objects(self): code = """if 1: import gc, os, sys, signal @@ -233,7 +229,6 @@ def test_trampoline_works_after_fork_with_many_code_objects(self): self.assertEqual(process.returncode, 0, stderr) self.assertEqual(stderr, "") - @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_sys_api(self): code = """if 1: import sys diff --git a/Misc/NEWS.d/next/Build/2026-10-21-18-00-00.gh-issue-128883.perf-trampoline.rst b/Misc/NEWS.d/next/Build/2026-10-21-18-00-00.gh-issue-128883.perf-trampoline.rst new file mode 100644 index 00000000000000..e250415e72af14 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-10-21-18-00-00.gh-issue-128883.perf-trampoline.rst @@ -0,0 +1,2 @@ +Fix crashes with ``-X perf`` and ``-X perf_jit`` in BOLT builds. +The ELF perf trampoline templates now use read-only data sections. diff --git a/Python/asm_trampoline.S b/Python/asm_trampoline.S index 2513cde4e76495..dd0d5f8ec8bff4 100644 --- a/Python/asm_trampoline.S +++ b/Python/asm_trampoline.S @@ -1,6 +1,11 @@ #include "asm_trampoline_aarch64.h" +/* CPython copies this template into executable memory. */ +#if defined(__ELF__) + .section .rodata +#else .text +#endif .globl _Py_trampoline_func_start # The following assembly is equivalent to: # PyObject *