Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions Lib/test/test_frame_pointer_unwind.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import os
import platform
import shlex
import subprocess
import sys
import sysconfig
Expand Down Expand Up @@ -89,6 +90,78 @@ def _frame_pointers_expected(machine):
return None


def _is_arm32_build():
if sys.maxsize >= 2**32:
return False

abi = " ".join(
value for value in (
sysconfig.get_config_var("MULTIARCH"),
sysconfig.get_config_var("HOST_GNU_TYPE"),
sysconfig.get_config_var("SOABI"),
)
if value
).lower()
return "arm" in abi


def _cflags_have_unwind_tables(cflags):
unwind_tables = False
asynchronous_unwind_tables = False
exceptions = False

try:
options = shlex.split(cflags)
except ValueError:
options = cflags.split()

for option in options:
if option == "-funwind-tables":
unwind_tables = True
elif option == "-fno-unwind-tables":
unwind_tables = False
elif option == "-fasynchronous-unwind-tables":
asynchronous_unwind_tables = True
elif option == "-fno-asynchronous-unwind-tables":
asynchronous_unwind_tables = False
elif option == "-fexceptions":
exceptions = True
elif option == "-fno-exceptions":
exceptions = False

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That's a lot of untested logic.
Should we skip the test for any 32-bit Arm?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I tend to agree with you. On Arm 32bit you can have unwind data with any of these flags: -funwind-tables, -fasynchronous-unwind-tables, -fexceptions


return unwind_tables or asynchronous_unwind_tables or exceptions


def _build_has_unwind_tables():
cflags = [
value for value in (
sysconfig.get_config_var("PY_CORE_CFLAGS"),
sysconfig.get_config_var("PY_STDMODULE_CFLAGS"),
)
if value
]
if not cflags:
cflags = [
value for value in (
sysconfig.get_config_var("PY_CFLAGS"),
sysconfig.get_config_var("CFLAGS"),
)
if value
]

return (
bool(cflags)
and all(_cflags_have_unwind_tables(value) for value in cflags)
)


def _gnu_backtrace_requires_unwind_tables():
if not _is_arm32_build():
return False

return not _build_has_unwind_tables()


def _build_stack_and_unwind(unwinder):
import operator

Expand Down Expand Up @@ -295,6 +368,10 @@ def test_manual_unwind_respects_frame_pointers(self):
@support.requires_gil_enabled("test requires the GIL enabled")
@unittest.skipIf(support.is_wasi, "test not supported on WASI")
@unittest.skipUnless(sys.platform == "linux", "GNU backtrace unwinding test requires Linux")
@unittest.skipIf(
_gnu_backtrace_requires_unwind_tables(),
"GNU backtrace unwinding on Arm 32-bit requires unwind tables",
)
class GnuBacktraceUnwindTests(unittest.TestCase):

def setUp(self):
Expand Down
Loading