Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
//===-- AdbClient.h ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_AdbClient_h_
#define liblldb_AdbClient_h_
#include "lldb/Utility/Status.h"
#include <chrono>
#include <functional>
#include <list>
#include <memory>
#include <string>
#include <vector>
namespace lldb_private {
class FileSpec;
namespace platform_android {
class AdbClient {
public:
enum UnixSocketNamespace {
UnixSocketNamespaceAbstract,
UnixSocketNamespaceFileSystem,
};
using DeviceIDList = std::list<std::string>;
class SyncService {
friend class AdbClient;
public:
~SyncService();
Status PullFile(const FileSpec &remote_file, const FileSpec &local_file);
Status PushFile(const FileSpec &local_file, const FileSpec &remote_file);
Status Stat(const FileSpec &remote_file, uint32_t &mode, uint32_t &size,
uint32_t &mtime);
bool IsConnected() const;
private:
explicit SyncService(std::unique_ptr<Connection> &&conn);
Status SendSyncRequest(const char *request_id, const uint32_t data_len,
const void *data);
Status ReadSyncHeader(std::string &response_id, uint32_t &data_len);
Status PullFileChunk(std::vector<char> &buffer, bool &eof);
Status ReadAllBytes(void *buffer, size_t size);
Status internalPullFile(const FileSpec &remote_file,
const FileSpec &local_file);
Status internalPushFile(const FileSpec &local_file,
const FileSpec &remote_file);
Status internalStat(const FileSpec &remote_file, uint32_t &mode,
uint32_t &size, uint32_t &mtime);
Status executeCommand(const std::function<Status()> &cmd);
std::unique_ptr<Connection> m_conn;
};
static Status CreateByDeviceID(const std::string &device_id, AdbClient &adb);
AdbClient();
explicit AdbClient(const std::string &device_id);
~AdbClient();
const std::string &GetDeviceID() const;
Status GetDevices(DeviceIDList &device_list);
Status SetPortForwarding(const uint16_t local_port,
const uint16_t remote_port);
Status SetPortForwarding(const uint16_t local_port,
llvm::StringRef remote_socket_name,
const UnixSocketNamespace socket_namespace);
Status DeletePortForwarding(const uint16_t local_port);
Status Shell(const char *command, std::chrono::milliseconds timeout,
std::string *output);
Status ShellToFile(const char *command, std::chrono::milliseconds timeout,
const FileSpec &output_file_spec);
std::unique_ptr<SyncService> GetSyncService(Status &error);
Status SwitchDeviceTransport();
private:
Status Connect();
void SetDeviceID(const std::string &device_id);
Status SendMessage(const std::string &packet, const bool reconnect = true);
Status SendDeviceMessage(const std::string &packet);
Status ReadMessage(std::vector<char> &message);
Status ReadMessageStream(std::vector<char> &message,
std::chrono::milliseconds timeout);
Status GetResponseError(const char *response_id);
Status ReadResponseStatus();
Status Sync();
Status StartSync();
Status internalShell(const char *command, std::chrono::milliseconds timeout,
std::vector<char> &output_buf);
Status ReadAllBytes(void *buffer, size_t size);
std::string m_device_id;
std::unique_ptr<Connection> m_conn;
};
} // namespace platform_android
} // namespace lldb_private
#endif // liblldb_AdbClient_h_

View File

@@ -0,0 +1,13 @@
add_lldb_library(lldbPluginPlatformAndroid PLUGIN
AdbClient.cpp
PlatformAndroid.cpp
PlatformAndroidRemoteGDBServer.cpp
LINK_LIBS
lldbCore
lldbHost
lldbPluginPlatformLinux
lldbPluginPlatformGDB
LINK_COMPONENTS
Support
)

View File

