diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-01-07-23-07-17.gh-issue-126910.d8zdm-.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-07-23-07-17.gh-issue-126910.d8zdm-.rst new file mode 100644 index 00000000000000..c86bfdb306f4c9 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-01-07-23-07-17.gh-issue-126910.d8zdm-.rst @@ -0,0 +1,2 @@ +Set frame pointers in ``x86_64-unknown-linux-gnu`` JIT code, allowing +most native profilers and debuggers to unwind through them. diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index 39be353ec30858..79a8ead8ff69a3 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -51,6 +51,7 @@ class _Target(typing.Generic[_S, _R]): debug: bool = False verbose: bool = False cflags: str = "" + frame_pointers: bool = False llvm_version: str = _llvm._LLVM_VERSION known_symbols: dict[str, int] = dataclasses.field(default_factory=dict) pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve() @@ -174,10 +175,13 @@ async def _compile( "-o", f"{s}", f"{c}", - *self.args, - # Allow user-provided CFLAGS to override any defaults - *shlex.split(self.cflags), ] + if self.frame_pointers: + frame_pointer = "all" if opname == "shim" else "reserved" + args_s += ["-Xclang", f"-mframe-pointer={frame_pointer}"] + args_s += self.args + # Allow user-provided CFLAGS to override any defaults + args_s += shlex.split(self.cflags) await _llvm.run( "clang", args_s, echo=self.verbose, llvm_version=self.llvm_version ) @@ -613,7 +617,9 @@ def get_target(host: str) -> _COFF32 | _COFF64 | _ELF | _MachO: condition = "defined(__x86_64__) && defined(__linux__)" args = ["-fno-pic", "-mcmodel=medium", "-mlarge-data-threshold=0", "-fno-plt"] optimizer = _optimizers.OptimizerX86 - target = _ELF(host, condition, args=args, optimizer=optimizer) + target = _ELF( + host, condition, args=args, optimizer=optimizer, frame_pointers=True + ) else: raise ValueError(host) return target