diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py index 6c28947bdeabaa..7fe16116b00b99 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): for define_eval_hook in (False, True): code = """if 1: 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_aarch64.S b/Python/asm_trampoline_aarch64.S index b3aeb728de200c..4052ea6e13edec 100644 --- a/Python/asm_trampoline_aarch64.S +++ b/Python/asm_trampoline_aarch64.S @@ -35,7 +35,12 @@ #define GNU_PROPERTY_AARCH64_GCS 0 #endif +/* CPython copies this template into executable memory. */ +#if defined(__ELF__) + .section .rodata +#else .text +#endif #if defined(__aarch64__) && defined(__AARCH64EL__) && !defined(__ILP32__) #if defined(__APPLE__) .globl __Py_trampoline_func_start diff --git a/Python/asm_trampoline_riscv64.S b/Python/asm_trampoline_riscv64.S index 6125ba95373f95..7d32c904c995ec 100644 --- a/Python/asm_trampoline_riscv64.S +++ b/Python/asm_trampoline_riscv64.S @@ -1,4 +1,5 @@ - .text +/* CPython copies this template into executable memory. */ + .section .rodata .globl _Py_trampoline_func_start _Py_trampoline_func_start: addi sp,sp,-16 diff --git a/Python/asm_trampoline_x86_64.S b/Python/asm_trampoline_x86_64.S index 0e6b11589eafc8..0f83a4575828c2 100644 --- a/Python/asm_trampoline_x86_64.S +++ b/Python/asm_trampoline_x86_64.S @@ -1,4 +1,9 @@ +/* CPython copies this template into executable memory. */ +#if defined(__ELF__) + .section .rodata +#else .text +#endif #ifdef __x86_64__ #if defined(__APPLE__) .globl __Py_trampoline_func_start