@@ -0,0 +1,403 @@
//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/UriParser.h"
// Project includes
#include "AdbClient.h"
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_android;
using namespace std::chrono;
static uint32_t g_initialize_count = 0;
static const unsigned int g_android_default_cache_size =
2048; // Fits inside 4k adb packet.
void PlatformAndroid::Initialize() {
PlatformLinux::Initialize();
if (g_initialize_count++ == 0) {
#if defined(__ANDROID__)
PlatformSP default_platform_sp(new PlatformAndroid(true));
default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
Platform::SetHostPlatform(default_platform_sp);
#endif
PluginManager::RegisterPlugin(
PlatformAndroid::GetPluginNameStatic(false),
PlatformAndroid::GetPluginDescriptionStatic(false),
PlatformAndroid::CreateInstance);
}
}
void PlatformAndroid::Terminate() {
if (g_initialize_count > 0) {
if (--g_initialize_count == 0) {
PluginManager::UnregisterPlugin(PlatformAndroid::CreateInstance);
}
}
PlatformLinux::Terminate();
}
PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log) {
const char *arch_name;
if (arch && arch->GetArchitectureName())
arch_name = arch->GetArchitectureName();
else
arch_name = "<null>";
const char *triple_cstr =
arch ? arch->GetTriple().getTriple().c_str() : "<null>";
log->Printf("PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__,
force ? "true" : "false", arch_name, triple_cstr);
}
bool create = force;
if (create == false && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor()) {
case llvm::Triple::PC:
create = true;
break;
#if defined(__ANDROID__)
// Only accept "unknown" for the vendor if the host is android and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified_
case llvm::Triple::VendorType::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
#endif
default:
break;
}
if (create) {
switch (triple.getOS()) {
case llvm::Triple::Android:
break;
#if defined(__ANDROID__)
// Only accept "unknown" for the OS if the host is android and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
#endif
default:
create = false;
break;
}
}
}
if (create) {
if (log)
log->Printf("PlatformAndroid::%s() creating remote-android platform",
__FUNCTION__);
return PlatformSP(new PlatformAndroid(false));
}
if (log)
log->Printf(
"PlatformAndroid::%s() aborting creation of remote-android platform",
__FUNCTION__);
return PlatformSP();
}
PlatformAndroid::PlatformAndroid(bool is_host)
: PlatformLinux(is_host), m_sdk_version(0) {}
PlatformAndroid::~PlatformAndroid() {}
ConstString PlatformAndroid::GetPluginNameStatic(bool is_host) {
if (is_host) {
static ConstString g_host_name(Platform::GetHostPlatformName());
return g_host_name;
} else {
static ConstString g_remote_name("remote-android");
return g_remote_name;
}
}
const char *PlatformAndroid::GetPluginDescriptionStatic(bool is_host) {
if (is_host)
return "Local Android user platform plug-in.";
else
return "Remote Android user platform plug-in.";
}
ConstString PlatformAndroid::GetPluginName() {
return GetPluginNameStatic(IsHost());
}
Status PlatformAndroid::ConnectRemote(Args &args) {
m_device_id.clear();
if (IsHost()) {
return Status("can't connect to the host platform '%s', always connected",
GetPluginName().GetCString());
}
if (!m_remote_platform_sp)
m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());
int port;
llvm::StringRef scheme, host, path;
const char *url = args.GetArgumentAtIndex(0);
if (!url)
return Status("URL is null.");
if (!UriParser::Parse(url, scheme, host, port, path))
return Status("Invalid URL: %s", url);
if (host != "localhost")
m_device_id = host;
auto error = PlatformLinux::ConnectRemote(args);
if (error.Success()) {
AdbClient adb;
error = AdbClient::CreateByDeviceID(m_device_id, adb);
if (error.Fail())
return error;
m_device_id = adb.GetDeviceID();
}
return error;
}
Status PlatformAndroid::GetFile(const FileSpec &source,
const FileSpec &destination) {
if (IsHost() || !m_remote_platform_sp)
return PlatformLinux::GetFile(source, destination);
FileSpec source_spec(source.GetPath(false), false,
FileSpec::ePathSyntaxPosix);
if (source_spec.IsRelative())
source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
source_spec.GetCString(false));
Status error;
auto sync_service = GetSyncService(error);
if (error.Fail())
return error;
uint32_t mode = 0, size = 0, mtime = 0;
error = sync_service->Stat(source_spec, mode, size, mtime);
if (error.Fail())
return error;
if (mode != 0)
return sync_service->PullFile(source_spec, destination);
auto source_file = source_spec.GetCString(false);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'",
source_file);
if (strchr(source_file, '\'') != nullptr)
return Status("Doesn't support single-quotes in filenames");
// mode == 0 can signify that adbd cannot access the file
// due security constraints - try "cat ..." as a fallback.
AdbClient adb(m_device_id);
char cmd[PATH_MAX];
snprintf(cmd, sizeof(cmd), "cat '%s'", source_file);
return adb.ShellToFile(cmd, minutes(1), destination);
}
Status PlatformAndroid::PutFile(const FileSpec &source,
const FileSpec &destination, uint32_t uid,
uint32_t gid) {
if (IsHost() || !m_remote_platform_sp)
return PlatformLinux::PutFile(source, destination, uid, gid);
FileSpec destination_spec(destination.GetPath(false), false,
FileSpec::ePathSyntaxPosix);
if (destination_spec.IsRelative())
destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
destination_spec.GetCString(false));
// TODO: Set correct uid and gid on remote file.
Status error;
auto sync_service = GetSyncService(error);
if (error.Fail())
return error;
return sync_service->PushFile(source, destination_spec);
}
const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); }
Status PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec,
const uint64_t src_offset,
const uint64_t src_size,
const FileSpec &dst_file_spec) {
if (src_offset != 0)
return Status("Invalid offset - %" PRIu64, src_offset);
return GetFile(src_file_spec, dst_file_spec);
}
Status PlatformAndroid::DisconnectRemote() {
Status error = PlatformLinux::DisconnectRemote();
if (error.Success()) {
m_device_id.clear();
m_sdk_version = 0;
}
return error;
}
uint32_t PlatformAndroid::GetDefaultMemoryCacheLineSize() {
return g_android_default_cache_size;
}
uint32_t PlatformAndroid::GetSdkVersion() {
if (!IsConnected())
return 0;
if (m_sdk_version != 0)
return m_sdk_version;
std::string version_string;
AdbClient adb(m_device_id);
Status error =
adb.Shell("getprop ro.build.version.sdk", seconds(5), &version_string);
version_string = llvm::StringRef(version_string).trim().str();
if (error.Fail() || version_string.empty()) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM);
if (log)
log->Printf("Get SDK version failed. (error: %s, output: %s)",
error.AsCString(), version_string.c_str());
return 0;
}
m_sdk_version = StringConvert::ToUInt32(version_string.c_str());
return m_sdk_version;
}
Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
const FileSpec &dst_file_spec) {
// For oat file we can try to fetch additional debug info from the device
ConstString extension = module_sp->GetFileSpec().GetFileNameExtension();
if (extension != ConstString("oat") && extension != ConstString("odex"))
return Status(
"Symbol file downloading only supported for oat and odex files");
// If we have no information about the platform file we can't execute oatdump
if (!module_sp->GetPlatformFileSpec())
return Status("No platform file specified");
// Symbolizer isn't available before SDK version 23
if (GetSdkVersion() < 23)
return Status("Symbol file generation only supported on SDK 23+");
// If we already have symtab then we don't have to try and generate one
if (module_sp->GetSectionList()->FindSectionByName(ConstString(".symtab")) !=
nullptr)
return Status("Symtab already available in the module");
AdbClient adb(m_device_id);
std::string tmpdir;
Status error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp",
seconds(5), &tmpdir);
if (error.Fail() || tmpdir.empty())
return Status("Failed to generate temporary directory on the device (%s)",
error.AsCString());
tmpdir = llvm::StringRef(tmpdir).trim().str();
// Create file remover for the temporary directory created on the device
std::unique_ptr<std::string, std::function<void(std::string *)>>
tmpdir_remover(&tmpdir, [&adb](std::string *s) {
StreamString command;
command.Printf("rm -rf %s", s->c_str());
Status error = adb.Shell(command.GetData(), seconds(5), nullptr);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log && error.Fail())
log->Printf("Failed to remove temp directory: %s", error.AsCString());
});
FileSpec symfile_platform_filespec(tmpdir, false);
symfile_platform_filespec.AppendPathComponent("symbolized.oat");
// Execute oatdump on the remote device to generate a file with symtab
StreamString command;
command.Printf("oatdump --symbolize=%s --output=%s",
module_sp->GetPlatformFileSpec().GetCString(false),
symfile_platform_filespec.GetCString(false));
error = adb.Shell(command.GetData(), minutes(1), nullptr);
if (error.Fail())
return Status("Oatdump failed: %s", error.AsCString());
// Download the symbolfile from the remote device
return GetFile(symfile_platform_filespec, dst_file_spec);
}
bool PlatformAndroid::GetRemoteOSVersion() {
m_major_os_version = GetSdkVersion();
m_minor_os_version = 0;
m_update_os_version = 0;
return m_major_os_version != 0;
}
llvm::StringRef
PlatformAndroid::GetLibdlFunctionDeclarations(lldb_private::Process *process) {
SymbolContextList matching_symbols;
std::vector<const char *> dl_open_names = { "__dl_dlopen", "dlopen" };
const char *dl_open_name = nullptr;
Target &target = process->GetTarget();
for (auto name: dl_open_names) {
if (target.GetImages().FindFunctionSymbols(ConstString(name),
eFunctionNameTypeFull,
matching_symbols)) {
dl_open_name = name;
break;
}
}
// Older platform versions have the dl function symbols mangled
if (dl_open_name == dl_open_names[0])
return R"(
extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
extern "C" int dlclose(void*) asm("__dl_dlclose");
extern "C" char* dlerror(void) asm("__dl_dlerror");
)";
return PlatformPOSIX::GetLibdlFunctionDeclarations(process);
}
AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) {
if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
return m_adb_sync_svc.get();
AdbClient adb(m_device_id);
m_adb_sync_svc = adb.GetSyncService(error);
return (error.Success()) ? m_adb_sync_svc.get() : nullptr;
}

View File

@@ -0,0 +1,95 @@
//===-- PlatformAndroid.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformAndroid_h_
#define liblldb_PlatformAndroid_h_
// C Includes
// C++ Includes
#include <memory>
#include <string>
// Other libraries and framework includes
// Project includes
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "AdbClient.h"
namespace lldb_private {
namespace platform_android {
class PlatformAndroid : public platform_linux::PlatformLinux {
public:
PlatformAndroid(bool is_host);
~PlatformAndroid() override;
static void Initialize();
static void Terminate();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch);
static ConstString GetPluginNameStatic(bool is_host);
static const char *GetPluginDescriptionStatic(bool is_host);
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override { return 1; }
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
Status ConnectRemote(Args &args) override;
Status GetFile(const FileSpec &source, const FileSpec &destination) override;
Status PutFile(const FileSpec &source, const FileSpec &destination,
uint32_t uid = UINT32_MAX, uint32_t gid = UINT32_MAX) override;
uint32_t GetSdkVersion();
bool GetRemoteOSVersion() override;
Status DisconnectRemote() override;
uint32_t GetDefaultMemoryCacheLineSize() override;
protected:
const char *GetCacheHostname() override;
Status DownloadModuleSlice(const FileSpec &src_file_spec,
const uint64_t src_offset, const uint64_t src_size,
const FileSpec &dst_file_spec) override;
Status DownloadSymbolFile(const lldb::ModuleSP &module_sp,
const FileSpec &dst_file_spec) override;
llvm::StringRef
GetLibdlFunctionDeclarations(lldb_private::Process *process) override;
private:
AdbClient::SyncService *GetSyncService(Status &error);
std::unique_ptr<AdbClient::SyncService> m_adb_sync_svc;
std::string m_device_id;
uint32_t m_sdk_version;
DISALLOW_COPY_AND_ASSIGN(PlatformAndroid);
};
} // namespace platofor_android
} // namespace lldb_private
#endif // liblldb_PlatformAndroid_h_

