|
1 | 1 | import json |
2 | 2 | import os |
3 | 3 | import platform |
| 4 | +import shlex |
4 | 5 | import subprocess |
5 | 6 | import sys |
6 | 7 | import sysconfig |
@@ -89,19 +90,76 @@ def _frame_pointers_expected(machine): |
89 | 90 | return None |
90 | 91 |
|
91 | 92 |
|
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: |
94 | 95 | return False |
95 | 96 |
|
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 = [ |
97 | 137 | value for value in ( |
98 | | - sysconfig.get_config_var("PY_CFLAGS"), |
99 | 138 | sysconfig.get_config_var("PY_CORE_CFLAGS"), |
100 | | - sysconfig.get_config_var("CFLAGS"), |
| 139 | + sysconfig.get_config_var("PY_STDMODULE_CFLAGS"), |
101 | 140 | ) |
102 | 141 | 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) |
103 | 155 | ) |
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() |
105 | 163 |
|
106 | 164 |
|
107 | 165 | def _build_stack_and_unwind(unwinder): |
@@ -311,8 +369,8 @@ def test_manual_unwind_respects_frame_pointers(self): |
311 | 369 | @unittest.skipIf(support.is_wasi, "test not supported on WASI") |
312 | 370 | @unittest.skipUnless(sys.platform == "linux", "GNU backtrace unwinding test requires Linux") |
313 | 371 | @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", |
316 | 374 | ) |
317 | 375 | class GnuBacktraceUnwindTests(unittest.TestCase): |
318 | 376 |
|
|
0 commit comments