GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GH-126910: Allow native profilers and debuggers to unwind through JIT frames by brandtbucher · Pull Request #143548 · python/cpython

Conversation

@brandtbucher

@brandtbucher brandtbucher commented Jan 8, 2026 •
edited by bedevere-app Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Most unwinders will optimistically fall back to frame pointers if DWARF unwind info isn't present for a given frame. This patch enables frame pointers in JIT code on x86-64 Linux, by setting them in the "shim" frame and reserving the frame pointer register in the rest of the JIT code. @Fidget-Spinner can confirm that this works for the unwinders in https://github.com/pablogsal/cpython-unwind.

Perf impact is neutral.

  • Issue: Supporting stack unwinding in the JIT compiler #126910

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Fidget-Spinner reacted with hooray emoji savannahostrowski reacted with heart emoji
All reactions
  • 🎉 1 reaction
  • ❤️ 1 reaction
brandtbucher added 4 commits January 7, 2026 18:50
@brandtbucher
Reserve the frame pointer in JIT code
d76d264
@brandtbucher
shim -> trampoline
c214c07
@brandtbucher
trampoline -> shim
8cfff6f
@brandtbucher
Clean up
766d404
@brandtbucher
brandtbucher requested a review from pablogsal January 8, 2026 07:03
@brandtbucher
brandtbucher requested review from diegorusso and savannahostrowski as code owners January 8, 2026 07:03
@bedevere-app bedevere-app Bot added the awaiting core review label Jan 8, 2026
@brandtbucher brandtbucher changed the title Allow native profilers and debuggers to unwind through JIT frames GH-126910: Allow native profilers and debuggers to unwind through JIT frames Jan 8, 2026
@bedevere-app bedevere-app Bot mentioned this pull request Jan 8, 2026
Supporting stack unwinding in the JIT compiler #126910
Open
@brandtbucher
blurb add
ae8649f
@pablogsal

pablogsal commented Jan 8, 2026

Copy link
Copy Markdown
Member

This patch enables frame pointers in JIT code on x86-64 Linux

What's the situation in aarch64?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Fidget-Spinner

Fidget-Spinner commented Jan 8, 2026

Copy link
Copy Markdown
Member

Can confirm this works for everything except GNU backtrace, and for that one I think we're just missing debug info.

pablogsal reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal

pablogsal commented Jan 9, 2026

Copy link
Copy Markdown
Member

BTW we should check gdb and lldb as well but my guess is that those have the biggest set of tricks under the sleeve so I assume this won't be a problem....

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@Fidget-Spinner

Fidget-Spinner commented Jan 13, 2026

Copy link
Copy Markdown
Member

PYTHON_JIT=0

[GNU backtrace]
Total frames: 56
Showing first 10 frames:
  # 0  /home/ken/Documents/GitHub/cpython-unwind/stackunwind.cpython-315-x86_64-linux-gnu.so(+0x23f4) [0x7b3bfc4bc3f4]
  # 1  ./python(PyObject_Vectorcall+0x43) [0x5706adb32893]
  # 2  ./python(_Py_VectorCallInstrumentation_StackRefSteal+0x176) [0x5706adc5d8e6]
  # 3  ./python(_PyEval_EvalFrameDefault+0x23be) [0x5706adc60a9e]
  # 4  ./python(+0x2223c6) [0x5706adc5d3c6]
  # 5  ./python(PyObject_Vectorcall+0x43) [0x5706adb32893]
  # 6  ./python(_Py_BuiltinCallFastWithKeywords_StackRefSteal+0x146) [0x5706adc5dd46]
  # 7  ./python(_PyEval_EvalFrameDefault+0x2e5c) [0x5706adc6153c]
  # 8  ./python(+0x2223c6) [0x5706adc5d3c6]
  # 9  ./python(PyObject_Vectorcall+0x43) [0x5706adb32893]
  ... (46 more frames)

[libunwind]
Total frames: 54
Showing first 10 frames:
  # 0  PyObject_Vectorcall+0x43
  # 1  _Py_VectorCall_StackRefSteal+0x15d
  # 2  _PyEval_EvalFrameDefault+0x4a89
  # 3  _PyEval_Vector+0x276
  # 4  PyObject_Vectorcall+0x43
  # 5  _Py_BuiltinCallFastWithKeywords_StackRefSteal+0x146
  # 6  _PyEval_EvalFrameDefault+0x2e5c
  # 7  _PyEval_Vector+0x276
  # 8  PyObject_Vectorcall+0x43
  # 9  _Py_BuiltinCallFastWithKeywords_StackRefSteal+0x146
  ... (44 more frames)