View File

@@ -0,0 +1,234 @@
//===-- PlatformAndroidRemoteGDBServer.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Other libraries and framework includes
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/common/TCPSocket.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/UriParser.h"
#include "PlatformAndroidRemoteGDBServer.h"
#include <sstream>
using namespace lldb;
using namespace lldb_private;
using namespace platform_android;
static const lldb::pid_t g_remote_platform_pid =
0; // Alias for the process id of lldb-platform
static Status ForwardPortWithAdb(
const uint16_t local_port, const uint16_t remote_port,
llvm::StringRef remote_socket_name,
const llvm::Optional<AdbClient::UnixSocketNamespace> &socket_namespace,
std::string &device_id) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
AdbClient adb;
auto error = AdbClient::CreateByDeviceID(device_id, adb);
if (error.Fail())
return error;
device_id = adb.GetDeviceID();
if (log)
log->Printf("Connected to Android device \"%s\"", device_id.c_str());
if (remote_port != 0) {
if (log)
log->Printf("Forwarding remote TCP port %d to local TCP port %d",
remote_port, local_port);
return adb.SetPortForwarding(local_port, remote_port);
}
if (log)
log->Printf("Forwarding remote socket \"%s\" to local TCP port %d",
remote_socket_name.str().c_str(), local_port);
if (!socket_namespace)
return Status("Invalid socket namespace");
return adb.SetPortForwarding(local_port, remote_socket_name,
*socket_namespace);
}
static Status DeleteForwardPortWithAdb(uint16_t local_port,
const std::string &device_id) {
AdbClient adb(device_id);
return adb.DeletePortForwarding(local_port);
}
static Status FindUnusedPort(uint16_t &port) {
Status error;
std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(true, false));
if (error.Fail())
return error;
error = tcp_socket->Listen("127.0.0.1:0", 1);
if (error.Success())
port = tcp_socket->GetLocalPortNumber();
return error;
}
PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer() {}
PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer() {
for (const auto &it : m_port_forwards)
DeleteForwardPortWithAdb(it.second, m_device_id);
}
bool PlatformAndroidRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid,
std::string &connect_url) {
uint16_t remote_port = 0;
std::string socket_name;
if (!m_gdb_client.LaunchGDBServer("127.0.0.1", pid, remote_port, socket_name))
return false;
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
auto error =
MakeConnectURL(pid, remote_port, socket_name.c_str(), connect_url);
if (error.Success() && log)
log->Printf("gdbserver connect URL: %s", connect_url.c_str());
return error.Success();
}
bool PlatformAndroidRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) {
DeleteForwardPort(pid);
return m_gdb_client.KillSpawnedProcess(pid);
}
Status PlatformAndroidRemoteGDBServer::ConnectRemote(Args &args) {
m_device_id.clear();
if (args.GetArgumentCount() != 1)
return Status(
"\"platform connect\" takes a single argument: <connect-url>");
int remote_port;
llvm::StringRef scheme, host, path;
const char *url = args.GetArgumentAtIndex(0);
if (!url)
return Status("URL is null.");
if (!UriParser::Parse(url, scheme, host, remote_port, path))
return Status("Invalid URL: %s", url);
if (host != "localhost")
m_device_id = host;
m_socket_namespace.reset();
if (scheme == ConnectionFileDescriptor::UNIX_CONNECT_SCHEME)
m_socket_namespace = AdbClient::UnixSocketNamespaceFileSystem;
else if (scheme == ConnectionFileDescriptor::UNIX_ABSTRACT_CONNECT_SCHEME)
m_socket_namespace = AdbClient::UnixSocketNamespaceAbstract;
std::string connect_url;
auto error =
MakeConnectURL(g_remote_platform_pid, (remote_port < 0) ? 0 : remote_port,
path, connect_url);
if (error.Fail())
return error;
args.ReplaceArgumentAtIndex(0, connect_url);
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("Rewritten platform connect URL: %s", connect_url.c_str());
error = PlatformRemoteGDBServer::ConnectRemote(args);
if (error.Fail())
DeleteForwardPort(g_remote_platform_pid);
return error;
}
Status PlatformAndroidRemoteGDBServer::DisconnectRemote() {
DeleteForwardPort(g_remote_platform_pid);
return PlatformRemoteGDBServer::DisconnectRemote();
}
void PlatformAndroidRemoteGDBServer::DeleteForwardPort(lldb::pid_t pid) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
auto it = m_port_forwards.find(pid);
if (it == m_port_forwards.end())
return;
const auto port = it->second;
const auto error = DeleteForwardPortWithAdb(port, m_device_id);
if (error.Fail()) {
if (log)
log->Printf("Failed to delete port forwarding (pid=%" PRIu64
", port=%d, device=%s): %s",
pid, port, m_device_id.c_str(), error.AsCString());
}
m_port_forwards.erase(it);
}
Status PlatformAndroidRemoteGDBServer::MakeConnectURL(
const lldb::pid_t pid, const uint16_t remote_port,
llvm::StringRef remote_socket_name, std::string &connect_url) {
static const int kAttempsNum = 5;
Status error;
// There is a race possibility that somebody will occupy
// a port while we're in between FindUnusedPort and ForwardPortWithAdb -
// adding the loop to mitigate such problem.
for (auto i = 0; i < kAttempsNum; ++i) {
uint16_t local_port = 0;
error = FindUnusedPort(local_port);
if (error.Fail())
return error;
error = ForwardPortWithAdb(local_port, remote_port, remote_socket_name,
m_socket_namespace, m_device_id);
if (error.Success()) {
m_port_forwards[pid] = local_port;
std::ostringstream url_str;
url_str << "connect://localhost:" << local_port;
connect_url = url_str.str();
break;
}
}
return error;
}
lldb::ProcessSP PlatformAndroidRemoteGDBServer::ConnectProcess(
llvm::StringRef connect_url, llvm::StringRef plugin_name,
lldb_private::Debugger &debugger, lldb_private::Target *target,
lldb_private::Status &error) {
// We don't have the pid of the remote gdbserver when it isn't started by us
// but we still want
// to store the list of port forwards we set up in our port forward map.
// Generate a fake pid for
// these cases what won't collide with any other valid pid on android.
static lldb::pid_t s_remote_gdbserver_fake_pid = 0xffffffffffffffffULL;
int remote_port;
llvm::StringRef scheme, host, path;
if (!UriParser::Parse(connect_url, scheme, host, remote_port, path)) {
error.SetErrorStringWithFormat("Invalid URL: %s",
connect_url.str().c_str());
return nullptr;
}
std::string new_connect_url;
error = MakeConnectURL(s_remote_gdbserver_fake_pid--,
(remote_port < 0) ? 0 : remote_port, path,
new_connect_url);
if (error.Fail())
return nullptr;
return PlatformRemoteGDBServer::ConnectProcess(new_connect_url, plugin_name,
debugger, target, error);
}

