Skip to content

Commit 79d2133

Browse files
authored
bpo-32962: Fix test_gdb failure in debug build with -mcet -fcf-protection -O0 (GH-9656)
When Python is built with the intel control-flow protection flags, -mcet -fcf-protection, gdb is not able to read the stack without actually jumping inside the function. This means an extra 'next' command is required to make the $pc (program counter) enter the function and make the stack of the function exposed to gdb. Co-Authored-By: Marcel Plch <[email protected]> (cherry picked from commit 9b7c74c)
1 parent 7b31397 commit 79d2133

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

Lib/test/test_gdb.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,23 @@ def get_gdb_version():
5454

5555
PYTHONHASHSEED = '123'
5656

57+
58+
def cet_protection():
59+
cflags = sysconfig.get_config_var('CFLAGS')
60+
if not cflags:
61+
return False
62+
flags = cflags.split()
63+
# True if "-mcet -fcf-protection" options are found, but false
64+
# if "-fcf-protection=none" or "-fcf-protection=return" is found.
65+
return (('-mcet' in flags)
66+
and any((flag.startswith('-fcf-protection')
67+
and not flag.endswith(("=none", "=return")))
68+
for flag in flags))
69+
70+
# Control-flow enforcement technology
71+
CET_PROTECTION = cet_protection()
72+
73+
5774
def run_gdb(*args, **env_vars):
5875
"""Runs gdb in --batch mode with the additional arguments given by *args.
5976
@@ -162,6 +179,12 @@ def get_stack_trace(self, source=None, script=None,
162179
commands += ['set print entry-values no']
163180

164181
if cmds_after_breakpoint:
182+
if CET_PROTECTION:
183+
# bpo-32962: When Python is compiled with -mcet
184+
# -fcf-protection, function arguments are unusable before
185+
# running the first instruction of the function entry point.
186+
# The 'next' command makes the required first step.
187+
commands += ['next']
165188
commands += cmds_after_breakpoint
166189
else:
167190
commands += ['backtrace']
@@ -869,9 +892,17 @@ def __init__(self):
869892
id("first break point")
870893
l = MyList()
871894
''')
895+
cmds_after_breakpoint = ['break wrapper_call', 'continue']
896+
if CET_PROTECTION:
897+
# bpo-32962: same case as in get_stack_trace():
898+
# we need an additional 'next' command in order to read
899+
# arguments of the innermost function of the call stack.
900+
cmds_after_breakpoint.append('next')
901+
cmds_after_breakpoint.append('py-bt')
902+
872903
# Verify with "py-bt":
873904
gdb_output = self.get_stack_trace(cmd,
874-
cmds_after_breakpoint=['break wrapper_call', 'continue', 'py-bt'])
905+
cmds_after_breakpoint=cmds_after_breakpoint)
875906
self.assertRegex(gdb_output,
876907
r"<method-wrapper u?'__init__' of MyList object at ")
877908

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed test_gdb when Python is compiled with flags -mcet -fcf-protection -O0.

0 commit comments

Comments
 (0)