Skip to content

Commit cb52a24

Browse files
committed
Refine ARM GNU backtrace unwind-table detection
1 parent 3358e2d commit cb52a24

1 file changed

Lines changed: 66 additions & 8 deletions

File tree

Lib/test/test_frame_pointer_unwind.py

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22
import os
33
import platform
4+
import shlex
45
import subprocess
56
import sys
67
import sysconfig
@@ -89,19 +90,76 @@ def _frame_pointers_expected(machine):
8990
return None
9091

9192

92-
def _gnu_backtrace_requires_unwind_tables(machine):
93-
if not (sys.maxsize < 2**32 and machine.startswith("arm")):
93+
def _is_arm32_build():
94+
if sys.maxsize >= 2**32:
9495
return False
9596

96-
cflags = " ".join(
97+
abi = " ".join(
98+
value for value in (
99+
sysconfig.get_config_var("MULTIARCH"),
100+
sysconfig.get_config_var("HOST_GNU_TYPE"),
101+
sysconfig.get_config_var("SOABI"),
102+
)
103+
if value
104+
).lower()
105+
return "arm" in abi
106+
107+
108+
def _cflags_have_unwind_tables(cflags):
109+
unwind_tables = False
110+
asynchronous_unwind_tables = False
111+
exceptions = False
112+
113+
try:
114+
options = shlex.split(cflags)
115+
except ValueError:
116+
options = cflags.split()
117+
118+
for option in options:
119+
if option == "-funwind-tables":
120+
unwind_tables = True
121+
elif option == "-fno-unwind-tables":
122+
unwind_tables = False
123+
elif option == "-fasynchronous-unwind-tables":
124+
asynchronous_unwind_tables = True
125+
elif option == "-fno-asynchronous-unwind-tables":
126+
asynchronous_unwind_tables = False
127+
elif option == "-fexceptions":
128+
exceptions = True
129+
elif option == "-fno-exceptions":
130+
exceptions = False
131+
132+
return unwind_tables or asynchronous_unwind_tables or exceptions
133+
134+
135+
def _build_has_unwind_tables():
136+
cflags = [
97137
value for value in (
98-
sysconfig.get_config_var("PY_CFLAGS"),
99138
sysconfig.get_config_var("PY_CORE_CFLAGS"),
100-
sysconfig.get_config_var("CFLAGS"),
139+
sysconfig.get_config_var("PY_STDMODULE_CFLAGS"),
101140
)
102141
if value
142+
]
143+
if not cflags:
144+
cflags = [
145+
value for value in (
146+
sysconfig.get_config_var("PY_CFLAGS"),
147+
sysconfig.get_config_var("CFLAGS"),
148+
)
149+
if value
150+
]
151+
152+
return (
153+
bool(cflags)
154+
and all(_cflags_have_unwind_tables(value) for value in cflags)
103155
)
104-
return "-funwind-tables" not in cflags.split()
156+
157+
158+
def _gnu_backtrace_requires_unwind_tables():
159+
if not _is_arm32_build():
160+
return False
161+
162+
return not _build_has_unwind_tables()
105163

106164

107165
def _build_stack_and_unwind(unwinder):
@@ -311,8 +369,8 @@ def test_manual_unwind_respects_frame_pointers(self):
311369
@unittest.skipIf(support.is_wasi, "test not supported on WASI")
312370
@unittest.skipUnless(sys.platform == "linux", "GNU backtrace unwinding test requires Linux")
313371
@unittest.skipIf(
314-
_gnu_backtrace_requires_unwind_tables(platform.machine().lower()),
315-
"GNU backtrace unwinding on Arm 32-bit requires -funwind-tables",
372+
_gnu_backtrace_requires_unwind_tables(),
373+
"GNU backtrace unwinding on Arm 32-bit requires unwind tables",
316374
)
317375
class GnuBacktraceUnwindTests(unittest.TestCase):
318376

0 commit comments

Comments
 (0)