3
3
import os
4
4
import platform
5
5
import re
6
+ import shutil
6
7
import subprocess
7
8
import tempfile
8
9
@@ -87,12 +88,82 @@ def find_asan_runtime():
87
88
.strip ()
88
89
)
89
90
91
+
90
92
# Searches for a runtime library with the given name and returns a tool
91
93
# substitution of the same name and the found path.
92
94
def add_runtime (name ):
93
95
return ToolSubst (f"%{ name } " , find_runtime (name ))
94
96
95
97
98
+ # Provide the path to asan runtime lib 'libclang_rt.asan_osx_dynamic.dylib' if
99
+ # available. This is darwin specific since it's currently only needed on darwin.
100
+ # Stolen from llvm/test/lit.cfg.py with a few modifications
101
+ def get_asan_rtlib ():
102
+ if not "asan" in config .available_features or not "Darwin" in config .host_os :
103
+ return ""
104
+ # Find the asan rt lib
105
+ resource_dir = (
106
+ subprocess .check_output ([config .host_cc .strip (), "-print-resource-dir" ])
107
+ .decode ("utf-8" )
108
+ .strip ()
109
+ )
110
+ return os .path .join (
111
+ resource_dir , "lib" , "darwin" , "libclang_rt.asan_osx_dynamic.dylib"
112
+ )
113
+
114
+
115
+ # On macOS, we can't do the DYLD_INSERT_LIBRARIES trick with a shim python
116
+ # binary as the ASan interceptors get loaded too late. Also, when SIP is
117
+ # enabled, we can't inject libraries into system binaries at all, so we need a
118
+ # copy of the "real" python to work with.
119
+ # Stolen from lldb/test/API/lit.cfg.py with a few modifications
120
+ def find_real_python_interpreter ():
121
+ # If we're running in a virtual environment, we have to copy Python into
122
+ # the virtual environment for it to work.
123
+ if sys .prefix != sys .base_prefix :
124
+ copied_python = os .path .join (sys .prefix , "bin" , "copied-python" )
125
+ else :
126
+ copied_python = os .path .join (config .lldb_build_directory , "copied-python" )
127
+
128
+ # Avoid doing any work if we already copied the binary.
129
+ if os .path .isfile (copied_python ):
130
+ return copied_python
131
+
132
+ # Find the "real" python binary.
133
+ real_python = (
134
+ subprocess .check_output (
135
+ [
136
+ config .python_executable ,
137
+ os .path .join (
138
+ os .path .dirname (os .path .realpath (__file__ )),
139
+ "get_darwin_real_python.py" ,
140
+ ),
141
+ ]
142
+ )
143
+ .decode ("utf-8" )
144
+ .strip ()
145
+ )
146
+
147
+ shutil .copy (real_python , copied_python )
148
+
149
+ # Now make sure the copied Python works. The Python in Xcode has a relative
150
+ # RPATH and cannot be copied.
151
+ try :
152
+ # We don't care about the output, just make sure it runs.
153
+ subprocess .check_call ([copied_python , "-V" ])
154
+ except subprocess .CalledProcessError :
155
+ # The copied Python didn't work. Assume we're dealing with the Python
156
+ # interpreter in Xcode. Given that this is not a system binary SIP
157
+ # won't prevent us form injecting the interceptors, but when running in
158
+ # a virtual environment, we can't use it directly. Create a symlink
159
+ # instead.
160
+ os .remove (copied_python )
161
+ os .symlink (real_python , copied_python )
162
+
163
+ # The copied Python works.
164
+ return copied_python
165
+
166
+
96
167
llvm_config .with_system_environment (["HOME" , "INCLUDE" , "LIB" , "TMP" , "TEMP" ])
97
168
98
169
llvm_config .use_default_substitutions ()
@@ -107,6 +178,7 @@ def add_runtime(name):
107
178
"LICENSE.txt" ,
108
179
"lit.cfg.py" ,
109
180
"lit.site.cfg.py" ,
181
+ "get_darwin_real_python.py" ,
110
182
]
111
183
112
184
# Tweak the PATH to include the tools dir.
@@ -188,11 +260,31 @@ def add_runtime(name):
188
260
)
189
261
190
262
python_executable = config .python_executable
191
- # Python configuration with sanitizer requires some magic preloading. This will only work on clang/linux.
192
- # TODO: detect Darwin/Windows situation (or mark these tests as unsupported on these platforms).
193
- if "asan" in config .available_features and "Linux" in config .host_os :
194
- _asan_rt = find_asan_runtime ()
195
- python_executable = f"env LD_PRELOAD={ _asan_rt } { config .python_executable } "
263
+ # Python configuration with sanitizer requires some magic preloading. This will only work on clang/linux/darwin.
264
+ # TODO: detect Windows situation (or mark these tests as unsupported on these platforms).
265
+ if "asan" in config .available_features :
266
+ if "Linux" in config .host_os :
267
+ _asan_rt = find_asan_runtime ()
268
+ python_executable = f"env LD_PRELOAD={ _asan_rt } { config .python_executable } "
269
+ if "Darwin" in config .host_os :
270
+ # Ensure we use a non-shim Python executable, for the `DYLD_INSERT_LIBRARIES`
271
+ # env variable to take effect
272
+ real_python_executable = find_real_python_interpreter ()
273
+ if real_python_executable :
274
+ python_executable = real_python_executable
275
+ lit_config .note (
276
+ "Using {} instead of {}" .format (
277
+ python_executable , config .python_executable
278
+ )
279
+ )
280
+
281
+ asan_rtlib = get_asan_rtlib ()
282
+ lit_config .note ("Using ASan rtlib {}" .format (asan_rtlib ))
283
+ config .environment ["MallocNanoZone" ] = "0"
284
+ config .environment ["ASAN_OPTIONS" ] = "detect_stack_use_after_return=1"
285
+ config .environment ["DYLD_INSERT_LIBRARIES" ] = asan_rtlib
286
+
287
+
196
288
# On Windows the path to python could contains spaces in which case it needs to be provided in quotes.
197
289
# This is the equivalent of how %python is setup in llvm/utils/lit/lit/llvm/config.py.
198
290
elif "Windows" in config .host_os :
0 commit comments