[Lldb-commits] [lldb] 98e50a7 - [lldb] Honor the CPU type & subtype when launching on macOS

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Wed Feb 3 13:42:07 PST 2021


Author: Jonas Devlieghere
Date: 2021-02-03T13:42:00-08:00
New Revision: 98e50a7d4c12d2c32eb15e55cbb2e1f89a802e28

URL: https://github.com/llvm/llvm-project/commit/98e50a7d4c12d2c32eb15e55cbb2e1f89a802e28
DIFF: https://github.com/llvm/llvm-project/commit/98e50a7d4c12d2c32eb15e55cbb2e1f89a802e28.diff

LOG: [lldb] Honor the CPU type & subtype when launching on macOS

Honor the CPU type (and subtype) when launching the inferior on macOS.

Part of this functionality was thought to be no longer needed and
removed in 85bd4369610fe60397455c8e0914a09288285e84, however it's still
needed, for example to launch binaries under Rosetta 2 on Apple Silicon.

This patch will use posix_spawnattr_setarchpref_np if available and
fallback to posix_spawnattr_setbinpref_np if not.

Differential revision: https://reviews.llvm.org/D95922

Added: 
    lldb/test/API/macosx/posix_spawn/Makefile
    lldb/test/API/macosx/posix_spawn/TestLaunchProcessPosixSpawn.py
    lldb/test/API/macosx/posix_spawn/arm64.c
    lldb/test/API/macosx/posix_spawn/x86_64.c
    lldb/test/API/macosx/posix_spawn/x86_64h.c

Modified: 
    lldb/source/Host/macosx/objcxx/Host.mm
    lldb/source/Utility/ArchSpec.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm
index 8cd3b3591993..907be0a716c2 100644
--- a/lldb/source/Host/macosx/objcxx/Host.mm
+++ b/lldb/source/Host/macosx/objcxx/Host.mm
@@ -38,6 +38,7 @@
 
 #include <asl.h>
 #include <crt_externs.h>
+#include <dlfcn.h>
 #include <grp.h>
 #include <libproc.h>
 #include <pwd.h>
@@ -1108,6 +1109,55 @@ static Status LaunchProcessPosixSpawn(const char *exe_path,
     }
   }
 
+  // Don't set the binpref if a shell was provided. After all, that's only
+  // going to affect what version of the shell is launched, not what fork of
+  // the binary is launched.  We insert "arch --arch <ARCH> as part of the
+  // shell invocation to do that job on OSX.
+  if (launch_info.GetShell() == FileSpec()) {
+    const ArchSpec &arch_spec = launch_info.GetArchitecture();
+    cpu_type_t cpu_type = arch_spec.GetMachOCPUType();
+    cpu_type_t cpu_subtype = arch_spec.GetMachOCPUSubType();
+    const bool set_cpu_type =
+        cpu_type != 0 && cpu_type != static_cast<cpu_type_t>(UINT32_MAX) &&
+        cpu_type != static_cast<cpu_type_t>(LLDB_INVALID_CPUTYPE);
+    const bool set_cpu_subtype =
+        cpu_subtype != 0 &&
+        cpu_subtype != static_cast<cpu_subtype_t>(UINT32_MAX) &&
+        cpu_subtype != CPU_SUBTYPE_X86_64_H;
+    if (set_cpu_type) {
+      size_t ocount = 0;
+      typedef int (*posix_spawnattr_setarchpref_np_t)(
+          posix_spawnattr_t *, size_t, cpu_type_t *, cpu_subtype_t *, size_t *);
+      posix_spawnattr_setarchpref_np_t posix_spawnattr_setarchpref_np_fn =
+          (posix_spawnattr_setarchpref_np_t)dlsym(
+              RTLD_DEFAULT, "posix_spawnattr_setarchpref_np");
+      if (set_cpu_subtype && posix_spawnattr_setarchpref_np_fn) {
+        error.SetError((*posix_spawnattr_setarchpref_np_fn)(
+                           &attr, 1, &cpu_type, &cpu_subtype, &ocount),
+                       eErrorTypePOSIX);
+        if (error.Fail())
+          LLDB_LOG(log,
+                   "error: {0}, ::posix_spawnattr_setarchpref_np ( &attr, 1, "
+                   "cpu_type = {1:x}, cpu_subtype = {1:x}, count => {2} )",
+                   error, cpu_type, cpu_subtype, ocount);
+
+        if (error.Fail() || ocount != 1)
+          return error;
+      } else {
+        error.SetError(
+            ::posix_spawnattr_setbinpref_np(&attr, 1, &cpu_type, &ocount),
+            eErrorTypePOSIX);
+        if (error.Fail())
+          LLDB_LOG(log,
+                   "error: {0}, ::posix_spawnattr_setbinpref_np ( &attr, 1, "
+                   "cpu_type = {1:x}, count => {2} )",
+                   error, cpu_type, ocount);
+        if (error.Fail() || ocount != 1)
+          return error;
+      }
+    }
+  }
+
   const char *tmp_argv[2];
   char *const *argv = const_cast<char *const *>(
       launch_info.GetArguments().GetConstArgumentVector());

diff  --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp
index c13e2389cfed..52fbf3551b1a 100644
--- a/lldb/source/Utility/ArchSpec.cpp
+++ b/lldb/source/Utility/ArchSpec.cpp
@@ -291,8 +291,8 @@ static const ArchDefinitionEntry g_macho_arch_entries[] = {
     {ArchSpec::eCore_arm_armv7m,      llvm::MachO::CPU_TYPE_ARM,        llvm::MachO::CPU_SUBTYPE_ARM_V7M,       UINT32_MAX, SUBTYPE_MASK},
     {ArchSpec::eCore_arm_armv7em,     llvm::MachO::CPU_TYPE_ARM,        llvm::MachO::CPU_SUBTYPE_ARM_V7EM,      UINT32_MAX, SUBTYPE_MASK},
     {ArchSpec::eCore_arm_arm64e,      llvm::MachO::CPU_TYPE_ARM64,      llvm::MachO::CPU_SUBTYPE_ARM64E,        UINT32_MAX, SUBTYPE_MASK},
-    {ArchSpec::eCore_arm_arm64,       llvm::MachO::CPU_TYPE_ARM64,      llvm::MachO::CPU_SUBTYPE_ARM64_V8,      UINT32_MAX, SUBTYPE_MASK},
     {ArchSpec::eCore_arm_arm64,       llvm::MachO::CPU_TYPE_ARM64,      llvm::MachO::CPU_SUBTYPE_ARM64_ALL,     UINT32_MAX, SUBTYPE_MASK},
+    {ArchSpec::eCore_arm_arm64,       llvm::MachO::CPU_TYPE_ARM64,      llvm::MachO::CPU_SUBTYPE_ARM64_V8,      UINT32_MAX, SUBTYPE_MASK},
     {ArchSpec::eCore_arm_arm64,       llvm::MachO::CPU_TYPE_ARM64,      13,                                     UINT32_MAX, SUBTYPE_MASK},
     {ArchSpec::eCore_arm_arm64_32,    llvm::MachO::CPU_TYPE_ARM64_32,   0,                                      UINT32_MAX, SUBTYPE_MASK},
     {ArchSpec::eCore_arm_arm64_32,    llvm::MachO::CPU_TYPE_ARM64_32,   1,                                      UINT32_MAX, SUBTYPE_MASK},

diff  --git a/lldb/test/API/macosx/posix_spawn/Makefile b/lldb/test/API/macosx/posix_spawn/Makefile
new file mode 100644
index 000000000000..7ae46ca95828
--- /dev/null
+++ b/lldb/test/API/macosx/posix_spawn/Makefile
@@ -0,0 +1,18 @@
+EXE := fat.out
+LIPO=lipo
+
+include Makefile.rules
+
+all: fat.out
+
+x86_64.out: x86_64.c
+	$(CC) -isysroot $(SDKROOT) -target x86_64-apple-macosx10.9 -o x86_64.out $<
+
+x86_64h.out: x86_64h.c
+	$(CC) -isysroot $(SDKROOT) -target x86_64h-apple-macosx10.9 -o x86_64h.out $<
+
+arm64.out: arm64.c
+	$(CC) -isysroot $(SDKROOT) -target arm64-apple-macosx10.9 -o arm64.out $<
+
+fat.out: x86_64.out x86_64h.out arm64.out
+	$(LIPO) -o fat.out -create $^

diff  --git a/lldb/test/API/macosx/posix_spawn/TestLaunchProcessPosixSpawn.py b/lldb/test/API/macosx/posix_spawn/TestLaunchProcessPosixSpawn.py
new file mode 100644
index 000000000000..335f75e04bfb
--- /dev/null
+++ b/lldb/test/API/macosx/posix_spawn/TestLaunchProcessPosixSpawn.py
@@ -0,0 +1,73 @@
+import contextlib
+import os
+import unittest2
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+def haswell():
+    features = subprocess.check_output(["sysctl", "machdep.cpu"])
+    return "AVX2" in features.decode('utf-8')
+
+
+def apple_silicon():
+    features = subprocess.check_output(["sysctl", "machdep.cpu"])
+    return "Apple M" in features.decode('utf-8')
+
+
+ at contextlib.contextmanager
+def remove_from_env(var):
+    old_environ = os.environ.copy()
+    del os.environ[var]
+    try:
+        yield
+    finally:
+        os.environ.clear()
+        os.environ.update(old_environ)
+
+
+class TestLaunchProcessPosixSpawn(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+    mydir = TestBase.compute_mydir(__file__)
+
+    def no_haswell(self):
+        if not haswell():
+            return "Current CPU is not Haswell"
+        return None
+
+    def no_apple_silicon(self):
+        if not apple_silicon():
+            return "Current CPU is not Apple Silicon"
+        return None
+
+    def run_arch(self, exe, arch):
+        self.runCmd('target create -arch {} {}'.format(arch, exe))
+        self.runCmd('run')
+
+        process = self.dbg.GetSelectedTarget().process
+        self.assertEqual(process.GetState(), lldb.eStateExited)
+        self.assertIn('slice: {}'.format(arch), process.GetSTDOUT(1000))
+
+    @skipUnlessDarwin
+    @skipIfDarwinEmbedded
+    @skipTestIfFn(no_haswell)
+    def test_haswell(self):
+        self.build()
+        exe = self.getBuildArtifact("fat.out")
+        self.run_arch(exe, 'x86_64')
+        self.run_arch(exe, 'x86_64h')
+
+    @skipUnlessDarwin
+    @skipIfDarwinEmbedded
+    @skipTestIfFn(no_apple_silicon)
+    def test_apple_silicon(self):
+        self.build()
+        exe = self.getBuildArtifact("fat.out")
+
+        # We need to remove LLDB_DEBUGSERVER_PATH from the environment if it's
+        # set so that the Rosetta debugserver is picked for x86_64.
+        with remove_from_env('LLDB_DEBUGSERVER_PATH'):
+            self.run_arch(exe, 'x86_64')
+            self.run_arch(exe, 'arm64')

diff  --git a/lldb/test/API/macosx/posix_spawn/arm64.c b/lldb/test/API/macosx/posix_spawn/arm64.c
new file mode 100644
index 000000000000..9a399963a0d5
--- /dev/null
+++ b/lldb/test/API/macosx/posix_spawn/arm64.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+int main() {
+  printf("slice: arm64\n");
+  return 0;
+}

diff  --git a/lldb/test/API/macosx/posix_spawn/x86_64.c b/lldb/test/API/macosx/posix_spawn/x86_64.c
new file mode 100644
index 000000000000..992da02fba62
--- /dev/null
+++ b/lldb/test/API/macosx/posix_spawn/x86_64.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+int main() {
+  printf("slice: x86_64\n");
+  return 0;
+}

diff  --git a/lldb/test/API/macosx/posix_spawn/x86_64h.c b/lldb/test/API/macosx/posix_spawn/x86_64h.c
new file mode 100644
index 000000000000..e890029083bd
--- /dev/null
+++ b/lldb/test/API/macosx/posix_spawn/x86_64h.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+int main() {
+  printf("slice: x86_64h\n");
+  return 0;
+}


        


More information about the lldb-commits mailing list