Skip to content

Fix platform selection on Apple Silicon #4072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lldb/include/lldb/Target/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ class Platform : public PluginInterface {
static lldb::PlatformSP GetHostPlatform();

static lldb::PlatformSP
GetPlatformForArchitecture(const ArchSpec &arch, ArchSpec *platform_arch_ptr);
GetPlatformForArchitecture(const ArchSpec &arch,
const ArchSpec &process_host_arch = {},
ArchSpec *platform_arch_ptr = nullptr);

static const char *GetHostPlatformName();

Expand All @@ -107,6 +109,7 @@ class Platform : public PluginInterface {
static lldb::PlatformSP Create(ConstString name, Status &error);

static lldb::PlatformSP Create(const ArchSpec &arch,
const ArchSpec &process_host_arch,
ArchSpec *platform_arch_ptr, Status &error);

/// Augments the triple either with information from platform or the host
Expand Down Expand Up @@ -311,7 +314,8 @@ class Platform : public PluginInterface {

/// Get the platform's supported architectures in the order in which they
/// should be searched.
virtual std::vector<ArchSpec> GetSupportedArchitectures() = 0;
virtual std::vector<ArchSpec>
GetSupportedArchitectures(const ArchSpec &process_host_arch) = 0;

virtual size_t GetSoftwareBreakpointTrapOpcode(Target &target,
BreakpointSite *bp_site);
Expand All @@ -333,6 +337,7 @@ class Platform : public PluginInterface {
/// Lets a platform answer if it is compatible with a given architecture and
/// the target triple contained within.
virtual bool IsCompatibleArchitecture(const ArchSpec &arch,
const ArchSpec &process_host_arch,
bool exact_arch_match,
ArchSpec *compatible_arch_ptr);

Expand Down
3 changes: 3 additions & 0 deletions lldb/include/lldb/Target/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,9 @@ class Process : public std::enable_shared_from_this<Process>,
virtual JITLoaderList &GetJITLoaders();

public:
/// Get the system architecture for this process.
virtual ArchSpec GetSystemArchitecture() { return {}; }

/// Get the system runtime plug-in for this process.
///
/// \return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
from lldbsuite.test.gdbclientutils import *
from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase


class TestPlatformMacOSX(GDBRemoteTestBase):

mydir = TestBase.compute_mydir(__file__)

class MyResponder(MockGDBServerResponder):

def __init__(self, host):
self.host_ostype = host
MockGDBServerResponder.__init__(self)

def respond(self, packet):
if packet == "qProcessInfo":
return self.qProcessInfo()
return MockGDBServerResponder.respond(self, packet)

def qHostInfo(self):
return "cputype:16777223;cpusubtype:2;ostype:%s;vendor:apple;os_version:10.15.4;maccatalyst_version:13.4;endian:little;ptrsize:8;" % self.host_ostype

def qProcessInfo(self):
return "pid:a860;parent-pid:d2a0;real-uid:1f5;real-gid:14;effective-uid:1f5;effective-gid:14;cputype:100000c;cpusubtype:2;ptrsize:8;ostype:ios;vendor:apple;endian:little;"

def vCont(self):
return "vCont;"

def platform_test(self, host, expected_triple, expected_platform):
self.server.responder = self.MyResponder(host)
if self.TraceOn():
self.runCmd("log enable gdb-remote packets")
self.addTearDownHook(
lambda: self.runCmd("log disable gdb-remote packets"))

target = self.dbg.CreateTargetWithFileAndArch(None, None)
process = self.connect(target)

triple = target.GetTriple()
self.assertEqual(triple, expected_triple)

platform = target.GetPlatform()
self.assertEqual(platform.GetName(), expected_platform)

@skipIfRemote
def test_ios(self):
self.platform_test(host="ios",
expected_triple="arm64e-apple-ios-",
expected_platform="remote-ios")

@skipIfRemote
@skipUnlessDarwin
@skipUnlessArch("arm64")
def test_macos(self):
self.platform_test(host="macosx",
expected_triple="arm64e-apple-ios-",
expected_platform="host")
52 changes: 52 additions & 0 deletions lldb/lldb/unittests/Platform/PlatformMacOSXTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===-- PlatformMacOSXTest.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "gtest/gtest.h"

#include "Plugins/Platform/MacOSX/PlatformMacOSX.h"
#include "TestingSupport/SubsystemRAII.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Platform.h"

using namespace lldb;
using namespace lldb_private;

class PlatformMacOSXTest : public ::testing::Test {
SubsystemRAII<FileSystem, HostInfo, PlatformMacOSX> subsystems;
};

static bool containsArch(const std::vector<ArchSpec> &archs,
const ArchSpec &arch) {
return std::find_if(archs.begin(), archs.end(), [&](const ArchSpec &other) {
return arch.IsExactMatch(other);
}) != archs.end();
}

TEST_F(PlatformMacOSXTest, TestGetSupportedArchitectures) {
PlatformMacOSX platform;

const ArchSpec x86_macosx_arch("x86_64-apple-macosx");

EXPECT_TRUE(containsArch(platform.GetSupportedArchitectures(x86_macosx_arch),
x86_macosx_arch));
EXPECT_TRUE(
containsArch(platform.GetSupportedArchitectures({}), x86_macosx_arch));

#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
const ArchSpec arm64_macosx_arch("arm64-apple-macosx");
const ArchSpec arm64_ios_arch("arm64-apple-ios");

EXPECT_TRUE(containsArch(
platform.GetSupportedArchitectures(arm64_macosx_arch), arm64_ios_arch));
EXPECT_TRUE(
containsArch(platform.GetSupportedArchitectures({}), arm64_ios_arch));
EXPECT_FALSE(containsArch(platform.GetSupportedArchitectures(arm64_ios_arch),
arm64_ios_arch));
#endif
}
12 changes: 6 additions & 6 deletions lldb/source/Interpreter/OptionGroupPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@ PlatformSP OptionGroupPlatform::CreatePlatformWithOptions(
if (!m_platform_name.empty()) {
platform_sp = Platform::Create(ConstString(m_platform_name.c_str()), error);
if (platform_sp) {
if (platform_arch.IsValid() &&
!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
error.SetErrorStringWithFormat("platform '%s' doesn't support '%s'",
platform_sp->GetName().GetCString(),
arch.GetTriple().getTriple().c_str());
if (platform_arch.IsValid() && !platform_sp->IsCompatibleArchitecture(
arch, {}, false, &platform_arch)) {
error.SetErrorStringWithFormatv("platform '{0}' doesn't support '{1}'",
platform_sp->GetPluginName(),
arch.GetTriple().getTriple());
platform_sp.reset();
return platform_sp;
}
}
} else if (arch.IsValid()) {
platform_sp = Platform::Create(arch, &platform_arch, error);
platform_sp = Platform::Create(arch, {}, &platform_arch, error);
}

if (platform_sp) {
Expand Down
5 changes: 3 additions & 2 deletions lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,10 @@ PlatformFreeBSD::PlatformFreeBSD(bool is_host)
}
}

std::vector<ArchSpec> PlatformFreeBSD::GetSupportedArchitectures() {
std::vector<ArchSpec>
PlatformFreeBSD::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectures();
return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch);
return m_supported_architectures;
}

Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class PlatformFreeBSD : public PlatformPOSIX {

void GetStatus(Stream &strm) override;

std::vector<ArchSpec> GetSupportedArchitectures() override;
std::vector<ArchSpec>
GetSupportedArchitectures(const ArchSpec &process_host_arch) override;

bool CanDebugProcess() override;

Expand Down
5 changes: 3 additions & 2 deletions lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,10 @@ PlatformLinux::PlatformLinux(bool is_host)
}
}

std::vector<ArchSpec> PlatformLinux::GetSupportedArchitectures() {
std::vector<ArchSpec>
PlatformLinux::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectures();
return m_remote_platform_sp->GetSupportedArchitectures(process_host_arch);
return m_supported_architectures;
}

Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Platform/Linux/PlatformLinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ class PlatformLinux : public PlatformPOSIX {

void GetStatus(Stream &strm) override;

std::vector<ArchSpec> GetSupportedArchitectures() override;
std::vector<ArchSpec>
GetSupportedArchitectures(const ArchSpec &process_host_arch) override;

uint32_t GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ CoreSimulatorSupport::Device PlatformAppleSimulator::GetSimulatorDevice() {
}
#endif

std::vector<ArchSpec> PlatformAppleSimulator::GetSupportedArchitectures() {
std::vector<ArchSpec> PlatformAppleSimulator::GetSupportedArchitectures(
const ArchSpec &process_host_arch) {
std::vector<ArchSpec> result(m_supported_triples.size());
llvm::transform(m_supported_triples, result.begin(),
[](llvm::StringRef triple) { return ArchSpec(triple); });
Expand Down Expand Up @@ -382,7 +383,7 @@ Status PlatformAppleSimulator::ResolveExecutable(
StreamString arch_names;
llvm::ListSeparator LS;
ArchSpec platform_arch;
for (const ArchSpec &arch : GetSupportedArchitectures()) {
for (const ArchSpec &arch : GetSupportedArchitectures({})) {
resolved_module_spec.GetArchitecture() = arch;

// Only match x86 with x86 and x86_64 with x86_64...
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ class PlatformAppleSimulator : public PlatformDarwin {
lldb_private::Target &target,
lldb_private::Status &error) override;

std::vector<lldb_private::ArchSpec> GetSupportedArchitectures() override;
std::vector<lldb_private::ArchSpec> GetSupportedArchitectures(
const lldb_private::ArchSpec &process_host_arch) override;

lldb_private::Status ResolveExecutable(
const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,8 @@ Status PlatformDarwinKernel::ExamineKextForMatchingUUID(
return {};
}

std::vector<ArchSpec> PlatformDarwinKernel::GetSupportedArchitectures() {
std::vector<ArchSpec> PlatformDarwinKernel::GetSupportedArchitectures(
const ArchSpec &process_host_arch) {
std::vector<ArchSpec> result;
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
ARMGetSupportedArchitectures(result);
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ class PlatformDarwinKernel : public PlatformDarwin {
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules,
bool *did_create_ptr) override;

std::vector<lldb_private::ArchSpec> GetSupportedArchitectures() override;
std::vector<lldb_private::ArchSpec> GetSupportedArchitectures(
const lldb_private::ArchSpec &process_host_arch) override;

bool SupportsModules() override { return false; }

Expand Down
15 changes: 12 additions & 3 deletions lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,10 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
return {};
}

std::vector<ArchSpec> PlatformMacOSX::GetSupportedArchitectures() {
std::vector<ArchSpec>
PlatformMacOSX::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
std::vector<ArchSpec> result;
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
// macOS for ARM64 support both native and translated x86_64 processes

// When cmdline lldb is run on iOS, watchOS, etc, it is still
// using "PlatformMacOSX".
llvm::Triple::OSType host_os = GetHostOSType();
Expand All @@ -151,6 +150,16 @@ std::vector<ArchSpec> PlatformMacOSX::GetSupportedArchitectures() {
result.push_back(ArchSpec("x86_64-apple-ios-macabi"));
result.push_back(ArchSpec("arm64-apple-ios-macabi"));
result.push_back(ArchSpec("arm64e-apple-ios-macabi"));

// On Apple Silicon, the host platform is compatible with iOS triples to
// support unmodified "iPhone and iPad Apps on Apple Silicon Macs". Because
// the binaries are identical, we must rely on the host architecture to
// tell them apart and mark the host platform as compatible or not.
if (!process_host_arch ||
process_host_arch.GetTriple().getOS() == llvm::Triple::MacOSX) {
result.push_back(ArchSpec("arm64-apple-ios"));
result.push_back(ArchSpec("arm64e-apple-ios"));
}
}
#else
x86GetSupportedArchitectures(result);
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ class PlatformMacOSX : public PlatformDarwin {
return PlatformDarwin::GetFile(source, destination);
}

std::vector<lldb_private::ArchSpec> GetSupportedArchitectures() override;
std::vector<lldb_private::ArchSpec> GetSupportedArchitectures(
const lldb_private::ArchSpec &process_host_arch) override;

lldb_private::ConstString
GetSDKDirectory(lldb_private::Target &target) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ llvm::StringRef PlatformRemoteAppleBridge::GetDescriptionStatic() {
return "Remote BridgeOS platform plug-in.";
}

std::vector<ArchSpec> PlatformRemoteAppleBridge::GetSupportedArchitectures() {
std::vector<ArchSpec> PlatformRemoteAppleBridge::GetSupportedArchitectures(
const ArchSpec &process_host_arch) {
return {ArchSpec("arm64-apple-bridgeos")};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class PlatformRemoteAppleBridge : public PlatformRemoteDarwinDevice {

llvm::StringRef GetDescription() override { return GetDescriptionStatic(); }

std::vector<lldb_private::ArchSpec> GetSupportedArchitectures() override;
std::vector<lldb_private::ArchSpec> GetSupportedArchitectures(
const lldb_private::ArchSpec &process_host_arch) override;

protected:
llvm::StringRef GetDeviceSupportDirectoryName() override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ llvm::StringRef PlatformRemoteAppleTV::GetDescriptionStatic() {
return "Remote Apple TV platform plug-in.";
}

std::vector<ArchSpec> PlatformRemoteAppleTV::GetSupportedArchitectures() {
std::vector<ArchSpec> PlatformRemoteAppleTV::GetSupportedArchitectures(
const ArchSpec &process_host_arch) {
ArchSpec system_arch(GetSystemArchitecture());

const ArchSpec::Core system_core = system_arch.GetCore();
Expand Down
3 changes: 2 additions & 1 deletion lldb/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class PlatformRemoteAppleTV : public PlatformRemoteDarwinDevice {

llvm::StringRef GetDescription() override { return GetDescriptionStatic(); }

std::vector<lldb_private::ArchSpec> GetSupportedArchitectures() override;
std::vector<lldb_private::ArchSpec> GetSupportedArchitectures(
const lldb_private::ArchSpec &process_host_arch) override;

protected:
llvm::StringRef GetDeviceSupportDirectoryName() override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ llvm::StringRef PlatformRemoteAppleWatch::GetDescriptionStatic() {
PlatformRemoteAppleWatch::PlatformRemoteAppleWatch()
: PlatformRemoteDarwinDevice() {}

std::vector<ArchSpec> PlatformRemoteAppleWatch::GetSupportedArchitectures() {
std::vector<ArchSpec>
PlatformRemoteAppleWatch::GetSupportedArchitectures(const ArchSpec &host_info) {
ArchSpec system_arch(GetSystemArchitecture());

const ArchSpec::Core system_core = system_arch.GetCore();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class PlatformRemoteAppleWatch : public PlatformRemoteDarwinDevice {

// lldb_private::Platform functions

std::vector<lldb_private::ArchSpec> GetSupportedArchitectures() override;
std::vector<lldb_private::ArchSpec> GetSupportedArchitectures(
const lldb_private::ArchSpec &process_host_arch) override;

protected:
llvm::StringRef GetDeviceSupportDirectoryName() override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable(
// the correct order) and see if we can find a match that way
StreamString arch_names;
llvm::ListSeparator LS;
for (const ArchSpec &arch : GetSupportedArchitectures()) {
ArchSpec process_host_arch;
for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
resolved_module_spec.GetArchitecture() = arch;
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
nullptr, nullptr, nullptr);
Expand Down
Loading