[libdw (DWARF)]
Total frames: 54
Showing first 10 frames:
  # 0  PyObject_Vectorcall
  # 1  _Py_VectorCall_StackRefSteal
  # 2  _PyEval_EvalFrameDefault
  # 3  _PyEval_Vector
  # 4  PyObject_Vectorcall
  # 5  _Py_BuiltinCallFastWithKeywords_StackRefSteal
  # 6  _PyEval_EvalFrameDefault
  # 7  _PyEval_Vector
  # 8  PyObject_Vectorcall
  # 9  _Py_BuiltinCallFastWithKeywords_StackRefSteal
  ... (44 more frames)

[Manual frame pointers]
Total frames: 2
Showing first 2 frames:
  # 0  0x5706adb32893
  # 1  0x7ffeb5887bc8

======================================================================
  Remote Stack Unwinding Test (libunwind-ptrace)
======================================================================

[Parent] Attaching to child process (PID: 50223)...
[Child 50223] Ready for sampling

[libunwind-ptrace (remote)]
Total frames: 16
Showing first 15 frames:
  # 0  0x00007b3bfc0eca7a in __clock_nanosleep + 0x5a (sp=0x00007ffeb5887180)
  # 1  0x00005706add904cc in time_sleep + 0x9c (sp=0x00007ffeb5887200)
  # 2  0x00005706adb32893 in PyObject_Vectorcall + 0x43 (sp=0x00007ffeb5887240)
  # 3  0x00005706adc5d8e6 in _Py_VectorCallInstrumentation_StackRefSteal + 0x176 (sp=0x00007ffeb5887260)
  # 4  0x00005706adc60a9e in _PyEval_EvalFrameDefault + 0x23be (sp=0x00007ffeb5887310)
  # 5  0x00005706adc5d0f6 in PyEval_EvalCode + 0x156 (sp=0x00007ffeb5887550)
  # 6  0x00005706add05bc6 in run_mod + 0x3f6 (sp=0x00007ffeb5887610)
  # 7  0x00005706add0325e in _PyRun_SimpleFileObject + 0x35e (sp=0x00007ffeb5887670)
  # 8  0x00005706add02cb3 in _PyRun_AnyFileObject + 0x73 (sp=0x00007ffeb58876e0)
  # 9  0x00005706add2a3f1 in pymain_run_file + 0x171 (sp=0x00007ffeb5887710)
  #10  0x00005706add29d09 in Py_RunMain + 0x689 (sp=0x00007ffeb58877d0)
  #11  0x00005706add29ffa in pymain_main + 0x14a (sp=0x00007ffeb5887850)
  #12  0x00005706add2a04d in Py_BytesMain + 0x2d (sp=0x00007ffeb5887ac0)
  #13  0x00007b3bfc02a1ca in __libc_start_call_main + 0x7a (sp=0x00007ffeb5887af0)
  #14  0x00007b3bfc02a28b in __libc_start_main_alias_2 + 0x8b (sp=0x00007ffeb5887b90)
  ... (1 more frames)

[elfutils native (remote)]
Total frames: 16
Showing first 15 frames:
  # 0  clock_nanosleep@GLIBC_2.2.5 (clock_nanosleep.c:78)
  # 1  time_sleep (0x5706add904cb)
  # 2  PyObject_Vectorcall (0x5706adb32892)
  # 3  _Py_VectorCallInstrumentation_StackRefSteal (0x5706adc5d8e5)
  # 4  _PyEval_EvalFrameDefault (0x5706adc60a9d)
  # 5  PyEval_EvalCode (0x5706adc5d0f5)
  # 6  run_mod (0x5706add05bc5)
  # 7  _PyRun_SimpleFileObject (0x5706add0325d)
  # 8  _PyRun_AnyFileObject (0x5706add02cb2)
  # 9  pymain_run_file (0x5706add2a3f0)
  #10  Py_RunMain (0x5706add29d08)
  #11  pymain_main (0x5706add29ff9)
  #12  Py_BytesMain (0x5706add2a04c)
  #13  __libc_start_call_main (libc_start_call_main.h:58)
  #14  __libc_start_main@@GLIBC_2.34 (libc-start.c:360)
  ... (1 more frames)

[Parent] Detaching and terminating child...

======================================================================
  Tests Complete
======================================================================


PYTHON_JIT=1