View File

@@ -0,0 +1,68 @@
//===-- PlatformAndroidRemoteGDBServer.h ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformAndroidRemoteGDBServer_h_
#define liblldb_PlatformAndroidRemoteGDBServer_h_
// C Includes
// C++ Includes
#include <map>
#include <utility>
// Other libraries and framework includes
// Project includes
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
#include "llvm/ADT/Optional.h"
#include "AdbClient.h"
namespace lldb_private {
namespace platform_android {
class PlatformAndroidRemoteGDBServer
: public platform_gdb_server::PlatformRemoteGDBServer {
public:
PlatformAndroidRemoteGDBServer();
~PlatformAndroidRemoteGDBServer() override;
Status ConnectRemote(Args &args) override;
Status DisconnectRemote() override;
lldb::ProcessSP ConnectProcess(llvm::StringRef connect_url,
llvm::StringRef plugin_name,
lldb_private::Debugger &debugger,
lldb_private::Target *target,
lldb_private::Status &error) override;
protected:
std::string m_device_id;
std::map<lldb::pid_t, uint16_t> m_port_forwards;
llvm::Optional<AdbClient::UnixSocketNamespace> m_socket_namespace;
bool LaunchGDBServer(lldb::pid_t &pid, std::string &connect_url) override;
bool KillSpawnedProcess(lldb::pid_t pid) override;
void DeleteForwardPort(lldb::pid_t pid);
Status MakeConnectURL(const lldb::pid_t pid, const uint16_t remote_port,
llvm::StringRef remote_socket_name,
std::string &connect_url);
private:
DISALLOW_COPY_AND_ASSIGN(PlatformAndroidRemoteGDBServer);
};
} // namespace platform_android
} // namespace lldb_private
#endif // liblldb_PlatformAndroidRemoteGDBServer_h_

View File

@@ -0,0 +1,18 @@
#if (CMAKE_SYSTEM_NAME MATCHES "Linux")
add_subdirectory(Linux)
#elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
add_subdirectory(FreeBSD)
#elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
add_subdirectory(NetBSD)
#elseif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
add_subdirectory(OpenBSD)
#elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX)
#elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
add_subdirectory(Windows)
#endif()
add_subdirectory(POSIX)
add_subdirectory(gdb-server)
add_subdirectory(Kalimba)
add_subdirectory(Android)

View File

@@ -0,0 +1,9 @@
add_lldb_library(lldbPluginPlatformFreeBSD PLUGIN
PlatformFreeBSD.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbHost
lldbTarget
)

View File

@@ -0,0 +1,332 @@
//===-- PlatformFreeBSD.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PlatformFreeBSD.h"
#include "lldb/Host/Config.h"
// C Includes
#include <stdio.h>
#ifndef LLDB_DISABLE_POSIX
#include <sys/utsname.h>
#endif
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
// Define these constants from FreeBSD mman.h for use when targeting
// remote FreeBSD systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_freebsd;
static uint32_t g_initialize_count = 0;
//------------------------------------------------------------------
PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
arch ? arch->GetArchitectureName() : "<null>",
arch ? arch->GetTriple().getTriple() : "<null>");
bool create = force;
if (create == false && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getOS()) {
case llvm::Triple::FreeBSD:
create = true;
break;
#if defined(__FreeBSD__)
// Only accept "unknown" for the OS if the host is BSD and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
#endif
default:
break;
}
}
LLDB_LOG(log, "create = {0}", create);
if (create) {
return PlatformSP(new PlatformFreeBSD(false));
}
return PlatformSP();
}
ConstString PlatformFreeBSD::GetPluginNameStatic(bool is_host) {
if (is_host) {
static ConstString g_host_name(Platform::GetHostPlatformName());
return g_host_name;
} else {
static ConstString g_remote_name("remote-freebsd");
return g_remote_name;
}
}
const char *PlatformFreeBSD::GetPluginDescriptionStatic(bool is_host) {
if (is_host)
return "Local FreeBSD user platform plug-in.";
else
return "Remote FreeBSD user platform plug-in.";
}
ConstString PlatformFreeBSD::GetPluginName() {
return GetPluginNameStatic(IsHost());
}
void PlatformFreeBSD::Initialize() {
Platform::Initialize();
if (g_initialize_count++ == 0) {
#if defined(__FreeBSD__)
PlatformSP default_platform_sp(new PlatformFreeBSD(true));
default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
Platform::SetHostPlatform(default_platform_sp);
#endif
PluginManager::RegisterPlugin(
PlatformFreeBSD::GetPluginNameStatic(false),
PlatformFreeBSD::GetPluginDescriptionStatic(false),
PlatformFreeBSD::CreateInstance, nullptr);
}
}
void PlatformFreeBSD::Terminate() {
if (g_initialize_count > 0) {
if (--g_initialize_count == 0) {
PluginManager::UnregisterPlugin(PlatformFreeBSD::CreateInstance);
}
}
PlatformPOSIX::Terminate();
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformFreeBSD::PlatformFreeBSD(bool is_host)
: PlatformPOSIX(is_host) // This is the local host platform
{}
PlatformFreeBSD::~PlatformFreeBSD() = default;
bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
if (IsHost()) {
ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
if (hostArch.GetTriple().isOSFreeBSD()) {
if (idx == 0) {
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
// If the default host architecture is 64-bit, look for a 32-bit variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
}
}
}
} else {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
llvm::Triple triple;
// Set the OS to FreeBSD
triple.setOS(llvm::Triple::FreeBSD);
// Set the architecture
switch (idx) {
case 0:
triple.setArchName("x86_64");
break;
case 1:
triple.setArchName("i386");
break;
case 2:
triple.setArchName("aarch64");
break;
case 3:
triple.setArchName("arm");
break;
case 4:
triple.setArchName("mips64");
break;
case 5:
triple.setArchName("mips");
break;
case 6:
triple.setArchName("ppc64");
break;
case 7:
triple.setArchName("ppc");
break;
default:
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
// vendor by
// calling triple.SetVendorName("unknown") so that it is a "unspecified
// unknown".
// This means when someone calls triple.GetVendorName() it will return an
// empty string
// which indicates that the vendor can be set when two architectures are
// merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
return true;
}
return false;
}
void PlatformFreeBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
#ifndef LLDB_DISABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-FreeBSD information (when running
// on Mac OS for example).
if (IsHost()) {
struct utsname un;
if (uname(&un))
return;
strm.Printf(" Kernel: %s\n", un.sysname);
strm.Printf(" Release: %s\n", un.release);
strm.Printf(" Version: %s\n", un.version);
}
#endif
}
size_t
PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode(Target &target,
BreakpointSite *bp_site) {
switch (target.GetArchitecture().GetMachine()) {
case llvm::Triple::arm: {
lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
AddressClass addr_class = eAddressClassUnknown;
if (bp_loc_sp) {
addr_class = bp_loc_sp->GetAddress().GetAddressClass();
if (addr_class == eAddressClassUnknown &&
(bp_loc_sp->GetAddress().GetFileAddress() & 1))
addr_class = eAddressClassCodeAlternateISA;
}
if (addr_class == eAddressClassCodeAlternateISA) {
// TODO: Enable when FreeBSD supports thumb breakpoints.
// FreeBSD kernel as of 10.x, does not support thumb breakpoints
return 0;
}
static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7};
size_t trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
assert(bp_site);
if (bp_site->SetTrapOpcode(g_arm_breakpoint_opcode, trap_opcode_size))
return trap_opcode_size;
}
LLVM_FALLTHROUGH;
default:
return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
}
}
Status PlatformFreeBSD::LaunchProcess(ProcessLaunchInfo &launch_info) {
Status error;
if (IsHost()) {
error = Platform::LaunchProcess(launch_info);
} else {
if (m_remote_platform_sp)
error = m_remote_platform_sp->LaunchProcess(launch_info);
else
error.SetErrorString("the platform is not currently connected");
}
return error;
}
lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
Debugger &debugger, Target *target,
Status &error) {
lldb::ProcessSP process_sp;
if (IsHost()) {
if (target == NULL) {
TargetSP new_target_sp;
ArchSpec emptyArchSpec;
error = debugger.GetTargetList().CreateTarget(debugger, "", emptyArchSpec,
false, m_remote_platform_sp,
new_target_sp);
target = new_target_sp.get();
} else
error.Clear();
if (target && error.Success()) {
debugger.GetTargetList().SetSelectedTarget(target);
// The freebsd always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
// Just like the darwin plugin.
process_sp = target->CreateProcess(
attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
if (process_sp)
error = process_sp->Attach(attach_info);
}
} else {
if (m_remote_platform_sp)
process_sp =
m_remote_platform_sp->Attach(attach_info, debugger, target, error);
else
error.SetErrorString("the platform is not currently connected");
}
return process_sp;
}
// FreeBSD processes cannot yet be launched by spawning and attaching.
bool PlatformFreeBSD::CanDebugProcess() {
return false;
}
void PlatformFreeBSD::CalculateTrapHandlerSymbolNames() {
m_trap_handlers.push_back(ConstString("_sigtramp"));
}
MmapArgList PlatformFreeBSD::GetMmapArgumentList(const ArchSpec &arch,
addr_t addr, addr_t length,
unsigned prot, unsigned flags,
addr_t fd, addr_t offset) {
uint64_t flags_platform = 0;
if (flags & eMmapFlagsPrivate)
flags_platform |= MAP_PRIVATE;
if (flags & eMmapFlagsAnon)
flags_platform |= MAP_ANON;
MmapArgList args({addr, length, prot, flags_platform, fd, offset});
if (arch.GetTriple().getArch() == llvm::Triple::x86)
args.push_back(0);
return args;
}

View File

@@ -0,0 +1,76 @@
//===-- PlatformFreeBSD.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformFreeBSD_h_
#define liblldb_PlatformFreeBSD_h_
#include "Plugins/Platform/POSIX/PlatformPOSIX.h"
namespace lldb_private {
namespace platform_freebsd {
class PlatformFreeBSD : public PlatformPOSIX {
public:
PlatformFreeBSD(bool is_host);
~PlatformFreeBSD() override;
static void Initialize();
static void Terminate();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch);
static ConstString GetPluginNameStatic(bool is_host);
static const char *GetPluginDescriptionStatic(bool is_host);
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override { return 1; }
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
const char *GetDescription() override {
return GetPluginDescriptionStatic(IsHost());
}
void GetStatus(Stream &strm) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
bool CanDebugProcess() override;
size_t GetSoftwareBreakpointTrapOpcode(Target &target,
BreakpointSite *bp_site) override;
Status LaunchProcess(ProcessLaunchInfo &launch_info) override;
lldb::ProcessSP Attach(ProcessAttachInfo &attach_info, Debugger &debugger,
Target *target, Status &error) override;
void CalculateTrapHandlerSymbolNames() override;
MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr,
lldb::addr_t length, unsigned prot,
unsigned flags, lldb::addr_t fd,
lldb::addr_t offset) override;
private:
DISALLOW_COPY_AND_ASSIGN(PlatformFreeBSD);
};
} // namespace platform_freebsd
} // namespace lldb_private
#endif // liblldb_PlatformFreeBSD_h_

View File

@@ -0,0 +1,8 @@
add_lldb_library(lldbPluginPlatformKalimba PLUGIN
PlatformKalimba.cpp
LINK_LIBS
lldbCore
lldbHost
lldbTarget
)

View File

@@ -0,0 +1,157 @@
//===-- PlatformKalimba.cpp ---------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PlatformKalimba.h"
#include "lldb/Host/Config.h"
// C++ Includes
// Other libraries and framework includes
// Project includes
#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/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
using namespace lldb;
using namespace lldb_private;
static uint32_t g_initialize_count = 0;
PlatformSP PlatformKalimba::CreateInstance(bool force, const ArchSpec *arch) {
bool create = force;
if (create == false && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor()) {
case llvm::Triple::CSR:
create = true;
break;
default:
break;
}
}
if (create)
return PlatformSP(new PlatformKalimba(false));
return PlatformSP();
}
lldb_private::ConstString
PlatformKalimba::GetPluginNameStatic(bool /*is_host*/) {
static ConstString g_remote_name("kalimba");
return g_remote_name;
}
const char *PlatformKalimba::GetPluginDescriptionStatic(bool /*is_host*/) {
return "Kalimba user platform plug-in.";
}
lldb_private::ConstString PlatformKalimba::GetPluginName() {
return GetPluginNameStatic(false);
}
void PlatformKalimba::Initialize() {
Platform::Initialize();
if (g_initialize_count++ == 0) {
PluginManager::RegisterPlugin(
PlatformKalimba::GetPluginNameStatic(false),
PlatformKalimba::GetPluginDescriptionStatic(false),
PlatformKalimba::CreateInstance);
}
}
void PlatformKalimba::Terminate() {
if (g_initialize_count > 0) {
if (--g_initialize_count == 0) {
PluginManager::UnregisterPlugin(PlatformKalimba::CreateInstance);
}
}
Platform::Terminate();
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformKalimba::PlatformKalimba(bool is_host)
: Platform(is_host), // This is the local host platform
m_remote_platform_sp() {}
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformKalimba::~PlatformKalimba() {}
bool PlatformKalimba::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
if (idx == 0) {
arch = ArchSpec("kalimba3-csr-unknown");
return true;
}
if (idx == 1) {
arch = ArchSpec("kalimba4-csr-unknown");
return true;
}
if (idx == 2) {
arch = ArchSpec("kalimba5-csr-unknown");
return true;
}
return false;
}
void PlatformKalimba::GetStatus(Stream &strm) { Platform::GetStatus(strm); }
size_t
PlatformKalimba::GetSoftwareBreakpointTrapOpcode(Target & /*target*/,
BreakpointSite * /*bp_site*/) {
// the target hardware does not support software breakpoints
return 0;
}
Status PlatformKalimba::LaunchProcess(ProcessLaunchInfo &launch_info) {
Status error;
if (IsHost()) {
error.SetErrorString("native execution is not possible");
} else {
error.SetErrorString("the platform is not currently connected");
}
return error;
}
lldb::ProcessSP PlatformKalimba::Attach(ProcessAttachInfo &attach_info,
Debugger &debugger, Target *target,
Status &error) {
lldb::ProcessSP process_sp;
if (IsHost()) {
error.SetErrorString("native execution is not possible");
} else {
if (m_remote_platform_sp)
process_sp =
m_remote_platform_sp->Attach(attach_info, debugger, target, error);
else
error.SetErrorString("the platform is not currently connected");
}
return process_sp;
}
void PlatformKalimba::CalculateTrapHandlerSymbolNames() {
// TODO Research this sometime.
}

View File

