vsk updated this revision to Diff 262799.
vsk added a comment.

- Reinstated comment about SIP to explain why we copy python
- Added a platform check


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79607/new/

https://reviews.llvm.org/D79607

Files:
  lldb/test/API/get_darwin_real_python.py
  lldb/test/API/lldbtest.py


Index: lldb/test/API/lldbtest.py
===================================================================
--- lldb/test/API/lldbtest.py
+++ lldb/test/API/lldbtest.py
@@ -3,6 +3,7 @@
 import tempfile
 import subprocess
 import sys
+import platform
 
 import lit.Test
 import lit.TestRunner
@@ -75,19 +76,21 @@
         builddir = getBuildDir(cmd)
         mkdir_p(builddir)
 
-        # The macOS system integrity protection (SIP) doesn't allow injecting
-        # libraries into system binaries, but this can be worked around by
-        # copying the binary into a different location.
+        # On macOS, we can't do the DYLD_INSERT_LIBRARIES trick with a shim
+        # python binary as the ASan interceptors get loaded too late. Also,
+        # when SIP is enabled, we can't inject libraries into system binaries
+        # at all, so we need a copy of the "real" python to work with.
+        #
+        # Find the "real" python binary, copy it, and invoke it.
         if 'DYLD_INSERT_LIBRARIES' in test.config.environment and \
-                (executable.startswith('/System/') or \
-                executable.startswith('/usr/bin/')):
+                platform.system() == 'Darwin':
             copied_python = os.path.join(builddir, 'copied-system-python')
             if not os.path.isfile(copied_python):
                 import shutil, subprocess
                 python = subprocess.check_output([
                     executable,
-                    '-c',
-                    'import sys; print(sys.executable)'
+                    os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                        'get_darwin_real_python.py')
                 ]).decode('utf-8').strip()
                 shutil.copy(python, copied_python)
             cmd[0] = copied_python
Index: lldb/test/API/get_darwin_real_python.py
===================================================================
--- /dev/null
+++ lldb/test/API/get_darwin_real_python.py
@@ -0,0 +1,14 @@
+# On macOS, system python binaries like /usr/bin/python and $(xcrun -f python3)
+# are shims. They do some light validation work and then spawn the "real" 
python
+# binary. Find the "real" python by asking dyld -- sys.executable reports the
+# wrong thing more often than not. This is also useful when we're running under
+# a Homebrew python3 binary, which also appears to be some kind of shim.
+def getDarwinRealPythonExecutable():
+    import ctypes
+    dyld = ctypes.cdll.LoadLibrary('/usr/lib/system/libdyld.dylib')
+    namelen = ctypes.c_ulong(1024)
+    name = ctypes.create_string_buffer(b'\000', namelen.value)
+    dyld._NSGetExecutablePath(ctypes.byref(name), ctypes.byref(namelen))
+    return name.value.decode('utf-8').strip()
+
+print(getDarwinRealPythonExecutable())


Index: lldb/test/API/lldbtest.py
===================================================================
--- lldb/test/API/lldbtest.py
+++ lldb/test/API/lldbtest.py
@@ -3,6 +3,7 @@
 import tempfile
 import subprocess
 import sys
+import platform
 
 import lit.Test
 import lit.TestRunner
@@ -75,19 +76,21 @@
         builddir = getBuildDir(cmd)
         mkdir_p(builddir)
 
-        # The macOS system integrity protection (SIP) doesn't allow injecting
-        # libraries into system binaries, but this can be worked around by
-        # copying the binary into a different location.
+        # On macOS, we can't do the DYLD_INSERT_LIBRARIES trick with a shim
+        # python binary as the ASan interceptors get loaded too late. Also,
+        # when SIP is enabled, we can't inject libraries into system binaries
+        # at all, so we need a copy of the "real" python to work with.
+        #
+        # Find the "real" python binary, copy it, and invoke it.
         if 'DYLD_INSERT_LIBRARIES' in test.config.environment and \
-                (executable.startswith('/System/') or \
-                executable.startswith('/usr/bin/')):
+                platform.system() == 'Darwin':
             copied_python = os.path.join(builddir, 'copied-system-python')
             if not os.path.isfile(copied_python):
                 import shutil, subprocess
                 python = subprocess.check_output([
                     executable,
-                    '-c',
-                    'import sys; print(sys.executable)'
+                    os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                        'get_darwin_real_python.py')
                 ]).decode('utf-8').strip()
                 shutil.copy(python, copied_python)
             cmd[0] = copied_python
Index: lldb/test/API/get_darwin_real_python.py
===================================================================
--- /dev/null
+++ lldb/test/API/get_darwin_real_python.py
@@ -0,0 +1,14 @@
+# On macOS, system python binaries like /usr/bin/python and $(xcrun -f python3)
+# are shims. They do some light validation work and then spawn the "real" python
+# binary. Find the "real" python by asking dyld -- sys.executable reports the
+# wrong thing more often than not. This is also useful when we're running under
+# a Homebrew python3 binary, which also appears to be some kind of shim.
+def getDarwinRealPythonExecutable():
+    import ctypes
+    dyld = ctypes.cdll.LoadLibrary('/usr/lib/system/libdyld.dylib')
+    namelen = ctypes.c_ulong(1024)
+    name = ctypes.create_string_buffer(b'\000', namelen.value)
+    dyld._NSGetExecutablePath(ctypes.byref(name), ctypes.byref(namelen))
+    return name.value.decode('utf-8').strip()
+
+print(getDarwinRealPythonExecutable())
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to