======================================================================
  Local Stack Unwinding Tests
======================================================================

Testing various unwinding methods on the same deep call stack...

[GNU backtrace]
Total frames: 8
Showing first 8 frames:
  # 0  /home/ken/Documents/GitHub/cpython-unwind/stackunwind.cpython-315-x86_64-linux-gnu.so(+0x23f4) [0x7ed57fec43f4]
  # 1  ./python(PyObject_Vectorcall+0x43) [0x5999ea29e893]
  # 2  ./python(_Py_VectorCallInstrumentation_StackRefSteal+0x176) [0x5999ea3c98e6]
  # 3  ./python(_PyEval_EvalFrameDefault+0x23be) [0x5999ea3cca9e]
  # 4  ./python(+0x2223c6) [0x5999ea3c93c6]
  # 5  ./python(PyObject_Vectorcall+0x43) [0x5999ea29e893]
  # 6  ./python(_Py_BuiltinCallFastWithKeywords_StackRefSteal+0x146) [0x5999ea3c9d46]
  # 7  [0x7ed57febf61d]

[libunwind]
Total frames: 64
Showing first 10 frames:
  # 0  PyObject_Vectorcall+0x43
  # 1  _Py_VectorCall_StackRefSteal+0x15d
  # 2  _PyEval_EvalFrameDefault+0x4a89
  # 3  _PyEval_Vector+0x276
  # 4  PyObject_Vectorcall+0x43
  # 5  _Py_BuiltinCallFastWithKeywords_StackRefSteal+0x146
  # 6  <unknown>
  # 7  _PyEval_EvalFrameDefault+0x6a4b
  # 8  _PyEval_Vector+0x276
  # 9  PyObject_Vectorcall+0x43
  ... (54 more frames)

[libdw (DWARF)]
Total frames: 64
Showing first 10 frames:
  # 0  PyObject_Vectorcall
  # 1  _Py_VectorCall_StackRefSteal
  # 2  _PyEval_EvalFrameDefault
  # 3  _PyEval_Vector
  # 4  PyObject_Vectorcall
  # 5  _Py_BuiltinCallFastWithKeywords_StackRefSteal
  # 6  <unknown>
  # 7  _PyEval_EvalFrameDefault
  # 8  _PyEval_Vector
  # 9  PyObject_Vectorcall
  ... (54 more frames)

[Manual frame pointers]
Total frames: 2
Showing first 2 frames:
  # 0  0x5999ea29e893
  # 1  0x7ffdfea57f28

======================================================================
  Remote Stack Unwinding Test (libunwind-ptrace)
======================================================================

[Parent] Attaching to child process (PID: 50282)...
[Child 50282] Ready for sampling

[libunwind-ptrace (remote)]
Total frames: 16
Showing first 15 frames:
  # 0  0x00007ed57faeca7a in __clock_nanosleep + 0x5a (sp=0x00007ffdfea574e0)
  # 1  0x00005999ea4fc4cc in time_sleep + 0x9c (sp=0x00007ffdfea57560)
  # 2  0x00005999ea29e893 in PyObject_Vectorcall + 0x43 (sp=0x00007ffdfea575a0)
  # 3  0x00005999ea3c98e6 in _Py_VectorCallInstrumentation_StackRefSteal + 0x176 (sp=0x00007ffdfea575c0)
  # 4  0x00005999ea3cca9e in _PyEval_EvalFrameDefault + 0x23be (sp=0x00007ffdfea57670)
  # 5  0x00005999ea3c90f6 in PyEval_EvalCode + 0x156 (sp=0x00007ffdfea578b0)
  # 6  0x00005999ea471bc6 in run_mod + 0x3f6 (sp=0x00007ffdfea57970)
  # 7  0x00005999ea46f25e in _PyRun_SimpleFileObject + 0x35e (sp=0x00007ffdfea579d0)
  # 8  0x00005999ea46ecb3 in _PyRun_AnyFileObject + 0x73 (sp=0x00007ffdfea57a40)
  # 9  0x00005999ea4963f1 in pymain_run_file + 0x171 (sp=0x00007ffdfea57a70)
  #10  0x00005999ea495d09 in Py_RunMain + 0x689 (sp=0x00007ffdfea57b30)
  #11  0x00005999ea495ffa in pymain_main + 0x14a (sp=0x00007ffdfea57bb0)
  #12  0x00005999ea49604d in Py_BytesMain + 0x2d (sp=0x00007ffdfea57e20)
  #13  0x00007ed57fa2a1ca in __libc_start_call_main + 0x7a (sp=0x00007ffdfea57e50)
  #14  0x00007ed57fa2a28b in __libc_start_main_alias_2 + 0x8b (sp=0x00007ffdfea57ef0)
  ... (1 more frames)