@@ -0,0 +1,79 @@
//===-- PlatformKalimba.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformKalimba_h_
#define liblldb_PlatformKalimba_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Target/Platform.h"
namespace lldb_private {
class PlatformKalimba : public Platform {
public:
PlatformKalimba(bool is_host);
~PlatformKalimba() override;
static void Initialize();
static void Terminate();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
static lldb::PlatformSP CreateInstance(bool force,
const lldb_private::ArchSpec *arch);
static lldb_private::ConstString GetPluginNameStatic(bool is_host);
static const char *GetPluginDescriptionStatic(bool is_host);
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override { return 1; }
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
const char *GetDescription() override {
return GetPluginDescriptionStatic(IsHost());
}
void GetStatus(Stream &strm) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
size_t GetSoftwareBreakpointTrapOpcode(Target &target,
BreakpointSite *bp_site) override;
lldb_private::Status
LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override;
lldb::ProcessSP Attach(ProcessAttachInfo &attach_info, Debugger &debugger,
Target *target, Status &error) override;
// Kalimba processes can not be launched by spawning and attaching.
bool CanDebugProcess() override { return false; }
void CalculateTrapHandlerSymbolNames() override;
protected:
lldb::PlatformSP m_remote_platform_sp;
private:
DISALLOW_COPY_AND_ASSIGN(PlatformKalimba);
};
} // namespace lldb_private
#endif // liblldb_PlatformKalimba_h_

View File

@@ -0,0 +1,11 @@
add_lldb_library(lldbPluginPlatformLinux PLUGIN
PlatformLinux.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbHost
lldbInterpreter
lldbTarget
lldbPluginPlatformPOSIX
)

View File

@@ -0,0 +1,415 @@
//===-- PlatformLinux.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PlatformLinux.h"
#include "lldb/Host/Config.h"
// C Includes
#include <stdio.h>
#ifndef LLDB_DISABLE_POSIX
#include <sys/utsname.h>
#endif
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
// Define these constants from Linux mman.h for use when targeting
// remote linux systems even when host has different values.
#define MAP_PRIVATE 2
#define MAP_ANON 0x20
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_linux;
static uint32_t g_initialize_count = 0;
//------------------------------------------------------------------
PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
arch ? arch->GetArchitectureName() : "<null>",
arch ? arch->GetTriple().getTriple() : "<null>");
bool create = force;
if (create == false && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getOS()) {
case llvm::Triple::Linux:
create = true;
break;
#if defined(__linux__)
// Only accept "unknown" for the OS if the host is linux and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
#endif
default:
break;
}
}
LLDB_LOG(log, "create = {0}", create);
if (create) {
return PlatformSP(new PlatformLinux(false));
}
return PlatformSP();
}
ConstString PlatformLinux::GetPluginNameStatic(bool is_host) {
if (is_host) {
static ConstString g_host_name(Platform::GetHostPlatformName());
return g_host_name;
} else {
static ConstString g_remote_name("remote-linux");
return g_remote_name;
}
}
const char *PlatformLinux::GetPluginDescriptionStatic(bool is_host) {
if (is_host)
return "Local Linux user platform plug-in.";
else
return "Remote Linux user platform plug-in.";
}
ConstString PlatformLinux::GetPluginName() {
return GetPluginNameStatic(IsHost());
}
void PlatformLinux::Initialize() {
PlatformPOSIX::Initialize();
if (g_initialize_count++ == 0) {
#if defined(__linux__) && !defined(__ANDROID__)
PlatformSP default_platform_sp(new PlatformLinux(true));
default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
Platform::SetHostPlatform(default_platform_sp);
#endif
PluginManager::RegisterPlugin(
PlatformLinux::GetPluginNameStatic(false),
PlatformLinux::GetPluginDescriptionStatic(false),
PlatformLinux::CreateInstance, nullptr);
}
}
void PlatformLinux::Terminate() {
if (g_initialize_count > 0) {
if (--g_initialize_count == 0) {
PluginManager::UnregisterPlugin(PlatformLinux::CreateInstance);
}
}
PlatformPOSIX::Terminate();
}
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformLinux::PlatformLinux(bool is_host)
: PlatformPOSIX(is_host) // This is the local host platform
{}
PlatformLinux::~PlatformLinux() = default;
bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
if (IsHost()) {
ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
if (hostArch.GetTriple().isOSLinux()) {
if (idx == 0) {
arch = hostArch;
return arch.IsValid();
} else if (idx == 1) {
// If the default host architecture is 64-bit, look for a 32-bit variant
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) {
arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
return arch.IsValid();
}
}
}
} else {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
llvm::Triple triple;
// Set the OS to linux
triple.setOS(llvm::Triple::Linux);
// Set the architecture
switch (idx) {
case 0:
triple.setArchName("x86_64");
break;
case 1:
triple.setArchName("i386");
break;
case 2:
triple.setArchName("arm");
break;
case 3:
triple.setArchName("aarch64");
break;
case 4:
triple.setArchName("mips64");
break;
case 5:
triple.setArchName("hexagon");
break;
case 6:
triple.setArchName("mips");
break;
case 7:
triple.setArchName("mips64el");
break;
case 8:
triple.setArchName("mipsel");
break;
case 9:
triple.setArchName("s390x");
break;
default:
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
// vendor by
// calling triple.SetVendorName("unknown") so that it is a "unspecified
// unknown".
// This means when someone calls triple.GetVendorName() it will return an
// empty string
// which indicates that the vendor can be set when two architectures are
// merged
// Now set the triple into "arch" and return true
arch.SetTriple(triple);
return true;
}
return false;
}
void PlatformLinux::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
#ifndef LLDB_DISABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-Linux information (when running
// on Mac OS for example).
if (IsHost()) {
struct utsname un;
if (uname(&un))
return;
strm.Printf(" Kernel: %s\n", un.sysname);
strm.Printf(" Release: %s\n", un.release);
strm.Printf(" Version: %s\n", un.version);
}
#endif
}
int32_t
PlatformLinux::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
int32_t resume_count = 0;
// Always resume past the initial stop when we use eLaunchFlagDebug
if (launch_info.GetFlags().Test(eLaunchFlagDebug)) {
// Resume past the stop for the final exec into the true inferior.
++resume_count;
}
// If we're not launching a shell, we're done.
const FileSpec &shell = launch_info.GetShell();
if (!shell)
return resume_count;
std::string shell_string = shell.GetPath();
// We're in a shell, so for sure we have to resume past the shell exec.
++resume_count;
// Figure out what shell we're planning on using.
const char *shell_name = strrchr(shell_string.c_str(), '/');
if (shell_name == NULL)
shell_name = shell_string.c_str();
else
shell_name++;
if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 ||
strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) {
// These shells seem to re-exec themselves. Add another resume.
++resume_count;
}
return resume_count;
}
bool PlatformLinux::CanDebugProcess() {
if (IsHost()) {
return true;
} else {
// If we're connected, we can debug.
return IsConnected();
}
}
// For local debugging, Linux will override the debug logic to use llgs-launch
// rather than lldb-launch, llgs-attach. This differs from current lldb-launch,
// debugserver-attach approach on MacOSX.
lldb::ProcessSP
PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new
// target, else use existing one
Status &error) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
LLDB_LOG(log, "target {0}", target);
// If we're a remote host, use standard behavior from parent class.
if (!IsHost())
return PlatformPOSIX::DebugProcess(launch_info, debugger, target, error);
//
// For local debugging, we'll insist on having ProcessGDBRemote create the
// process.
//
ProcessSP process_sp;
// Make sure we stop at the entry point
launch_info.GetFlags().Set(eLaunchFlagDebug);
// We always launch the process we are going to debug in a separate process
// group, since then we can handle ^C interrupts ourselves w/o having to worry
// about the target getting them as well.
launch_info.SetLaunchInSeparateProcessGroup(true);
// Ensure we have a target.
if (target == nullptr) {
LLDB_LOG(log, "creating new target");
TargetSP new_target_sp;
error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
nullptr, new_target_sp);
if (error.Fail()) {
LLDB_LOG(log, "failed to create new target: {0}", error);
return process_sp;
}
target = new_target_sp.get();
if (!target) {
error.SetErrorString("CreateTarget() returned nullptr");
LLDB_LOG(log, "error: {0}", error);
return process_sp;
}
}
// Mark target as currently selected target.
debugger.GetTargetList().SetSelectedTarget(target);
// Now create the gdb-remote process.
LLDB_LOG(log, "having target create process with gdb-remote plugin");
process_sp = target->CreateProcess(
launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr);
if (!process_sp) {
error.SetErrorString("CreateProcess() failed for gdb-remote process");
LLDB_LOG(log, "error: {0}", error);
return process_sp;
}
LLDB_LOG(log, "successfully created process");
// Adjust launch for a hijacker.
ListenerSP listener_sp;
if (!launch_info.GetHijackListener()) {
LLDB_LOG(log, "setting up hijacker");
listener_sp =
Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack");
launch_info.SetHijackListener(listener_sp);
process_sp->HijackProcessEvents(listener_sp);
}
// Log file actions.
if (log) {
LLDB_LOG(log, "launching process with the following file actions:");
StreamString stream;
size_t i = 0;
const FileAction *file_action;
while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) {
file_action->Dump(stream);
LLDB_LOG(log, "{0}", stream.GetData());
stream.Clear();
}
}
// Do the launch.
error = process_sp->Launch(launch_info);
if (error.Success()) {
// Handle the hijacking of process events.
if (listener_sp) {
const StateType state = process_sp->WaitForProcessToStop(
llvm::None, NULL, false, listener_sp);
LLDB_LOG(log, "pid {0} state {0}", process_sp->GetID(), state);
}
// Hook up process PTY if we have one (which we should for local debugging
// with llgs).
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
LLDB_LOG(log, "hooked up STDIO pty to process");
} else
LLDB_LOG(log, "not using process STDIO pty");
} else {
LLDB_LOG(log, "process launch failed: {0}", error);
// FIXME figure out appropriate cleanup here. Do we delete the target? Do
// we delete the process? Does our caller do that?
}
return process_sp;
}
void PlatformLinux::CalculateTrapHandlerSymbolNames() {
m_trap_handlers.push_back(ConstString("_sigtramp"));
}
MmapArgList PlatformLinux::GetMmapArgumentList(const ArchSpec &arch,
addr_t addr, addr_t length,
unsigned prot, unsigned flags,
addr_t fd, addr_t offset) {
uint64_t flags_platform = 0;
uint64_t map_anon = MAP_ANON;
// To get correct flags for MIPS Architecture
if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
arch.GetTriple().getArch() == llvm::Triple::mips64el ||
arch.GetTriple().getArch() == llvm::Triple::mips ||
arch.GetTriple().getArch() == llvm::Triple::mipsel)
map_anon = 0x800;
if (flags & eMmapFlagsPrivate)
flags_platform |= MAP_PRIVATE;
if (flags & eMmapFlagsAnon)
flags_platform |= map_anon;
MmapArgList args({addr, length, prot, flags_platform, fd, offset});
return args;
}

View File

@@ -0,0 +1,74 @@
//===-- PlatformLinux.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformLinux_h_
#define liblldb_PlatformLinux_h_
#include "Plugins/Platform/POSIX/PlatformPOSIX.h"
namespace lldb_private {
namespace platform_linux {
class PlatformLinux : public PlatformPOSIX {
public:
PlatformLinux(bool is_host);
~PlatformLinux() override;
static void Initialize();
static void Terminate();
//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch);
static ConstString GetPluginNameStatic(bool is_host);
static const char *GetPluginDescriptionStatic(bool is_host);
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override { return 1; }
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
const char *GetDescription() override {
return GetPluginDescriptionStatic(IsHost());
}
void GetStatus(Stream &strm) override;
bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
int32_t GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) override;
bool CanDebugProcess() override;
lldb::ProcessSP DebugProcess(ProcessLaunchInfo &launch_info,
Debugger &debugger, Target *target,
Status &error) override;
void CalculateTrapHandlerSymbolNames() override;
MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr,
lldb::addr_t length, unsigned prot,
unsigned flags, lldb::addr_t fd,
lldb::addr_t offset) override;
private:
DISALLOW_COPY_AND_ASSIGN(PlatformLinux);
};
} // namespace platform_linux
} // namespace lldb_private
#endif // liblldb_PlatformLinux_h_

View File

@@ -0,0 +1,43 @@
list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
PlatformDarwin.cpp
PlatformDarwinKernel.cpp
PlatformMacOSX.cpp
PlatformRemoteiOS.cpp
PlatformRemoteAppleTV.cpp
PlatformRemoteAppleWatch.cpp
PlatformRemoteDarwinDevice.cpp
)
list(APPEND PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES
PlatformAppleSimulator.cpp
PlatformiOSSimulator.cpp
PlatformiOSSimulatorCoreSimulatorSupport.mm
PlatformAppleTVSimulator.cpp
PlatformAppleWatchSimulator.cpp
)
if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
include_directories(${LIBXML2_INCLUDE_DIR})
list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
${PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES})
else()
list(APPEND LLVM_OPTIONAL_SOURCES
${PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES})
endif()
add_lldb_library(lldbPluginPlatformMacOSX PLUGIN
${PLUGIN_PLATFORM_MACOSX_SOURCES}
LINK_LIBS
clangBasic
lldbBreakpoint
lldbCore
lldbHost
lldbInterpreter
lldbSymbol
lldbTarget
lldbUtility
lldbPluginPlatformPOSIX
LINK_COMPONENTS
Support
)

View File

@@ -0,0 +1,270 @@
//===-- PlatformAppleSimulator.cpp ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "PlatformAppleSimulator.h"
// C Includes
#if defined(__APPLE__)
#include <dlfcn.h>
#endif
// C++ Includes
#include <mutex>
#include <thread>
// Other libraries and framework includes
// Project includes
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/Support/Threading.h"
using namespace lldb;
using namespace lldb_private;
#if !defined(__APPLE__)
#define UNSUPPORTED_ERROR ("Apple simulators aren't supported on this platform")
#endif
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
void PlatformAppleSimulator::Initialize() { PlatformDarwin::Initialize(); }
void PlatformAppleSimulator::Terminate() { PlatformDarwin::Terminate(); }
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformAppleSimulator::PlatformAppleSimulator()
: PlatformDarwin(true), m_core_sim_path_mutex(),
m_core_simulator_framework_path(), m_device() {}
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
PlatformAppleSimulator::~PlatformAppleSimulator() {}
lldb_private::Status PlatformAppleSimulator::LaunchProcess(
lldb_private::ProcessLaunchInfo &launch_info) {
#if defined(__APPLE__)
LoadCoreSimulator();
CoreSimulatorSupport::Device device(GetSimulatorDevice());
if (device.GetState() != CoreSimulatorSupport::Device::State::Booted) {
Status boot_err;
device.Boot(boot_err);
if (boot_err.Fail())
return boot_err;
}
auto spawned = device.Spawn(launch_info);
if (spawned) {
launch_info.SetProcessID(spawned.GetPID());
return Status();
} else
return spawned.GetError();
#else
Status err;
err.SetErrorString(UNSUPPORTED_ERROR);
return err;
#endif
}
void PlatformAppleSimulator::GetStatus(Stream &strm) {
#if defined(__APPLE__)
// This will get called by subclasses, so just output status on the
// current simulator
PlatformAppleSimulator::LoadCoreSimulator();
CoreSimulatorSupport::DeviceSet devices =
CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
GetDeveloperDirectory());
const size_t num_devices = devices.GetNumDevices();
if (num_devices) {
strm.Printf("Available devices:\n");
for (size_t i = 0; i < num_devices; ++i) {
CoreSimulatorSupport::Device device = devices.GetDeviceAtIndex(i);
strm.Printf(" %s: %s\n", device.GetUDID().c_str(),
device.GetName().c_str());
}
if (m_device.hasValue() && m_device->operator bool()) {
strm.Printf("Current device: %s: %s", m_device->GetUDID().c_str(),
m_device->GetName().c_str());
if (m_device->GetState() == CoreSimulatorSupport::Device::State::Booted) {
strm.Printf(" state = booted");
}
strm.Printf("\nType \"platform connect <ARG>\" where <ARG> is a device "
"UDID or a device name to disconnect and connect to a "
"different device.\n");
} else {
strm.Printf("No current device is selected, \"platform connect <ARG>\" "
"where <ARG> is a device UDID or a device name to connect to "
"a specific device.\n");
}
} else {
strm.Printf("No devices are available.\n");
}
#else
strm.Printf(UNSUPPORTED_ERROR);
#endif
}
Status PlatformAppleSimulator::ConnectRemote(Args &args) {
#if defined(__APPLE__)
Status error;
if (args.GetArgumentCount() == 1) {
if (m_device)
DisconnectRemote();
PlatformAppleSimulator::LoadCoreSimulator();
const char *arg_cstr = args.GetArgumentAtIndex(0);
if (arg_cstr) {
std::string arg_str(arg_cstr);
CoreSimulatorSupport::DeviceSet devices =
CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
GetDeveloperDirectory());
devices.ForEach(
[this, &arg_str](const CoreSimulatorSupport::Device &device) -> bool {
if (arg_str == device.GetUDID() || arg_str == device.GetName()) {
m_device = device;
return false; // Stop iterating
} else {
return true; // Keep iterating
}
});
if (!m_device)
error.SetErrorStringWithFormat(
"no device with UDID or name '%s' was found", arg_cstr);
}
} else {
error.SetErrorString("this command take a single UDID argument of the "
"device you want to connect to.");
}
return error;
#else
Status err;
err.SetErrorString(UNSUPPORTED_ERROR);
return err;
#endif
}
Status PlatformAppleSimulator::DisconnectRemote() {
#if defined(__APPLE__)
m_device.reset();
return Status();
#else
Status err;
err.SetErrorString(UNSUPPORTED_ERROR);
return err;
#endif
}
lldb::ProcessSP PlatformAppleSimulator::DebugProcess(
ProcessLaunchInfo &launch_info, Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new target, else use
// existing one
Status &error) {
#if defined(__APPLE__)
ProcessSP process_sp;
// Make sure we stop at the entry point
launch_info.GetFlags().Set(eLaunchFlagDebug);
// We always launch the process we are going to debug in a separate process
// group, since then we can handle ^C interrupts ourselves w/o having to worry
// about the target getting them as well.
launch_info.SetLaunchInSeparateProcessGroup(true);
error = LaunchProcess(launch_info);
if (error.Success()) {
if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
ProcessAttachInfo attach_info(launch_info);
process_sp = Attach(attach_info, debugger, target, error);
if (process_sp) {
launch_info.SetHijackListener(attach_info.GetHijackListener());
// Since we attached to the process, it will think it needs to detach
// if the process object just goes away without an explicit call to
// Process::Kill() or Process::Detach(), so let it know to kill the
// process if this happens.
process_sp->SetShouldDetach(false);
// If we didn't have any file actions, the pseudo terminal might
// have been used where the slave side was given as the file to
// open for stdin/out/err after we have already opened the master
// so we can read/write stdin/out/err.
int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor();
if (pty_fd != PseudoTerminal::invalid_fd) {
process_sp->SetSTDIOFileDescriptor(pty_fd);
}
}
}
}
return process_sp;
#else
return ProcessSP();
#endif
}
FileSpec PlatformAppleSimulator::GetCoreSimulatorPath() {
#if defined(__APPLE__)
std::lock_guard<std::mutex> guard(m_core_sim_path_mutex);
if (!m_core_simulator_framework_path.hasValue()) {
const char *developer_dir = GetDeveloperDirectory();
if (developer_dir) {
StreamString cs_path;
cs_path.Printf(
"%s/Library/PrivateFrameworks/CoreSimulator.framework/CoreSimulator",
developer_dir);
const bool resolve_path = true;
m_core_simulator_framework_path =
FileSpec(cs_path.GetData(), resolve_path);
}
}
return m_core_simulator_framework_path.getValue();
#else
return FileSpec();
#endif
}
void PlatformAppleSimulator::LoadCoreSimulator() {
#if defined(__APPLE__)
static llvm::once_flag g_load_core_sim_flag;
llvm::call_once(g_load_core_sim_flag, [this] {
const std::string core_sim_path(GetCoreSimulatorPath().GetPath());
if (core_sim_path.size())
dlopen(core_sim_path.c_str(), RTLD_LAZY);
});
#endif
}
#if defined(__APPLE__)
CoreSimulatorSupport::Device PlatformAppleSimulator::GetSimulatorDevice() {
if (!m_device.hasValue()) {
const CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id =
CoreSimulatorSupport::DeviceType::ProductFamilyID::iPhone;
m_device = CoreSimulatorSupport::DeviceSet::GetAvailableDevices(
GetDeveloperDirectory())
.GetFanciest(dev_id);
}
if (m_device.hasValue())
return m_device.getValue();
else
return CoreSimulatorSupport::Device();
}
#endif

View File

@@ -0,0 +1,72 @@
//===-- PlatformAppleSimulator.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_PlatformAppleSimulator_h_
#define liblldb_PlatformAppleSimulator_h_
// C Includes
// C++ Includes
#include <mutex>
// Other libraries and framework includes
// Project includes
#include "PlatformDarwin.h"
#include "PlatformiOSSimulatorCoreSimulatorSupport.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/ADT/Optional.h"
class PlatformAppleSimulator : public PlatformDarwin {
public:
//------------------------------------------------------------
// Class Functions
//------------------------------------------------------------
static void Initialize();
static void Terminate();
//------------------------------------------------------------
// Class Methods
//------------------------------------------------------------
PlatformAppleSimulator();
virtual ~PlatformAppleSimulator();
lldb_private::Status
LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override;
void GetStatus(lldb_private::Stream &strm) override;
lldb_private::Status ConnectRemote(lldb_private::Args &args) override;
lldb_private::Status DisconnectRemote() override;
lldb::ProcessSP DebugProcess(lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target,
lldb_private::Status &error) override;
protected:
std::mutex m_core_sim_path_mutex;
llvm::Optional<lldb_private::FileSpec> m_core_simulator_framework_path;
llvm::Optional<CoreSimulatorSupport::Device> m_device;
lldb_private::FileSpec GetCoreSimulatorPath();
void LoadCoreSimulator();
#if defined(__APPLE__)
CoreSimulatorSupport::Device GetSimulatorDevice();
#endif
private:
DISALLOW_COPY_AND_ASSIGN(PlatformAppleSimulator);
};
#endif // liblldb_PlatformAppleSimulator_h_

Some files were not shown because too many files have changed in this diff Show More