Bug report
Bug description:
Adding the following below to the Python/bytecodes.c caused test_bt_unwinds_from_inside_jit_executor to fail for me even though by itself it's a NOOP change.
Edit: At time of edit this test does not fail however I've referenced base commits where it has failed.
tier2 op(_GUARD_BUILTINS_IS_CANONICAL, (--)) {
DEOPT_IF(BUILTINS() != tstate->interp->builtins);
}
Test Failure
```
======================================================================
ERROR: test_bt_unwinds_from_inside_jit_executor (test.test_gdb.test_jit.JitBacktraceTests.test_bt_unwinds_from_inside_jit_executor)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/test_jit.py", line 199, in test_bt_unwinds_from_inside_jit_executor
gdb_output = self.get_stack_trace(
script=JIT_SAMPLE_SCRIPT,
...<5 lines>...
PYTHON_JIT="1",
)
File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/test_jit.py", line 88, in get_stack_trace
return super().get_stack_trace(**kwargs)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/util.py", line 265, in get_stack_trace
out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED, **env_vars)
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/util.py", line 88, in run_gdb
raise Exception(f"{cmd_text} failed with exit code {proc.returncode}, "
...<2 lines>...
f"stderr={stderr!r}")
Exception: /usr/bin/gdb --batch -nx --init-eval-command 'add-auto-load-safe-path /home/runner/work/cpython/cpython/python-gdb.py' '--eval-command=set breakpoint pending yes' '--eval-command=break builtin_id' '--eval-command=set print address off' --eval-command=run '--eval-command=set print entry-values no' '--eval-command=python exec("import gdb\ntarget = '"'"'py::jit:executor'"'"'\nfor _ in range(20):\n frame = gdb.selected_frame()\n if frame is not None and frame.name() == target:\n break\n gdb.execute('"'"'finish'"'"')\nelse:\n raise RuntimeError('"'"'did not reach %s'"'"' % target)\n")' '--eval-command=python exec("import gdb\ntarget = '"'"'py::jit:executor'"'"'\nfor _ in range(4):\n frame = gdb.selected_frame()\n if frame is None or frame.name() != target:\n raise RuntimeError('"'"'left JIT region during stepping: '"'"'\n + repr(frame and frame.name()))\n gdb.execute('"'"'si'"'"')\nframe = gdb.selected_frame()\nif frame is None or frame.name() != target:\n raise RuntimeError('"'"'stepped out of JIT region after si'"'"')\n")' --eval-command=bt --args /home/runner/work/cpython/cpython/python -S /home/runner/work/cpython/cpython/Lib/test/test_gdb/gdb_jit_sample.py failed with exit code 1, expected exit code 0:
stdout='Breakpoint 1 at 0x2b8e8c: file Python/clinic/bltinmodule.c.h, line 755.\n[Thread debugging using libthread_db enabled]\nUsing host libthread_db library "/usr/lib/aarch64-linux-gnu/libthread_db.so.1".\n\nBreakpoint 1, builtin_id (self=, v=42) at Python/clinic/bltinmodule.c.h:755\n755\t return_value = builtin_id_impl((PyModuleDef *)self, v);\n_PyObject_VectorcallTstate (tstate=<_PyRuntime+249576>, callable=, args=, nargsf=, kwnames=) at ./Include/internal/pycore_call.h:144\n144\t res = func(callable, args, nargsf, kwnames);\nValue returned is $1 = 187649991800368\n_Py_VectorCallInstrumentation_StackRefSteal (callable=187649991800368, arguments=, total_args=1, kwnames=0x0, call_instrumentation=false, frame=, this_instr=, tstate=) at Python/ceval.c:774\n774\t STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);\n_PyEval_EvalFrameDefault (tstate=<_PyRuntime+249576>, frame=, throwflag=0) at Python/generated_cases.c.h:1916\n1916\t if (res_o == NULL) {\nValue returned is $2 = 187649991800368\n_PyEval_EvalFrame (tstate=<_PyRuntime+249576>, frame=, throwflag=0) at ./Include/internal/pycore_ceval.h:122\n122\t return _PyEval_EvalFrameDefault(tstate, frame, throwflag);\nValue returned is $3 = None\n[Inferior 1 (process 21431) exited normally]\n'
stderr="Python Exception : No frame is currently selected.\nError occurred in Python: No frame is currently selected.\nPython Exception : No frame is currently selected.\nError occurred in Python: No frame is currently selected.\nNo stack.\n"
```
This caused #157766 to fail however recently this is passing again with the latest main from merge. Commit 212e6035133 is an example of where this fails, however recent changes to main do not fail any more.
From what I can tell with claude assistance this is related due to veneer being emitted.
Before, main snapshot (adrp at page offset 0xf7c, no veneer):
2d3f7c adrp x0, <GOT page> ; page address of the global offset table (GOT)
2d3f80 ldr x0, [x0, #2392] ; load &__stack_chk_guard from the GOT
2d3f84 ldr x3, [sp, #120] ; load the canary saved on this frame's stack
2d3f88 ldr x2, [x0] ; load the current guard value
2d3f8c subs x3, x3, x2 ; compare; mismatch → __stack_chk_fail
After, + tier2 op (adrp at page offset 0x03c, patched):
2d403c adrp x0, <GOT page>
2d4040 ldr x0, [x0, #2408]
2d4044 ldr x3, [sp, #120]
2d4048 b e843419@… ; ← ld replaced the 4th instruction
...
e843419@…: ldr x2, [x0] ; the same load, relocated
b 2d404c ; jump back to the subs
When we hit the vaneer it looks to break the gdb call tracking chaining so likely the test is catching a genuine bug. It seems to be fairly random if vaneer is emitted depending on the layout generated by the source code.
I added the AI analysis and some steps to reproducing in docker here
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Bug report
Bug description:
Adding the following below to the
Python/bytecodes.ccausedtest_bt_unwinds_from_inside_jit_executorto fail for me even though by itself it's a NOOP change.Edit: At time of edit this test does not fail however I've referenced base commits where it has failed.
Test Failure
``` ====================================================================== ERROR: test_bt_unwinds_from_inside_jit_executor (test.test_gdb.test_jit.JitBacktraceTests.test_bt_unwinds_from_inside_jit_executor) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/test_jit.py", line 199, in test_bt_unwinds_from_inside_jit_executor gdb_output = self.get_stack_trace( script=JIT_SAMPLE_SCRIPT, ...<5 lines>... PYTHON_JIT="1", ) File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/test_jit.py", line 88, in get_stack_trace return super().get_stack_trace(**kwargs) ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^ File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/util.py", line 265, in get_stack_trace out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED, **env_vars) ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/util.py", line 88, in run_gdb raise Exception(f"{cmd_text} failed with exit code {proc.returncode}, " ...<2 lines>... f"stderr={stderr!r}") Exception: /usr/bin/gdb --batch -nx --init-eval-command 'add-auto-load-safe-path /home/runner/work/cpython/cpython/python-gdb.py' '--eval-command=set breakpoint pending yes' '--eval-command=break builtin_id' '--eval-command=set print address off' --eval-command=run '--eval-command=set print entry-values no' '--eval-command=python exec("import gdb\ntarget = '"'"'py::jit:executor'"'"'\nfor _ in range(20):\n frame = gdb.selected_frame()\n if frame is not None and frame.name() == target:\n break\n gdb.execute('"'"'finish'"'"')\nelse:\n raise RuntimeError('"'"'did not reach %s'"'"' % target)\n")' '--eval-command=python exec("import gdb\ntarget = '"'"'py::jit:executor'"'"'\nfor _ in range(4):\n frame = gdb.selected_frame()\n if frame is None or frame.name() != target:\n raise RuntimeError('"'"'left JIT region during stepping: '"'"'\n + repr(frame and frame.name()))\n gdb.execute('"'"'si'"'"')\nframe = gdb.selected_frame()\nif frame is None or frame.name() != target:\n raise RuntimeError('"'"'stepped out of JIT region after si'"'"')\n")' --eval-command=bt --args /home/runner/work/cpython/cpython/python -S /home/runner/work/cpython/cpython/Lib/test/test_gdb/gdb_jit_sample.py failed with exit code 1, expected exit code 0: stdout='Breakpoint 1 at 0x2b8e8c: file Python/clinic/bltinmodule.c.h, line 755.\n[Thread debugging using libthread_db enabled]\nUsing host libthread_db library "/usr/lib/aarch64-linux-gnu/libthread_db.so.1".\n\nBreakpoint 1, builtin_id (self=, v=42) at Python/clinic/bltinmodule.c.h:755\n755\t return_value = builtin_id_impl((PyModuleDef *)self, v);\n_PyObject_VectorcallTstate (tstate=<_PyRuntime+249576>, callable=, args=, nargsf=, kwnames=) at ./Include/internal/pycore_call.h:144\n144\t res = func(callable, args, nargsf, kwnames);\nValue returned is $1 = 187649991800368\n_Py_VectorCallInstrumentation_StackRefSteal (callable=187649991800368, arguments=, total_args=1, kwnames=0x0, call_instrumentation=false, frame=, this_instr=, tstate=) at Python/ceval.c:774\n774\t STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);\n_PyEval_EvalFrameDefault (tstate=<_PyRuntime+249576>, frame=, throwflag=0) at Python/generated_cases.c.h:1916\n1916\t if (res_o == NULL) {\nValue returned is $2 = 187649991800368\n_PyEval_EvalFrame (tstate=<_PyRuntime+249576>, frame=, throwflag=0) at ./Include/internal/pycore_ceval.h:122\n122\t return _PyEval_EvalFrameDefault(tstate, frame, throwflag);\nValue returned is $3 = None\n[Inferior 1 (process 21431) exited normally]\n' stderr="Python Exception : No frame is currently selected.\nError occurred in Python: No frame is currently selected.\nPython Exception : No frame is currently selected.\nError occurred in Python: No frame is currently selected.\nNo stack.\n" ```This caused #157766 to fail however recently this is passing again with the latest main from merge. Commit
212e6035133is an example of where this fails, however recent changes to main do not fail any more.From what I can tell with claude assistance this is related due to
veneerbeing emitted.When we hit the
vaneerit looks to break the gdb call tracking chaining so likely the test is catching a genuine bug. It seems to be fairly random if vaneer is emitted depending on the layout generated by the source code.I added the AI analysis and some steps to reproducing in docker here
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux