diff --git a/lldb/source/Host/macosx/objcxx/Host.mm b/lldb/source/Host/macosx/objcxx/Host.mm --- a/lldb/source/Host/macosx/objcxx/Host.mm +++ b/lldb/source/Host/macosx/objcxx/Host.mm @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -1108,6 +1109,55 @@ } } + // 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 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(UINT32_MAX) && + cpu_type != static_cast(LLDB_INVALID_CPUTYPE); + const bool set_cpu_subtype = + cpu_subtype != 0 && + cpu_subtype != static_cast(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( launch_info.GetArguments().GetConstArgumentVector()); diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -291,8 +291,8 @@ {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 --- /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 --- /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') + + +@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 --- /dev/null +++ b/lldb/test/API/macosx/posix_spawn/arm64.c @@ -0,0 +1,5 @@ +#include +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 --- /dev/null +++ b/lldb/test/API/macosx/posix_spawn/x86_64.c @@ -0,0 +1,5 @@ +#include +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 --- /dev/null +++ b/lldb/test/API/macosx/posix_spawn/x86_64h.c @@ -0,0 +1,5 @@ +#include +int main() { + printf("slice: x86_64h\n"); + return 0; +}