[elfutils native (remote)]
Total frames: 16
Showing first 15 frames:
  # 0  clock_nanosleep@GLIBC_2.2.5 (clock_nanosleep.c:78)
  # 1  time_sleep (0x5999ea4fc4cb)
  # 2  PyObject_Vectorcall (0x5999ea29e892)
  # 3  _Py_VectorCallInstrumentation_StackRefSteal (0x5999ea3c98e5)
  # 4  _PyEval_EvalFrameDefault (0x5999ea3cca9d)
  # 5  PyEval_EvalCode (0x5999ea3c90f5)
  # 6  run_mod (0x5999ea471bc5)
  # 7  _PyRun_SimpleFileObject (0x5999ea46f25d)
  # 8  _PyRun_AnyFileObject (0x5999ea46ecb2)
  # 9  pymain_run_file (0x5999ea4963f0)
  #10  Py_RunMain (0x5999ea495d08)
  #11  pymain_main (0x5999ea495ff9)
  #12  Py_BytesMain (0x5999ea49604c)
  #13  __libc_start_call_main (libc_start_call_main.h:58)
  #14  __libc_start_main@@GLIBC_2.34 (libc-start.c:360)
  ... (1 more frames)

[Parent] Detaching and terminating child...

======================================================================
  Tests Complete
======================================================================
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@diegorusso

diegorusso commented Jan 14, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

This patch enables frame pointers in JIT code on x86-64 Linux

What's the situation in aarch64?

Replied here: #126910 (comment)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

diegorusso
diegorusso previously requested changes Mar 13, 2026
View reviewed changes

@diegorusso diegorusso left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get this enabled for AArch64 as well?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-app bedevere-app Bot added awaiting changes and removed awaiting core review labels Mar 13, 2026
@bedevere-app

bedevere-app Bot commented Mar 13, 2026

Copy link
Copy Markdown

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@chris-eibl

chris-eibl commented Mar 13, 2026

Copy link
Copy Markdown
Member

This would also work for Windows 32bit. I've done successful experiments with @diegorusso's #144137 back then.

I just don't know how much we're willing to do wrt jit and Windows 32bit?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@brandtbucher
Merge branch 'main' into jit-unwind
8c038c8
Fidget-Spinner
Fidget-Spinner approved these changes Mar 24, 2026
View reviewed changes

@Fidget-Spinner Fidget-Spinner left a comment •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@diegorusso I think you can make a follow-up PR for AArch64. We don't need to hold up this PR because of that.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

diegorusso reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@bedevere-app bedevere-app Bot added awaiting merge and removed awaiting changes labels Mar 24, 2026
@Fidget-Spinner
Fidget-Spinner dismissed diegorusso’s stale review March 24, 2026 17:13

We can make a follow-up PR for AArch64.

@Fidget-Spinner
Fidget-Spinner merged commit 535b09c into python:main Mar 24, 2026
77 of 78 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@bedevere-app bedevere-app Bot removed the awaiting merge label Mar 24, 2026
@diegorusso diegorusso mentioned this pull request Mar 27, 2026
GH-126910: reserve FP on AArch64 when generating JIT stencils #146520
Merged
@pablogsal pablogsal mentioned this pull request Apr 4, 2026
gh-130273: Fix traceback color output with unicode characters #142529
Merged
clin1234 pushed a commit to clin1234/cpython that referenced this pull request Apr 16, 2026
@brandtbucher @clin1234
pythonGH-126910: Allow most native profilers and debuggers to unwind …
3d04df6
…through JIT frames (pythonGH-143548)
ljfp pushed a commit to ljfp/cpython that referenced this pull request Apr 25, 2026
@brandtbucher @ljfp
pythonGH-126910: Allow most native profilers and debuggers to unwind …
5db3b69
…through JIT frames (pythonGH-143548)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@Fidget-Spinner Fidget-Spinner Fidget-Spinner approved these changes
@diegorusso diegorusso diegorusso left review comments
@pablogsal pablogsal Awaiting requested review from pablogsal
@savannahostrowski savannahostrowski Awaiting requested review from savannahostrowski

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

5 participants

@brandtbucher @pablogsal @Fidget-Spinner @diegorusso @chris-eibl
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.