Because Host::RunShellCommand runs commands through $SHELL there is an opportunity for this to fail spectacularly on systems that use custom shells with odd behaviors. This patch makes these situations easier to debug by at least logging the result of the failed xcrun invocation. It also doesn't run xcrun through a shell any more. rdar://102389438 Differential Revision: https://reviews.llvm.org/D138060
227 lines
7.9 KiB
C++
227 lines
7.9 KiB
C++
//===-- PlatformMacOSX.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 "PlatformMacOSX.h"
|
|
#include "PlatformRemoteMacOSX.h"
|
|
#include "PlatformRemoteiOS.h"
|
|
#if defined(__APPLE__)
|
|
#include "PlatformAppleSimulator.h"
|
|
#include "PlatformDarwinKernel.h"
|
|
#include "PlatformRemoteAppleBridge.h"
|
|
#include "PlatformRemoteAppleTV.h"
|
|
#include "PlatformRemoteAppleWatch.h"
|
|
#endif
|
|
#include "lldb/Breakpoint/BreakpointLocation.h"
|
|
#include "lldb/Core/Debugger.h"
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Core/ModuleList.h"
|
|
#include "lldb/Core/ModuleSpec.h"
|
|
#include "lldb/Core/PluginManager.h"
|
|
#include "lldb/Host/Config.h"
|
|
#include "lldb/Host/Host.h"
|
|
#include "lldb/Host/HostInfo.h"
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
#include "lldb/Target/Process.h"
|
|
#include "lldb/Target/Target.h"
|
|
#include "lldb/Utility/DataBufferHeap.h"
|
|
#include "lldb/Utility/FileSpec.h"
|
|
#include "lldb/Utility/Log.h"
|
|
#include "lldb/Utility/Status.h"
|
|
#include "lldb/Utility/StreamString.h"
|
|
|
|
#include <sstream>
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
LLDB_PLUGIN_DEFINE(PlatformMacOSX)
|
|
|
|
static uint32_t g_initialize_count = 0;
|
|
|
|
void PlatformMacOSX::Initialize() {
|
|
PlatformDarwin::Initialize();
|
|
PlatformRemoteiOS::Initialize();
|
|
PlatformRemoteMacOSX::Initialize();
|
|
#if defined(__APPLE__)
|
|
PlatformAppleSimulator::Initialize();
|
|
PlatformDarwinKernel::Initialize();
|
|
PlatformRemoteAppleTV::Initialize();
|
|
PlatformRemoteAppleWatch::Initialize();
|
|
PlatformRemoteAppleBridge::Initialize();
|
|
#endif
|
|
|
|
if (g_initialize_count++ == 0) {
|
|
#if defined(__APPLE__)
|
|
PlatformSP default_platform_sp(new PlatformMacOSX());
|
|
default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
|
|
Platform::SetHostPlatform(default_platform_sp);
|
|
#endif
|
|
PluginManager::RegisterPlugin(PlatformMacOSX::GetPluginNameStatic(),
|
|
PlatformMacOSX::GetDescriptionStatic(),
|
|
PlatformMacOSX::CreateInstance);
|
|
}
|
|
}
|
|
|
|
void PlatformMacOSX::Terminate() {
|
|
if (g_initialize_count > 0) {
|
|
if (--g_initialize_count == 0) {
|
|
PluginManager::UnregisterPlugin(PlatformMacOSX::CreateInstance);
|
|
}
|
|
}
|
|
|
|
#if defined(__APPLE__)
|
|
PlatformRemoteAppleBridge::Terminate();
|
|
PlatformRemoteAppleWatch::Terminate();
|
|
PlatformRemoteAppleTV::Terminate();
|
|
PlatformDarwinKernel::Terminate();
|
|
PlatformAppleSimulator::Terminate();
|
|
#endif
|
|
PlatformRemoteMacOSX::Initialize();
|
|
PlatformRemoteiOS::Terminate();
|
|
PlatformDarwin::Terminate();
|
|
}
|
|
|
|
llvm::StringRef PlatformMacOSX::GetDescriptionStatic() {
|
|
return "Local Mac OS X user platform plug-in.";
|
|
}
|
|
|
|
PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) {
|
|
// The only time we create an instance is when we are creating a remote
|
|
// macosx platform which is handled by PlatformRemoteMacOSX.
|
|
return PlatformSP();
|
|
}
|
|
|
|
/// Default Constructor
|
|
PlatformMacOSX::PlatformMacOSX() : PlatformDarwinDevice(true) {}
|
|
|
|
ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
|
|
ModuleSP exe_module_sp(target.GetExecutableModule());
|
|
if (!exe_module_sp)
|
|
return {};
|
|
|
|
ObjectFile *objfile = exe_module_sp->GetObjectFile();
|
|
if (!objfile)
|
|
return {};
|
|
|
|
llvm::VersionTuple version = objfile->GetSDKVersion();
|
|
if (version.empty())
|
|
return {};
|
|
|
|
// First try to find an SDK that matches the given SDK version.
|
|
if (FileSpec fspec = HostInfo::GetXcodeContentsDirectory()) {
|
|
StreamString sdk_path;
|
|
sdk_path.Printf("%s/Developer/Platforms/MacOSX.platform/Developer/"
|
|
"SDKs/MacOSX%u.%u.sdk",
|
|
fspec.GetPath().c_str(), version.getMajor(),
|
|
*version.getMinor());
|
|
if (FileSystem::Instance().Exists(fspec))
|
|
return ConstString(sdk_path.GetString());
|
|
}
|
|
|
|
// Use the default SDK as a fallback.
|
|
auto sdk_path_or_err = HostInfo::GetXcodeSDKPath(XcodeSDK::GetAnyMacOS());
|
|
if (!sdk_path_or_err) {
|
|
Debugger::ReportError("Error while searching for Xcode SDK: " +
|
|
toString(sdk_path_or_err.takeError()));
|
|
return {};
|
|
}
|
|
|
|
FileSpec fspec(*sdk_path_or_err);
|
|
if (fspec) {
|
|
if (FileSystem::Instance().Exists(fspec))
|
|
return ConstString(fspec.GetPath());
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::vector<ArchSpec>
|
|
PlatformMacOSX::GetSupportedArchitectures(const ArchSpec &process_host_arch) {
|
|
std::vector<ArchSpec> result;
|
|
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
|
|
// When cmdline lldb is run on iOS, watchOS, etc, it is still
|
|
// using "PlatformMacOSX".
|
|
llvm::Triple::OSType host_os = GetHostOSType();
|
|
ARMGetSupportedArchitectures(result, host_os);
|
|
|
|
if (host_os == llvm::Triple::MacOSX) {
|
|
// We can't use x86GetSupportedArchitectures() because it uses
|
|
// the system architecture for some of its return values and also
|
|
// has a 32bits variant.
|
|
result.push_back(ArchSpec("x86_64-apple-macosx"));
|
|
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);
|
|
result.push_back(ArchSpec("x86_64-apple-ios-macabi"));
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
lldb_private::Status PlatformMacOSX::GetSharedModule(
|
|
const lldb_private::ModuleSpec &module_spec, Process *process,
|
|
lldb::ModuleSP &module_sp,
|
|
const lldb_private::FileSpecList *module_search_paths_ptr,
|
|
llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {
|
|
Status error = GetSharedModuleWithLocalCache(module_spec, module_sp,
|
|
module_search_paths_ptr,
|
|
old_modules, did_create_ptr);
|
|
|
|
if (module_sp) {
|
|
if (module_spec.GetArchitecture().GetCore() ==
|
|
ArchSpec::eCore_x86_64_x86_64h) {
|
|
ObjectFile *objfile = module_sp->GetObjectFile();
|
|
if (objfile == nullptr) {
|
|
// We didn't find an x86_64h slice, fall back to a x86_64 slice
|
|
ModuleSpec module_spec_x86_64(module_spec);
|
|
module_spec_x86_64.GetArchitecture() = ArchSpec("x86_64-apple-macosx");
|
|
lldb::ModuleSP x86_64_module_sp;
|
|
llvm::SmallVector<lldb::ModuleSP, 1> old_x86_64_modules;
|
|
bool did_create = false;
|
|
Status x86_64_error = GetSharedModuleWithLocalCache(
|
|
module_spec_x86_64, x86_64_module_sp, module_search_paths_ptr,
|
|
&old_x86_64_modules, &did_create);
|
|
if (x86_64_module_sp && x86_64_module_sp->GetObjectFile()) {
|
|
module_sp = x86_64_module_sp;
|
|
if (old_modules)
|
|
old_modules->append(old_x86_64_modules.begin(),
|
|
old_x86_64_modules.end());
|
|
if (did_create_ptr)
|
|
*did_create_ptr = did_create;
|
|
return x86_64_error;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!module_sp) {
|
|
error = FindBundleBinaryInExecSearchPaths(module_spec, process, module_sp,
|
|
module_search_paths_ptr,
|
|
old_modules, did_create_ptr);
|
|
}
|
|
return error;
|
|
}
|
|
|
|
llvm::StringRef PlatformMacOSX::GetDeviceSupportDirectoryName() {
|
|
return "macOS DeviceSupport";
|
|
}
|
|
|
|
llvm::StringRef PlatformMacOSX::GetPlatformName() { return "MacOSX.platform"; }
|