summaryrefslogtreecommitdiff
path: root/source/Plugins/Platform
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Platform')
-rw-r--r--source/Plugins/Platform/Android/AdbClient.cpp569
-rw-r--r--source/Plugins/Platform/Android/AdbClient.h132
-rw-r--r--source/Plugins/Platform/Android/CMakeLists.txt5
-rw-r--r--source/Plugins/Platform/Android/Makefile14
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroid.cpp389
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroid.h114
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp275
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h79
-rw-r--r--source/Plugins/Platform/CMakeLists.txt16
-rw-r--r--source/Plugins/Platform/FreeBSD/CMakeLists.txt3
-rw-r--r--source/Plugins/Platform/FreeBSD/Makefile14
-rw-r--r--source/Plugins/Platform/Kalimba/CMakeLists.txt3
-rw-r--r--source/Plugins/Platform/Kalimba/Makefile14
-rw-r--r--source/Plugins/Platform/Kalimba/PlatformKalimba.cpp324
-rw-r--r--source/Plugins/Platform/Kalimba/PlatformKalimba.h99
-rw-r--r--source/Plugins/Platform/Linux/CMakeLists.txt3
-rw-r--r--source/Plugins/Platform/Linux/Makefile14
-rw-r--r--source/Plugins/Platform/Linux/PlatformLinux.cpp868
-rw-r--r--source/Plugins/Platform/Linux/PlatformLinux.h122
-rw-r--r--source/Plugins/Platform/MacOSX/CMakeLists.txt27
-rw-r--r--source/Plugins/Platform/MacOSX/Makefile15
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp303
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h81
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp466
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h121
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp466
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h120
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwin.cpp1705
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwin.h156
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp979
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h228
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp386
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformMacOSX.h104
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp912
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h171
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp944
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h173
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp974
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h173
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp502
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h116
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h315
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm773
-rw-r--r--source/Plugins/Platform/Makefile36
-rw-r--r--source/Plugins/Platform/NetBSD/CMakeLists.txt3
-rw-r--r--source/Plugins/Platform/NetBSD/Makefile14
-rw-r--r--source/Plugins/Platform/POSIX/CMakeLists.txt3
-rw-r--r--source/Plugins/Platform/POSIX/Makefile14
-rw-r--r--source/Plugins/Platform/Windows/CMakeLists.txt3
-rw-r--r--source/Plugins/Platform/Windows/Makefile14
-rw-r--r--source/Plugins/Platform/Windows/PlatformWindows.cpp753
-rw-r--r--source/Plugins/Platform/Windows/PlatformWindows.h169
-rw-r--r--source/Plugins/Platform/gdb-server/CMakeLists.txt3
-rw-r--r--source/Plugins/Platform/gdb-server/Makefile14
54 files changed, 14293 insertions, 0 deletions
diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp
new file mode 100644
index 0000000000000..736447fd22d21
--- /dev/null
+++ b/source/Plugins/Platform/Android/AdbClient.cpp
@@ -0,0 +1,569 @@
+//===-- AdbClient.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/Core/DataBuffer.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataEncoder.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/FileUtilities.h"
+
+// Project includes
+#include "AdbClient.h"
+
+#include <limits.h>
+
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::platform_android;
+
+namespace {
+
+const uint32_t kReadTimeout = 1000000; // 1 second
+const char * kOKAY = "OKAY";
+const char * kFAIL = "FAIL";
+const char * kDATA = "DATA";
+const char * kDONE = "DONE";
+
+const char * kSEND = "SEND";
+const char * kRECV = "RECV";
+const char * kSTAT = "STAT";
+
+const size_t kSyncPacketLen = 8;
+// Maximum size of a filesync DATA packet.
+const size_t kMaxPushData = 2*1024;
+// Default mode for pushed files.
+const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG
+
+const char * kSocketNamespaceAbstract = "localabstract";
+const char * kSocketNamespaceFileSystem = "localfilesystem";
+
+} // namespace
+
+Error
+AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb)
+{
+ DeviceIDList connect_devices;
+ auto error = adb.GetDevices(connect_devices);
+ if (error.Fail())
+ return error;
+
+ if (device_id.empty())
+ {
+ if (connect_devices.size() != 1)
+ return Error("Expected a single connected device, got instead %" PRIu64,
+ static_cast<uint64_t>(connect_devices.size()));
+
+ adb.SetDeviceID(connect_devices.front());
+ }
+ else
+ {
+ auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id);
+ if (find_it == connect_devices.end())
+ return Error("Device \"%s\" not found", device_id.c_str());
+
+ adb.SetDeviceID(*find_it);
+ }
+ return error;
+}
+
+AdbClient::AdbClient (const std::string &device_id)
+ : m_device_id (device_id)
+{
+}
+
+void
+AdbClient::SetDeviceID (const std::string &device_id)
+{
+ m_device_id = device_id;
+}
+
+const std::string&
+AdbClient::GetDeviceID() const
+{
+ return m_device_id;
+}
+
+Error
+AdbClient::Connect ()
+{
+ Error error;
+ m_conn.Connect ("connect://localhost:5037", &error);
+
+ return error;
+}
+
+Error
+AdbClient::GetDevices (DeviceIDList &device_list)
+{
+ device_list.clear ();
+
+ auto error = SendMessage ("host:devices");
+ if (error.Fail ())
+ return error;
+
+ error = ReadResponseStatus ();
+ if (error.Fail ())
+ return error;
+
+ std::vector<char> in_buffer;
+ error = ReadMessage (in_buffer);
+
+ llvm::StringRef response (&in_buffer[0], in_buffer.size ());
+ llvm::SmallVector<llvm::StringRef, 4> devices;
+ response.split (devices, "\n", -1, false);
+
+ for (const auto device: devices)
+ device_list.push_back (device.split ('\t').first);
+
+ return error;
+}
+
+Error
+AdbClient::SetPortForwarding (const uint16_t local_port, const uint16_t remote_port)
+{
+ char message[48];
+ snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", local_port, remote_port);
+
+ const auto error = SendDeviceMessage (message);
+ if (error.Fail ())
+ return error;
+
+ return ReadResponseStatus ();
+}
+
+Error
+AdbClient::SetPortForwarding (const uint16_t local_port,
+ const char* remote_socket_name,
+ const UnixSocketNamespace socket_namespace)
+{
+ char message[PATH_MAX];
+ const char * sock_namespace_str = (socket_namespace == UnixSocketNamespaceAbstract) ?
+ kSocketNamespaceAbstract : kSocketNamespaceFileSystem;
+ snprintf (message, sizeof (message), "forward:tcp:%d;%s:%s",
+ local_port,
+ sock_namespace_str,
+ remote_socket_name);
+
+ const auto error = SendDeviceMessage (message);
+ if (error.Fail ())
+ return error;
+
+ return ReadResponseStatus ();
+}
+
+Error
+AdbClient::DeletePortForwarding (const uint16_t local_port)
+{
+ char message[32];
+ snprintf (message, sizeof (message), "killforward:tcp:%d", local_port);
+
+ const auto error = SendDeviceMessage (message);
+ if (error.Fail ())
+ return error;
+
+ return ReadResponseStatus ();
+}
+
+Error
+AdbClient::SendMessage (const std::string &packet, const bool reconnect)
+{
+ Error error;
+ if (reconnect)
+ {
+ error = Connect ();
+ if (error.Fail ())
+ return error;
+ }
+
+ char length_buffer[5];
+ snprintf (length_buffer, sizeof (length_buffer), "%04x", static_cast<int>(packet.size ()));
+
+ ConnectionStatus status;
+
+ m_conn.Write (length_buffer, 4, status, &error);
+ if (error.Fail ())
+ return error;
+
+ m_conn.Write (packet.c_str (), packet.size (), status, &error);
+ return error;
+}
+
+Error
+AdbClient::SendDeviceMessage (const std::string &packet)
+{
+ std::ostringstream msg;
+ msg << "host-serial:" << m_device_id << ":" << packet;
+ return SendMessage (msg.str ());
+}
+
+Error
+AdbClient::ReadMessage (std::vector<char> &message)
+{
+ message.clear ();
+
+ char buffer[5];
+ buffer[4] = 0;
+
+ auto error = ReadAllBytes (buffer, 4);
+ if (error.Fail ())
+ return error;
+
+ unsigned int packet_len = 0;
+ sscanf (buffer, "%x", &packet_len);
+
+ message.resize (packet_len, 0);
+ error = ReadAllBytes (&message[0], packet_len);
+ if (error.Fail ())
+ message.clear ();
+
+ return error;
+}
+
+Error
+AdbClient::ReadMessageStream (std::vector<char>& message, uint32_t timeout_ms)
+{
+ auto start = std::chrono::steady_clock::now();
+ message.clear();
+
+ Error error;
+ lldb::ConnectionStatus status = lldb::eConnectionStatusSuccess;
+ char buffer[1024];
+ while (error.Success() && status == lldb::eConnectionStatusSuccess)
+ {
+ auto end = std::chrono::steady_clock::now();
+ uint32_t elapsed_time = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
+ if (elapsed_time >= timeout_ms)
+ return Error("Timed out");
+
+ size_t n = m_conn.Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error);
+ if (n > 0)
+ message.insert(message.end(), &buffer[0], &buffer[n]);
+ }
+ return error;
+}
+
+Error
+AdbClient::ReadResponseStatus()
+{
+ char response_id[5];
+
+ static const size_t packet_len = 4;
+ response_id[packet_len] = 0;
+
+ auto error = ReadAllBytes (response_id, packet_len);
+ if (error.Fail ())
+ return error;
+
+ if (strncmp (response_id, kOKAY, packet_len) != 0)
+ return GetResponseError (response_id);
+
+ return error;
+}
+
+Error
+AdbClient::GetResponseError (const char *response_id)
+{
+ if (strcmp (response_id, kFAIL) != 0)
+ return Error ("Got unexpected response id from adb: \"%s\"", response_id);
+
+ std::vector<char> error_message;
+ auto error = ReadMessage (error_message);
+ if (error.Success ())
+ error.SetErrorString (std::string (&error_message[0], error_message.size ()).c_str ());
+
+ return error;
+}
+
+Error
+AdbClient::SwitchDeviceTransport ()
+{
+ std::ostringstream msg;
+ msg << "host:transport:" << m_device_id;
+
+ auto error = SendMessage (msg.str ());
+ if (error.Fail ())
+ return error;
+
+ return ReadResponseStatus ();
+}
+
+Error
+AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file)
+{
+ auto error = StartSync ();
+ if (error.Fail ())
+ return error;
+
+ const auto local_file_path = local_file.GetPath ();
+ llvm::FileRemover local_file_remover (local_file_path.c_str ());
+
+ std::ofstream dst (local_file_path, std::ios::out | std::ios::binary);
+ if (!dst.is_open ())
+ return Error ("Unable to open local file %s", local_file_path.c_str());
+
+ const auto remote_file_path = remote_file.GetPath (false);
+ error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ());
+ if (error.Fail ())
+ return error;
+
+ std::vector<char> chunk;
+ bool eof = false;
+ while (!eof)
+ {
+ error = PullFileChunk (chunk, eof);
+ if (error.Fail ())
+ return error;
+ if (!eof)
+ dst.write (&chunk[0], chunk.size ());
+ }
+
+ local_file_remover.releaseFile ();
+ return error;
+}
+
+Error
+AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file)
+{
+ auto error = StartSync ();
+ if (error.Fail ())
+ return error;
+
+ const auto local_file_path (local_file.GetPath ());
+ std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary);
+ if (!src.is_open ())
+ return Error ("Unable to open local file %s", local_file_path.c_str());
+
+ std::stringstream file_description;
+ file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode;
+ std::string file_description_str = file_description.str();
+ error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str());
+ if (error.Fail ())
+ return error;
+
+ char chunk[kMaxPushData];
+ while (!src.eof() && !src.read(chunk, kMaxPushData).bad())
+ {
+ size_t chunk_size = src.gcount();
+ error = SendSyncRequest(kDATA, chunk_size, chunk);
+ if (error.Fail ())
+ return Error ("Failed to send file chunk: %s", error.AsCString ());
+ }
+ error = SendSyncRequest(kDONE, local_file.GetModificationTime().seconds(), nullptr);
+ if (error.Fail ())
+ return error;
+
+ std::string response_id;
+ uint32_t data_len;
+ error = ReadSyncHeader (response_id, data_len);
+ if (error.Fail ())
+ return Error ("Failed to read DONE response: %s", error.AsCString ());
+ if (response_id == kFAIL)
+ {
+ std::string error_message (data_len, 0);
+ error = ReadAllBytes (&error_message[0], data_len);
+ if (error.Fail ())
+ return Error ("Failed to read DONE error message: %s", error.AsCString ());
+ return Error ("Failed to push file: %s", error_message.c_str ());
+ }
+ else if (response_id != kOKAY)
+ return Error ("Got unexpected DONE response: %s", response_id.c_str ());
+
+ // If there was an error reading the source file, finish the adb file
+ // transfer first so that adb isn't expecting any more data.
+ if (src.bad())
+ return Error ("Failed read on %s", local_file_path.c_str());
+ return error;
+}
+
+Error
+AdbClient::StartSync ()
+{
+ auto error = SwitchDeviceTransport ();
+ if (error.Fail ())
+ return Error ("Failed to switch to device transport: %s", error.AsCString ());
+
+ error = Sync ();
+ if (error.Fail ())
+ return Error ("Sync failed: %s", error.AsCString ());
+
+ return error;
+}
+
+Error
+AdbClient::Sync ()
+{
+ auto error = SendMessage ("sync:", false);
+ if (error.Fail ())
+ return error;
+
+ return ReadResponseStatus ();
+}
+
+Error
+AdbClient::PullFileChunk (std::vector<char> &buffer, bool &eof)
+{
+ buffer.clear ();
+
+ std::string response_id;
+ uint32_t data_len;
+ auto error = ReadSyncHeader (response_id, data_len);
+ if (error.Fail ())
+ return error;
+
+ if (response_id == kDATA)
+ {
+ buffer.resize (data_len, 0);
+ error = ReadAllBytes (&buffer[0], data_len);
+ if (error.Fail ())
+ buffer.clear ();
+ }
+ else if (response_id == kDONE)
+ {
+ eof = true;
+ }
+ else if (response_id == kFAIL)
+ {
+ std::string error_message (data_len, 0);
+ error = ReadAllBytes (&error_message[0], data_len);
+ if (error.Fail ())
+ return Error ("Failed to read pull error message: %s", error.AsCString ());
+ return Error ("Failed to pull file: %s", error_message.c_str ());
+ }
+ else
+ return Error ("Pull failed with unknown response: %s", response_id.c_str ());
+
+ return Error ();
+}
+
+Error
+AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data)
+{
+ const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0));
+ DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*));
+ auto offset = encoder.PutData (0, request_id, strlen(request_id));
+ encoder.PutU32 (offset, data_len);
+
+ Error error;
+ ConnectionStatus status;
+ m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error);
+ if (error.Fail ())
+ return error;
+
+ if (data)
+ m_conn.Write (data, data_len, status, &error);
+ return error;
+}
+
+Error
+AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len)
+{
+ char buffer[kSyncPacketLen];
+
+ auto error = ReadAllBytes (buffer, kSyncPacketLen);
+ if (error.Success ())
+ {
+ response_id.assign (&buffer[0], 4);
+ DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*));
+ offset_t offset = 0;
+ data_len = extractor.GetU32 (&offset);
+ }
+
+ return error;
+}
+
+Error
+AdbClient::ReadAllBytes (void *buffer, size_t size)
+{
+ Error error;
+ ConnectionStatus status;
+ char *read_buffer = static_cast<char*>(buffer);
+
+ size_t tota_read_bytes = 0;
+ while (tota_read_bytes < size)
+ {
+ auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error);
+ if (error.Fail ())
+ return error;
+ tota_read_bytes += read_bytes;
+ }
+ return error;
+}
+
+Error
+AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime)
+{
+ auto error = StartSync ();
+ if (error.Fail ())
+ return error;
+
+ const std::string remote_file_path (remote_file.GetPath (false));
+ error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ());
+ if (error.Fail ())
+ return Error ("Failed to send request: %s", error.AsCString ());
+
+ static const size_t stat_len = strlen (kSTAT);
+ static const size_t response_len = stat_len + (sizeof (uint32_t) * 3);
+
+ std::vector<char> buffer (response_len);
+ error = ReadAllBytes (&buffer[0], buffer.size ());
+ if (error.Fail ())
+ return Error ("Failed to read response: %s", error.AsCString ());
+
+ DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*));
+ offset_t offset = 0;
+
+ const void* command = extractor.GetData (&offset, stat_len);
+ if (!command)
+ return Error ("Failed to get response command");
+ const char* command_str = static_cast<const char*> (command);
+ if (strncmp (command_str, kSTAT, stat_len))
+ return Error ("Got invalid stat command: %s", command_str);
+
+ mode = extractor.GetU32 (&offset);
+ size = extractor.GetU32 (&offset);
+ mtime = extractor.GetU32 (&offset);
+ return Error ();
+}
+
+Error
+AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output)
+{
+ auto error = SwitchDeviceTransport ();
+ if (error.Fail ())
+ return Error ("Failed to switch to device transport: %s", error.AsCString ());
+
+ StreamString adb_command;
+ adb_command.Printf("shell:%s", command);
+ error = SendMessage (adb_command.GetData(), false);
+ if (error.Fail ())
+ return error;
+
+ error = ReadResponseStatus ();
+ if (error.Fail ())
+ return error;
+
+ std::vector<char> in_buffer;
+ error = ReadMessageStream (in_buffer, timeout_ms);
+ if (error.Fail())
+ return error;
+
+ if (output)
+ output->assign(in_buffer.begin(), in_buffer.end());
+ return error;
+}
diff --git a/source/Plugins/Platform/Android/AdbClient.h b/source/Plugins/Platform/Android/AdbClient.h
new file mode 100644
index 0000000000000..4ec411d1411dd
--- /dev/null
+++ b/source/Plugins/Platform/Android/AdbClient.h
@@ -0,0 +1,132 @@
+//===-- 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_
+
+// C Includes
+
+// C++ Includes
+
+#include <list>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
+
+namespace lldb_private {
+
+class FileSpec;
+
+namespace platform_android {
+
+class AdbClient
+{
+public:
+ enum UnixSocketNamespace
+ {
+ UnixSocketNamespaceAbstract,
+ UnixSocketNamespaceFileSystem,
+ };
+
+ using DeviceIDList = std::list<std::string>;
+
+ static Error
+ CreateByDeviceID(const std::string &device_id, AdbClient &adb);
+
+ AdbClient () = default;
+ explicit AdbClient (const std::string &device_id);
+
+ const std::string&
+ GetDeviceID() const;
+
+ Error
+ GetDevices (DeviceIDList &device_list);
+
+ Error
+ SetPortForwarding (const uint16_t local_port, const uint16_t remote_port);
+
+ Error
+ SetPortForwarding (const uint16_t local_port,
+ const char* remote_socket_name,
+ const UnixSocketNamespace socket_namespace);
+
+ Error
+ DeletePortForwarding (const uint16_t local_port);
+
+ Error
+ PullFile (const FileSpec &remote_file, const FileSpec &local_file);
+
+ Error
+ PushFile (const FileSpec &local_file, const FileSpec &remote_file);
+
+ Error
+ Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime);
+
+ Error
+ Shell (const char* command, uint32_t timeout_ms, std::string* output);
+
+private:
+ Error
+ Connect ();
+
+ void
+ SetDeviceID (const std::string &device_id);
+
+ Error
+ SendMessage (const std::string &packet, const bool reconnect = true);
+
+ Error
+ SendDeviceMessage (const std::string &packet);
+
+ Error
+ SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data);
+
+ Error
+ ReadSyncHeader (std::string &response_id, uint32_t &data_len);
+
+ Error
+ ReadMessage (std::vector<char> &message);
+
+ Error
+ ReadMessageStream (std::vector<char> &message, uint32_t timeout_ms);
+
+ Error
+ GetResponseError (const char *response_id);
+
+ Error
+ ReadResponseStatus ();
+
+ Error
+ SwitchDeviceTransport ();
+
+ Error
+ Sync ();
+
+ Error
+ StartSync ();
+
+ Error
+ PullFileChunk (std::vector<char> &buffer, bool &eof);
+
+ Error
+ ReadAllBytes (void *buffer, size_t size);
+
+ std::string m_device_id;
+ ConnectionFileDescriptor m_conn;
+};
+
+} // namespace platform_android
+} // namespace lldb_private
+
+#endif // liblldb_AdbClient_h_
diff --git a/source/Plugins/Platform/Android/CMakeLists.txt b/source/Plugins/Platform/Android/CMakeLists.txt
new file mode 100644
index 0000000000000..e831a33a4b6d4
--- /dev/null
+++ b/source/Plugins/Platform/Android/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_lldb_library(lldbPluginPlatformAndroid
+ AdbClient.cpp
+ PlatformAndroid.cpp
+ PlatformAndroidRemoteGDBServer.cpp
+ )
diff --git a/source/Plugins/Platform/Android/Makefile b/source/Plugins/Platform/Android/Makefile
new file mode 100644
index 0000000000000..aa186f924e66c
--- /dev/null
+++ b/source/Plugins/Platform/Android/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/Android/Makefile ------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformAndroid
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp
new file mode 100644
index 0000000000000..e842884c046a3
--- /dev/null
+++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -0,0 +1,389 @@
+//===-- PlatformAndroid.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/Log.h"
+#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 "Utility/UriParser.h"
+
+// Project includes
+#include "AdbClient.h"
+#include "PlatformAndroid.h"
+#include "PlatformAndroidRemoteGDBServer.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::platform_android;
+
+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());
+}
+
+Error
+PlatformAndroid::ConnectRemote(Args& args)
+{
+ m_device_id.clear();
+
+ if (IsHost())
+ {
+ return Error ("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;
+ std::string scheme, host, path;
+ const char *url = args.GetArgumentAtIndex(0);
+ if (!url)
+ return Error("URL is null.");
+ if (!UriParser::Parse(url, scheme, host, port, path))
+ return Error("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;
+}
+
+Error
+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));
+
+ AdbClient adb (m_device_id);
+ return adb.PullFile (source_spec, destination);
+}
+
+Error
+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));
+
+ AdbClient adb (m_device_id);
+ // TODO: Set correct uid and gid on remote file.
+ return adb.PushFile(source, destination_spec);
+}
+
+const char *
+PlatformAndroid::GetCacheHostname ()
+{
+ return m_device_id.c_str ();
+}
+
+Error
+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 Error ("Invalid offset - %" PRIu64, src_offset);
+
+ return GetFile (src_file_spec, dst_file_spec);
+}
+
+Error
+PlatformAndroid::DisconnectRemote()
+{
+ Error 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);
+ Error error = adb.Shell("getprop ro.build.version.sdk", 5000 /* ms */, &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;
+}
+
+Error
+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
+ if (module_sp->GetFileSpec().GetFileNameExtension() != ConstString("oat"))
+ return Error("Symbol file downloading only supported for oat files");
+
+ // If we have no information about the platform file we can't execute oatdump
+ if (!module_sp->GetPlatformFileSpec())
+ return Error("No platform file specified");
+
+ // Symbolizer isn't available before SDK version 23
+ if (GetSdkVersion() < 23)
+ return Error("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 Error("Symtab already available in the module");
+
+ AdbClient adb(m_device_id);
+
+ std::string tmpdir;
+ Error error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp", 5000 /* ms */, &tmpdir);
+ if (error.Fail() || tmpdir.empty())
+ return Error("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,
+ [this, &adb](std::string* s) {
+ StreamString command;
+ command.Printf("rm -rf %s", s->c_str());
+ Error error = adb.Shell(command.GetData(), 5000 /* ms */, nullptr);
+
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
+ if (error.Fail())
+ log->Printf("Failed to remove temp directory: %s", error.AsCString());
+ }
+ );
+
+ FileSpec symfile_platform_filespec(tmpdir.c_str(), 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(), 60000 /* ms */, nullptr);
+ if (error.Fail())
+ return Error("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;
+}
+
+const char*
+PlatformAndroid::GetLibdlFunctionDeclarations() const
+{
+ 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");
+ )";
+}
diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h
new file mode 100644
index 0000000000000..119d0a0bdf04d
--- /dev/null
+++ b/source/Plugins/Platform/Android/PlatformAndroid.h
@@ -0,0 +1,114 @@
+//===-- 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 <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "Plugins/Platform/Linux/PlatformLinux.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
+ //------------------------------------------------------------
+
+ Error
+ ConnectRemote (Args& args) override;
+
+ Error
+ GetFile (const FileSpec& source,
+ const FileSpec& destination) override;
+
+ Error
+ PutFile (const FileSpec& source,
+ const FileSpec& destination,
+ uint32_t uid = UINT32_MAX,
+ uint32_t gid = UINT32_MAX) override;
+
+ uint32_t
+ GetSdkVersion();
+
+ bool
+ GetRemoteOSVersion() override;
+
+ Error
+ DisconnectRemote () override;
+
+ uint32_t
+ GetDefaultMemoryCacheLineSize() override;
+
+ protected:
+ const char *
+ GetCacheHostname () override;
+
+ Error
+ DownloadModuleSlice (const FileSpec &src_file_spec,
+ const uint64_t src_offset,
+ const uint64_t src_size,
+ const FileSpec &dst_file_spec) override;
+
+ Error
+ DownloadSymbolFile (const lldb::ModuleSP& module_sp,
+ const FileSpec& dst_file_spec) override;
+
+ const char*
+ GetLibdlFunctionDeclarations() const override;
+
+ private:
+ 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_
diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
new file mode 100644
index 0000000000000..3d91dd6b7a32f
--- /dev/null
+++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -0,0 +1,275 @@
+//===-- 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/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Host/common/TCPSocket.h"
+#include "PlatformAndroidRemoteGDBServer.h"
+#include "Utility/UriParser.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 Error
+ForwardPortWithAdb (const uint16_t local_port,
+ const uint16_t remote_port,
+ const char* 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, local_port);
+
+ if (!socket_namespace)
+ return Error("Invalid socket namespace");
+
+ return adb.SetPortForwarding(local_port, remote_socket_name, *socket_namespace);
+}
+
+static Error
+DeleteForwardPortWithAdb (uint16_t local_port, const std::string& device_id)
+{
+ AdbClient adb (device_id);
+ return adb.DeletePortForwarding (local_port);
+}
+
+static Error
+FindUnusedPort (uint16_t& port)
+{
+ Error error;
+ std::unique_ptr<TCPSocket> tcp_socket(new TCPSocket(false, error));
+ 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);
+}
+
+Error
+PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
+{
+ m_device_id.clear();
+
+ if (args.GetArgumentCount() != 1)
+ return Error("\"platform connect\" takes a single argument: <connect-url>");
+
+ int remote_port;
+ std::string scheme, host, path;
+ const char *url = args.GetArgumentAtIndex (0);
+ if (!url)
+ return Error("URL is null.");
+ if (!UriParser::Parse (url, scheme, host, remote_port, path))
+ return Error("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.c_str (),
+ connect_url);
+
+ if (error.Fail ())
+ return error;
+
+ args.ReplaceArgumentAtIndex (0, connect_url.c_str ());
+
+ 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;
+}
+
+Error
+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);
+}
+
+Error
+PlatformAndroidRemoteGDBServer::MakeConnectURL(const lldb::pid_t pid,
+ const uint16_t remote_port,
+ const char* remote_socket_name,
+ std::string& connect_url)
+{
+ static const int kAttempsNum = 5;
+
+ Error 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(const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &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;
+ std::string scheme, host, path;
+ if (!UriParser::Parse(connect_url, scheme, host, remote_port, path))
+ {
+ error.SetErrorStringWithFormat("Invalid URL: %s", connect_url);
+ return nullptr;
+ }
+
+ std::string new_connect_url;
+ error = MakeConnectURL(s_remote_gdbserver_fake_pid--,
+ (remote_port < 0) ? 0 : remote_port,
+ path.c_str(),
+ new_connect_url);
+ if (error.Fail())
+ return nullptr;
+
+ return PlatformRemoteGDBServer::ConnectProcess(new_connect_url.c_str(),
+ plugin_name,
+ debugger,
+ target,
+ error);
+}
+
+size_t
+PlatformAndroidRemoteGDBServer::ConnectToWaitingProcesses(Debugger& debugger, Error& error)
+{
+ std::vector<std::string> connection_urls;
+ GetPendingGdbServerList(connection_urls);
+
+ for (size_t i = 0; i < connection_urls.size(); ++i)
+ {
+ ConnectProcess(connection_urls[i].c_str(), nullptr, debugger, nullptr, error);
+ if (error.Fail())
+ return i; // We already connected to i process succsessfully
+ }
+ return connection_urls.size();
+}
diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
new file mode 100644
index 0000000000000..3d2653812dedc
--- /dev/null
+++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
@@ -0,0 +1,79 @@
+//===-- 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;
+
+ Error
+ ConnectRemote (Args& args) override;
+
+ Error
+ DisconnectRemote () override;
+
+ lldb::ProcessSP
+ ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error) override;
+
+ size_t
+ ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& 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);
+
+ Error
+ MakeConnectURL(const lldb::pid_t pid,
+ const uint16_t remote_port,
+ const char* remote_socket_name,
+ std::string& connect_url);
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformAndroidRemoteGDBServer);
+};
+
+} // namespace platform_android
+} // namespace lldb_private
+
+#endif // liblldb_PlatformAndroidRemoteGDBServer_h_
diff --git a/source/Plugins/Platform/CMakeLists.txt b/source/Plugins/Platform/CMakeLists.txt
new file mode 100644
index 0000000000000..2e3a3f7c1b2e2
--- /dev/null
+++ b/source/Plugins/Platform/CMakeLists.txt
@@ -0,0 +1,16 @@
+#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 "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)
diff --git a/source/Plugins/Platform/FreeBSD/CMakeLists.txt b/source/Plugins/Platform/FreeBSD/CMakeLists.txt
new file mode 100644
index 0000000000000..57153969c3b48
--- /dev/null
+++ b/source/Plugins/Platform/FreeBSD/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginPlatformFreeBSD
+ PlatformFreeBSD.cpp
+ )
diff --git a/source/Plugins/Platform/FreeBSD/Makefile b/source/Plugins/Platform/FreeBSD/Makefile
new file mode 100644
index 0000000000000..e5c25d8504df6
--- /dev/null
+++ b/source/Plugins/Platform/FreeBSD/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/FreeBSD/Makefile ------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformFreeBSD
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/Kalimba/CMakeLists.txt b/source/Plugins/Platform/Kalimba/CMakeLists.txt
new file mode 100644
index 0000000000000..df0bf9761a006
--- /dev/null
+++ b/source/Plugins/Platform/Kalimba/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginPlatformKalimba
+ PlatformKalimba.cpp
+ )
diff --git a/source/Plugins/Platform/Kalimba/Makefile b/source/Plugins/Platform/Kalimba/Makefile
new file mode 100644
index 0000000000000..c22b7d21c13d1
--- /dev/null
+++ b/source/Plugins/Platform/Kalimba/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/Kalimba/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformKalimba
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp b/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp
new file mode 100644
index 0000000000000..2f1e4d5543201
--- /dev/null
+++ b/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp
@@ -0,0 +1,324 @@
+//===-- 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/Error.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/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.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 ();
+}
+
+Error
+PlatformKalimba::ResolveExecutable (const ModuleSpec &ms,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ char exe_path[PATH_MAX];
+ ModuleSpec resolved_module_spec(ms);
+
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ {
+ resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
+ }
+
+ if (error.Success())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ if (error.Fail())
+ {
+ // If we failed, it may be because the vendor and os aren't known. If that is the
+ // case, try setting them to the host architecture and give it another try.
+ llvm::Triple &module_triple = resolved_module_spec.GetArchitecture().GetTriple();
+ bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
+ bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
+ if (!is_vendor_specified || !is_os_specified)
+ {
+ const llvm::Triple &host_triple = HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple();
+
+ if (!is_vendor_specified)
+ module_triple.setVendorName (host_triple.getVendorName());
+ if (!is_os_specified)
+ module_triple.setOSName (host_triple.getOSName());
+
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ }
+ }
+
+ // TODO find out why exe_module_sp might be NULL
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+ {
+ exe_module_sp.reset();
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+ }
+ else
+ {
+ // No valid architecture was specified, ask the platform for
+ // the architectures that we should be using (in the correct order)
+ // and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ }
+
+ return error;
+}
+
+Error
+PlatformKalimba::GetFileWithUUID (const FileSpec & /*platform_file*/,
+ const UUID * /*uuid_ptr*/, FileSpec & /*local_file*/)
+{
+ return Error();
+}
+
+
+//------------------------------------------------------------------
+/// 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::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ bool success = false;
+ if (IsHost())
+ {
+ success = false;
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+ }
+ return success;
+}
+
+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;
+}
+
+Error
+PlatformKalimba::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error 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,
+ Error &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.
+}
diff --git a/source/Plugins/Platform/Kalimba/PlatformKalimba.h b/source/Plugins/Platform/Kalimba/PlatformKalimba.h
new file mode 100644
index 0000000000000..dd68415838f03
--- /dev/null
+++ b/source/Plugins/Platform/Kalimba/PlatformKalimba.h
@@ -0,0 +1,99 @@
+//===-- 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
+ //------------------------------------------------------------
+ Error ResolveExecutable(const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription() override
+ {
+ return GetPluginDescriptionStatic(IsHost());
+ }
+
+ void GetStatus(Stream &strm) override;
+
+ Error GetFileWithUUID(const FileSpec &platform_file, const UUID *uuid, FileSpec &local_file) override;
+
+ bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info) override;
+
+ bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
+
+ size_t GetSoftwareBreakpointTrapOpcode(Target &target, BreakpointSite *bp_site) override;
+
+ lldb_private::Error LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override;
+
+ lldb::ProcessSP Attach(ProcessAttachInfo &attach_info, Debugger &debugger, Target *target,
+ Error &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_
diff --git a/source/Plugins/Platform/Linux/CMakeLists.txt b/source/Plugins/Platform/Linux/CMakeLists.txt
new file mode 100644
index 0000000000000..4a9eb1460e388
--- /dev/null
+++ b/source/Plugins/Platform/Linux/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginPlatformLinux
+ PlatformLinux.cpp
+ )
diff --git a/source/Plugins/Platform/Linux/Makefile b/source/Plugins/Platform/Linux/Makefile
new file mode 100644
index 0000000000000..2877fddf0bcd8
--- /dev/null
+++ b/source/Plugins/Platform/Linux/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/Linux/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformLinux
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp
new file mode 100644
index 0000000000000..8dc9769844c73
--- /dev/null
+++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -0,0 +1,868 @@
+//===-- 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/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/Property.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.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;
+
+//------------------------------------------------------------------
+/// Code to handle the PlatformLinux settings
+//------------------------------------------------------------------
+
+namespace
+{
+ class PlatformLinuxProperties : public Properties
+ {
+ public:
+ PlatformLinuxProperties();
+
+ ~PlatformLinuxProperties() override = default;
+
+ static ConstString&
+ GetSettingName ();
+
+ private:
+ static const PropertyDefinition*
+ GetStaticPropertyDefinitions();
+ };
+
+ typedef std::shared_ptr<PlatformLinuxProperties> PlatformLinuxPropertiesSP;
+
+} // anonymous namespace
+
+PlatformLinuxProperties::PlatformLinuxProperties() :
+ Properties ()
+{
+ m_collection_sp.reset (new OptionValueProperties(GetSettingName ()));
+ m_collection_sp->Initialize (GetStaticPropertyDefinitions ());
+}
+
+ConstString&
+PlatformLinuxProperties::GetSettingName ()
+{
+ static ConstString g_setting_name("linux");
+ return g_setting_name;
+}
+
+const PropertyDefinition*
+PlatformLinuxProperties::GetStaticPropertyDefinitions()
+{
+ static PropertyDefinition
+ g_properties[] =
+ {
+ { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL }
+ };
+
+ return g_properties;
+}
+
+static const PlatformLinuxPropertiesSP &
+GetGlobalProperties()
+{
+ static PlatformLinuxPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ g_settings_sp.reset (new PlatformLinuxProperties ());
+ return g_settings_sp;
+}
+
+void
+PlatformLinux::DebuggerInitialize (Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformLinuxProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForPlatformPlugin (debugger,
+ GetGlobalProperties()->GetValueProperties(),
+ ConstString ("Properties for the PlatformLinux plug-in."),
+ is_global_setting);
+ }
+}
+
+//------------------------------------------------------------------
+
+PlatformSP
+PlatformLinux::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 ("PlatformLinux::%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.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;
+ }
+ }
+
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s() creating remote-linux platform", __FUNCTION__);
+ return PlatformSP(new PlatformLinux(false));
+ }
+
+ if (log)
+ log->Printf ("PlatformLinux::%s() aborting creation of remote-linux platform", __FUNCTION__);
+
+ 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,
+ PlatformLinux::DebuggerInitialize);
+ }
+}
+
+void
+PlatformLinux::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformLinux::CreateInstance);
+ }
+ }
+
+ PlatformPOSIX::Terminate ();
+}
+
+Error
+PlatformLinux::ResolveExecutable (const ModuleSpec &ms,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ char exe_path[PATH_MAX];
+ ModuleSpec resolved_module_spec (ms);
+
+ if (IsHost())
+ {
+ // If we have "ls" as the exe_file, resolve the executable location based on
+ // the current path variables
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ {
+ resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ }
+
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ {
+ error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ {
+ error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
+ }
+ else
+ {
+ // We may connect to a process and use the provided executable (Don't use local $PATH).
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
+ }
+ }
+
+ if (error.Success())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ if (error.Fail())
+ {
+ // If we failed, it may be because the vendor and os aren't known. If that is the
+ // case, try setting them to the host architecture and give it another try.
+ llvm::Triple &module_triple = resolved_module_spec.GetArchitecture().GetTriple();
+ bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
+ bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
+ if (!is_vendor_specified || !is_os_specified)
+ {
+ const llvm::Triple &host_triple = HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple();
+
+ if (!is_vendor_specified)
+ module_triple.setVendorName (host_triple.getVendorName());
+ if (!is_os_specified)
+ module_triple.setOSName (host_triple.getOSName());
+
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ }
+ }
+
+ // TODO find out why exe_module_sp might be NULL
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+ {
+ exe_module_sp.reset();
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+ }
+ else
+ {
+ // No valid architecture was specified, ask the platform for
+ // the architectures that we should be using (in the correct order)
+ // and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ }
+
+ return error;
+}
+
+Error
+PlatformLinux::GetFileWithUUID (const FileSpec &platform_file,
+ const UUID *uuid_ptr, FileSpec &local_file)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
+ }
+
+ // Default to the local case
+ local_file = platform_file;
+ return Error();
+}
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformLinux::PlatformLinux (bool is_host) :
+ PlatformPOSIX(is_host) // This is the local host platform
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformLinux::~PlatformLinux() = default;
+
+bool
+PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ bool success = false;
+ if (IsHost())
+ {
+ success = Platform::GetProcessInfo (pid, process_info);
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+ }
+ return success;
+}
+
+uint32_t
+PlatformLinux::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ uint32_t match_count = 0;
+ if (IsHost())
+ {
+ // Let the base class figure out the host details
+ match_count = Platform::FindProcesses (match_info, process_infos);
+ }
+ else
+ {
+ // If we are remote, we can only return results if we are connected
+ if (m_remote_platform_sp)
+ match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
+ }
+ return match_count;
+}
+
+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;
+ 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
+}
+
+size_t
+PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target,
+ BreakpointSite *bp_site)
+{
+ ArchSpec arch = target.GetArchitecture();
+ const uint8_t *trap_opcode = NULL;
+ size_t trap_opcode_size = 0;
+
+ switch (arch.GetMachine())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case llvm::Triple::aarch64:
+ {
+ static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 };
+ trap_opcode = g_aarch64_opcode;
+ trap_opcode_size = sizeof(g_aarch64_opcode);
+ }
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
+ trap_opcode = g_i386_breakpoint_opcode;
+ trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
+ }
+ break;
+ case llvm::Triple::hexagon:
+ {
+ static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 };
+ trap_opcode = g_hex_opcode;
+ trap_opcode_size = sizeof(g_hex_opcode);
+ }
+ break;
+ case llvm::Triple::arm:
+ {
+ // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
+ // but the linux kernel does otherwise.
+ static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
+ static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
+
+ 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)
+ {
+ trap_opcode = g_thumb_breakpoint_opcode;
+ trap_opcode_size = sizeof(g_thumb_breakpoint_opcode);
+ }
+ else
+ {
+ trap_opcode = g_arm_breakpoint_opcode;
+ trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
+ }
+ }
+ break;
+ case llvm::Triple::mips:
+ case llvm::Triple::mips64:
+ {
+ static const uint8_t g_hex_opcode[] = { 0x00, 0x00, 0x00, 0x0d };
+ trap_opcode = g_hex_opcode;
+ trap_opcode_size = sizeof(g_hex_opcode);
+ }
+ break;
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64el:
+ {
+ static const uint8_t g_hex_opcode[] = { 0x0d, 0x00, 0x00, 0x00 };
+ trap_opcode = g_hex_opcode;
+ trap_opcode_size = sizeof(g_hex_opcode);
+ }
+ break;
+ }
+
+ if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+ return trap_opcode_size;
+ return 0;
+}
+
+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
+ Error &error)
+{
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf ("PlatformLinux::%s entered (target %p)", __FUNCTION__, static_cast<void*>(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)
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s creating new target", __FUNCTION__);
+
+ TargetSP new_target_sp;
+ error = debugger.GetTargetList().CreateTarget (debugger,
+ nullptr,
+ nullptr,
+ false,
+ nullptr,
+ new_target_sp);
+ if (error.Fail ())
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s failed to create new target: %s", __FUNCTION__, error.AsCString ());
+ return process_sp;
+ }
+
+ target = new_target_sp.get();
+ if (!target)
+ {
+ error.SetErrorString ("CreateTarget() returned nullptr");
+ if (log)
+ log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
+ return process_sp;
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s using provided target", __FUNCTION__);
+ }
+
+ // Mark target as currently selected target.
+ debugger.GetTargetList().SetSelectedTarget(target);
+
+ // Now create the gdb-remote process.
+ if (log)
+ log->Printf ("PlatformLinux::%s having target create process with gdb-remote plugin", __FUNCTION__);
+ process_sp = target->CreateProcess (launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr);
+
+ if (!process_sp)
+ {
+ error.SetErrorString ("CreateProcess() failed for gdb-remote process");
+ if (log)
+ log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ());
+ return process_sp;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s successfully created process", __FUNCTION__);
+ }
+
+ // Adjust launch for a hijacker.
+ ListenerSP listener_sp;
+ if (!launch_info.GetHijackListener ())
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s setting up hijacker", __FUNCTION__);
+
+ listener_sp.reset (new Listener("lldb.PlatformLinux.DebugProcess.hijack"));
+ launch_info.SetHijackListener (listener_sp);
+ process_sp->HijackProcessEvents (listener_sp.get ());
+ }
+
+ // Log file actions.
+ if (log)
+ {
+ log->Printf ("PlatformLinux::%s launching process with the following file actions:", __FUNCTION__);
+
+ StreamString stream;
+ size_t i = 0;
+ const FileAction *file_action;
+ while ((file_action = launch_info.GetFileActionAtIndex (i++)) != nullptr)
+ {
+ file_action->Dump (stream);
+ log->PutCString (stream.GetString().c_str ());
+ 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 (NULL, NULL, false, listener_sp.get());
+
+ if (state == eStateStopped)
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s pid %" PRIu64 " state %s\n",
+ __FUNCTION__, process_sp->GetID (), StateAsCString (state));
+ }
+ else
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s pid %" PRIu64 " state is not stopped - %s\n",
+ __FUNCTION__, process_sp->GetID (), StateAsCString (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 != lldb_utility::PseudoTerminal::invalid_fd)
+ {
+ process_sp->SetSTDIOFileDescriptor(pty_fd);
+ if (log)
+ log->Printf ("PlatformLinux::%s pid %" PRIu64 " hooked up STDIO pty to process", __FUNCTION__, process_sp->GetID ());
+ }
+ else
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s pid %" PRIu64 " not using process STDIO pty", __FUNCTION__, process_sp->GetID ());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("PlatformLinux::%s process launch failed: %s", __FUNCTION__, error.AsCString ());
+ // 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"));
+}
+
+uint64_t
+PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, unsigned flags)
+{
+ 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;
+ return flags_platform;
+}
+
+ConstString
+PlatformLinux::GetFullNameForDylib (ConstString basename)
+{
+ if (basename.IsEmpty())
+ return basename;
+
+ StreamString stream;
+ stream.Printf("lib%s.so", basename.GetCString());
+ return ConstString(stream.GetData());
+}
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.h b/source/Plugins/Platform/Linux/PlatformLinux.h
new file mode 100644
index 0000000000000..770a20c90cce6
--- /dev/null
+++ b/source/Plugins/Platform/Linux/PlatformLinux.h
@@ -0,0 +1,122 @@
+//===-- 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_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#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
+ DebuggerInitialize (Debugger &debugger);
+
+ 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
+ //------------------------------------------------------------
+ Error
+ ResolveExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetPluginDescriptionStatic(IsHost());
+ }
+
+ void
+ GetStatus (Stream &strm) override;
+
+ Error
+ GetFileWithUUID (const FileSpec &platform_file,
+ const UUID* uuid, FileSpec &local_file) override;
+
+ bool
+ GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info) override;
+
+ uint32_t
+ FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) override;
+
+ size_t
+ GetSoftwareBreakpointTrapOpcode (Target &target,
+ BreakpointSite *bp_site) override;
+
+ int32_t
+ GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info) override;
+
+ bool
+ CanDebugProcess () override;
+
+ lldb::ProcessSP
+ DebugProcess (ProcessLaunchInfo &launch_info,
+ Debugger &debugger,
+ Target *target,
+ Error &error) override;
+
+ void
+ CalculateTrapHandlerSymbolNames () override;
+
+ uint64_t
+ ConvertMmapFlagsToPlatform(const ArchSpec &arch, unsigned flags) override;
+
+ ConstString
+ GetFullNameForDylib (ConstString basename) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformLinux);
+ };
+
+} // namespace platform_linux
+} // namespace lldb_private
+
+#endif // liblldb_PlatformLinux_h_
diff --git a/source/Plugins/Platform/MacOSX/CMakeLists.txt b/source/Plugins/Platform/MacOSX/CMakeLists.txt
new file mode 100644
index 0000000000000..02566ab3db06d
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/CMakeLists.txt
@@ -0,0 +1,27 @@
+list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
+ PlatformDarwin.cpp
+ PlatformDarwinKernel.cpp
+ PlatformMacOSX.cpp
+ PlatformRemoteiOS.cpp
+ PlatformRemoteAppleTV.cpp
+ PlatformRemoteAppleWatch.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_PLATFORM_MACOSX_SOURCES})
diff --git a/source/Plugins/Platform/MacOSX/Makefile b/source/Plugins/Platform/MacOSX/Makefile
new file mode 100644
index 0000000000000..3e61dc982bd63
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/Makefile
@@ -0,0 +1,15 @@
+##===- source/Plugins/Platform/MacOSX/Makefile -------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformMacOSX
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
+
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
new file mode 100644
index 0000000000000..eea2844d5649f
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
@@ -0,0 +1,303 @@
+//===-- 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/Core/Error.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/PseudoTerminal.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_simulator_framework_path()
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformAppleSimulator::~PlatformAppleSimulator()
+{
+}
+
+lldb_private::Error
+PlatformAppleSimulator::LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info)
+{
+#if defined(__APPLE__)
+ LoadCoreSimulator();
+ CoreSimulatorSupport::Device device(GetSimulatorDevice());
+
+ if (device.GetState() != CoreSimulatorSupport::Device::State::Booted)
+ {
+ Error 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 Error();
+ }
+ else
+ return spawned.GetError();
+#else
+ Error 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();
+ 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
+}
+
+Error
+PlatformAppleSimulator::ConnectRemote (Args& args)
+{
+#if defined(__APPLE__)
+ Error 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();
+ 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
+ Error err;
+ err.SetErrorString(UNSUPPORTED_ERROR);
+ return err;
+#endif
+}
+
+Error
+PlatformAppleSimulator::DisconnectRemote ()
+{
+#if defined(__APPLE__)
+ m_device.reset();
+ return Error();
+#else
+ Error 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
+ Error &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 != lldb_utility::PseudoTerminal::invalid_fd)
+ {
+ process_sp->SetSTDIOFileDescriptor(pty_fd);
+ }
+ }
+ }
+ }
+
+ return process_sp;
+#else
+ return ProcessSP();
+#endif
+}
+
+FileSpec
+PlatformAppleSimulator::GetCoreSimulatorPath()
+{
+#if defined(__APPLE__)
+ Mutex::Locker locker (m_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 std::once_flag g_load_core_sim_flag;
+ std::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().GetFanciest(dev_id);
+ }
+
+ if (m_device.hasValue())
+ return m_device.getValue();
+ else
+ return CoreSimulatorSupport::Device();
+}
+#endif
+
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
new file mode 100644
index 0000000000000..de8673b2a2af1
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
@@ -0,0 +1,81 @@
+//===-- 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
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Host/FileSpec.h"
+#include "PlatformDarwin.h"
+#include "PlatformiOSSimulatorCoreSimulatorSupport.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::Error
+ LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info) override;
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ lldb_private::Error
+ ConnectRemote (lldb_private::Args& args) override;
+
+ lldb_private::Error
+ DisconnectRemote () override;
+
+ lldb::ProcessSP
+ DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error) override;
+
+protected:
+ 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_
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
new file mode 100644
index 0000000000000..f537934a9172a
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
@@ -0,0 +1,466 @@
+//===-- PlatformAppleTVSimulator.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformAppleTVSimulator.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void
+PlatformAppleTVSimulator::Initialize ()
+{
+ PlatformDarwin::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+ PluginManager::RegisterPlugin (PlatformAppleTVSimulator::GetPluginNameStatic(),
+ PlatformAppleTVSimulator::GetDescriptionStatic(),
+ PlatformAppleTVSimulator::CreateInstance);
+ }
+}
+
+void
+PlatformAppleTVSimulator::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformAppleTVSimulator::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate ();
+}
+
+PlatformSP
+PlatformAppleTVSimulator::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 ("PlatformAppleTVSimulator::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ bool create = force;
+ if (create == false && arch && arch->IsValid())
+ {
+ switch (arch->GetMachine())
+ {
+ case llvm::Triple::x86_64:
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ switch (triple.getVendor())
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::TvOS:
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+#endif
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformAppleTVSimulator::%s() creating platform", __FUNCTION__);
+
+ return PlatformSP(new PlatformAppleTVSimulator ());
+ }
+
+ if (log)
+ log->Printf ("PlatformAppleTVSimulator::%s() aborting creation of platform", __FUNCTION__);
+
+ return PlatformSP();
+}
+
+
+lldb_private::ConstString
+PlatformAppleTVSimulator::GetPluginNameStatic ()
+{
+ static ConstString g_name("tvos-simulator");
+ return g_name;
+}
+
+const char *
+PlatformAppleTVSimulator::GetDescriptionStatic()
+{
+ return "Apple TV simulator platform plug-in.";
+}
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformAppleTVSimulator::PlatformAppleTVSimulator () :
+ PlatformDarwin (true),
+ m_sdk_directory ()
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformAppleTVSimulator::~PlatformAppleTVSimulator()
+{
+}
+
+
+void
+PlatformAppleTVSimulator::GetStatus (Stream &strm)
+{
+ Platform::GetStatus (strm);
+ const char *sdk_directory = GetSDKDirectoryAsCString();
+ if (sdk_directory)
+ strm.Printf (" SDK Path: \"%s\"\n", sdk_directory);
+ else
+ strm.PutCString (" SDK Path: error: unable to locate SDK\n");
+}
+
+
+Error
+PlatformAppleTVSimulator::ResolveExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ ModuleSpec resolved_module_spec(module_spec);
+
+ // If we have "ls" as the exe_file, resolve the executable loation based on
+ // the current path variables
+ // TODO: resolve bare executables in the Platform SDK
+// if (!resolved_exe_file.Exists())
+// resolved_exe_file.ResolveExecutableLocation ();
+
+ // Resolve any executable within a bundle on MacOSX
+ // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ return error;
+ exe_module_sp.reset();
+ }
+ // No valid architecture was specified or the exact ARM slice wasn't
+ // found so ask the platform for the architectures that we should be
+ // using (in the correct order) and see if we can find a match that way
+ StreamString arch_names;
+ ArchSpec platform_arch;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ // Only match x86 with x86 and x86_64 with x86_64...
+ if (!module_spec.GetArchitecture().IsValid() || module_spec.GetArchitecture().GetCore() == resolved_module_spec.GetArchitecture().GetCore())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (platform_arch.GetArchitectureName());
+ }
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ module_spec.GetFileSpec().GetPath().c_str());
+ }
+
+ return error;
+}
+
+static FileSpec::EnumerateDirectoryResult
+EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const FileSpec &file_spec)
+{
+ if (file_type == FileSpec::eFileTypeDirectory)
+ {
+ const char *filename = file_spec.GetFilename().GetCString();
+ if (filename && strncmp(filename, "AppleTVSimulator", strlen ("AppleTVSimulator")) == 0)
+ {
+ ::snprintf ((char *)baton, PATH_MAX, "%s", filename);
+ return FileSpec::eEnumerateDirectoryResultQuit;
+ }
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+
+
+const char *
+PlatformAppleTVSimulator::GetSDKDirectoryAsCString()
+{
+ Mutex::Locker locker (m_mutex);
+ if (m_sdk_directory.empty())
+ {
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir)
+ {
+ char sdks_directory[PATH_MAX];
+ char sdk_dirname[PATH_MAX];
+ sdk_dirname[0] = '\0';
+ snprintf (sdks_directory,
+ sizeof(sdks_directory),
+ "%s/Platforms/AppleTVSimulator.platform/Developer/SDKs",
+ developer_dir);
+ FileSpec simulator_sdk_spec;
+ bool find_directories = true;
+ bool find_files = false;
+ bool find_other = false;
+ FileSpec::EnumerateDirectory (sdks_directory,
+ find_directories,
+ find_files,
+ find_other,
+ EnumerateDirectoryCallback,
+ sdk_dirname);
+
+ if (sdk_dirname[0])
+ {
+ m_sdk_directory = sdks_directory;
+ m_sdk_directory.append (1, '/');
+ m_sdk_directory.append (sdk_dirname);
+ return m_sdk_directory.c_str();
+ }
+ }
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_sdk_directory.assign (1, '\0');
+ }
+
+ // We should have put a single NULL character into m_sdk_directory
+ // or it should have a valid path if the code gets here
+ assert (m_sdk_directory.empty() == false);
+ if (m_sdk_directory[0])
+ return m_sdk_directory.c_str();
+ return NULL;
+}
+
+Error
+PlatformAppleTVSimulator::GetSymbolFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ Error error;
+ char platform_file_path[PATH_MAX];
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ char resolved_path[PATH_MAX];
+
+ const char * sdk_dir = GetSDKDirectoryAsCString();
+ if (sdk_dir)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/%s",
+ sdk_dir,
+ platform_file_path);
+
+ // First try in the SDK and see if the file is in there
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+
+ // Else fall back to the actual path itself
+ local_file.SetFile(platform_file_path, true);
+ if (local_file.Exists())
+ return error;
+
+ }
+ error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
+ platform_file_path,
+ GetPluginName().GetCString());
+ }
+ else
+ {
+ error.SetErrorString ("invalid platform file argument");
+ }
+ return error;
+}
+
+Error
+PlatformAppleTVSimulator::GetSharedModule (const ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ // For AppleTV, the SDK files are all cached locally on the host
+ // system. So first we ask for the file in the cached SDK,
+ // then we attempt to get a shared module for the right architecture
+ // with the right UUID.
+ Error error;
+ ModuleSpec platform_module_spec (module_spec);
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+ error = GetSymbolFile (platform_file, module_spec.GetUUIDPtr(), platform_module_spec.GetFileSpec());
+ if (error.Success())
+ {
+ error = ResolveExecutable (platform_module_spec, module_sp, module_search_paths_ptr);
+ }
+ else
+ {
+ const bool always_create = false;
+ error = ModuleList::GetSharedModule (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr,
+ always_create);
+
+ }
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(platform_file);
+
+ return error;
+}
+
+
+uint32_t
+PlatformAppleTVSimulator::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ ProcessInstanceInfoList all_osx_process_infos;
+ // First we get all OSX processes
+ const uint32_t n = Host::FindProcesses (match_info, all_osx_process_infos);
+
+ // Now we filter them down to only the TvOS triples
+ for (uint32_t i=0; i<n; ++i)
+ {
+ const ProcessInstanceInfo &proc_info = all_osx_process_infos.GetProcessInfoAtIndex(i);
+ if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::TvOS) {
+ process_infos.Append(proc_info);
+ }
+ }
+ return process_infos.GetSize();
+}
+
+bool
+PlatformAppleTVSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ static const ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
+
+ if (idx == 0)
+ {
+ arch = platform_arch;
+ if (arch.IsValid())
+ {
+ arch.GetTriple().setOS (llvm::Triple::TvOS);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
new file mode 100644
index 0000000000000..0990f07292039
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
@@ -0,0 +1,121 @@
+//===-- PlatformAppleTVSimulator.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_PlatformAppleTVSimulator_h_
+#define liblldb_PlatformAppleTVSimulator_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "PlatformDarwin.h"
+
+class PlatformAppleTVSimulator : public PlatformDarwin
+{
+public:
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // Class Methods
+ //------------------------------------------------------------
+ PlatformAppleTVSimulator ();
+
+ virtual
+ ~PlatformAppleTVSimulator();
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ lldb_private::Error
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic();
+ }
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ virtual lldb_private::Error
+ GetSymbolFile (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ uint32_t
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+ void
+ AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
+ {
+ return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+ }
+
+protected:
+ std::string m_sdk_directory;
+ std::string m_build_update;
+
+ const char *
+ GetSDKDirectoryAsCString();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformAppleTVSimulator);
+
+};
+
+
+#endif // liblldb_PlatformAppleTVSimulator_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
new file mode 100644
index 0000000000000..ea8e789b2920d
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
@@ -0,0 +1,466 @@
+//===-- PlatformAppleWatchSimulator.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformAppleWatchSimulator.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void
+PlatformAppleWatchSimulator::Initialize ()
+{
+ PlatformDarwin::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+ PluginManager::RegisterPlugin (PlatformAppleWatchSimulator::GetPluginNameStatic(),
+ PlatformAppleWatchSimulator::GetDescriptionStatic(),
+ PlatformAppleWatchSimulator::CreateInstance);
+ }
+}
+
+void
+PlatformAppleWatchSimulator::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformAppleWatchSimulator::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate ();
+}
+
+PlatformSP
+PlatformAppleWatchSimulator::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 ("PlatformAppleWatchSimulator::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ bool create = force;
+ if (create == false && arch && arch->IsValid())
+ {
+ switch (arch->GetMachine())
+ {
+ case llvm::Triple::x86_64:
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ switch (triple.getVendor())
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::WatchOS:
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+#endif
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformAppleWatchSimulator::%s() creating platform", __FUNCTION__);
+
+ return PlatformSP(new PlatformAppleWatchSimulator ());
+ }
+
+ if (log)
+ log->Printf ("PlatformAppleWatchSimulator::%s() aborting creation of platform", __FUNCTION__);
+
+ return PlatformSP();
+}
+
+
+lldb_private::ConstString
+PlatformAppleWatchSimulator::GetPluginNameStatic ()
+{
+ static ConstString g_name("watchos-simulator");
+ return g_name;
+}
+
+const char *
+PlatformAppleWatchSimulator::GetDescriptionStatic()
+{
+ return "Apple Watch simulator platform plug-in.";
+}
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformAppleWatchSimulator::PlatformAppleWatchSimulator () :
+ PlatformDarwin (true),
+ m_sdk_directory ()
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformAppleWatchSimulator::~PlatformAppleWatchSimulator()
+{
+}
+
+
+void
+PlatformAppleWatchSimulator::GetStatus (Stream &strm)
+{
+ Platform::GetStatus (strm);
+ const char *sdk_directory = GetSDKDirectoryAsCString();
+ if (sdk_directory)
+ strm.Printf (" SDK Path: \"%s\"\n", sdk_directory);
+ else
+ strm.PutCString (" SDK Path: error: unable to locate SDK\n");
+}
+
+
+Error
+PlatformAppleWatchSimulator::ResolveExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ ModuleSpec resolved_module_spec(module_spec);
+
+ // If we have "ls" as the exe_file, resolve the executable loation based on
+ // the current path variables
+ // TODO: resolve bare executables in the Platform SDK
+// if (!resolved_exe_file.Exists())
+// resolved_exe_file.ResolveExecutableLocation ();
+
+ // Resolve any executable within a bundle on MacOSX
+ // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ return error;
+ exe_module_sp.reset();
+ }
+ // No valid architecture was specified or the exact ARM slice wasn't
+ // found so ask the platform for the architectures that we should be
+ // using (in the correct order) and see if we can find a match that way
+ StreamString arch_names;
+ ArchSpec platform_arch;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ // Only match x86 with x86 and x86_64 with x86_64...
+ if (!module_spec.GetArchitecture().IsValid() || module_spec.GetArchitecture().GetCore() == resolved_module_spec.GetArchitecture().GetCore())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (platform_arch.GetArchitectureName());
+ }
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ module_spec.GetFileSpec().GetPath().c_str());
+ }
+
+ return error;
+}
+
+static FileSpec::EnumerateDirectoryResult
+EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const FileSpec &file_spec)
+{
+ if (file_type == FileSpec::eFileTypeDirectory)
+ {
+ const char *filename = file_spec.GetFilename().GetCString();
+ if (filename && strncmp(filename, "AppleWatchSimulator", strlen ("AppleWatchSimulator")) == 0)
+ {
+ ::snprintf ((char *)baton, PATH_MAX, "%s", filename);
+ return FileSpec::eEnumerateDirectoryResultQuit;
+ }
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+
+
+const char *
+PlatformAppleWatchSimulator::GetSDKDirectoryAsCString()
+{
+ Mutex::Locker locker (m_mutex);
+ if (m_sdk_directory.empty())
+ {
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir)
+ {
+ char sdks_directory[PATH_MAX];
+ char sdk_dirname[PATH_MAX];
+ sdk_dirname[0] = '\0';
+ snprintf (sdks_directory,
+ sizeof(sdks_directory),
+ "%s/Platforms/AppleWatchSimulator.platform/Developer/SDKs",
+ developer_dir);
+ FileSpec simulator_sdk_spec;
+ bool find_directories = true;
+ bool find_files = false;
+ bool find_other = false;
+ FileSpec::EnumerateDirectory (sdks_directory,
+ find_directories,
+ find_files,
+ find_other,
+ EnumerateDirectoryCallback,
+ sdk_dirname);
+
+ if (sdk_dirname[0])
+ {
+ m_sdk_directory = sdks_directory;
+ m_sdk_directory.append (1, '/');
+ m_sdk_directory.append (sdk_dirname);
+ return m_sdk_directory.c_str();
+ }
+ }
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_sdk_directory.assign (1, '\0');
+ }
+
+ // We should have put a single NULL character into m_sdk_directory
+ // or it should have a valid path if the code gets here
+ assert (m_sdk_directory.empty() == false);
+ if (m_sdk_directory[0])
+ return m_sdk_directory.c_str();
+ return NULL;
+}
+
+Error
+PlatformAppleWatchSimulator::GetSymbolFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ Error error;
+ char platform_file_path[PATH_MAX];
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ char resolved_path[PATH_MAX];
+
+ const char * sdk_dir = GetSDKDirectoryAsCString();
+ if (sdk_dir)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/%s",
+ sdk_dir,
+ platform_file_path);
+
+ // First try in the SDK and see if the file is in there
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+
+ // Else fall back to the actual path itself
+ local_file.SetFile(platform_file_path, true);
+ if (local_file.Exists())
+ return error;
+
+ }
+ error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
+ platform_file_path,
+ GetPluginName().GetCString());
+ }
+ else
+ {
+ error.SetErrorString ("invalid platform file argument");
+ }
+ return error;
+}
+
+Error
+PlatformAppleWatchSimulator::GetSharedModule (const ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ // For AppleWatch, the SDK files are all cached locally on the host
+ // system. So first we ask for the file in the cached SDK,
+ // then we attempt to get a shared module for the right architecture
+ // with the right UUID.
+ Error error;
+ ModuleSpec platform_module_spec (module_spec);
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+ error = GetSymbolFile (platform_file, module_spec.GetUUIDPtr(), platform_module_spec.GetFileSpec());
+ if (error.Success())
+ {
+ error = ResolveExecutable (platform_module_spec, module_sp, module_search_paths_ptr);
+ }
+ else
+ {
+ const bool always_create = false;
+ error = ModuleList::GetSharedModule (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr,
+ always_create);
+
+ }
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(platform_file);
+
+ return error;
+}
+
+
+uint32_t
+PlatformAppleWatchSimulator::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ ProcessInstanceInfoList all_osx_process_infos;
+ // First we get all OSX processes
+ const uint32_t n = Host::FindProcesses (match_info, all_osx_process_infos);
+
+ // Now we filter them down to only the WatchOS triples
+ for (uint32_t i=0; i<n; ++i)
+ {
+ const ProcessInstanceInfo &proc_info = all_osx_process_infos.GetProcessInfoAtIndex(i);
+ if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::WatchOS) {
+ process_infos.Append(proc_info);
+ }
+ }
+ return process_infos.GetSize();
+}
+
+bool
+PlatformAppleWatchSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ static const ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
+
+ if (idx == 0)
+ {
+ arch = platform_arch;
+ if (arch.IsValid())
+ {
+ arch.GetTriple().setOS (llvm::Triple::WatchOS);
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
new file mode 100644
index 0000000000000..8bcc0d4784fc6
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
@@ -0,0 +1,120 @@
+//===-- PlatformAppleWatchSimulator.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_PlatformAppleWatchSimulator_h_
+#define liblldb_PlatformAppleWatchSimulator_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "PlatformDarwin.h"
+
+class PlatformAppleWatchSimulator : public PlatformDarwin
+{
+public:
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // Class Methods
+ //------------------------------------------------------------
+ PlatformAppleWatchSimulator ();
+
+ virtual
+ ~PlatformAppleWatchSimulator();
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ lldb_private::Error
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic();
+ }
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ virtual lldb_private::Error
+ GetSymbolFile (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ uint32_t
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+ void
+ AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
+ {
+ return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+ }
+
+protected:
+ std::string m_sdk_directory;
+ std::string m_build_update;
+
+ const char *
+ GetSDKDirectoryAsCString();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformAppleWatchSimulator);
+
+};
+
+#endif // liblldb_PlatformAppleWatchSimulator_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
new file mode 100644
index 0000000000000..fb38630710a15
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -0,0 +1,1705 @@
+//===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformDarwin.h"
+
+// C Includes
+#include <string.h>
+
+// C++ Includes
+#include <algorithm>
+#include <mutex>
+
+// Other libraries and framework includes
+#include "clang/Basic/VersionTuple.h"
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointSite.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Host/StringConvert.h"
+#include "lldb/Host/XML.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "llvm/ADT/STLExtras.h"
+
+#if defined (__APPLE__)
+#include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformDarwin::PlatformDarwin (bool is_host) :
+ PlatformPOSIX(is_host), // This is the local host platform
+ m_developer_directory ()
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformDarwin::~PlatformDarwin()
+{
+}
+
+FileSpecList
+PlatformDarwin::LocateExecutableScriptingResources (Target *target,
+ Module &module,
+ Stream* feedback_stream)
+{
+ FileSpecList file_list;
+ if (target && target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython)
+ {
+ // NB some extensions might be meaningful and should not be stripped - "this.binary.file"
+ // should not lose ".file" but GetFileNameStrippingExtension() will do precisely that.
+ // Ideally, we should have a per-platform list of extensions (".exe", ".app", ".dSYM", ".framework")
+ // which should be stripped while leaving "this.binary.file" as-is.
+ ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+
+ FileSpec module_spec = module.GetFileSpec();
+
+ if (module_spec)
+ {
+ SymbolVendor *symbols = module.GetSymbolVendor ();
+ if (symbols)
+ {
+ SymbolFile *symfile = symbols->GetSymbolFile();
+ if (symfile)
+ {
+ ObjectFile *objfile = symfile->GetObjectFile();
+ if (objfile)
+ {
+ FileSpec symfile_spec (objfile->GetFileSpec());
+ if (symfile_spec && symfile_spec.Exists())
+ {
+ while (module_spec.GetFilename())
+ {
+ std::string module_basename (module_spec.GetFilename().GetCString());
+ std::string original_module_basename (module_basename);
+
+ bool was_keyword = false;
+
+ // FIXME: for Python, we cannot allow certain characters in module
+ // filenames we import. Theoretically, different scripting languages may
+ // have different sets of forbidden tokens in filenames, and that should
+ // be dealt with by each ScriptInterpreter. For now, we just replace dots
+ // with underscores, but if we ever support anything other than Python
+ // we will need to rework this
+ std::replace(module_basename.begin(), module_basename.end(), '.', '_');
+ std::replace(module_basename.begin(), module_basename.end(), ' ', '_');
+ std::replace(module_basename.begin(), module_basename.end(), '-', '_');
+ if (script_interpreter && script_interpreter->IsReservedWord(module_basename.c_str()))
+ {
+ module_basename.insert(module_basename.begin(), '_');
+ was_keyword = true;
+ }
+
+ StreamString path_string;
+ StreamString original_path_string;
+ // for OSX we are going to be in .dSYM/Contents/Resources/DWARF/<basename>
+ // let us go to .dSYM/Contents/Resources/Python/<basename>.py and see if the file exists
+ path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), module_basename.c_str());
+ original_path_string.Printf("%s/../Python/%s.py",symfile_spec.GetDirectory().GetCString(), original_module_basename.c_str());
+ FileSpec script_fspec(path_string.GetData(), true);
+ FileSpec orig_script_fspec(original_path_string.GetData(), true);
+
+ // if we did some replacements of reserved characters, and a file with the untampered name
+ // exists, then warn the user that the file as-is shall not be loaded
+ if (feedback_stream)
+ {
+ if (module_basename != original_module_basename
+ && orig_script_fspec.Exists())
+ {
+ const char* reason_for_complaint = was_keyword ? "conflicts with a keyword" : "contains reserved characters";
+ if (script_fspec.Exists())
+ feedback_stream->Printf("warning: the symbol file '%s' contains a debug script. However, its name"
+ " '%s' %s and as such cannot be loaded. LLDB will"
+ " load '%s' instead. Consider removing the file with the malformed name to"
+ " eliminate this warning.\n",
+ symfile_spec.GetPath().c_str(),
+ original_path_string.GetData(),
+ reason_for_complaint,
+ path_string.GetData());
+ else
+ feedback_stream->Printf("warning: the symbol file '%s' contains a debug script. However, its name"
+ " %s and as such cannot be loaded. If you intend"
+ " to have this script loaded, please rename '%s' to '%s' and retry.\n",
+ symfile_spec.GetPath().c_str(),
+ reason_for_complaint,
+ original_path_string.GetData(),
+ path_string.GetData());
+ }
+ }
+
+ if (script_fspec.Exists())
+ {
+ file_list.Append (script_fspec);
+ break;
+ }
+
+ // If we didn't find the python file, then keep
+ // stripping the extensions and try again
+ ConstString filename_no_extension (module_spec.GetFileNameStrippingExtension());
+ if (module_spec.GetFilename() == filename_no_extension)
+ break;
+
+ module_spec.GetFilename() = filename_no_extension;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return file_list;
+}
+
+Error
+PlatformDarwin::ResolveExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ char exe_path[PATH_MAX];
+ ModuleSpec resolved_module_spec(module_spec);
+
+ if (IsHost())
+ {
+ // If we have "ls" as the exe_file, resolve the executable loation based on
+ // the current path variables
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ {
+ module_spec.GetFileSpec().GetPath (exe_path, sizeof(exe_path));
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ }
+
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
+
+ // Resolve any executable within a bundle on MacOSX
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ {
+ const uint32_t permissions = resolved_module_spec.GetFileSpec().GetPermissions();
+ if (permissions && (permissions & eFilePermissionsEveryoneR) == 0)
+ error.SetErrorStringWithFormat ("executable '%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ else
+ error.SetErrorStringWithFormat ("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ {
+ error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
+ }
+ else
+ {
+ // We may connect to a process and use the provided executable (Don't use local $PATH).
+
+ // Resolve any executable within a bundle on MacOSX
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetFilename().AsCString(""));
+ }
+ }
+
+
+ if (error.Success())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
+
+ if (error.Fail() || exe_module_sp.get() == NULL || exe_module_sp->GetObjectFile() == NULL)
+ {
+ exe_module_sp.reset();
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+ }
+ else
+ {
+ // No valid architecture was specified, ask the platform for
+ // the architectures that we should be using (in the correct order)
+ // and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = GetSharedModule (resolved_module_spec,
+ NULL,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ }
+
+ return error;
+}
+
+Error
+PlatformDarwin::ResolveSymbolFile (Target &target,
+ const ModuleSpec &sym_spec,
+ FileSpec &sym_file)
+{
+ Error error;
+ sym_file = sym_spec.GetSymbolFileSpec();
+ if (sym_file.Exists())
+ {
+ if (sym_file.GetFileType() == FileSpec::eFileTypeDirectory)
+ {
+ sym_file = Symbols::FindSymbolFileInBundle (sym_file,
+ sym_spec.GetUUIDPtr(),
+ sym_spec.GetArchitecturePtr());
+ }
+ }
+ else
+ {
+ if (sym_spec.GetUUID().IsValid())
+ {
+
+ }
+ }
+ return error;
+
+}
+
+static lldb_private::Error
+MakeCacheFolderForFile (const FileSpec& module_cache_spec)
+{
+ FileSpec module_cache_folder = module_cache_spec.CopyByRemovingLastPathComponent();
+ return FileSystem::MakeDirectory(module_cache_folder, eFilePermissionsDirectoryDefault);
+}
+
+static lldb_private::Error
+BringInRemoteFile (Platform* platform,
+ const lldb_private::ModuleSpec &module_spec,
+ const FileSpec& module_cache_spec)
+{
+ MakeCacheFolderForFile(module_cache_spec);
+ Error err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec);
+ return err;
+}
+
+lldb_private::Error
+PlatformDarwin::GetSharedModuleWithLocalCache (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[%s] Trying to find module %s/%s - platform path %s/%s symbol path %s/%s",
+ (IsHost() ? "host" : "remote"),
+ module_spec.GetFileSpec().GetDirectory().AsCString(),
+ module_spec.GetFileSpec().GetFilename().AsCString(),
+ module_spec.GetPlatformFileSpec().GetDirectory().AsCString(),
+ module_spec.GetPlatformFileSpec().GetFilename().AsCString(),
+ module_spec.GetSymbolFileSpec().GetDirectory().AsCString(),
+ module_spec.GetSymbolFileSpec().GetFilename().AsCString());
+
+ Error err;
+
+ err = ModuleList::GetSharedModule(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
+ if (module_sp)
+ return err;
+
+ if (!IsHost())
+ {
+ std::string cache_path(GetLocalCacheDirectory());
+ // Only search for a locally cached file if we have a valid cache path
+ if (!cache_path.empty())
+ {
+ std::string module_path (module_spec.GetFileSpec().GetPath());
+ cache_path.append(module_path);
+ FileSpec module_cache_spec(cache_path.c_str(),false);
+
+ // if rsync is supported, always bring in the file - rsync will be very efficient
+ // when files are the same on the local and remote end of the connection
+ if (this->GetSupportsRSync())
+ {
+ err = BringInRemoteFile (this, module_spec, module_cache_spec);
+ if (err.Fail())
+ return err;
+ if (module_cache_spec.Exists())
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[%s] module %s/%s was rsynced and is now there",
+ (IsHost() ? "host" : "remote"),
+ module_spec.GetFileSpec().GetDirectory().AsCString(),
+ module_spec.GetFileSpec().GetFilename().AsCString());
+ ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
+ module_sp.reset(new Module(local_spec));
+ module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+ return Error();
+ }
+ }
+
+ // try to find the module in the cache
+ if (module_cache_spec.Exists())
+ {
+ // get the local and remote MD5 and compare
+ if (m_remote_platform_sp)
+ {
+ // when going over the *slow* GDB remote transfer mechanism we first check
+ // the hashes of the files - and only do the actual transfer if they differ
+ uint64_t high_local,high_remote,low_local,low_remote;
+ FileSystem::CalculateMD5(module_cache_spec, low_local, high_local);
+ m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), low_remote, high_remote);
+ if (low_local != low_remote || high_local != high_remote)
+ {
+ // bring in the remote file
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[%s] module %s/%s needs to be replaced from remote copy",
+ (IsHost() ? "host" : "remote"),
+ module_spec.GetFileSpec().GetDirectory().AsCString(),
+ module_spec.GetFileSpec().GetFilename().AsCString());
+ Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
+ if (err.Fail())
+ return err;
+ }
+ }
+
+ ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
+ module_sp.reset(new Module(local_spec));
+ module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[%s] module %s/%s was found in the cache",
+ (IsHost() ? "host" : "remote"),
+ module_spec.GetFileSpec().GetDirectory().AsCString(),
+ module_spec.GetFileSpec().GetFilename().AsCString());
+ return Error();
+ }
+
+ // bring in the remote module file
+ if (log)
+ log->Printf("[%s] module %s/%s needs to come in remotely",
+ (IsHost() ? "host" : "remote"),
+ module_spec.GetFileSpec().GetDirectory().AsCString(),
+ module_spec.GetFileSpec().GetFilename().AsCString());
+ Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
+ if (err.Fail())
+ return err;
+ if (module_cache_spec.Exists())
+ {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("[%s] module %s/%s is now cached and fine",
+ (IsHost() ? "host" : "remote"),
+ module_spec.GetFileSpec().GetDirectory().AsCString(),
+ module_spec.GetFileSpec().GetFilename().AsCString());
+ ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
+ module_sp.reset(new Module(local_spec));
+ module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+ return Error();
+ }
+ else
+ return Error("unable to obtain valid module file");
+ }
+ else
+ return Error("no cache path");
+ }
+ else
+ return Error ("unable to resolve module");
+}
+
+Error
+PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec,
+ Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ Error error;
+ module_sp.reset();
+
+ if (IsRemote())
+ {
+ // If we have a remote platform always, let it try and locate
+ // the shared module first.
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+ }
+ }
+
+ if (!module_sp)
+ {
+ // Fall back to the local platform and find the file locally
+ error = Platform::GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+ if (!module_sp && module_search_paths_ptr && platform_file)
+ {
+ // We can try to pull off part of the file path up to the bundle
+ // directory level and try any module search paths...
+ FileSpec bundle_directory;
+ if (Host::GetBundleDirectory (platform_file, bundle_directory))
+ {
+ if (platform_file == bundle_directory)
+ {
+ ModuleSpec new_module_spec (module_spec);
+ new_module_spec.GetFileSpec() = bundle_directory;
+ if (Host::ResolveExecutableInBundle (new_module_spec.GetFileSpec()))
+ {
+ Error new_error (Platform::GetSharedModule (new_module_spec,
+ process,
+ module_sp,
+ NULL,
+ old_module_sp_ptr,
+ did_create_ptr));
+
+ if (module_sp)
+ return new_error;
+ }
+ }
+ else
+ {
+ char platform_path[PATH_MAX];
+ char bundle_dir[PATH_MAX];
+ platform_file.GetPath (platform_path, sizeof(platform_path));
+ const size_t bundle_directory_len = bundle_directory.GetPath (bundle_dir, sizeof(bundle_dir));
+ char new_path[PATH_MAX];
+ size_t num_module_search_paths = module_search_paths_ptr->GetSize();
+ for (size_t i=0; i<num_module_search_paths; ++i)
+ {
+ const size_t search_path_len = module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(new_path, sizeof(new_path));
+ if (search_path_len < sizeof(new_path))
+ {
+ snprintf (new_path + search_path_len, sizeof(new_path) - search_path_len, "/%s", platform_path + bundle_directory_len);
+ FileSpec new_file_spec (new_path, false);
+ if (new_file_spec.Exists())
+ {
+ ModuleSpec new_module_spec (module_spec);
+ new_module_spec.GetFileSpec() = new_file_spec;
+ Error new_error (Platform::GetSharedModule (new_module_spec,
+ process,
+ module_sp,
+ NULL,
+ old_module_sp_ptr,
+ did_create_ptr));
+
+ if (module_sp)
+ {
+ module_sp->SetPlatformFileSpec(new_file_spec);
+ return new_error;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+ return error;
+}
+
+size_t
+PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
+{
+ const uint8_t *trap_opcode = NULL;
+ uint32_t trap_opcode_size = 0;
+ bool bp_is_thumb = false;
+
+ llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
+ switch (machine)
+ {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC };
+ trap_opcode = g_i386_breakpoint_opcode;
+ trap_opcode_size = sizeof(g_i386_breakpoint_opcode);
+ }
+ break;
+
+ case llvm::Triple::aarch64:
+ {
+ // TODO: fix this with actual darwin breakpoint opcode for arm64.
+ // right now debugging uses the Z packets with GDB remote so this
+ // is not needed, but the size needs to be correct...
+ static const uint8_t g_arm64_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
+ trap_opcode = g_arm64_breakpoint_opcode;
+ trap_opcode_size = sizeof(g_arm64_breakpoint_opcode);
+ }
+ break;
+
+ case llvm::Triple::thumb:
+ bp_is_thumb = true; // Fall through...
+ case llvm::Triple::arm:
+ {
+ static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
+ static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
+
+ // Auto detect arm/thumb if it wasn't explicitly specified
+ if (!bp_is_thumb)
+ {
+ lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
+ if (bp_loc_sp)
+ bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass () == eAddressClassCodeAlternateISA;
+ }
+ if (bp_is_thumb)
+ {
+ trap_opcode = g_thumb_breakpooint_opcode;
+ trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
+ break;
+ }
+ trap_opcode = g_arm_breakpoint_opcode;
+ trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
+ }
+ break;
+
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ {
+ static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
+ trap_opcode = g_ppc_breakpoint_opcode;
+ trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
+ }
+ break;
+
+ default:
+ assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()");
+ break;
+ }
+
+ if (trap_opcode && trap_opcode_size)
+ {
+ if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+ return trap_opcode_size;
+ }
+ return 0;
+
+}
+
+bool
+PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ bool success = false;
+ if (IsHost())
+ {
+ success = Platform::GetProcessInfo (pid, process_info);
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+ }
+ return success;
+}
+
+uint32_t
+PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ uint32_t match_count = 0;
+ if (IsHost())
+ {
+ // Let the base class figure out the host details
+ match_count = Platform::FindProcesses (match_info, process_infos);
+ }
+ else
+ {
+ // If we are remote, we can only return results if we are connected
+ if (m_remote_platform_sp)
+ match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
+ }
+ return match_count;
+}
+
+bool
+PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches (lldb_private::Target &target, const lldb::ModuleSP &module_sp)
+{
+ if (!module_sp)
+ return false;
+
+ ObjectFile *obj_file = module_sp->GetObjectFile();
+ if (!obj_file)
+ return false;
+
+ ObjectFile::Type obj_type = obj_file->GetType();
+ if (obj_type == ObjectFile::eTypeDynamicLinker)
+ return true;
+ else
+ return false;
+}
+
+bool
+PlatformDarwin::x86GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
+ if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h)
+ {
+ switch (idx)
+ {
+ case 0:
+ arch = host_arch;
+ return true;
+
+ case 1:
+ arch.SetTriple("x86_64-apple-macosx");
+ return true;
+
+ case 2:
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
+ return true;
+
+ default: return false;
+ }
+ }
+ else
+ {
+ if (idx == 0)
+ {
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
+ return arch.IsValid();
+ }
+ else if (idx == 1)
+ {
+ ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
+ ArchSpec platform_arch64(HostInfo::GetArchitecture(HostInfo::eArchKind64));
+ if (platform_arch.IsExactMatch(platform_arch64))
+ {
+ // This macosx platform supports both 32 and 64 bit. Since we already
+ // returned the 64 bit arch for idx == 0, return the 32 bit arch
+ // for idx == 1
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
+ return arch.IsValid();
+ }
+ }
+ }
+ return false;
+}
+
+// The architecture selection rules for arm processors
+// These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f processor.
+
+bool
+PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ ArchSpec system_arch (GetSystemArchitecture());
+
+ // When lldb is running on a watch or tv, set the arch OS name appropriately.
+#if defined (TARGET_OS_TV) && TARGET_OS_TV == 1
+#define OSNAME "tvos"
+#elif defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+#define OSNAME "watchos"
+#else
+#define OSNAME "ios"
+#endif
+
+ const ArchSpec::Core system_core = system_arch.GetCore();
+ switch (system_core)
+ {
+ default:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("arm64-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv7f-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv7k-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv7s-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("armv7m-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("armv7em-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 12: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 13: arch.SetTriple ("thumbv7f-apple-" OSNAME); return true;
+ case 14: arch.SetTriple ("thumbv7k-apple-" OSNAME); return true;
+ case 15: arch.SetTriple ("thumbv7s-apple-" OSNAME); return true;
+ case 16: arch.SetTriple ("thumbv7m-apple-" OSNAME); return true;
+ case 17: arch.SetTriple ("thumbv7em-apple-" OSNAME); return true;
+ case 18: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 19: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 20: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 21: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 22: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_arm64:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("arm64-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv7s-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv7f-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv7m-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv7em-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 12: arch.SetTriple ("thumbv7f-apple-" OSNAME); return true;
+ case 13: arch.SetTriple ("thumbv7k-apple-" OSNAME); return true;
+ case 14: arch.SetTriple ("thumbv7s-apple-" OSNAME); return true;
+ case 15: arch.SetTriple ("thumbv7m-apple-" OSNAME); return true;
+ case 16: arch.SetTriple ("thumbv7em-apple-" OSNAME); return true;
+ case 17: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 18: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 19: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 20: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 21: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7f:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7f-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumbv7f-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 12: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 13: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7k:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7k-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumbv7k-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 12: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 13: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7s:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7s-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumbv7s-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 12: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 13: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7m:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7m-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumbv7m-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 12: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 13: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7em:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7em-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumbv7em-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 12: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 13: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("thumbv7-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 10: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 11: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv6m:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv6m-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("thumbv6m-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 8: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 9: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv6:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv6-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("thumbv6-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 6: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 7: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv5:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv5-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("thumbv5-apple-" OSNAME); return true;
+ case 4: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 5: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv4:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv4-apple-" OSNAME); return true;
+ case 1: arch.SetTriple ("arm-apple-" OSNAME); return true;
+ case 2: arch.SetTriple ("thumbv4t-apple-" OSNAME); return true;
+ case 3: arch.SetTriple ("thumb-apple-" OSNAME); return true;
+ default: break;
+ }
+ break;
+ }
+ arch.Clear();
+ return false;
+}
+
+
+const char *
+PlatformDarwin::GetDeveloperDirectory()
+{
+ Mutex::Locker locker (m_mutex);
+ if (m_developer_directory.empty())
+ {
+ bool developer_dir_path_valid = false;
+ char developer_dir_path[PATH_MAX];
+ FileSpec temp_file_spec;
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, temp_file_spec))
+ {
+ if (temp_file_spec.GetPath (developer_dir_path, sizeof(developer_dir_path)))
+ {
+ char *shared_frameworks = strstr (developer_dir_path, "/SharedFrameworks/LLDB.framework");
+ if (shared_frameworks)
+ {
+ ::snprintf (shared_frameworks,
+ sizeof(developer_dir_path) - (shared_frameworks - developer_dir_path),
+ "/Developer");
+ developer_dir_path_valid = true;
+ }
+ else
+ {
+ char *lib_priv_frameworks = strstr (developer_dir_path, "/Library/PrivateFrameworks/LLDB.framework");
+ if (lib_priv_frameworks)
+ {
+ *lib_priv_frameworks = '\0';
+ developer_dir_path_valid = true;
+ }
+ }
+ }
+ }
+
+ if (!developer_dir_path_valid)
+ {
+ std::string xcode_dir_path;
+ const char *xcode_select_prefix_dir = getenv ("XCODE_SELECT_PREFIX_DIR");
+ if (xcode_select_prefix_dir)
+ xcode_dir_path.append (xcode_select_prefix_dir);
+ xcode_dir_path.append ("/usr/share/xcode-select/xcode_dir_path");
+ temp_file_spec.SetFile(xcode_dir_path.c_str(), false);
+ size_t bytes_read = temp_file_spec.ReadFileContents(0, developer_dir_path, sizeof(developer_dir_path), NULL);
+ if (bytes_read > 0)
+ {
+ developer_dir_path[bytes_read] = '\0';
+ while (developer_dir_path[bytes_read-1] == '\r' ||
+ developer_dir_path[bytes_read-1] == '\n')
+ developer_dir_path[--bytes_read] = '\0';
+ developer_dir_path_valid = true;
+ }
+ }
+
+ if (!developer_dir_path_valid)
+ {
+ FileSpec xcode_select_cmd ("/usr/bin/xcode-select", false);
+ if (xcode_select_cmd.Exists())
+ {
+ int exit_status = -1;
+ int signo = -1;
+ std::string command_output;
+ Error error = Host::RunShellCommand ("/usr/bin/xcode-select --print-path",
+ NULL, // current working directory
+ &exit_status,
+ &signo,
+ &command_output,
+ 2, // short timeout
+ false); // don't run in a shell
+ if (error.Success() && exit_status == 0 && !command_output.empty())
+ {
+ const char *cmd_output_ptr = command_output.c_str();
+ developer_dir_path[sizeof (developer_dir_path) - 1] = '\0';
+ size_t i;
+ for (i = 0; i < sizeof (developer_dir_path) - 1; i++)
+ {
+ if (cmd_output_ptr[i] == '\r' || cmd_output_ptr[i] == '\n' || cmd_output_ptr[i] == '\0')
+ break;
+ developer_dir_path[i] = cmd_output_ptr[i];
+ }
+ developer_dir_path[i] = '\0';
+
+ FileSpec devel_dir (developer_dir_path, false);
+ if (devel_dir.Exists() && devel_dir.IsDirectory())
+ {
+ developer_dir_path_valid = true;
+ }
+ }
+ }
+ }
+
+ if (developer_dir_path_valid)
+ {
+ temp_file_spec.SetFile (developer_dir_path, false);
+ if (temp_file_spec.Exists())
+ {
+ m_developer_directory.assign (developer_dir_path);
+ return m_developer_directory.c_str();
+ }
+ }
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_developer_directory.assign (1, '\0');
+ }
+
+ // We should have put a single NULL character into m_developer_directory
+ // or it should have a valid path if the code gets here
+ assert (m_developer_directory.empty() == false);
+ if (m_developer_directory[0])
+ return m_developer_directory.c_str();
+ return NULL;
+}
+
+
+BreakpointSP
+PlatformDarwin::SetThreadCreationBreakpoint (Target &target)
+{
+ BreakpointSP bp_sp;
+ static const char *g_bp_names[] =
+ {
+ "start_wqthread",
+ "_pthread_wqthread",
+ "_pthread_start",
+ };
+
+ static const char *g_bp_modules[] =
+ {
+ "libsystem_c.dylib",
+ "libSystem.B.dylib"
+ };
+
+ FileSpecList bp_modules;
+ for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++)
+ {
+ const char *bp_module = g_bp_modules[i];
+ bp_modules.Append(FileSpec(bp_module, false));
+ }
+
+ bool internal = true;
+ bool hardware = false;
+ LazyBool skip_prologue = eLazyBoolNo;
+ bp_sp = target.CreateBreakpoint (&bp_modules,
+ NULL,
+ g_bp_names,
+ llvm::array_lengthof(g_bp_names),
+ eFunctionNameTypeFull,
+ eLanguageTypeUnknown,
+ skip_prologue,
+ internal,
+ hardware);
+ bp_sp->SetBreakpointKind("thread-creation");
+
+ return bp_sp;
+}
+
+
+int32_t
+PlatformDarwin::GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info)
+{
+ const FileSpec &shell = launch_info.GetShell();
+ if (!shell)
+ return 1;
+
+ std::string shell_string = shell.GetPath();
+ 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, "sh") == 0)
+ {
+ // /bin/sh re-exec's itself as /bin/bash requiring another resume.
+ // But it only does this if the COMMAND_MODE environment variable
+ // is set to "legacy".
+ const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+ if (envp != NULL)
+ {
+ for (int i = 0; envp[i] != NULL; i++)
+ {
+ if (strcmp (envp[i], "COMMAND_MODE=legacy" ) == 0)
+ return 2;
+ }
+ }
+ return 1;
+ }
+ else if (strcmp (shell_name, "csh") == 0
+ || strcmp (shell_name, "tcsh") == 0
+ || strcmp (shell_name, "zsh") == 0)
+ {
+ // csh and tcsh always seem to re-exec themselves.
+ return 2;
+ }
+ else
+ return 1;
+}
+
+void
+PlatformDarwin::CalculateTrapHandlerSymbolNames ()
+{
+ m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
+
+
+static const char *const sdk_strings[] = {
+ "MacOSX",
+ "iPhoneSimulator",
+ "iPhoneOS",
+};
+
+static FileSpec
+CheckPathForXcode(const FileSpec &fspec)
+{
+ if (fspec.Exists())
+ {
+ const char substr[] = ".app/Contents/";
+
+ std::string path_to_shlib = fspec.GetPath();
+ size_t pos = path_to_shlib.rfind(substr);
+ if (pos != std::string::npos)
+ {
+ path_to_shlib.erase(pos + strlen(substr));
+ FileSpec ret (path_to_shlib.c_str(), false);
+
+ FileSpec xcode_binary_path = ret;
+ xcode_binary_path.AppendPathComponent("MacOS");
+ xcode_binary_path.AppendPathComponent("Xcode");
+
+ if (xcode_binary_path.Exists())
+ {
+ return ret;
+ }
+ }
+ }
+ return FileSpec();
+}
+
+static FileSpec
+GetXcodeContentsPath ()
+{
+ static FileSpec g_xcode_filespec;
+ static std::once_flag g_once_flag;
+ std::call_once(g_once_flag, []() {
+
+
+ FileSpec fspec;
+
+ // First get the program file spec. If lldb.so or LLDB.framework is running
+ // in a program and that program is Xcode, the path returned with be the path
+ // to Xcode.app/Contents/MacOS/Xcode, so this will be the correct Xcode to use.
+ fspec = HostInfo::GetProgramFileSpec();
+
+ if (fspec)
+ {
+ // Ignore the current binary if it is python.
+ std::string basename_lower = fspec.GetFilename ().GetCString ();
+ std::transform(basename_lower.begin (), basename_lower.end (), basename_lower.begin (), tolower);
+ if (basename_lower != "python")
+ {
+ g_xcode_filespec = CheckPathForXcode(fspec);
+ }
+ }
+
+ // Next check DEVELOPER_DIR environment variable
+ if (!g_xcode_filespec)
+ {
+ const char *developer_dir_env_var = getenv("DEVELOPER_DIR");
+ if (developer_dir_env_var && developer_dir_env_var[0])
+ {
+ g_xcode_filespec = CheckPathForXcode(FileSpec(developer_dir_env_var, true));
+ }
+
+ // Fall back to using "xcrun" to find the selected Xcode
+ if (!g_xcode_filespec)
+ {
+ int status = 0;
+ int signo = 0;
+ std::string output;
+ const char *command = "/usr/bin/xcode-select -p";
+ lldb_private::Error error = Host::RunShellCommand (command, // shell command to run
+ NULL, // current working directory
+ &status, // Put the exit status of the process in here
+ &signo, // Put the signal that caused the process to exit in here
+ &output, // Get the output from the command and place it in this string
+ 3); // Timeout in seconds to wait for shell program to finish
+ if (status == 0 && !output.empty())
+ {
+ size_t first_non_newline = output.find_last_not_of("\r\n");
+ if (first_non_newline != std::string::npos)
+ {
+ output.erase(first_non_newline+1);
+ }
+ output.append("/..");
+
+ g_xcode_filespec = CheckPathForXcode(FileSpec(output.c_str(), false));
+ }
+ }
+ }
+ });
+
+ return g_xcode_filespec;
+}
+
+bool
+PlatformDarwin::SDKSupportsModules (SDKType sdk_type, uint32_t major, uint32_t minor, uint32_t micro)
+{
+ switch (sdk_type)
+ {
+ case SDKType::MacOSX:
+ if (major > 10 || (major == 10 && minor >= 10))
+ return true;
+ break;
+ case SDKType::iPhoneOS:
+ case SDKType::iPhoneSimulator:
+ if (major >= 8)
+ return true;
+ break;
+ }
+
+ return false;
+}
+
+bool
+PlatformDarwin::SDKSupportsModules (SDKType desired_type, const FileSpec &sdk_path)
+{
+ ConstString last_path_component = sdk_path.GetLastPathComponent();
+
+ if (last_path_component)
+ {
+ const llvm::StringRef sdk_name = last_path_component.GetStringRef();
+
+ llvm::StringRef version_part;
+
+ if (sdk_name.startswith(sdk_strings[(int)desired_type]))
+ {
+ version_part = sdk_name.drop_front(strlen(sdk_strings[(int)desired_type]));
+ }
+ else
+ {
+ return false;
+ }
+
+ const size_t major_dot_offset = version_part.find('.');
+ if (major_dot_offset == llvm::StringRef::npos)
+ return false;
+
+ const llvm::StringRef major_version = version_part.slice(0, major_dot_offset);
+ const llvm::StringRef minor_part = version_part.drop_front(major_dot_offset + 1);
+
+ const size_t minor_dot_offset = minor_part.find('.');
+ if (minor_dot_offset == llvm::StringRef::npos)
+ return false;
+
+ const llvm::StringRef minor_version = minor_part.slice(0, minor_dot_offset);
+
+ unsigned int major = 0;
+ unsigned int minor = 0;
+ unsigned int micro = 0;
+
+ if (major_version.getAsInteger(10, major))
+ return false;
+
+ if (minor_version.getAsInteger(10, minor))
+ return false;
+
+ return SDKSupportsModules(desired_type, major, minor, micro);
+ }
+
+ return false;
+}
+
+FileSpec::EnumerateDirectoryResult
+PlatformDarwin::DirectoryEnumerator(void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &spec)
+{
+ SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo*>(baton);
+
+ if (SDKSupportsModules(enumerator_info->sdk_type, spec))
+ {
+ enumerator_info->found_path = spec;
+ return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
+ }
+
+ return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
+}
+
+FileSpec
+PlatformDarwin::FindSDKInXcodeForModules (SDKType sdk_type,
+ const FileSpec &sdks_spec)
+{
+ // Look inside Xcode for the required installed iOS SDK version
+
+ if (!sdks_spec.IsDirectory())
+ return FileSpec();
+
+ const bool find_directories = true;
+ const bool find_files = false;
+ const bool find_other = true; // include symlinks
+
+ SDKEnumeratorInfo enumerator_info;
+
+ enumerator_info.sdk_type = sdk_type;
+
+ FileSpec::EnumerateDirectory(sdks_spec.GetPath().c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ DirectoryEnumerator,
+ &enumerator_info);
+
+ if (enumerator_info.found_path.IsDirectory())
+ return enumerator_info.found_path;
+ else
+ return FileSpec();
+}
+
+FileSpec
+PlatformDarwin::GetSDKDirectoryForModules (SDKType sdk_type)
+{
+ switch (sdk_type)
+ {
+ case SDKType::MacOSX:
+ case SDKType::iPhoneSimulator:
+ case SDKType::iPhoneOS:
+ break;
+ }
+
+ FileSpec sdks_spec = GetXcodeContentsPath();
+ sdks_spec.AppendPathComponent("Developer");
+ sdks_spec.AppendPathComponent("Platforms");
+
+ switch (sdk_type)
+ {
+ case SDKType::MacOSX:
+ sdks_spec.AppendPathComponent("MacOSX.platform");
+ break;
+ case SDKType::iPhoneSimulator:
+ sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
+ break;
+ case SDKType::iPhoneOS:
+ sdks_spec.AppendPathComponent("iPhoneOS.platform");
+ break;
+ }
+
+ sdks_spec.AppendPathComponent("Developer");
+ sdks_spec.AppendPathComponent("SDKs");
+
+ if (sdk_type == SDKType::MacOSX)
+ {
+ uint32_t major = 0;
+ uint32_t minor = 0;
+ uint32_t micro = 0;
+
+ if (HostInfo::GetOSVersion(major, minor, micro))
+ {
+ if (SDKSupportsModules(SDKType::MacOSX, major, minor, micro))
+ {
+ // We slightly prefer the exact SDK for this machine. See if it is there.
+
+ FileSpec native_sdk_spec = sdks_spec;
+ StreamString native_sdk_name;
+ native_sdk_name.Printf("MacOSX%u.%u.sdk", major, minor);
+ native_sdk_spec.AppendPathComponent(native_sdk_name.GetString().c_str());
+
+ if (native_sdk_spec.Exists())
+ {
+ return native_sdk_spec;
+ }
+ }
+ }
+ }
+
+ return FindSDKInXcodeForModules(sdk_type, sdks_spec);
+}
+
+void
+PlatformDarwin::AddClangModuleCompilationOptionsForSDKType (Target *target, std::vector<std::string> &options, SDKType sdk_type)
+{
+ const std::vector<std::string> apple_arguments =
+ {
+ "-x", "objective-c++",
+ "-fobjc-arc",
+ "-fblocks",
+ "-D_ISO646_H",
+ "-D__ISO646_H"
+ };
+
+ options.insert(options.end(),
+ apple_arguments.begin(),
+ apple_arguments.end());
+
+ StreamString minimum_version_option;
+ uint32_t versions[3] = { 0, 0, 0 };
+ bool use_current_os_version = false;
+ switch (sdk_type)
+ {
+ case SDKType::iPhoneOS:
+#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
+ use_current_os_version = true;
+#else
+ use_current_os_version = false;
+#endif
+ break;
+
+ case SDKType::iPhoneSimulator:
+ use_current_os_version = false;
+ break;
+
+ case SDKType::MacOSX:
+#if defined (__i386__) || defined (__x86_64__)
+ use_current_os_version = true;
+#else
+ use_current_os_version = false;
+#endif
+ break;
+ }
+
+ bool versions_valid = false;
+ if (use_current_os_version)
+ versions_valid = GetOSVersion(versions[0], versions[1], versions[2]);
+ else if (target)
+ {
+ // Our OS doesn't match our executable so we need to get the min OS version from the object file
+ ModuleSP exe_module_sp = target->GetExecutableModule();
+ if (exe_module_sp)
+ {
+ ObjectFile *object_file = exe_module_sp->GetObjectFile();
+ if (object_file)
+ versions_valid = object_file->GetMinimumOSVersion(versions, 3) > 0;
+ }
+ }
+ // Only add the version-min options if we got a version from somewhere
+ if (versions_valid && versions[0] != UINT32_MAX)
+ {
+ // Make any invalid versions be zero if needed
+ if (versions[1] == UINT32_MAX)
+ versions[1] = 0;
+ if (versions[2] == UINT32_MAX)
+ versions[2] = 0;
+
+ switch (sdk_type)
+ {
+ case SDKType::iPhoneOS:
+ minimum_version_option.PutCString("-mios-version-min=");
+ minimum_version_option.PutCString(clang::VersionTuple(versions[0], versions[1], versions[2]).getAsString().c_str());
+ break;
+ case SDKType::iPhoneSimulator:
+ minimum_version_option.PutCString("-mios-simulator-version-min=");
+ minimum_version_option.PutCString(clang::VersionTuple(versions[0], versions[1], versions[2]).getAsString().c_str());
+ break;
+ case SDKType::MacOSX:
+ minimum_version_option.PutCString("-mmacosx-version-min=");
+ minimum_version_option.PutCString(clang::VersionTuple(versions[0], versions[1], versions[2]).getAsString().c_str());
+ }
+ options.push_back(minimum_version_option.GetString());
+ }
+
+ FileSpec sysroot_spec;
+ // Scope for mutex locker below
+ {
+ Mutex::Locker locker (m_mutex);
+ sysroot_spec = GetSDKDirectoryForModules(sdk_type);
+ }
+
+ if (sysroot_spec.IsDirectory())
+ {
+ options.push_back("-isysroot");
+ options.push_back(sysroot_spec.GetPath());
+ }
+}
+
+ConstString
+PlatformDarwin::GetFullNameForDylib (ConstString basename)
+{
+ if (basename.IsEmpty())
+ return basename;
+
+ StreamString stream;
+ stream.Printf("lib%s.dylib", basename.GetCString());
+ return ConstString(stream.GetData());
+}
+
+bool
+PlatformDarwin::GetOSVersion (uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update,
+ Process *process)
+{
+ if (process && strstr(GetPluginName().GetCString(), "-simulator"))
+ {
+ lldb_private::ProcessInstanceInfo proc_info;
+ if (Host::GetProcessInfo(process->GetID(), proc_info))
+ {
+ Args &env = proc_info.GetEnvironmentEntries();
+ const size_t n = env.GetArgumentCount();
+ const llvm::StringRef k_runtime_version("SIMULATOR_RUNTIME_VERSION=");
+ const llvm::StringRef k_dyld_root_path("DYLD_ROOT_PATH=");
+ std::string dyld_root_path;
+
+ for (size_t i=0; i<n; ++i)
+ {
+ const char *env_cstr = env.GetArgumentAtIndex(i);
+ if (env_cstr)
+ {
+ llvm::StringRef env_str(env_cstr);
+ if (env_str.startswith(k_runtime_version))
+ {
+ llvm::StringRef version_str(env_str.substr(k_runtime_version.size()));
+ Args::StringToVersion (version_str.data(), major, minor, update);
+ if (major != UINT32_MAX)
+ return true;
+ }
+ else if (env_str.startswith(k_dyld_root_path))
+ {
+ dyld_root_path = env_str.substr(k_dyld_root_path.size()).str();
+ }
+ }
+ }
+
+ if (!dyld_root_path.empty())
+ {
+ dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
+ ApplePropertyList system_version_plist(dyld_root_path.c_str());
+ std::string product_version;
+ if (system_version_plist.GetValueAsString("ProductVersion", product_version))
+ {
+ Args::StringToVersion (product_version.c_str(), major, minor, update);
+ return major != UINT32_MAX;
+ }
+ }
+
+ }
+ // For simulator platforms, do NOT call back through Platform::GetOSVersion()
+ // as it might call Process::GetHostOSVersion() which we don't want as it will be
+ // incorrect
+ return false;
+ }
+
+ return Platform::GetOSVersion(major, minor, update, process);
+}
+
+lldb_private::FileSpec
+PlatformDarwin::LocateExecutable (const char *basename)
+{
+ // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled in with
+ // any executable directories that should be searched.
+ static std::vector<FileSpec> g_executable_dirs;
+
+ // Find the global list of directories that we will search for
+ // executables once so we don't keep doing the work over and over.
+ static std::once_flag g_once_flag;
+ std::call_once(g_once_flag, []() {
+
+ // When locating executables, trust the DEVELOPER_DIR first if it is set
+ FileSpec xcode_contents_dir = GetXcodeContentsPath();
+ if (xcode_contents_dir)
+ {
+ FileSpec xcode_lldb_resources = xcode_contents_dir;
+ xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
+ xcode_lldb_resources.AppendPathComponent("LLDB.framework");
+ xcode_lldb_resources.AppendPathComponent("Resources");
+ if (xcode_lldb_resources.Exists())
+ {
+ FileSpec dir;
+ dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
+ g_executable_dirs.push_back(dir);
+ }
+ }
+ });
+
+ // Now search the global list of executable directories for the executable we
+ // are looking for
+ for (const auto &executable_dir : g_executable_dirs)
+ {
+ FileSpec executable_file;
+ executable_file.GetDirectory() = executable_dir.GetDirectory();
+ executable_file.GetFilename().SetCString(basename);
+ if (executable_file.Exists())
+ return executable_file;
+ }
+
+ return FileSpec();
+}
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
new file mode 100644
index 0000000000000..b280b35da6551
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -0,0 +1,156 @@
+//===-- PlatformDarwin.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_PlatformDarwin_h_
+#define liblldb_PlatformDarwin_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Host/FileSpec.h"
+#include "Plugins/Platform/POSIX/PlatformPOSIX.h"
+
+class PlatformDarwin : public PlatformPOSIX
+{
+public:
+ PlatformDarwin(bool is_host);
+
+ ~PlatformDarwin() override;
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ lldb_private::Error
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr) override;
+
+ lldb_private::Error
+ ResolveSymbolFile (lldb_private::Target &target,
+ const lldb_private::ModuleSpec &sym_spec,
+ lldb_private::FileSpec &sym_file) override;
+
+ lldb_private::FileSpecList
+ LocateExecutableScriptingResources (lldb_private::Target *target,
+ lldb_private::Module &module,
+ lldb_private::Stream* feedback_stream) override;
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ size_t
+ GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target,
+ lldb_private::BreakpointSite *bp_site) override;
+
+ bool
+ GetProcessInfo (lldb::pid_t pid,
+ lldb_private::ProcessInstanceInfo &proc_info) override;
+
+ lldb::BreakpointSP
+ SetThreadCreationBreakpoint (lldb_private::Target &target) override;
+
+ uint32_t
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos) override;
+
+ bool
+ ModuleIsExcludedForUnconstrainedSearches(lldb_private::Target &target,
+ const lldb::ModuleSP &module_sp) override;
+
+ bool
+ ARMGetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
+
+ bool
+ x86GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
+
+ int32_t
+ GetResumeCountForLaunchInfo (lldb_private::ProcessLaunchInfo &launch_info) override;
+
+ void
+ CalculateTrapHandlerSymbolNames () override;
+
+ bool
+ GetOSVersion (uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update,
+ lldb_private::Process *process = nullptr) override;
+
+ bool
+ SupportsModules () override { return true; }
+
+ lldb_private::ConstString
+ GetFullNameForDylib (lldb_private::ConstString basename) override;
+
+ lldb_private::FileSpec
+ LocateExecutable (const char *basename) override;
+
+protected:
+ void
+ ReadLibdispatchOffsetsAddress (lldb_private::Process *process);
+
+ void
+ ReadLibdispatchOffsets (lldb_private::Process *process);
+
+ virtual lldb_private::Error
+ GetSharedModuleWithLocalCache (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr);
+
+ enum class SDKType {
+ MacOSX = 0,
+ iPhoneSimulator,
+ iPhoneOS,
+ };
+
+ static bool
+ SDKSupportsModules (SDKType sdk_type, uint32_t major, uint32_t minor, uint32_t micro);
+
+ static bool
+ SDKSupportsModules (SDKType desired_type, const lldb_private::FileSpec &sdk_path);
+
+ struct SDKEnumeratorInfo {
+ lldb_private::FileSpec found_path;
+ SDKType sdk_type;
+ };
+
+ static lldb_private::FileSpec::EnumerateDirectoryResult
+ DirectoryEnumerator(void *baton,
+ lldb_private::FileSpec::FileType file_type,
+ const lldb_private::FileSpec &spec);
+
+ static lldb_private::FileSpec
+ FindSDKInXcodeForModules (SDKType sdk_type,
+ const lldb_private::FileSpec &sdks_spec);
+
+ static lldb_private::FileSpec
+ GetSDKDirectoryForModules (PlatformDarwin::SDKType sdk_type);
+
+ void
+ AddClangModuleCompilationOptionsForSDKType (lldb_private::Target *target, std::vector<std::string> &options, SDKType sdk_type);
+
+ std::string m_developer_directory;
+
+ const char *
+ GetDeveloperDirectory();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformDarwin);
+};
+
+#endif // liblldb_PlatformDarwin_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
new file mode 100644
index 0000000000000..a502aa03eb269
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -0,0 +1,979 @@
+//===-- PlatformDarwinKernel.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformDarwinKernel.h"
+
+#if defined (__APPLE__) // This Plugin uses the Mac-specific source/Host/macosx/cfcpp utilities
+
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/OptionValueFileSpecList.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/Property.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "Host/macosx/cfcpp/CFCBundle.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void
+PlatformDarwinKernel::Initialize ()
+{
+ PlatformDarwin::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+ PluginManager::RegisterPlugin (PlatformDarwinKernel::GetPluginNameStatic(),
+ PlatformDarwinKernel::GetDescriptionStatic(),
+ PlatformDarwinKernel::CreateInstance,
+ PlatformDarwinKernel::DebuggerInitialize);
+ }
+}
+
+void
+PlatformDarwinKernel::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformDarwinKernel::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate ();
+}
+
+PlatformSP
+PlatformDarwinKernel::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 ("PlatformDarwinKernel::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ // This is a special plugin that we don't want to activate just based on an ArchSpec for normal
+ // userland debugging. It is only useful in kernel debug sessions and the DynamicLoaderDarwinPlugin
+ // (or a user doing 'platform select') will force the creation of this Platform plugin.
+ if (force == false)
+ {
+ if (log)
+ log->Printf ("PlatformDarwinKernel::%s() aborting creation of platform because force == false", __FUNCTION__);
+ return PlatformSP();
+ }
+
+ bool create = force;
+ LazyBool is_ios_debug_session = eLazyBoolCalculate;
+
+ if (create == false && arch && arch->IsValid())
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ switch (triple.getVendor())
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+ // Only accept "unknown" for vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+ default:
+ break;
+ }
+
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::Darwin:
+ case llvm::Triple::MacOSX:
+ case llvm::Triple::IOS:
+ case llvm::Triple::WatchOS:
+ case llvm::Triple::TvOS:
+ break;
+ // Only accept "vendor" for vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ if (arch && arch->IsValid())
+ {
+ switch (arch->GetMachine())
+ {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ is_ios_debug_session = eLazyBoolNo;
+ break;
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::thumb:
+ is_ios_debug_session = eLazyBoolYes;
+ break;
+ default:
+ is_ios_debug_session = eLazyBoolCalculate;
+ break;
+ }
+ }
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformDarwinKernel::%s() creating platform", __FUNCTION__);
+
+ return PlatformSP(new PlatformDarwinKernel (is_ios_debug_session));
+ }
+
+ if (log)
+ log->Printf ("PlatformDarwinKernel::%s() aborting creation of platform", __FUNCTION__);
+
+ return PlatformSP();
+}
+
+
+lldb_private::ConstString
+PlatformDarwinKernel::GetPluginNameStatic ()
+{
+ static ConstString g_name("darwin-kernel");
+ return g_name;
+}
+
+const char *
+PlatformDarwinKernel::GetDescriptionStatic()
+{
+ return "Darwin Kernel platform plug-in.";
+}
+
+//------------------------------------------------------------------
+/// Code to handle the PlatformDarwinKernel settings
+//------------------------------------------------------------------
+
+static PropertyDefinition
+g_properties[] =
+{
+ { "search-locally-for-kexts" , OptionValue::eTypeBoolean, true, true, NULL, NULL, "Automatically search for kexts on the local system when doing kernel debugging." },
+ { "kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL, "Directories/KDKs to search for kexts in when starting a kernel debug session." },
+ { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL }
+};
+
+enum {
+ ePropertySearchForKexts = 0,
+ ePropertyKextDirectories
+};
+
+
+
+class PlatformDarwinKernelProperties : public Properties
+{
+public:
+
+ static ConstString &
+ GetSettingName ()
+ {
+ static ConstString g_setting_name("darwin-kernel");
+ return g_setting_name;
+ }
+
+ PlatformDarwinKernelProperties() :
+ Properties ()
+ {
+ m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ virtual
+ ~PlatformDarwinKernelProperties()
+ {
+ }
+
+ bool
+ GetSearchForKexts() const
+ {
+ const uint32_t idx = ePropertySearchForKexts;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ }
+
+ FileSpecList &
+ GetKextDirectories() const
+ {
+ const uint32_t idx = ePropertyKextDirectories;
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
+ assert(option_value);
+ return option_value->GetCurrentValue();
+ }
+};
+
+typedef std::shared_ptr<PlatformDarwinKernelProperties> PlatformDarwinKernelPropertiesSP;
+
+static const PlatformDarwinKernelPropertiesSP &
+GetGlobalProperties()
+{
+ static PlatformDarwinKernelPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ g_settings_sp.reset (new PlatformDarwinKernelProperties ());
+ return g_settings_sp;
+}
+
+void
+PlatformDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformDarwinKernelProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForPlatformPlugin (debugger,
+ GetGlobalProperties()->GetValueProperties(),
+ ConstString ("Properties for the PlatformDarwinKernel plug-in."),
+ is_global_setting);
+ }
+}
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_session) :
+ PlatformDarwin (false), // This is a remote platform
+ m_name_to_kext_path_map(),
+ m_search_directories(),
+ m_kernel_binaries(),
+ m_ios_debug_session(is_ios_debug_session)
+
+{
+ if (GetGlobalProperties()->GetSearchForKexts())
+ {
+ CollectKextAndKernelDirectories ();
+ IndexKextsInDirectories ();
+ IndexKernelsInDirectories ();
+ }
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformDarwinKernel::~PlatformDarwinKernel()
+{
+}
+
+
+void
+PlatformDarwinKernel::GetStatus (Stream &strm)
+{
+ Platform::GetStatus (strm);
+ strm.Printf (" Debug session type: ");
+ if (m_ios_debug_session == eLazyBoolYes)
+ strm.Printf ("iOS kernel debugging\n");
+ else if (m_ios_debug_session == eLazyBoolNo)
+ strm.Printf ("Mac OS X kernel debugging\n");
+ else
+ strm.Printf ("unknown kernel debugging\n");
+ const uint32_t num_kext_dirs = m_search_directories.size();
+ for (uint32_t i=0; i<num_kext_dirs; ++i)
+ {
+ const FileSpec &kext_dir = m_search_directories[i];
+ strm.Printf (" Kext directories: [%2u] \"%s\"\n", i, kext_dir.GetPath().c_str());
+ }
+ strm.Printf (" Total number of kexts indexed: %d\n", (int) m_name_to_kext_path_map.size());
+}
+
+// Populate the m_search_directories vector with directories we should search
+// for kernel & kext binaries.
+
+void
+PlatformDarwinKernel::CollectKextAndKernelDirectories ()
+{
+ // Differentiate between "ios debug session" and "mac debug session" so we don't index
+ // kext bundles that won't be used in this debug session. If this is an ios kext debug
+ // session, looking in /System/Library/Extensions is a waste of stat()s, for example.
+
+ // Build up a list of all SDKs we'll be searching for directories of kexts/kernels
+ // e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk
+ std::vector<FileSpec> sdk_dirs;
+ if (m_ios_debug_session != eLazyBoolNo)
+ {
+ GetiOSSDKDirectoriesToSearch (sdk_dirs);
+ GetAppleTVOSSDKDirectoriesToSearch (sdk_dirs);
+ GetWatchOSSDKDirectoriesToSearch (sdk_dirs);
+ }
+ if (m_ios_debug_session != eLazyBoolYes)
+ GetMacSDKDirectoriesToSearch (sdk_dirs);
+
+ GetGenericSDKDirectoriesToSearch (sdk_dirs);
+
+ // Build up a list of directories that hold may kext bundles & kernels
+ //
+ // e.g. given /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
+ // find
+ // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/
+ // and
+ // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/System/Library/Extensions
+
+ std::vector<FileSpec> kext_dirs;
+ SearchSDKsForKextDirectories (sdk_dirs, kext_dirs);
+
+ if (m_ios_debug_session != eLazyBoolNo)
+ GetiOSDirectoriesToSearch (kext_dirs);
+ if (m_ios_debug_session != eLazyBoolYes)
+ GetMacDirectoriesToSearch (kext_dirs);
+
+ GetGenericDirectoriesToSearch (kext_dirs);
+
+ GetUserSpecifiedDirectoriesToSearch (kext_dirs);
+
+ GetKernelDirectoriesToSearch (kext_dirs);
+
+ GetCurrentDirectoryToSearch (kext_dirs);
+
+ // We now have a complete list of directories that we will search for kext bundles
+ m_search_directories = kext_dirs;
+}
+
+void
+PlatformDarwinKernel::GetiOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir == NULL)
+ developer_dir = "/Applications/Xcode.app/Contents/Developer";
+
+ char pathbuf[PATH_MAX];
+ ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/iPhoneOS.platform/Developer/SDKs", developer_dir);
+ FileSpec ios_sdk(pathbuf, true);
+ if (ios_sdk.Exists() && ios_sdk.IsDirectory())
+ {
+ directories.push_back (ios_sdk);
+ }
+}
+
+void
+PlatformDarwinKernel::GetAppleTVOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir == NULL)
+ developer_dir = "/Applications/Xcode.app/Contents/Developer";
+
+ char pathbuf[PATH_MAX];
+ ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/AppleTVOS.platform/Developer/SDKs", developer_dir);
+ FileSpec ios_sdk(pathbuf, true);
+ if (ios_sdk.Exists() && ios_sdk.IsDirectory())
+ {
+ directories.push_back (ios_sdk);
+ }
+}
+
+void
+PlatformDarwinKernel::GetWatchOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir == NULL)
+ developer_dir = "/Applications/Xcode.app/Contents/Developer";
+
+ char pathbuf[PATH_MAX];
+ ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/watchOS.platform/Developer/SDKs", developer_dir);
+ FileSpec ios_sdk(pathbuf, true);
+ if (ios_sdk.Exists() && ios_sdk.IsDirectory())
+ {
+ directories.push_back (ios_sdk);
+ }
+ else
+ {
+ ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/WatchOS.platform/Developer/SDKs", developer_dir);
+ FileSpec alt_watch_sdk(pathbuf, true);
+ if (ios_sdk.Exists() && ios_sdk.IsDirectory())
+ {
+ directories.push_back (ios_sdk);
+ }
+ }
+}
+
+
+void
+PlatformDarwinKernel::GetMacSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir == NULL)
+ developer_dir = "/Applications/Xcode.app/Contents/Developer";
+
+ char pathbuf[PATH_MAX];
+ ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/MacOSX.platform/Developer/SDKs", developer_dir);
+ FileSpec mac_sdk(pathbuf, true);
+ if (mac_sdk.Exists() && mac_sdk.IsDirectory())
+ {
+ directories.push_back (mac_sdk);
+ }
+}
+
+void
+PlatformDarwinKernel::GetGenericSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ FileSpec generic_sdk("/AppleInternal/Developer/KDKs", true);
+ if (generic_sdk.Exists() && generic_sdk.IsDirectory())
+ {
+ directories.push_back (generic_sdk);
+ }
+
+ // The KDKs distributed from Apple installed on external
+ // developer systems may be in directories like
+ // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
+ FileSpec installed_kdks("/Library/Developer/KDKs", true);
+ if (installed_kdks.Exists() && installed_kdks.IsDirectory())
+ {
+ directories.push_back (installed_kdks);
+ }
+}
+
+void
+PlatformDarwinKernel::GetiOSDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+}
+
+void
+PlatformDarwinKernel::GetMacDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ FileSpec sle("/System/Library/Extensions", true);
+ if (sle.Exists() && sle.IsDirectory())
+ {
+ directories.push_back(sle);
+ }
+
+ FileSpec le("/Library/Extensions", true);
+ if (le.Exists() && le.IsDirectory())
+ {
+ directories.push_back(le);
+ }
+
+ FileSpec kdk("/Volumes/KernelDebugKit", true);
+ if (kdk.Exists() && kdk.IsDirectory())
+ {
+ directories.push_back(kdk);
+ }
+}
+
+void
+PlatformDarwinKernel::GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir == NULL)
+ developer_dir = "/Applications/Xcode.app/Contents/Developer";
+
+ char pathbuf[PATH_MAX];
+ ::snprintf (pathbuf, sizeof (pathbuf), "%s/../Symbols", developer_dir);
+ FileSpec symbols_dir (pathbuf, true);
+ if (symbols_dir.Exists() && symbols_dir.IsDirectory())
+ {
+ directories.push_back (symbols_dir);
+ }
+}
+
+void
+PlatformDarwinKernel::GetKernelDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ FileSpec system_library_kernels ("/System/Library/Kernels", true);
+ if (system_library_kernels.Exists() && system_library_kernels.IsDirectory())
+ {
+ directories.push_back (system_library_kernels);
+ }
+ FileSpec slek("/System/Library/Extensions/KDK", true);
+ if (slek.Exists() && slek.IsDirectory())
+ {
+ directories.push_back(slek);
+ }
+}
+
+void
+PlatformDarwinKernel::GetCurrentDirectoryToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ directories.push_back (FileSpec (".", true));
+
+ FileSpec sle_directory ("System/Library/Extensions", true);
+ if (sle_directory.Exists() && sle_directory.IsDirectory())
+ {
+ directories.push_back (sle_directory);
+ }
+
+ FileSpec le_directory ("Library/Extensions", true);
+ if (le_directory.Exists() && le_directory.IsDirectory())
+ {
+ directories.push_back (le_directory);
+ }
+
+ FileSpec slk_directory ("System/Library/Kernels", true);
+ if (slk_directory.Exists() && slk_directory.IsDirectory())
+ {
+ directories.push_back (slk_directory);
+ }
+ FileSpec slek("System/Library/Extensions/KDK", true);
+ if (slek.Exists() && slek.IsDirectory())
+ {
+ directories.push_back(slek);
+ }
+}
+
+void
+PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
+{
+ FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories());
+ std::vector<FileSpec> possible_sdk_dirs;
+
+ const uint32_t user_dirs_count = user_dirs.GetSize();
+ for (uint32_t i = 0; i < user_dirs_count; i++)
+ {
+ FileSpec dir = user_dirs.GetFileSpecAtIndex (i);
+ dir.ResolvePath();
+ if (dir.Exists() && dir.IsDirectory())
+ {
+ directories.push_back (dir);
+ possible_sdk_dirs.push_back (dir); // does this directory have a *.sdk or *.kdk that we should look in?
+
+ // Is there a "System/Library/Extensions" subdir of this directory?
+ std::string dir_sle_path = dir.GetPath();
+ dir_sle_path.append ("/System/Library/Extensions");
+ FileSpec dir_sle(dir_sle_path.c_str(), true);
+ if (dir_sle.Exists() && dir_sle.IsDirectory())
+ {
+ directories.push_back (dir_sle);
+ }
+
+ // Is there a "System/Library/Kernels" subdir of this directory?
+ std::string dir_slk_path = dir.GetPath();
+ dir_slk_path.append ("/System/Library/Kernels");
+ FileSpec dir_slk(dir_slk_path.c_str(), true);
+ if (dir_slk.Exists() && dir_slk.IsDirectory())
+ {
+ directories.push_back (dir_slk);
+ }
+
+ // Is there a "System/Library/Extensions/KDK" subdir of this directory?
+ std::string dir_slek_path = dir.GetPath();
+ dir_slek_path.append ("/System/Library/Kernels");
+ FileSpec dir_slek(dir_slek_path.c_str(), true);
+ if (dir_slek.Exists() && dir_slek.IsDirectory())
+ {
+ directories.push_back (dir_slek);
+ }
+ }
+ }
+
+ SearchSDKsForKextDirectories (possible_sdk_dirs, directories);
+}
+
+// Scan through the SDK directories, looking for directories where kexts are likely.
+// Add those directories to kext_dirs.
+void
+PlatformDarwinKernel::SearchSDKsForKextDirectories (std::vector<lldb_private::FileSpec> sdk_dirs, std::vector<lldb_private::FileSpec> &kext_dirs)
+{
+ const uint32_t num_sdks = sdk_dirs.size();
+ for (uint32_t i = 0; i < num_sdks; i++)
+ {
+ const FileSpec &sdk_dir = sdk_dirs[i];
+ std::string sdk_dir_path = sdk_dir.GetPath();
+ if (!sdk_dir_path.empty())
+ {
+ const bool find_directories = true;
+ const bool find_files = false;
+ const bool find_other = false;
+ FileSpec::EnumerateDirectory (sdk_dir_path.c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ GetKextDirectoriesInSDK,
+ &kext_dirs);
+ }
+ }
+}
+
+// Callback for FileSpec::EnumerateDirectory().
+// Step through the entries in a directory like
+// /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
+// looking for any subdirectories of the form MacOSX10.8.Internal.sdk/System/Library/Extensions
+// Adds these to the vector of FileSpec's.
+
+FileSpec::EnumerateDirectoryResult
+PlatformDarwinKernel::GetKextDirectoriesInSDK (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &file_spec)
+{
+ if (file_type == FileSpec::eFileTypeDirectory
+ && (file_spec.GetFileNameExtension() == ConstString("sdk")
+ || file_spec.GetFileNameExtension() == ConstString("kdk")))
+ {
+ std::string kext_directory_path = file_spec.GetPath();
+
+ // Append the raw directory path, e.g. /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
+ // to the directory search list -- there may be kexts sitting directly
+ // in that directory instead of being in a System/Library/Extensions subdir.
+ ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
+
+ // Check to see if there is a System/Library/Extensions subdir & add it if it exists
+
+ std::string sle_kext_directory_path (kext_directory_path);
+ sle_kext_directory_path.append ("/System/Library/Extensions");
+ FileSpec sle_kext_directory (sle_kext_directory_path.c_str(), true);
+ if (sle_kext_directory.Exists() && sle_kext_directory.IsDirectory())
+ {
+ ((std::vector<lldb_private::FileSpec> *)baton)->push_back(sle_kext_directory);
+ }
+
+ // Check to see if there is a Library/Extensions subdir & add it if it exists
+
+ std::string le_kext_directory_path (kext_directory_path);
+ le_kext_directory_path.append ("/Library/Extensions");
+ FileSpec le_kext_directory (le_kext_directory_path.c_str(), true);
+ if (le_kext_directory.Exists() && le_kext_directory.IsDirectory())
+ {
+ ((std::vector<lldb_private::FileSpec> *)baton)->push_back(le_kext_directory);
+ }
+
+ // Check to see if there is a System/Library/Kernels subdir & add it if it exists
+ std::string slk_kernel_path (kext_directory_path);
+ slk_kernel_path.append ("/System/Library/Kernels");
+ FileSpec slk_kernel_directory (slk_kernel_path.c_str(), true);
+ if (slk_kernel_directory.Exists() && slk_kernel_directory.IsDirectory())
+ {
+ ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slk_kernel_directory);
+ }
+
+ // Check to see if there is a System/Library/Extensions/KDK subdir & add it if it exists
+ std::string slek_kernel_path (kext_directory_path);
+ slek_kernel_path.append ("/System/Library/Extensions/KDK");
+ FileSpec slek_kernel_directory (slek_kernel_path.c_str(), true);
+ if (slek_kernel_directory.Exists() && slek_kernel_directory.IsDirectory())
+ {
+ ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slek_kernel_directory);
+ }
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+void
+PlatformDarwinKernel::IndexKextsInDirectories ()
+{
+ std::vector<FileSpec> kext_bundles;
+
+ const uint32_t num_dirs = m_search_directories.size();
+ for (uint32_t i = 0; i < num_dirs; i++)
+ {
+ const FileSpec &dir = m_search_directories[i];
+ const bool find_directories = true;
+ const bool find_files = false;
+ const bool find_other = false;
+ FileSpec::EnumerateDirectory (dir.GetPath().c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ GetKextsInDirectory,
+ &kext_bundles);
+ }
+
+ const uint32_t num_kexts = kext_bundles.size();
+ for (uint32_t i = 0; i < num_kexts; i++)
+ {
+ const FileSpec &kext = kext_bundles[i];
+ CFCBundle bundle (kext.GetPath().c_str());
+ CFStringRef bundle_id (bundle.GetIdentifier());
+ if (bundle_id && CFGetTypeID (bundle_id) == CFStringGetTypeID ())
+ {
+ char bundle_id_buf[PATH_MAX];
+ if (CFStringGetCString (bundle_id, bundle_id_buf, sizeof (bundle_id_buf), kCFStringEncodingUTF8))
+ {
+ ConstString bundle_conststr(bundle_id_buf);
+ m_name_to_kext_path_map.insert(std::pair<ConstString, FileSpec>(bundle_conststr, kext));
+ }
+ }
+ }
+}
+
+// Callback for FileSpec::EnumerateDirectory().
+// Step through the entries in a directory like /System/Library/Extensions, find .kext bundles, add them
+// to the vector of FileSpecs.
+// If a .kext bundle has a Contents/PlugIns or PlugIns subdir, search for kexts in there too.
+
+FileSpec::EnumerateDirectoryResult
+PlatformDarwinKernel::GetKextsInDirectory (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &file_spec)
+{
+ if (file_type == FileSpec::eFileTypeDirectory && file_spec.GetFileNameExtension() == ConstString("kext"))
+ {
+ ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
+ std::string kext_bundle_path = file_spec.GetPath();
+ std::string search_here_too;
+ std::string contents_plugins_path = kext_bundle_path + "/Contents/PlugIns";
+ FileSpec contents_plugins (contents_plugins_path.c_str(), false);
+ if (contents_plugins.Exists() && contents_plugins.IsDirectory())
+ {
+ search_here_too = contents_plugins_path;
+ }
+ else
+ {
+ std::string plugins_path = kext_bundle_path + "/PlugIns";
+ FileSpec plugins (plugins_path.c_str(), false);
+ if (plugins.Exists() && plugins.IsDirectory())
+ {
+ search_here_too = plugins_path;
+ }
+ }
+
+ if (!search_here_too.empty())
+ {
+ const bool find_directories = true;
+ const bool find_files = false;
+ const bool find_other = false;
+ FileSpec::EnumerateDirectory (search_here_too.c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ GetKextsInDirectory,
+ baton);
+ }
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+void
+PlatformDarwinKernel::IndexKernelsInDirectories ()
+{
+ std::vector<FileSpec> kernels;
+
+
+ const uint32_t num_dirs = m_search_directories.size();
+ for (uint32_t i = 0; i < num_dirs; i++)
+ {
+ const FileSpec &dir = m_search_directories[i];
+ const bool find_directories = false;
+ const bool find_files = true;
+ const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s.
+ FileSpec::EnumerateDirectory (dir.GetPath().c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ GetKernelsInDirectory,
+ &m_kernel_binaries);
+ }
+}
+
+// Callback for FileSpec::EnumerateDirectory().
+// Step through the entries in a directory like /System/Library/Kernels/, find kernel binaries,
+// add them to m_kernel_binaries.
+
+// We're only doing a filename match here. We won't try opening the file to see if it's really
+// a kernel or not until we need to find a kernel of a given UUID. There's no cheap way to find
+// the UUID of a file (or if it's a Mach-O binary at all) without creating a whole Module for
+// the file and throwing it away if it's not wanted.
+
+FileSpec::EnumerateDirectoryResult
+PlatformDarwinKernel::GetKernelsInDirectory (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &file_spec)
+{
+ if (file_type == FileSpec::eFileTypeRegular || file_type == FileSpec::eFileTypeSymbolicLink)
+ {
+ ConstString filename = file_spec.GetFilename();
+ if (strncmp (filename.GetCString(), "kernel", 6) == 0
+ || strncmp (filename.GetCString(), "mach", 4) == 0)
+ {
+ // This is m_kernel_binaries but we're in a class method here
+ ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
+ }
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+
+Error
+PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec,
+ Process *process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ Error error;
+ module_sp.reset();
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+
+ // Treat the file's path as a kext bundle ID (e.g. "com.apple.driver.AppleIRController") and search our kext index.
+ std::string kext_bundle_id = platform_file.GetPath();
+ if (!kext_bundle_id.empty())
+ {
+ ConstString kext_bundle_cs(kext_bundle_id.c_str());
+ if (m_name_to_kext_path_map.count(kext_bundle_cs) > 0)
+ {
+ for (BundleIDToKextIterator it = m_name_to_kext_path_map.begin (); it != m_name_to_kext_path_map.end (); ++it)
+ {
+ if (it->first == kext_bundle_cs)
+ {
+ error = ExamineKextForMatchingUUID (it->second, module_spec.GetUUID(), module_spec.GetArchitecture(), module_sp);
+ if (module_sp.get())
+ {
+ return error;
+ }
+ }
+ }
+ }
+ }
+
+ if (kext_bundle_id.compare("mach_kernel") == 0 && module_spec.GetUUID().IsValid())
+ {
+ for (auto possible_kernel : m_kernel_binaries)
+ {
+ if (possible_kernel.Exists())
+ {
+ ModuleSpec kern_spec (possible_kernel);
+ kern_spec.GetUUID() = module_spec.GetUUID();
+ ModuleSP module_sp (new Module (kern_spec));
+ if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (kern_spec))
+ {
+ Error error;
+ error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL);
+ if (module_sp && module_sp->GetObjectFile())
+ {
+ return error;
+ }
+ }
+ }
+ }
+ }
+
+ // Else fall back to treating the file's path as an actual file path - defer to PlatformDarwin's GetSharedModule.
+ return PlatformDarwin::GetSharedModule (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
+}
+
+Error
+PlatformDarwinKernel::ExamineKextForMatchingUUID (const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, const ArchSpec &arch, ModuleSP &exe_module_sp)
+{
+ Error error;
+ FileSpec exe_file = kext_bundle_path;
+ Host::ResolveExecutableInBundle (exe_file);
+ if (exe_file.Exists())
+ {
+ ModuleSpec exe_spec (exe_file);
+ exe_spec.GetUUID() = uuid;
+ if (!uuid.IsValid())
+ {
+ exe_spec.GetArchitecture() = arch;
+ }
+
+ // First try to create a ModuleSP with the file / arch and see if the UUID matches.
+ // If that fails (this exec file doesn't have the correct uuid), don't call GetSharedModule
+ // (which may call in to the DebugSymbols framework and therefore can be slow.)
+ ModuleSP module_sp (new Module (exe_spec));
+ if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (exe_spec))
+ {
+ error = ModuleList::GetSharedModule (exe_spec, exe_module_sp, NULL, NULL, NULL);
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ {
+ return error;
+ }
+ }
+ exe_module_sp.reset();
+ }
+ return error;
+}
+
+bool
+PlatformDarwinKernel::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
+ return ARMGetSupportedArchitectureAtIndex (idx, arch);
+#else
+ return x86GetSupportedArchitectureAtIndex (idx, arch);
+#endif
+}
+
+void
+PlatformDarwinKernel::CalculateTrapHandlerSymbolNames ()
+{
+ m_trap_handlers.push_back(ConstString ("trap_from_kernel"));
+ m_trap_handlers.push_back(ConstString ("hndl_machine_check"));
+ m_trap_handlers.push_back(ConstString ("hndl_double_fault"));
+ m_trap_handlers.push_back(ConstString ("hndl_allintrs"));
+ m_trap_handlers.push_back(ConstString ("hndl_alltraps"));
+ m_trap_handlers.push_back(ConstString ("interrupt"));
+ m_trap_handlers.push_back(ConstString ("fleh_prefabt"));
+ m_trap_handlers.push_back(ConstString ("ExceptionVectorsBase"));
+ m_trap_handlers.push_back(ConstString ("ExceptionVectorsTable"));
+ m_trap_handlers.push_back(ConstString ("fleh_undef"));
+ m_trap_handlers.push_back(ConstString ("fleh_dataabt"));
+ m_trap_handlers.push_back(ConstString ("fleh_irq"));
+ m_trap_handlers.push_back(ConstString ("fleh_decirq"));
+ m_trap_handlers.push_back(ConstString ("fleh_fiq_generic"));
+ m_trap_handlers.push_back(ConstString ("fleh_dec"));
+
+}
+
+#else // __APPLE__
+
+// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on
+// PlatformDarwinKernel for the plug-in name, we compile just the plug-in name in
+// here to avoid issues. We are tracking an internal bug to resolve this issue by
+// either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to make
+// PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently not
+// compiled on other platforms due to the use of the Mac-specific
+// source/Host/macosx/cfcpp utilities.
+
+lldb_private::ConstString
+PlatformDarwinKernel::GetPluginNameStatic ()
+{
+ static lldb_private::ConstString g_name("darwin-kernel");
+ return g_name;
+}
+
+#endif // __APPLE__
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
new file mode 100644
index 0000000000000..c1fe23178bf47
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
@@ -0,0 +1,228 @@
+//===-- PlatformDarwinKernel.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_PlatformDarwinKernel_h_
+#define liblldb_PlatformDarwinKernel_h_
+
+#include "lldb/Core/ConstString.h"
+
+#if defined (__APPLE__) // This Plugin uses the Mac-specific source/Host/macosx/cfcpp utilities
+
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Host/FileSpec.h"
+
+// Project includes
+#include "PlatformDarwin.h"
+
+class PlatformDarwinKernel : public PlatformDarwin
+{
+public:
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ DebuggerInitialize (lldb_private::Debugger &debugger);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // Class Methods
+ //------------------------------------------------------------
+ PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_session);
+
+ virtual
+ ~PlatformDarwinKernel();
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic();
+ }
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process *process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+ bool
+ SupportsModules() override { return false; }
+
+ void
+ CalculateTrapHandlerSymbolNames () override;
+
+protected:
+
+ // Map from kext bundle ID ("com.apple.filesystems.exfat") to FileSpec for the kext bundle on
+ // the host ("/System/Library/Extensions/exfat.kext/Contents/Info.plist").
+ typedef std::multimap<lldb_private::ConstString, lldb_private::FileSpec> BundleIDToKextMap;
+ typedef BundleIDToKextMap::iterator BundleIDToKextIterator;
+
+ typedef std::vector<lldb_private::FileSpec> KernelBinaryCollection;
+
+ // Array of directories that were searched for kext bundles (used only for reporting to user)
+ typedef std::vector<lldb_private::FileSpec> DirectoriesSearchedCollection;
+ typedef DirectoriesSearchedCollection::iterator DirectoriesSearchedIterator;
+
+
+ static lldb_private::FileSpec::EnumerateDirectoryResult
+ GetKextDirectoriesInSDK (void *baton,
+ lldb_private::FileSpec::FileType file_type,
+ const lldb_private::FileSpec &file_spec);
+
+ static lldb_private::FileSpec::EnumerateDirectoryResult
+ GetKextsInDirectory (void *baton,
+ lldb_private::FileSpec::FileType file_type,
+ const lldb_private::FileSpec &file_spec);
+
+ // Populate m_search_directories vector of directories
+ void
+ CollectKextAndKernelDirectories ();
+
+ // Directories where we may find iOS SDKs with kext bundles in them
+ void
+ GetiOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find AppleTVOS SDKs with kext bundles in them
+ void
+ GetAppleTVOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find WatchOS SDKs with kext bundles in them
+ void
+ GetWatchOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find Mac OS X SDKs with kext bundles in them
+ void
+ GetMacSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find Mac OS X or iOS SDKs with kext bundles in them
+ void
+ GetGenericSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find iOS kext bundles
+ void
+ GetiOSDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find MacOSX kext bundles
+ void
+ GetMacDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find iOS or MacOSX kext bundles
+ void
+ GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories specified via the "kext-directories" setting - maybe KDK/SDKs, may be plain directories
+ void
+ GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ void
+ GetCurrentDirectoryToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Directories where we may find kernels exclusively
+ void
+ GetKernelDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories);
+
+ // Search through a vector of SDK FileSpecs, add any directories that may contain kexts
+ // to the vector of kext dir FileSpecs
+ void
+ SearchSDKsForKextDirectories (std::vector<lldb_private::FileSpec> sdk_dirs, std::vector<lldb_private::FileSpec> &kext_dirs);
+
+ // Search through all of the directories passed in, find all .kext bundles in those directories,
+ // get the CFBundleIDs out of the Info.plists and add the bundle ID and kext path to m_name_to_kext_path_map.
+ void
+ IndexKextsInDirectories ();
+
+ // Search through all of the directories passed in, find all kernel binaries in those directories
+ // (look for "kernel*", "mach.*", assume those are kernels. False positives aren't a huge problem.)
+ void
+ IndexKernelsInDirectories ();
+
+ // Callback which iterates over all the files in a given directory, looking for kernel binaries
+ static lldb_private::FileSpec::EnumerateDirectoryResult
+ GetKernelsInDirectory (void *baton,
+ lldb_private::FileSpec::FileType file_type,
+ const lldb_private::FileSpec &file_spec);
+
+ lldb_private::Error
+ ExamineKextForMatchingUUID (const lldb_private::FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, const lldb_private::ArchSpec &arch, lldb::ModuleSP &exe_module_sp);
+
+private:
+
+ BundleIDToKextMap m_name_to_kext_path_map; // multimap of CFBundleID to FileSpec on local filesystem
+ DirectoriesSearchedCollection m_search_directories; // list of directories we search for kexts/kernels
+ KernelBinaryCollection m_kernel_binaries; // list of kernel binaries we found on local filesystem
+ lldb_private::LazyBool m_ios_debug_session;
+
+ DISALLOW_COPY_AND_ASSIGN (PlatformDarwinKernel);
+
+};
+
+#else // __APPLE__
+
+// Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on
+// PlatformDarwinKernel for the plug-in name, we compile just the plug-in name in
+// here to avoid issues. We are tracking an internal bug to resolve this issue by
+// either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to make
+// PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently not
+// compiled on other platforms due to the use of the Mac-specific
+// source/Host/macosx/cfcpp utilities.
+
+class PlatformDarwinKernel
+{
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+};
+
+#endif // __APPLE__
+
+#endif // liblldb_PlatformDarwinKernel_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
new file mode 100644
index 0000000000000..7e15facc1b03b
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
@@ -0,0 +1,386 @@
+//===-- PlatformMacOSX.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformMacOSX.h"
+#include "lldb/Host/Config.h"
+
+// C++ Includes
+
+#include <sstream>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/FileSystem.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"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static uint32_t g_initialize_count = 0;
+
+void
+PlatformMacOSX::Initialize ()
+{
+ PlatformDarwin::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+#if defined (__APPLE__)
+ PlatformSP default_platform_sp (new PlatformMacOSX(true));
+ default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
+ Platform::SetHostPlatform (default_platform_sp);
+#endif
+ PluginManager::RegisterPlugin (PlatformMacOSX::GetPluginNameStatic(false),
+ PlatformMacOSX::GetDescriptionStatic(false),
+ PlatformMacOSX::CreateInstance);
+ }
+
+}
+
+void
+PlatformMacOSX::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformMacOSX::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate ();
+}
+
+PlatformSP
+PlatformMacOSX::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 ("PlatformMacOSX::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ // The only time we create an instance is when we are creating a remote
+ // macosx platform
+ const bool is_host = false;
+
+ bool create = force;
+ if (create == false && arch && arch->IsValid())
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ switch (triple.getVendor())
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::Darwin: // Deprecated, but still support Darwin for historical reasons
+ case llvm::Triple::MacOSX:
+ break;
+#if defined(__APPLE__)
+ // Only accept "vendor" for vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+#endif
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformMacOSX::%s() creating platform", __FUNCTION__);
+ return PlatformSP(new PlatformMacOSX (is_host));
+ }
+
+ if (log)
+ log->Printf ("PlatformMacOSX::%s() aborting creation of platform", __FUNCTION__);
+
+ return PlatformSP();
+}
+
+lldb_private::ConstString
+PlatformMacOSX::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-macosx");
+ return g_remote_name;
+ }
+}
+
+const char *
+PlatformMacOSX::GetDescriptionStatic (bool is_host)
+{
+ if (is_host)
+ return "Local Mac OS X user platform plug-in.";
+ else
+ return "Remote Mac OS X user platform plug-in.";
+}
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformMacOSX::PlatformMacOSX (bool is_host) :
+ PlatformDarwin (is_host)
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformMacOSX::~PlatformMacOSX()
+{
+}
+
+ConstString
+PlatformMacOSX::GetSDKDirectory (lldb_private::Target &target)
+{
+ ModuleSP exe_module_sp (target.GetExecutableModule());
+ if (exe_module_sp)
+ {
+ ObjectFile *objfile = exe_module_sp->GetObjectFile();
+ if (objfile)
+ {
+ std::string xcode_contents_path;
+ std::string default_xcode_sdk;
+ FileSpec fspec;
+ uint32_t versions[2];
+ if (objfile->GetSDKVersion(versions, sizeof(versions)))
+ {
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, fspec))
+ {
+ std::string path;
+ xcode_contents_path = fspec.GetPath();
+ size_t pos = xcode_contents_path.find("/Xcode.app/Contents/");
+ if (pos != std::string::npos)
+ {
+ // LLDB.framework is inside an Xcode app bundle, we can locate the SDK from here
+ xcode_contents_path.erase(pos + strlen("/Xcode.app/Contents/"));
+ }
+ else
+ {
+ xcode_contents_path.clear();
+ // Use the selected Xcode
+ int status = 0;
+ int signo = 0;
+ std::string output;
+ const char *command = "xcrun -sdk macosx --show-sdk-path";
+ lldb_private::Error error = RunShellCommand (command, // shell command to run
+ NULL, // current working directory
+ &status, // Put the exit status of the process in here
+ &signo, // Put the signal that caused the process to exit in here
+ &output, // Get the output from the command and place it in this string
+ 3); // Timeout in seconds to wait for shell program to finish
+ if (status == 0 && !output.empty())
+ {
+ size_t first_non_newline = output.find_last_not_of("\r\n");
+ if (first_non_newline != std::string::npos)
+ output.erase(first_non_newline+1);
+ default_xcode_sdk = output;
+
+ pos = default_xcode_sdk.find("/Xcode.app/Contents/");
+ if (pos != std::string::npos)
+ xcode_contents_path = default_xcode_sdk.substr(0, pos + strlen("/Xcode.app/Contents/"));
+ }
+ }
+ }
+
+ if (!xcode_contents_path.empty())
+ {
+ StreamString sdk_path;
+ sdk_path.Printf("%sDeveloper/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%u.%u.sdk", xcode_contents_path.c_str(), versions[0], versions[1]);
+ fspec.SetFile(sdk_path.GetString().c_str(), false);
+ if (fspec.Exists())
+ return ConstString(sdk_path.GetString().c_str());
+ }
+
+ if (!default_xcode_sdk.empty())
+ {
+ fspec.SetFile(default_xcode_sdk.c_str(), false);
+ if (fspec.Exists())
+ return ConstString(default_xcode_sdk.c_str());
+ }
+ }
+ }
+ }
+ return ConstString();
+}
+
+
+Error
+PlatformMacOSX::GetSymbolFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
+ }
+
+ // Default to the local case
+ local_file = platform_file;
+ return Error();
+}
+
+lldb_private::Error
+PlatformMacOSX::GetFileWithUUID (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file)
+{
+ if (IsRemote() && m_remote_platform_sp)
+ {
+ std::string local_os_build;
+#if !defined(__linux__)
+ HostInfo::GetOSBuildString(local_os_build);
+#endif
+ std::string remote_os_build;
+ m_remote_platform_sp->GetOSBuildString(remote_os_build);
+ if (local_os_build.compare(remote_os_build) == 0)
+ {
+ // same OS version: the local file is good enough
+ local_file = platform_file;
+ return Error();
+ }
+ else
+ {
+ // try to find the file in the cache
+ std::string cache_path(GetLocalCacheDirectory());
+ std::string module_path (platform_file.GetPath());
+ cache_path.append(module_path);
+ FileSpec module_cache_spec(cache_path.c_str(),false);
+ if (module_cache_spec.Exists())
+ {
+ local_file = module_cache_spec;
+ return Error();
+ }
+ // bring in the remote module file
+ FileSpec module_cache_folder = module_cache_spec.CopyByRemovingLastPathComponent();
+ // try to make the local directory first
+ Error err =
+ FileSystem::MakeDirectory(module_cache_folder, eFilePermissionsDirectoryDefault);
+ if (err.Fail())
+ return err;
+ err = GetFile(platform_file, module_cache_spec);
+ if (err.Fail())
+ return err;
+ if (module_cache_spec.Exists())
+ {
+ local_file = module_cache_spec;
+ return Error();
+ }
+ else
+ return Error("unable to obtain valid module file");
+ }
+ }
+ local_file = platform_file;
+ return Error();
+}
+
+bool
+PlatformMacOSX::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
+ return ARMGetSupportedArchitectureAtIndex (idx, arch);
+#else
+ return x86GetSupportedArchitectureAtIndex (idx, arch);
+#endif
+}
+
+lldb_private::Error
+PlatformMacOSX::GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ Error error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
+
+ if (module_sp)
+ {
+ if (module_spec.GetArchitecture().GetCore() == ArchSpec::eCore_x86_64_x86_64h)
+ {
+ ObjectFile *objfile = module_sp->GetObjectFile();
+ if (objfile == NULL)
+ {
+ // 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;
+ lldb::ModuleSP old_x86_64_module_sp;
+ bool did_create = false;
+ Error x86_64_error = GetSharedModuleWithLocalCache(module_spec_x86_64, x86_64_module_sp, module_search_paths_ptr, &old_x86_64_module_sp, &did_create);
+ if (x86_64_module_sp && x86_64_module_sp->GetObjectFile())
+ {
+ module_sp = x86_64_module_sp;
+ if (old_module_sp_ptr)
+ *old_module_sp_ptr = old_x86_64_module_sp;
+ if (did_create_ptr)
+ *did_create_ptr = did_create;
+ return x86_64_error;
+ }
+ }
+ }
+ }
+ return error;
+}
+
diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
new file mode 100644
index 0000000000000..10e177ea63626
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
@@ -0,0 +1,104 @@
+//===-- PlatformMacOSX.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_PlatformMacOSX_h_
+#define liblldb_PlatformMacOSX_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "PlatformDarwin.h"
+
+class PlatformMacOSX : public PlatformDarwin
+{
+public:
+ PlatformMacOSX(bool is_host);
+
+ ~PlatformMacOSX() override;
+
+ //------------------------------------------------------------
+ // Class functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic (bool is_host);
+
+ static const char *
+ GetDescriptionStatic(bool is_host);
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic (IsHost());
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic (IsHost());
+ }
+
+ lldb_private::Error
+ GetSymbolFile (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
+
+ lldb_private::Error
+ GetFile (const lldb_private::FileSpec& source,
+ const lldb_private::FileSpec& destination) override
+ {
+ return PlatformDarwin::GetFile (source,destination);
+ }
+
+ lldb_private::Error
+ GetFileWithUUID (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file) override;
+
+ bool GetSupportedArchitectureAtIndex(uint32_t idx, lldb_private::ArchSpec &arch) override;
+
+ lldb_private::ConstString GetSDKDirectory(lldb_private::Target &target) override;
+
+ void
+ AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
+ {
+ return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::MacOSX);
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformMacOSX);
+};
+
+#endif // liblldb_PlatformMacOSX_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
new file mode 100644
index 0000000000000..04231f27ff9b5
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
@@ -0,0 +1,912 @@
+//===-- PlatformRemoteAppleTV.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "PlatformRemoteAppleTV.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformRemoteAppleTV::PlatformRemoteAppleTV () :
+ PlatformDarwin (false), // This is a remote platform
+ m_sdk_directory_infos(),
+ m_device_support_directory(),
+ m_device_support_directory_for_os_version (),
+ m_build_update(),
+ m_last_module_sdk_idx (UINT32_MAX),
+ m_connected_module_sdk_idx (UINT32_MAX)
+{
+}
+
+PlatformRemoteAppleTV::SDKDirectoryInfo::SDKDirectoryInfo (const lldb_private::FileSpec &sdk_dir) :
+ directory(sdk_dir),
+ build(),
+ version_major(0),
+ version_minor(0),
+ version_update(0),
+ user_cached(false)
+{
+ const char *dirname_cstr = sdk_dir.GetFilename().GetCString();
+ const char *pos = Args::StringToVersion (dirname_cstr,
+ version_major,
+ version_minor,
+ version_update);
+
+ if (pos && pos[0] == ' ' && pos[1] == '(')
+ {
+ const char *build_start = pos + 2;
+ const char *end_paren = strchr (build_start, ')');
+ if (end_paren && build_start < end_paren)
+ build.SetCStringWithLength(build_start, end_paren - build_start);
+ }
+}
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void
+PlatformRemoteAppleTV::Initialize ()
+{
+ PlatformDarwin::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+ PluginManager::RegisterPlugin (PlatformRemoteAppleTV::GetPluginNameStatic(),
+ PlatformRemoteAppleTV::GetDescriptionStatic(),
+ PlatformRemoteAppleTV::CreateInstance);
+ }
+}
+
+void
+PlatformRemoteAppleTV::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformRemoteAppleTV::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate ();
+}
+
+PlatformSP
+PlatformRemoteAppleTV::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 ("PlatformRemoteAppleTV::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ bool create = force;
+ if (!create && arch && arch->IsValid())
+ {
+ switch (arch->GetMachine())
+ {
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::thumb:
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ llvm::Triple::VendorType vendor = triple.getVendor();
+ switch (vendor)
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+
+#endif
+ default:
+ break;
+ }
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::TvOS: // This is the right triple value for Apple TV debugging
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+#endif
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformRemoteAppleTV::%s() creating platform", __FUNCTION__);
+
+ return lldb::PlatformSP(new PlatformRemoteAppleTV ());
+ }
+
+ if (log)
+ log->Printf ("PlatformRemoteAppleTV::%s() aborting creation of platform", __FUNCTION__);
+
+ return lldb::PlatformSP();
+}
+
+lldb_private::ConstString
+PlatformRemoteAppleTV::GetPluginNameStatic ()
+{
+ static ConstString g_name("remote-tvos");
+ return g_name;
+}
+
+const char *
+PlatformRemoteAppleTV::GetDescriptionStatic()
+{
+ return "Remote Apple TV platform plug-in.";
+}
+
+void
+PlatformRemoteAppleTV::GetStatus (Stream &strm)
+{
+ Platform::GetStatus (strm);
+ const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
+ if (sdk_directory)
+ strm.Printf (" SDK Path: \"%s\"\n", sdk_directory);
+ else
+ strm.PutCString (" SDK Path: error: unable to locate SDK\n");
+
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ strm.Printf (" SDK Roots: [%2u] \"%s\"\n",
+ i,
+ sdk_dir_info.directory.GetPath().c_str());
+ }
+}
+
+Error
+PlatformRemoteAppleTV::ResolveExecutable (const ModuleSpec &ms,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ ModuleSpec resolved_module_spec(ms);
+
+ // Resolve any executable within a bundle on MacOSX
+ // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
+ {
+ error = ModuleList::GetSharedModule(resolved_module_spec,
+ exe_module_sp,
+ nullptr,
+ nullptr,
+ nullptr);
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ return error;
+ exe_module_sp.reset();
+ }
+ // No valid architecture was specified or the exact ARM slice wasn't
+ // found so ask the platform for the architectures that we should be
+ // using (in the correct order) and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule(resolved_module_spec,
+ exe_module_sp,
+ nullptr,
+ nullptr,
+ nullptr);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+
+ return error;
+}
+
+FileSpec::EnumerateDirectoryResult
+PlatformRemoteAppleTV::GetContainedFilesIntoVectorOfStringsCallback (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &file_spec)
+{
+ ((PlatformRemoteAppleTV::SDKDirectoryInfoCollection *)baton)->push_back(PlatformRemoteAppleTV::SDKDirectoryInfo(file_spec));
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+bool
+PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded()
+{
+ if (m_sdk_directory_infos.empty())
+ {
+ const char *device_support_dir = GetDeviceSupportDirectory();
+ if (device_support_dir)
+ {
+ const bool find_directories = true;
+ const bool find_files = false;
+ const bool find_other = false;
+
+ SDKDirectoryInfoCollection builtin_sdk_directory_infos;
+ FileSpec::EnumerateDirectory (m_device_support_directory.c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &builtin_sdk_directory_infos);
+
+ // Only add SDK directories that have symbols in them, some SDKs only contain
+ // developer disk images and no symbols, so they aren't useful to us.
+ FileSpec sdk_symbols_symlink_fspec;
+ for (const auto &sdk_directory_info : builtin_sdk_directory_infos)
+ {
+ sdk_symbols_symlink_fspec = sdk_directory_info.directory;
+ sdk_symbols_symlink_fspec.AppendPathComponent("Symbols.Internal");
+ if (sdk_symbols_symlink_fspec.Exists())
+ {
+ m_sdk_directory_infos.push_back(sdk_directory_info);
+ }
+ else
+ {
+ sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols");
+ if (sdk_symbols_symlink_fspec.Exists())
+ m_sdk_directory_infos.push_back(sdk_directory_info);
+ }
+ }
+
+ const uint32_t num_installed = m_sdk_directory_infos.size();
+ FileSpec local_sdk_cache("~/Library/Developer/Xcode/tvOS DeviceSupport", true);
+ if (!local_sdk_cache.Exists())
+ {
+ // Try looking for another possible name
+ local_sdk_cache = FileSpec("~/Library/Developer/Xcode/Apple TVOS DeviceSupport", true);
+ }
+ if (!local_sdk_cache.Exists())
+ {
+ // Try looking for another possible name
+ local_sdk_cache = FileSpec("~/Library/Developer/Xcode/AppleTVOS DeviceSupport", true);
+ }
+ if (!local_sdk_cache.Exists())
+ {
+ // Try looking for another possible name
+ local_sdk_cache = FileSpec("~/Library/Developer/Xcode/AppleTV OS DeviceSupport", true);
+ }
+ if (!local_sdk_cache.Exists())
+ {
+ // Try looking for another possible name
+ local_sdk_cache = FileSpec("~/Library/Developer/Xcode/Apple TV OS DeviceSupport", true);
+ }
+ if (local_sdk_cache.Exists())
+ {
+ char path[PATH_MAX];
+ if (local_sdk_cache.GetPath(path, sizeof(path)))
+ {
+ FileSpec::EnumerateDirectory (path,
+ find_directories,
+ find_files,
+ find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &m_sdk_directory_infos);
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ // First try for an exact match of major, minor and update
+ for (uint32_t i=num_installed; i<num_sdk_infos; ++i)
+ {
+ m_sdk_directory_infos[i].user_cached = true;
+ }
+ }
+ }
+ }
+ }
+ return !m_sdk_directory_infos.empty();
+}
+
+const PlatformRemoteAppleTV::SDKDirectoryInfo *
+PlatformRemoteAppleTV::GetSDKDirectoryForCurrentOSVersion ()
+{
+ uint32_t i;
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+
+ // Check to see if the user specified a build string. If they did, then
+ // be sure to match it.
+ std::vector<bool> check_sdk_info(num_sdk_infos, true);
+ ConstString build(m_sdk_build);
+ if (build)
+ {
+ for (i=0; i<num_sdk_infos; ++i)
+ check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
+ }
+
+ // If we are connected we can find the version of the OS the platform
+ // us running on and select the right SDK
+ uint32_t major, minor, update;
+ if (GetOSVersion(major, minor, update))
+ {
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ // First try for an exact match of major, minor and update
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major &&
+ m_sdk_directory_infos[i].version_minor == minor &&
+ m_sdk_directory_infos[i].version_update == update)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ // First try for an exact match of major and minor
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major &&
+ m_sdk_directory_infos[i].version_minor == minor)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ // Lastly try to match of major version only..
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ }
+ }
+ else if (build)
+ {
+ // No version, just a build number, search for the first one that matches
+ for (i=0; i<num_sdk_infos; ++i)
+ if (check_sdk_info[i])
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ return nullptr;
+}
+
+const PlatformRemoteAppleTV::SDKDirectoryInfo *
+PlatformRemoteAppleTV::GetSDKDirectoryForLatestOSVersion ()
+{
+ const PlatformRemoteAppleTV::SDKDirectoryInfo *result = nullptr;
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ // First try for an exact match of major, minor and update
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ if (sdk_dir_info.version_major != UINT32_MAX)
+ {
+ if (result == nullptr || sdk_dir_info.version_major > result->version_major)
+ {
+ result = &sdk_dir_info;
+ }
+ else if (sdk_dir_info.version_major == result->version_major)
+ {
+ if (sdk_dir_info.version_minor > result->version_minor)
+ {
+ result = &sdk_dir_info;
+ }
+ else if (sdk_dir_info.version_minor == result->version_minor)
+ {
+ if (sdk_dir_info.version_update > result->version_update)
+ {
+ result = &sdk_dir_info;
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
+
+const char *
+PlatformRemoteAppleTV::GetDeviceSupportDirectory()
+{
+ if (m_device_support_directory.empty())
+ {
+ const char *device_support_dir = GetDeveloperDirectory();
+ if (device_support_dir)
+ {
+ m_device_support_directory.assign (device_support_dir);
+ m_device_support_directory.append ("/Platforms/AppleTVOS.platform/DeviceSupport");
+ }
+ else
+ {
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_device_support_directory.assign (1, '\0');
+ }
+ }
+ // We should have put a single NULL character into m_device_support_directory
+ // or it should have a valid path if the code gets here
+ assert (m_device_support_directory.empty() == false);
+ if (m_device_support_directory[0])
+ return m_device_support_directory.c_str();
+ return nullptr;
+}
+
+const char *
+PlatformRemoteAppleTV::GetDeviceSupportDirectoryForOSVersion()
+{
+ if (m_sdk_sysroot)
+ return m_sdk_sysroot.GetCString();
+
+ if (m_device_support_directory_for_os_version.empty())
+ {
+ const PlatformRemoteAppleTV::SDKDirectoryInfo *sdk_dir_info = GetSDKDirectoryForCurrentOSVersion ();
+ if (sdk_dir_info == nullptr)
+ sdk_dir_info = GetSDKDirectoryForLatestOSVersion ();
+ if (sdk_dir_info)
+ {
+ char path[PATH_MAX];
+ if (sdk_dir_info->directory.GetPath(path, sizeof(path)))
+ {
+ m_device_support_directory_for_os_version = path;
+ return m_device_support_directory_for_os_version.c_str();
+ }
+ }
+ else
+ {
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_device_support_directory_for_os_version.assign (1, '\0');
+ }
+ }
+ // We should have put a single NULL character into m_device_support_directory_for_os_version
+ // or it should have a valid path if the code gets here
+ assert (m_device_support_directory_for_os_version.empty() == false);
+ if (m_device_support_directory_for_os_version[0])
+ return m_device_support_directory_for_os_version.c_str();
+ return nullptr;
+}
+
+uint32_t
+PlatformRemoteAppleTV::FindFileInAllSDKs (const char *platform_file_path,
+ FileSpecList &file_list)
+{
+ if (platform_file_path && platform_file_path[0] && UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ lldb_private::FileSpec local_file;
+ // First try for an exact match of major, minor and update
+ for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
+ {
+ if (GetFileInSDK (platform_file_path,
+ sdk_idx,
+ local_file))
+ {
+ file_list.Append(local_file);
+ }
+ }
+ }
+ return file_list.GetSize();
+}
+
+bool
+PlatformRemoteAppleTV::GetFileInSDK (const char *platform_file_path,
+ uint32_t sdk_idx,
+ lldb_private::FileSpec &local_file)
+{
+ if (sdk_idx < m_sdk_directory_infos.size())
+ {
+ char sdkroot_path[PATH_MAX];
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[sdk_idx];
+ if (sdk_dir_info.directory.GetPath(sdkroot_path, sizeof(sdkroot_path)))
+ {
+ const bool symbols_dirs_only = true;
+
+ return GetFileInSDKRoot (platform_file_path,
+ sdkroot_path,
+ symbols_dirs_only,
+ local_file);
+ }
+ }
+ return false;
+}
+
+bool
+PlatformRemoteAppleTV::GetFileInSDKRoot (const char *platform_file_path,
+ const char *sdkroot_path,
+ bool symbols_dirs_only,
+ lldb_private::FileSpec &local_file)
+{
+ if (sdkroot_path && sdkroot_path[0] && platform_file_path && platform_file_path[0])
+ {
+ char resolved_path[PATH_MAX];
+
+ if (!symbols_dirs_only)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return true;
+ }
+
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols.Internal%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return true;
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return true;
+ }
+ return false;
+}
+
+Error
+PlatformRemoteAppleTV::GetSymbolFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ Error error;
+ char platform_file_path[PATH_MAX];
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ char resolved_path[PATH_MAX];
+
+ const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion();
+ if (os_version_dir)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols.Internal/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+
+ }
+ local_file = platform_file;
+ if (local_file.Exists())
+ return error;
+
+ error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
+ platform_file_path,
+ GetPluginName().GetCString());
+ }
+ else
+ {
+ error.SetErrorString ("invalid platform file argument");
+ }
+ return error;
+}
+
+Error
+PlatformRemoteAppleTV::GetSharedModule (const ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ // For Apple TV, the SDK files are all cached locally on the host
+ // system. So first we ask for the file in the cached SDK,
+ // then we attempt to get a shared module for the right architecture
+ // with the right UUID.
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+
+ Error error;
+ char platform_file_path[PATH_MAX];
+
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ ModuleSpec platform_module_spec(module_spec);
+
+ UpdateSDKDirectoryInfosIfNeeded();
+
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+
+ // If we are connected we migth be able to correctly deduce the SDK directory
+ // using the OS build.
+ const uint32_t connected_sdk_idx = GetConnectedSDKIndex ();
+ if (connected_sdk_idx < num_sdk_infos)
+ {
+ if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ module_sp.reset();
+ error = ResolveExecutable(platform_module_spec,
+ module_sp,
+ nullptr);
+ if (module_sp)
+ {
+ m_last_module_sdk_idx = connected_sdk_idx;
+ error.Clear();
+ return error;
+ }
+ }
+ }
+
+ // Try the last SDK index if it is set as most files from an SDK
+ // will tend to be valid in that same SDK.
+ if (m_last_module_sdk_idx < num_sdk_infos)
+ {
+ if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ module_sp.reset();
+ error = ResolveExecutable(platform_module_spec,
+ module_sp,
+ nullptr);
+ if (module_sp)
+ {
+ error.Clear();
+ return error;
+ }
+ }
+ }
+
+ // First try for an exact match of major, minor and update
+ for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
+ {
+ if (m_last_module_sdk_idx == sdk_idx)
+ {
+ // Skip the last module SDK index if we already searched
+ // it above
+ continue;
+ }
+ if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
+
+ error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
+ if (module_sp)
+ {
+ // Remember the index of the last SDK that we found a file
+ // in in case the wrong SDK was selected.
+ m_last_module_sdk_idx = sdk_idx;
+ error.Clear();
+ return error;
+ }
+ }
+ }
+ }
+ // Not the module we are looking for... Nothing to see here...
+ module_sp.reset();
+
+ // This may not be an SDK-related module. Try whether we can bring in the thing to our local cache.
+ error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
+ if (error.Success())
+ return error;
+
+ const bool always_create = false;
+ error = ModuleList::GetSharedModule (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr,
+ always_create);
+
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(platform_file);
+
+ return error;
+}
+
+bool
+PlatformRemoteAppleTV::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ ArchSpec system_arch (GetSystemArchitecture());
+
+ const ArchSpec::Core system_core = system_arch.GetCore();
+ switch (system_core)
+ {
+ default:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("arm64-apple-tvos"); return true;
+ case 1: arch.SetTriple ("armv7s-apple-tvos"); return true;
+ case 2: arch.SetTriple ("armv7-apple-tvos"); return true;
+ case 3: arch.SetTriple ("thumbv7s-apple-tvos"); return true;
+ case 4: arch.SetTriple ("thumbv7-apple-tvos"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_arm64:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("arm64-apple-tvos"); return true;
+ case 1: arch.SetTriple ("armv7s-apple-tvos"); return true;
+ case 2: arch.SetTriple ("armv7-apple-tvos"); return true;
+ case 3: arch.SetTriple ("thumbv7s-apple-tvos"); return true;
+ case 4: arch.SetTriple ("thumbv7-apple-tvos"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7s:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7s-apple-tvos"); return true;
+ case 1: arch.SetTriple ("armv7-apple-tvos"); return true;
+ case 2: arch.SetTriple ("thumbv7s-apple-tvos"); return true;
+ case 3: arch.SetTriple ("thumbv7-apple-tvos"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7-apple-tvos"); return true;
+ case 1: arch.SetTriple ("thumbv7-apple-tvos"); return true;
+ default: break;
+ }
+ break;
+ }
+ arch.Clear();
+ return false;
+}
+
+uint32_t
+PlatformRemoteAppleTV::GetConnectedSDKIndex ()
+{
+ if (IsConnected())
+ {
+ if (m_connected_module_sdk_idx == UINT32_MAX)
+ {
+ std::string build;
+ if (GetRemoteOSBuildString(build))
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), build.c_str()))
+ {
+ m_connected_module_sdk_idx = i;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_connected_module_sdk_idx = UINT32_MAX;
+ }
+ return m_connected_module_sdk_idx;
+}
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h
new file mode 100644
index 0000000000000..28bd9df0fad7c
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h
@@ -0,0 +1,171 @@
+//===-- PlatformRemoteAppleTV.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_PlatformRemoteAppleTV_h_
+#define liblldb_PlatformRemoteAppleTV_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Host/FileSpec.h"
+
+#include "PlatformDarwin.h"
+
+class PlatformRemoteAppleTV : public PlatformDarwin
+{
+public:
+ PlatformRemoteAppleTV();
+
+ ~PlatformRemoteAppleTV() override = default;
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // Class Methods
+ //------------------------------------------------------------
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ lldb_private::Error
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic();
+ }
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ virtual lldb_private::Error
+ GetSymbolFile (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+ void
+ AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
+ {
+ return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::iPhoneOS);
+ }
+
+protected:
+ struct SDKDirectoryInfo
+ {
+ SDKDirectoryInfo (const lldb_private::FileSpec &sdk_dir_spec);
+ lldb_private::FileSpec directory;
+ lldb_private::ConstString build;
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t version_update;
+ bool user_cached;
+ };
+ typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection;
+ SDKDirectoryInfoCollection m_sdk_directory_infos;
+ std::string m_device_support_directory;
+ std::string m_device_support_directory_for_os_version;
+ std::string m_build_update;
+ uint32_t m_last_module_sdk_idx;
+ uint32_t m_connected_module_sdk_idx;
+
+ bool
+ UpdateSDKDirectoryInfosIfNeeded();
+
+ const char *
+ GetDeviceSupportDirectory();
+
+ const char *
+ GetDeviceSupportDirectoryForOSVersion();
+
+ const SDKDirectoryInfo *
+ GetSDKDirectoryForLatestOSVersion ();
+
+ const SDKDirectoryInfo *
+ GetSDKDirectoryForCurrentOSVersion ();
+
+ static lldb_private::FileSpec::EnumerateDirectoryResult
+ GetContainedFilesIntoVectorOfStringsCallback (void *baton,
+ lldb_private::FileSpec::FileType file_type,
+ const lldb_private::FileSpec &file_spec);
+
+ uint32_t
+ FindFileInAllSDKs (const char *platform_file_path,
+ lldb_private::FileSpecList &file_list);
+
+ bool
+ GetFileInSDK (const char *platform_file_path,
+ uint32_t sdk_idx,
+ lldb_private::FileSpec &local_file);
+
+ bool
+ GetFileInSDKRoot (const char *platform_file_path,
+ const char *sdkroot_path,
+ bool symbols_dirs_only,
+ lldb_private::FileSpec &local_file);
+
+ uint32_t
+ FindFileInAllSDKs (const lldb_private::FileSpec &platform_file,
+ lldb_private::FileSpecList &file_list);
+
+ uint32_t
+ GetConnectedSDKIndex ();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformRemoteAppleTV);
+};
+
+#endif // liblldb_PlatformRemoteAppleTV_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
new file mode 100644
index 0000000000000..808fd96a5284c
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
@@ -0,0 +1,944 @@
+//===-- PlatformRemoteAppleWatch.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "PlatformRemoteAppleWatch.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformRemoteAppleWatch::PlatformRemoteAppleWatch () :
+ PlatformDarwin (false), // This is a remote platform
+ m_sdk_directory_infos(),
+ m_device_support_directory(),
+ m_device_support_directory_for_os_version (),
+ m_build_update(),
+ m_last_module_sdk_idx (UINT32_MAX),
+ m_connected_module_sdk_idx (UINT32_MAX)
+{
+}
+
+PlatformRemoteAppleWatch::SDKDirectoryInfo::SDKDirectoryInfo (const lldb_private::FileSpec &sdk_dir) :
+ directory(sdk_dir),
+ build(),
+ version_major(0),
+ version_minor(0),
+ version_update(0),
+ user_cached(false)
+{
+ const char *dirname_cstr = sdk_dir.GetFilename().GetCString();
+ const char *pos = Args::StringToVersion (dirname_cstr,
+ version_major,
+ version_minor,
+ version_update);
+
+ if (pos && pos[0] == ' ' && pos[1] == '(')
+ {
+ const char *build_start = pos + 2;
+ const char *end_paren = strchr (build_start, ')');
+ if (end_paren && build_start < end_paren)
+ build.SetCStringWithLength(build_start, end_paren - build_start);
+ }
+}
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void
+PlatformRemoteAppleWatch::Initialize ()
+{
+ PlatformDarwin::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+ PluginManager::RegisterPlugin (PlatformRemoteAppleWatch::GetPluginNameStatic(),
+ PlatformRemoteAppleWatch::GetDescriptionStatic(),
+ PlatformRemoteAppleWatch::CreateInstance);
+ }
+}
+
+void
+PlatformRemoteAppleWatch::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformRemoteAppleWatch::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate ();
+}
+
+PlatformSP
+PlatformRemoteAppleWatch::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 ("PlatformRemoteAppleWatch::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ bool create = force;
+ if (!create && arch && arch->IsValid())
+ {
+ switch (arch->GetMachine())
+ {
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::thumb:
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ llvm::Triple::VendorType vendor = triple.getVendor();
+ switch (vendor)
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+
+#endif
+ default:
+ break;
+ }
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::WatchOS: // This is the right triple value for Apple Watch debugging
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+#endif
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
+ // If lldb is running on a watch, this isn't a RemoteWatch environment; it's a local system environment.
+ if (force == false)
+ {
+ create = false;
+ }
+#endif
+
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformRemoteAppleWatch::%s() creating platform", __FUNCTION__);
+
+ return lldb::PlatformSP(new PlatformRemoteAppleWatch ());
+ }
+
+ if (log)
+ log->Printf ("PlatformRemoteAppleWatch::%s() aborting creation of platform", __FUNCTION__);
+
+ return lldb::PlatformSP();
+}
+
+lldb_private::ConstString
+PlatformRemoteAppleWatch::GetPluginNameStatic ()
+{
+ static ConstString g_name("remote-watchos");
+ return g_name;
+}
+
+const char *
+PlatformRemoteAppleWatch::GetDescriptionStatic()
+{
+ return "Remote Apple Watch platform plug-in.";
+}
+
+void
+PlatformRemoteAppleWatch::GetStatus (Stream &strm)
+{
+ Platform::GetStatus (strm);
+ const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
+ if (sdk_directory)
+ strm.Printf (" SDK Path: \"%s\"\n", sdk_directory);
+ else
+ strm.PutCString (" SDK Path: error: unable to locate SDK\n");
+
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ strm.Printf (" SDK Roots: [%2u] \"%s\"\n",
+ i,
+ sdk_dir_info.directory.GetPath().c_str());
+ }
+}
+
+Error
+PlatformRemoteAppleWatch::ResolveExecutable (const ModuleSpec &ms,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ ModuleSpec resolved_module_spec(ms);
+
+ // Resolve any executable within a bundle on MacOSX
+ // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
+ {
+ error = ModuleList::GetSharedModule(resolved_module_spec,
+ exe_module_sp,
+ nullptr,
+ nullptr,
+ nullptr);
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ return error;
+ exe_module_sp.reset();
+ }
+ // No valid architecture was specified or the exact ARM slice wasn't
+ // found so ask the platform for the architectures that we should be
+ // using (in the correct order) and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule(resolved_module_spec,
+ exe_module_sp,
+ nullptr,
+ nullptr,
+ nullptr);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+
+ return error;
+}
+
+FileSpec::EnumerateDirectoryResult
+PlatformRemoteAppleWatch::GetContainedFilesIntoVectorOfStringsCallback (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &file_spec)
+{
+ ((PlatformRemoteAppleWatch::SDKDirectoryInfoCollection *)baton)->push_back(PlatformRemoteAppleWatch::SDKDirectoryInfo(file_spec));
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+bool
+PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded()
+{
+ if (m_sdk_directory_infos.empty())
+ {
+ const char *device_support_dir = GetDeviceSupportDirectory();
+ if (device_support_dir)
+ {
+ const bool find_directories = true;
+ const bool find_files = false;
+ const bool find_other = false;
+
+ SDKDirectoryInfoCollection builtin_sdk_directory_infos;
+ FileSpec::EnumerateDirectory (m_device_support_directory.c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &builtin_sdk_directory_infos);
+
+ // Only add SDK directories that have symbols in them, some SDKs only contain
+ // developer disk images and no symbols, so they aren't useful to us.
+ FileSpec sdk_symbols_symlink_fspec;
+ for (const auto &sdk_directory_info : builtin_sdk_directory_infos)
+ {
+ sdk_symbols_symlink_fspec = sdk_directory_info.directory;
+ sdk_symbols_symlink_fspec.AppendPathComponent("Symbols.Internal");
+ if (sdk_symbols_symlink_fspec.Exists())
+ {
+ m_sdk_directory_infos.push_back(sdk_directory_info);
+ }
+ else
+ {
+ sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols");
+ if (sdk_symbols_symlink_fspec.Exists())
+ m_sdk_directory_infos.push_back(sdk_directory_info);
+ }
+ }
+
+ const uint32_t num_installed = m_sdk_directory_infos.size();
+ FileSpec local_sdk_cache("~/Library/Developer/Xcode/watchOS DeviceSupport", true);
+ if (!local_sdk_cache.Exists())
+ {
+ local_sdk_cache = FileSpec("~/Library/Developer/Xcode/watch OS DeviceSupport", true);
+ }
+ if (!local_sdk_cache.Exists())
+ {
+ local_sdk_cache = FileSpec("~/Library/Developer/Xcode/WatchOS DeviceSupport", true);
+ }
+ if (!local_sdk_cache.Exists())
+ {
+ local_sdk_cache = FileSpec("~/Library/Developer/Xcode/Watch OS DeviceSupport", true);
+ }
+ if (local_sdk_cache.Exists())
+ {
+ char path[PATH_MAX];
+ if (local_sdk_cache.GetPath(path, sizeof(path)))
+ {
+ FileSpec::EnumerateDirectory (path,
+ find_directories,
+ find_files,
+ find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &m_sdk_directory_infos);
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ // First try for an exact match of major, minor and update
+ for (uint32_t i=num_installed; i<num_sdk_infos; ++i)
+ {
+ m_sdk_directory_infos[i].user_cached = true;
+ }
+ }
+ }
+ }
+ }
+ return !m_sdk_directory_infos.empty();
+}
+
+const PlatformRemoteAppleWatch::SDKDirectoryInfo *
+PlatformRemoteAppleWatch::GetSDKDirectoryForCurrentOSVersion ()
+{
+ uint32_t i;
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+
+ // Check to see if the user specified a build string. If they did, then
+ // be sure to match it.
+ std::vector<bool> check_sdk_info(num_sdk_infos, true);
+ ConstString build(m_sdk_build);
+ if (build)
+ {
+ for (i=0; i<num_sdk_infos; ++i)
+ check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
+ }
+
+ // If we are connected we can find the version of the OS the platform
+ // us running on and select the right SDK
+ uint32_t major, minor, update;
+ if (GetOSVersion(major, minor, update))
+ {
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ // First try for an exact match of major, minor and update
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major &&
+ m_sdk_directory_infos[i].version_minor == minor &&
+ m_sdk_directory_infos[i].version_update == update)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ // First try for an exact match of major and minor
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major &&
+ m_sdk_directory_infos[i].version_minor == minor)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ // Lastly try to match of major version only..
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ }
+ }
+ else if (build)
+ {
+ // No version, just a build number, search for the first one that matches
+ for (i=0; i<num_sdk_infos; ++i)
+ if (check_sdk_info[i])
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ return nullptr;
+}
+
+const PlatformRemoteAppleWatch::SDKDirectoryInfo *
+PlatformRemoteAppleWatch::GetSDKDirectoryForLatestOSVersion ()
+{
+ const PlatformRemoteAppleWatch::SDKDirectoryInfo *result = nullptr;
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ // First try for an exact match of major, minor and update
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ if (sdk_dir_info.version_major != UINT32_MAX)
+ {
+ if (result == nullptr || sdk_dir_info.version_major > result->version_major)
+ {
+ result = &sdk_dir_info;
+ }
+ else if (sdk_dir_info.version_major == result->version_major)
+ {
+ if (sdk_dir_info.version_minor > result->version_minor)
+ {
+ result = &sdk_dir_info;
+ }
+ else if (sdk_dir_info.version_minor == result->version_minor)
+ {
+ if (sdk_dir_info.version_update > result->version_update)
+ {
+ result = &sdk_dir_info;
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
+
+const char *
+PlatformRemoteAppleWatch::GetDeviceSupportDirectory()
+{
+ if (m_device_support_directory.empty())
+ {
+ const char *device_support_dir = GetDeveloperDirectory();
+ if (device_support_dir)
+ {
+ m_device_support_directory.assign (device_support_dir);
+ m_device_support_directory.append ("/Platforms/watchOS.platform/DeviceSupport");
+ FileSpec platform_device_support_dir (m_device_support_directory.c_str(), true);
+ if (!platform_device_support_dir.Exists())
+ {
+ std::string alt_platform_dirname = device_support_dir;
+ alt_platform_dirname.append ("/Platforms/WatchOS.platform/DeviceSupport");
+ FileSpec alt_platform_device_support_dir (m_device_support_directory.c_str(), true);
+ if (alt_platform_device_support_dir.Exists())
+ {
+ m_device_support_directory = alt_platform_dirname;
+ }
+ }
+ }
+ else
+ {
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_device_support_directory.assign (1, '\0');
+ }
+ }
+ // We should have put a single NULL character into m_device_support_directory
+ // or it should have a valid path if the code gets here
+ assert (m_device_support_directory.empty() == false);
+ if (m_device_support_directory[0])
+ return m_device_support_directory.c_str();
+ return nullptr;
+}
+
+const char *
+PlatformRemoteAppleWatch::GetDeviceSupportDirectoryForOSVersion()
+{
+ if (m_sdk_sysroot)
+ return m_sdk_sysroot.GetCString();
+
+ if (m_device_support_directory_for_os_version.empty())
+ {
+ const PlatformRemoteAppleWatch::SDKDirectoryInfo *sdk_dir_info = GetSDKDirectoryForCurrentOSVersion ();
+ if (sdk_dir_info == nullptr)
+ sdk_dir_info = GetSDKDirectoryForLatestOSVersion ();
+ if (sdk_dir_info)
+ {
+ char path[PATH_MAX];
+ if (sdk_dir_info->directory.GetPath(path, sizeof(path)))
+ {
+ m_device_support_directory_for_os_version = path;
+ return m_device_support_directory_for_os_version.c_str();
+ }
+ }
+ else
+ {
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_device_support_directory_for_os_version.assign (1, '\0');
+ }
+ }
+ // We should have put a single NULL character into m_device_support_directory_for_os_version
+ // or it should have a valid path if the code gets here
+ assert (m_device_support_directory_for_os_version.empty() == false);
+ if (m_device_support_directory_for_os_version[0])
+ return m_device_support_directory_for_os_version.c_str();
+ return nullptr;
+}
+
+uint32_t
+PlatformRemoteAppleWatch::FindFileInAllSDKs (const char *platform_file_path,
+ FileSpecList &file_list)
+{
+ if (platform_file_path && platform_file_path[0] && UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ lldb_private::FileSpec local_file;
+ // First try for an exact match of major, minor and update
+ for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
+ {
+ if (GetFileInSDK (platform_file_path,
+ sdk_idx,
+ local_file))
+ {
+ file_list.Append(local_file);
+ }
+ }
+ }
+ return file_list.GetSize();
+}
+
+bool
+PlatformRemoteAppleWatch::GetFileInSDK (const char *platform_file_path,
+ uint32_t sdk_idx,
+ lldb_private::FileSpec &local_file)
+{
+ if (sdk_idx < m_sdk_directory_infos.size())
+ {
+ char sdkroot_path[PATH_MAX];
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[sdk_idx];
+ if (sdk_dir_info.directory.GetPath(sdkroot_path, sizeof(sdkroot_path)))
+ {
+ const bool symbols_dirs_only = true;
+
+ return GetFileInSDKRoot (platform_file_path,
+ sdkroot_path,
+ symbols_dirs_only,
+ local_file);
+ }
+ }
+ return false;
+}
+
+bool
+PlatformRemoteAppleWatch::GetFileInSDKRoot (const char *platform_file_path,
+ const char *sdkroot_path,
+ bool symbols_dirs_only,
+ lldb_private::FileSpec &local_file)
+{
+ if (sdkroot_path && sdkroot_path[0] && platform_file_path && platform_file_path[0])
+ {
+ char resolved_path[PATH_MAX];
+
+ if (!symbols_dirs_only)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return true;
+ }
+
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols.Internal%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return true;
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return true;
+ }
+ return false;
+}
+
+Error
+PlatformRemoteAppleWatch::GetSymbolFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ Error error;
+ char platform_file_path[PATH_MAX];
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ char resolved_path[PATH_MAX];
+
+ const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion();
+ if (os_version_dir)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols.Internal/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+
+ }
+ local_file = platform_file;
+ if (local_file.Exists())
+ return error;
+
+ error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
+ platform_file_path,
+ GetPluginName().GetCString());
+ }
+ else
+ {
+ error.SetErrorString ("invalid platform file argument");
+ }
+ return error;
+}
+
+Error
+PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ // For Apple Watch, the SDK files are all cached locally on the host
+ // system. So first we ask for the file in the cached SDK,
+ // then we attempt to get a shared module for the right architecture
+ // with the right UUID.
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+
+ Error error;
+ char platform_file_path[PATH_MAX];
+
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ ModuleSpec platform_module_spec(module_spec);
+
+ UpdateSDKDirectoryInfosIfNeeded();
+
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+
+ // If we are connected we migth be able to correctly deduce the SDK directory
+ // using the OS build.
+ const uint32_t connected_sdk_idx = GetConnectedSDKIndex ();
+ if (connected_sdk_idx < num_sdk_infos)
+ {
+ if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ module_sp.reset();
+ error = ResolveExecutable(platform_module_spec,
+ module_sp,
+ nullptr);
+ if (module_sp)
+ {
+ m_last_module_sdk_idx = connected_sdk_idx;
+ error.Clear();
+ return error;
+ }
+ }
+ }
+
+ // Try the last SDK index if it is set as most files from an SDK
+ // will tend to be valid in that same SDK.
+ if (m_last_module_sdk_idx < num_sdk_infos)
+ {
+ if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ module_sp.reset();
+ error = ResolveExecutable(platform_module_spec,
+ module_sp,
+ nullptr);
+ if (module_sp)
+ {
+ error.Clear();
+ return error;
+ }
+ }
+ }
+
+ // First try for an exact match of major, minor and update
+ for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
+ {
+ if (m_last_module_sdk_idx == sdk_idx)
+ {
+ // Skip the last module SDK index if we already searched
+ // it above
+ continue;
+ }
+ if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
+
+ error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
+ if (module_sp)
+ {
+ // Remember the index of the last SDK that we found a file
+ // in in case the wrong SDK was selected.
+ m_last_module_sdk_idx = sdk_idx;
+ error.Clear();
+ return error;
+ }
+ }
+ }
+ }
+ // Not the module we are looking for... Nothing to see here...
+ module_sp.reset();
+
+ // This may not be an SDK-related module. Try whether we can bring in the thing to our local cache.
+ error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
+ if (error.Success())
+ return error;
+
+ const bool always_create = false;
+ error = ModuleList::GetSharedModule (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr,
+ always_create);
+
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(platform_file);
+
+ return error;
+}
+
+bool
+PlatformRemoteAppleWatch::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ ArchSpec system_arch (GetSystemArchitecture());
+
+ const ArchSpec::Core system_core = system_arch.GetCore();
+ switch (system_core)
+ {
+ default:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("arm64-apple-watchos"); return true;
+ case 1: arch.SetTriple ("armv7k-apple-watchos"); return true;
+ case 2: arch.SetTriple ("armv7s-apple-watchos"); return true;
+ case 3: arch.SetTriple ("armv7-apple-watchos"); return true;
+ case 4: arch.SetTriple ("thumbv7k-apple-watchos"); return true;
+ case 5: arch.SetTriple ("thumbv7-apple-watchos"); return true;
+ case 6: arch.SetTriple ("thumbv7s-apple-watchos"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_arm64:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("arm64-apple-watchos"); return true;
+ case 1: arch.SetTriple ("armv7k-apple-watchos"); return true;
+ case 2: arch.SetTriple ("armv7s-apple-watchos"); return true;
+ case 3: arch.SetTriple ("armv7-apple-watchos"); return true;
+ case 4: arch.SetTriple ("thumbv7k-apple-watchos"); return true;
+ case 5: arch.SetTriple ("thumbv7-apple-watchos"); return true;
+ case 6: arch.SetTriple ("thumbv7s-apple-watchos"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7k:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7k-apple-watchos"); return true;
+ case 1: arch.SetTriple ("armv7s-apple-watchos"); return true;
+ case 2: arch.SetTriple ("armv7-apple-watchos"); return true;
+ case 3: arch.SetTriple ("thumbv7k-apple-watchos"); return true;
+ case 4: arch.SetTriple ("thumbv7-apple-watchos"); return true;
+ case 5: arch.SetTriple ("thumbv7s-apple-watchos"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7s:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7s-apple-watchos"); return true;
+ case 1: arch.SetTriple ("armv7k-apple-watchos"); return true;
+ case 2: arch.SetTriple ("armv7-apple-watchos"); return true;
+ case 3: arch.SetTriple ("thumbv7k-apple-watchos"); return true;
+ case 4: arch.SetTriple ("thumbv7-apple-watchos"); return true;
+ case 5: arch.SetTriple ("thumbv7s-apple-watchos"); return true;
+ default: break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_armv7:
+ switch (idx)
+ {
+ case 0: arch.SetTriple ("armv7-apple-watchos"); return true;
+ case 1: arch.SetTriple ("armv7k-apple-watchos"); return true;
+ case 2: arch.SetTriple ("thumbv7k-apple-watchos"); return true;
+ case 3: arch.SetTriple ("thumbv7-apple-watchos"); return true;
+ default: break;
+ }
+ break;
+ }
+ arch.Clear();
+ return false;
+}
+
+uint32_t
+PlatformRemoteAppleWatch::GetConnectedSDKIndex ()
+{
+ if (IsConnected())
+ {
+ if (m_connected_module_sdk_idx == UINT32_MAX)
+ {
+ std::string build;
+ if (GetRemoteOSBuildString(build))
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), build.c_str()))
+ {
+ m_connected_module_sdk_idx = i;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_connected_module_sdk_idx = UINT32_MAX;
+ }
+ return m_connected_module_sdk_idx;
+}
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h
new file mode 100644
index 0000000000000..891bc5d1c6ef9
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h
@@ -0,0 +1,173 @@
+//===-- PlatformRemoteAppleWatch.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_PlatformRemoteAppleWatch_h_
+#define liblldb_PlatformRemoteAppleWatch_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Host/FileSpec.h"
+
+#include "PlatformDarwin.h"
+
+class PlatformRemoteAppleWatch : public PlatformDarwin
+{
+public:
+ PlatformRemoteAppleWatch();
+
+ ~PlatformRemoteAppleWatch() override = default;
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // Class Methods
+ //------------------------------------------------------------
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ lldb_private::Error
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic();
+ }
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ virtual lldb_private::Error
+ GetSymbolFile (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+ void
+ AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
+ {
+ return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::iPhoneOS);
+ }
+
+protected:
+ struct SDKDirectoryInfo
+ {
+ SDKDirectoryInfo (const lldb_private::FileSpec &sdk_dir_spec);
+ lldb_private::FileSpec directory;
+ lldb_private::ConstString build;
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t version_update;
+ bool user_cached;
+ };
+ typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection;
+ SDKDirectoryInfoCollection m_sdk_directory_infos;
+ std::string m_device_support_directory;
+ std::string m_device_support_directory_for_os_version;
+ std::string m_build_update;
+ uint32_t m_last_module_sdk_idx;
+ uint32_t m_connected_module_sdk_idx;
+
+ bool
+ UpdateSDKDirectoryInfosIfNeeded();
+
+ const char *
+ GetDeviceSupportDirectory();
+
+ const char *
+ GetDeviceSupportDirectoryForOSVersion();
+
+ const SDKDirectoryInfo *
+ GetSDKDirectoryForLatestOSVersion ();
+
+ const SDKDirectoryInfo *
+ GetSDKDirectoryForCurrentOSVersion ();
+
+ static lldb_private::FileSpec::EnumerateDirectoryResult
+ GetContainedFilesIntoVectorOfStringsCallback (void *baton,
+ lldb_private::FileSpec::FileType file_type,
+ const lldb_private::FileSpec &file_spec);
+
+ uint32_t
+ FindFileInAllSDKs (const char *platform_file_path,
+ lldb_private::FileSpecList &file_list);
+
+ bool
+ GetFileInSDK (const char *platform_file_path,
+ uint32_t sdk_idx,
+ lldb_private::FileSpec &local_file);
+
+ bool
+ GetFileInSDKRoot (const char *platform_file_path,
+ const char *sdkroot_path,
+ bool symbols_dirs_only,
+ lldb_private::FileSpec &local_file);
+
+ uint32_t
+ FindFileInAllSDKs (const lldb_private::FileSpec &platform_file,
+ lldb_private::FileSpecList &file_list);
+
+ uint32_t
+ GetConnectedSDKIndex ();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformRemoteAppleWatch);
+};
+
+#endif // liblldb_PlatformRemoteAppleWatch_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
new file mode 100644
index 0000000000000..75afa9019dcdc
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
@@ -0,0 +1,974 @@
+//===-- PlatformRemoteiOS.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformRemoteiOS.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+PlatformRemoteiOS::SDKDirectoryInfo::SDKDirectoryInfo (const lldb_private::FileSpec &sdk_dir) :
+ directory(sdk_dir),
+ build(),
+ version_major(0),
+ version_minor(0),
+ version_update(0),
+ user_cached(false)
+{
+ const char *dirname_cstr = sdk_dir.GetFilename().GetCString();
+ const char *pos = Args::StringToVersion (dirname_cstr,
+ version_major,
+ version_minor,
+ version_update);
+
+ if (pos && pos[0] == ' ' && pos[1] == '(')
+ {
+ const char *build_start = pos + 2;
+ const char *end_paren = strchr (build_start, ')');
+ if (end_paren && build_start < end_paren)
+ build.SetCStringWithLength(build_start, end_paren - build_start);
+ }
+}
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void
+PlatformRemoteiOS::Initialize ()
+{
+ PlatformDarwin::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+ PluginManager::RegisterPlugin (PlatformRemoteiOS::GetPluginNameStatic(),
+ PlatformRemoteiOS::GetDescriptionStatic(),
+ PlatformRemoteiOS::CreateInstance);
+ }
+}
+
+void
+PlatformRemoteiOS::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformRemoteiOS::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate ();
+}
+
+PlatformSP
+PlatformRemoteiOS::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 ("PlatformRemoteiOS::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ bool create = force;
+ if (create == false && arch && arch->IsValid())
+ {
+ switch (arch->GetMachine())
+ {
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::thumb:
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ llvm::Triple::VendorType vendor = triple.getVendor();
+ switch (vendor)
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+
+#endif
+ default:
+ break;
+ }
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::Darwin: // Deprecated, but still support Darwin for historical reasons
+ case llvm::Triple::IOS: // This is the right triple value for iOS debugging
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+#endif
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformRemoteiOS::%s() creating platform", __FUNCTION__);
+
+ return lldb::PlatformSP(new PlatformRemoteiOS ());
+ }
+
+ if (log)
+ log->Printf ("PlatformRemoteiOS::%s() aborting creation of platform", __FUNCTION__);
+
+ return lldb::PlatformSP();
+}
+
+
+lldb_private::ConstString
+PlatformRemoteiOS::GetPluginNameStatic ()
+{
+ static ConstString g_name("remote-ios");
+ return g_name;
+}
+
+const char *
+PlatformRemoteiOS::GetDescriptionStatic()
+{
+ return "Remote iOS platform plug-in.";
+}
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformRemoteiOS::PlatformRemoteiOS () :
+ PlatformDarwin (false), // This is a remote platform
+ m_sdk_directory_infos(),
+ m_device_support_directory(),
+ m_device_support_directory_for_os_version (),
+ m_build_update(),
+ m_last_module_sdk_idx (UINT32_MAX),
+ m_connected_module_sdk_idx (UINT32_MAX)
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformRemoteiOS::~PlatformRemoteiOS()
+{
+}
+
+
+void
+PlatformRemoteiOS::GetStatus (Stream &strm)
+{
+ Platform::GetStatus (strm);
+ const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
+ if (sdk_directory)
+ strm.Printf (" SDK Path: \"%s\"\n", sdk_directory);
+ else
+ strm.PutCString (" SDK Path: error: unable to locate SDK\n");
+
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ strm.Printf (" SDK Roots: [%2u] \"%s\"\n",
+ i,
+ sdk_dir_info.directory.GetPath().c_str());
+ }
+}
+
+
+Error
+PlatformRemoteiOS::ResolveExecutable (const ModuleSpec &ms,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ ModuleSpec resolved_module_spec(ms);
+
+ // Resolve any executable within a bundle on MacOSX
+ // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid() || resolved_module_spec.GetUUID().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ return error;
+ exe_module_sp.reset();
+ }
+ // No valid architecture was specified or the exact ARM slice wasn't
+ // found so ask the platform for the architectures that we should be
+ // using (in the correct order) and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+
+ return error;
+}
+
+FileSpec::EnumerateDirectoryResult
+PlatformRemoteiOS::GetContainedFilesIntoVectorOfStringsCallback (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &file_spec)
+{
+ ((PlatformRemoteiOS::SDKDirectoryInfoCollection *)baton)->push_back(PlatformRemoteiOS::SDKDirectoryInfo(file_spec));
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+bool
+PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded()
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (m_sdk_directory_infos.empty())
+ {
+ // A --sysroot option was supplied - add it to our list of SDKs to check
+ if (m_sdk_sysroot)
+ {
+ FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString(), true);
+ const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
+ m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
+ if (log)
+ {
+ log->Printf ("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded added --sysroot SDK directory %s", m_sdk_sysroot.GetCString());
+ }
+ return true;
+ }
+ const char *device_support_dir = GetDeviceSupportDirectory();
+ if (log)
+ {
+ log->Printf ("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded Got DeviceSupport directory %s", device_support_dir);
+ }
+ if (device_support_dir)
+ {
+ const bool find_directories = true;
+ const bool find_files = false;
+ const bool find_other = false;
+
+ SDKDirectoryInfoCollection builtin_sdk_directory_infos;
+ FileSpec::EnumerateDirectory (m_device_support_directory.c_str(),
+ find_directories,
+ find_files,
+ find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &builtin_sdk_directory_infos);
+
+ // Only add SDK directories that have symbols in them, some SDKs only contain
+ // developer disk images and no symbols, so they aren't useful to us.
+ FileSpec sdk_symbols_symlink_fspec;
+ for (const auto &sdk_directory_info : builtin_sdk_directory_infos)
+ {
+ sdk_symbols_symlink_fspec = sdk_directory_info.directory;
+ sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
+ if (sdk_symbols_symlink_fspec.Exists())
+ {
+ m_sdk_directory_infos.push_back(sdk_directory_info);
+ if (log)
+ {
+ log->Printf ("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded added builtin SDK directory %s", sdk_symbols_symlink_fspec.GetPath().c_str());
+ }
+ }
+ }
+
+ const uint32_t num_installed = m_sdk_directory_infos.size();
+ FileSpec local_sdk_cache("~/Library/Developer/Xcode/iOS DeviceSupport", true);
+ if (local_sdk_cache.Exists())
+ {
+ if (log)
+ {
+ log->Printf ("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded searching %s for additional SDKs", local_sdk_cache.GetPath().c_str());
+ }
+ char path[PATH_MAX];
+ if (local_sdk_cache.GetPath(path, sizeof(path)))
+ {
+ FileSpec::EnumerateDirectory (path,
+ find_directories,
+ find_files,
+ find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &m_sdk_directory_infos);
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ // First try for an exact match of major, minor and update
+ for (uint32_t i=num_installed; i<num_sdk_infos; ++i)
+ {
+ m_sdk_directory_infos[i].user_cached = true;
+ if (log)
+ {
+ log->Printf ("PlatformRemoteiOS::UpdateSDKDirectoryInfosIfNeeded user SDK directory %s", m_sdk_directory_infos[i].directory.GetPath().c_str());
+ }
+ }
+ }
+ }
+ }
+ }
+ return !m_sdk_directory_infos.empty();
+}
+
+const PlatformRemoteiOS::SDKDirectoryInfo *
+PlatformRemoteiOS::GetSDKDirectoryForCurrentOSVersion ()
+{
+ uint32_t i;
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+
+ // Check to see if the user specified a build string. If they did, then
+ // be sure to match it.
+ std::vector<bool> check_sdk_info(num_sdk_infos, true);
+ ConstString build(m_sdk_build);
+ if (build)
+ {
+ for (i=0; i<num_sdk_infos; ++i)
+ check_sdk_info[i] = m_sdk_directory_infos[i].build == build;
+ }
+
+ // If we are connected we can find the version of the OS the platform
+ // us running on and select the right SDK
+ uint32_t major, minor, update;
+ if (GetOSVersion(major, minor, update))
+ {
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ // First try for an exact match of major, minor and update
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major &&
+ m_sdk_directory_infos[i].version_minor == minor &&
+ m_sdk_directory_infos[i].version_update == update)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ // First try for an exact match of major and minor
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major &&
+ m_sdk_directory_infos[i].version_minor == minor)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ // Lastly try to match of major version only..
+ for (i=0; i<num_sdk_infos; ++i)
+ {
+ if (check_sdk_info[i])
+ {
+ if (m_sdk_directory_infos[i].version_major == major)
+ {
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ }
+ }
+ }
+ else if (build)
+ {
+ // No version, just a build number, search for the first one that matches
+ for (i=0; i<num_sdk_infos; ++i)
+ if (check_sdk_info[i])
+ return &m_sdk_directory_infos[i];
+ }
+ }
+ return NULL;
+}
+
+const PlatformRemoteiOS::SDKDirectoryInfo *
+PlatformRemoteiOS::GetSDKDirectoryForLatestOSVersion ()
+{
+ const PlatformRemoteiOS::SDKDirectoryInfo *result = NULL;
+ if (UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ // First try for an exact match of major, minor and update
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ if (sdk_dir_info.version_major != UINT32_MAX)
+ {
+ if (result == NULL || sdk_dir_info.version_major > result->version_major)
+ {
+ result = &sdk_dir_info;
+ }
+ else if (sdk_dir_info.version_major == result->version_major)
+ {
+ if (sdk_dir_info.version_minor > result->version_minor)
+ {
+ result = &sdk_dir_info;
+ }
+ else if (sdk_dir_info.version_minor == result->version_minor)
+ {
+ if (sdk_dir_info.version_update > result->version_update)
+ {
+ result = &sdk_dir_info;
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
+
+
+
+const char *
+PlatformRemoteiOS::GetDeviceSupportDirectory()
+{
+ if (m_device_support_directory.empty())
+ {
+ const char *device_support_dir = GetDeveloperDirectory();
+ if (device_support_dir)
+ {
+ m_device_support_directory.assign (device_support_dir);
+ m_device_support_directory.append ("/Platforms/iPhoneOS.platform/DeviceSupport");
+ }
+ else
+ {
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_device_support_directory.assign (1, '\0');
+ }
+ }
+ // We should have put a single NULL character into m_device_support_directory
+ // or it should have a valid path if the code gets here
+ assert (m_device_support_directory.empty() == false);
+ if (m_device_support_directory[0])
+ return m_device_support_directory.c_str();
+ return NULL;
+}
+
+
+const char *
+PlatformRemoteiOS::GetDeviceSupportDirectoryForOSVersion()
+{
+ if (m_sdk_sysroot)
+ return m_sdk_sysroot.GetCString();
+
+ if (m_device_support_directory_for_os_version.empty())
+ {
+ const PlatformRemoteiOS::SDKDirectoryInfo *sdk_dir_info = GetSDKDirectoryForCurrentOSVersion ();
+ if (sdk_dir_info == NULL)
+ sdk_dir_info = GetSDKDirectoryForLatestOSVersion ();
+ if (sdk_dir_info)
+ {
+ char path[PATH_MAX];
+ if (sdk_dir_info->directory.GetPath(path, sizeof(path)))
+ {
+ m_device_support_directory_for_os_version = path;
+ return m_device_support_directory_for_os_version.c_str();
+ }
+ }
+ else
+ {
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_device_support_directory_for_os_version.assign (1, '\0');
+ }
+ }
+ // We should have put a single NULL character into m_device_support_directory_for_os_version
+ // or it should have a valid path if the code gets here
+ assert (m_device_support_directory_for_os_version.empty() == false);
+ if (m_device_support_directory_for_os_version[0])
+ return m_device_support_directory_for_os_version.c_str();
+ return NULL;
+}
+
+uint32_t
+PlatformRemoteiOS::FindFileInAllSDKs (const char *platform_file_path,
+ FileSpecList &file_list)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE);
+ if (platform_file_path && platform_file_path[0] && UpdateSDKDirectoryInfosIfNeeded())
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ lldb_private::FileSpec local_file;
+ // First try for an exact match of major, minor and update
+ for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
+ {
+ if (log)
+ {
+ log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str());
+ }
+ if (GetFileInSDK (platform_file_path,
+ sdk_idx,
+ local_file))
+ {
+ file_list.Append(local_file);
+ }
+ }
+ }
+ return file_list.GetSize();
+}
+
+bool
+PlatformRemoteiOS::GetFileInSDK (const char *platform_file_path,
+ uint32_t sdk_idx,
+ lldb_private::FileSpec &local_file)
+{
+ if (sdk_idx < m_sdk_directory_infos.size())
+ {
+ char sdkroot_path[PATH_MAX];
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[sdk_idx];
+ if (sdk_dir_info.directory.GetPath(sdkroot_path, sizeof(sdkroot_path)))
+ {
+ const bool symbols_dirs_only = true;
+
+ return GetFileInSDKRoot (platform_file_path,
+ sdkroot_path,
+ symbols_dirs_only,
+ local_file);
+ }
+ }
+ return false;
+}
+
+
+bool
+PlatformRemoteiOS::GetFileInSDKRoot (const char *platform_file_path,
+ const char *sdkroot_path,
+ bool symbols_dirs_only,
+ lldb_private::FileSpec &local_file)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ if (sdkroot_path && sdkroot_path[0] && platform_file_path && platform_file_path[0])
+ {
+ char resolved_path[PATH_MAX];
+
+ if (!symbols_dirs_only)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ {
+ if (log)
+ {
+ log->Printf ("Found a copy of %s in the SDK dir %s", platform_file_path, sdkroot_path);
+ }
+ return true;
+ }
+ }
+
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols.Internal%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ {
+ if (log)
+ {
+ log->Printf ("Found a copy of %s in the SDK dir %s/Symbols.Internal", platform_file_path, sdkroot_path);
+ }
+ return true;
+ }
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols%s",
+ sdkroot_path,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ {
+ if (log)
+ {
+ log->Printf ("Found a copy of %s in the SDK dir %s/Symbols", platform_file_path, sdkroot_path);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+
+Error
+PlatformRemoteiOS::GetSymbolFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
+ Error error;
+ char platform_file_path[PATH_MAX];
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ char resolved_path[PATH_MAX];
+
+ const char * os_version_dir = GetDeviceSupportDirectoryForOSVersion();
+ if (os_version_dir)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ {
+ if (log)
+ {
+ log->Printf ("Found a copy of %s in the DeviceSupport dir %s", platform_file_path, os_version_dir);
+ }
+ return error;
+ }
+
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols.Internal/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ {
+ if (log)
+ {
+ log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", platform_file_path, os_version_dir);
+ }
+ return error;
+ }
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/Symbols/%s",
+ os_version_dir,
+ platform_file_path);
+
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ {
+ if (log)
+ {
+ log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols", platform_file_path, os_version_dir);
+ }
+ return error;
+ }
+
+ }
+ local_file = platform_file;
+ if (local_file.Exists())
+ return error;
+
+ error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
+ platform_file_path,
+ GetPluginName().GetCString());
+ }
+ else
+ {
+ error.SetErrorString ("invalid platform file argument");
+ }
+ return error;
+}
+
+Error
+PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec,
+ Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ // For iOS, the SDK files are all cached locally on the host
+ // system. So first we ask for the file in the cached SDK,
+ // then we attempt to get a shared module for the right architecture
+ // with the right UUID.
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+ Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE);
+
+ Error error;
+ char platform_file_path[PATH_MAX];
+
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ ModuleSpec platform_module_spec(module_spec);
+
+ UpdateSDKDirectoryInfosIfNeeded();
+
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+
+ // If we are connected we migth be able to correctly deduce the SDK directory
+ // using the OS build.
+ const uint32_t connected_sdk_idx = GetConnectedSDKIndex ();
+ if (connected_sdk_idx < num_sdk_infos)
+ {
+ if (log)
+ {
+ log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[connected_sdk_idx].directory.GetPath().c_str());
+ }
+ if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ module_sp.reset();
+ error = ResolveExecutable (platform_module_spec,
+ module_sp,
+ NULL);
+ if (module_sp)
+ {
+ m_last_module_sdk_idx = connected_sdk_idx;
+ error.Clear();
+ return error;
+ }
+ }
+ }
+
+ // Try the last SDK index if it is set as most files from an SDK
+ // will tend to be valid in that same SDK.
+ if (m_last_module_sdk_idx < num_sdk_infos)
+ {
+ if (log)
+ {
+ log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[m_last_module_sdk_idx].directory.GetPath().c_str());
+ }
+ if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ module_sp.reset();
+ error = ResolveExecutable (platform_module_spec,
+ module_sp,
+ NULL);
+ if (module_sp)
+ {
+ error.Clear();
+ return error;
+ }
+ }
+ }
+
+ // First try for an exact match of major, minor and update:
+ // If a particalar SDK version was specified via --version or --build, look for a match on disk.
+ const SDKDirectoryInfo *current_sdk_info = GetSDKDirectoryForCurrentOSVersion();
+ const uint32_t current_sdk_idx = GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
+ if (current_sdk_idx < num_sdk_infos && current_sdk_idx != m_last_module_sdk_idx)
+ {
+ if (log)
+ {
+ log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[current_sdk_idx].directory.GetPath().c_str());
+ }
+ if (GetFileInSDK (platform_file_path, current_sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ module_sp.reset();
+ error = ResolveExecutable (platform_module_spec,
+ module_sp,
+ NULL);
+ if (module_sp)
+ {
+ m_last_module_sdk_idx = current_sdk_idx;
+ error.Clear();
+ return error;
+ }
+ }
+ }
+
+ // Second try all SDKs that were found.
+ for (uint32_t sdk_idx=0; sdk_idx<num_sdk_infos; ++sdk_idx)
+ {
+ if (m_last_module_sdk_idx == sdk_idx)
+ {
+ // Skip the last module SDK index if we already searched
+ // it above
+ continue;
+ }
+ if (log)
+ {
+ log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str());
+ }
+ if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec()))
+ {
+ //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
+
+ error = ResolveExecutable (platform_module_spec, module_sp, NULL);
+ if (module_sp)
+ {
+ // Remember the index of the last SDK that we found a file
+ // in in case the wrong SDK was selected.
+ m_last_module_sdk_idx = sdk_idx;
+ error.Clear();
+ return error;
+ }
+ }
+ }
+ }
+ // Not the module we are looking for... Nothing to see here...
+ module_sp.reset();
+
+ // This may not be an SDK-related module. Try whether we can bring in the thing to our local cache.
+ error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
+ if (error.Success())
+ return error;
+
+ const bool always_create = false;
+ error = ModuleList::GetSharedModule (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr,
+ always_create);
+
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(platform_file);
+
+ return error;
+}
+
+bool
+PlatformRemoteiOS::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ return ARMGetSupportedArchitectureAtIndex (idx, arch);
+}
+
+uint32_t
+PlatformRemoteiOS::GetConnectedSDKIndex ()
+{
+ if (IsConnected())
+ {
+ if (m_connected_module_sdk_idx == UINT32_MAX)
+ {
+ std::string build;
+ if (GetRemoteOSBuildString(build))
+ {
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ for (uint32_t i=0; i<num_sdk_infos; ++i)
+ {
+ const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
+ if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), build.c_str()))
+ {
+ m_connected_module_sdk_idx = i;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ m_connected_module_sdk_idx = UINT32_MAX;
+ }
+ return m_connected_module_sdk_idx;
+}
+
+uint32_t
+PlatformRemoteiOS::GetSDKIndexBySDKDirectoryInfo (const SDKDirectoryInfo *sdk_info)
+{
+ if (sdk_info == NULL)
+ {
+ return UINT32_MAX;
+ }
+
+ return sdk_info - &m_sdk_directory_infos[0];
+}
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
new file mode 100644
index 0000000000000..9726d8238e137
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
@@ -0,0 +1,173 @@
+//===-- PlatformRemoteiOS.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_PlatformRemoteiOS_h_
+#define liblldb_PlatformRemoteiOS_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Host/FileSpec.h"
+#include "PlatformDarwin.h"
+
+class PlatformRemoteiOS : public PlatformDarwin
+{
+public:
+ PlatformRemoteiOS ();
+
+ ~PlatformRemoteiOS() override;
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ lldb_private::Error
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic();
+ }
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ virtual lldb_private::Error
+ GetSymbolFile (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+ void
+ AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
+ {
+ return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::iPhoneOS);
+ }
+
+protected:
+ struct SDKDirectoryInfo
+ {
+ SDKDirectoryInfo (const lldb_private::FileSpec &sdk_dir_spec);
+ lldb_private::FileSpec directory;
+ lldb_private::ConstString build;
+ uint32_t version_major;
+ uint32_t version_minor;
+ uint32_t version_update;
+ bool user_cached;
+ };
+
+ typedef std::vector<SDKDirectoryInfo> SDKDirectoryInfoCollection;
+
+ SDKDirectoryInfoCollection m_sdk_directory_infos;
+ std::string m_device_support_directory;
+ std::string m_device_support_directory_for_os_version;
+ std::string m_build_update;
+ uint32_t m_last_module_sdk_idx;
+ uint32_t m_connected_module_sdk_idx;
+
+ bool
+ UpdateSDKDirectoryInfosIfNeeded();
+
+ const char *
+ GetDeviceSupportDirectory();
+
+ const char *
+ GetDeviceSupportDirectoryForOSVersion();
+
+ const SDKDirectoryInfo *
+ GetSDKDirectoryForLatestOSVersion ();
+
+ const SDKDirectoryInfo *
+ GetSDKDirectoryForCurrentOSVersion ();
+
+ static lldb_private::FileSpec::EnumerateDirectoryResult
+ GetContainedFilesIntoVectorOfStringsCallback (void *baton,
+ lldb_private::FileSpec::FileType file_type,
+ const lldb_private::FileSpec &file_spec);
+
+ uint32_t
+ FindFileInAllSDKs (const char *platform_file_path,
+ lldb_private::FileSpecList &file_list);
+
+ bool
+ GetFileInSDK (const char *platform_file_path,
+ uint32_t sdk_idx,
+ lldb_private::FileSpec &local_file);
+
+ bool
+ GetFileInSDKRoot (const char *platform_file_path,
+ const char *sdkroot_path,
+ bool symbols_dirs_only,
+ lldb_private::FileSpec &local_file);
+
+ uint32_t
+ FindFileInAllSDKs (const lldb_private::FileSpec &platform_file,
+ lldb_private::FileSpecList &file_list);
+
+ uint32_t
+ GetConnectedSDKIndex ();
+
+ // Get index of SDK in SDKDirectoryInfoCollection by its pointer and return UINT32_MAX if that SDK not found.
+ uint32_t
+ GetSDKIndexBySDKDirectoryInfo (const SDKDirectoryInfo *sdk_info);
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformRemoteiOS);
+};
+
+#endif // liblldb_PlatformRemoteiOS_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
new file mode 100644
index 0000000000000..cbe9c7949a4a6
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
@@ -0,0 +1,502 @@
+//===-- PlatformiOSSimulator.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformiOSSimulator.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void
+PlatformiOSSimulator::Initialize ()
+{
+ PlatformAppleSimulator::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+ PluginManager::RegisterPlugin (PlatformiOSSimulator::GetPluginNameStatic(),
+ PlatformiOSSimulator::GetDescriptionStatic(),
+ PlatformiOSSimulator::CreateInstance);
+ }
+}
+
+void
+PlatformiOSSimulator::Terminate ()
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+ PluginManager::UnregisterPlugin (PlatformiOSSimulator::CreateInstance);
+ }
+ }
+
+ PlatformAppleSimulator::Terminate ();
+}
+
+PlatformSP
+PlatformiOSSimulator::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 ("PlatformiOSSimulator::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ bool create = force;
+ if (create == false && arch && arch->IsValid())
+ {
+ switch (arch->GetMachine())
+ {
+ case llvm::Triple::x86_64:
+ case llvm::Triple::x86:
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ switch (triple.getVendor())
+ {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::Darwin: // Deprecated, but still support Darwin for historical reasons
+ case llvm::Triple::MacOSX:
+ case llvm::Triple::IOS: // IOS is not used for simulator triples, but accept it just in case
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the OS if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownOS:
+ create = !arch->TripleOSWasSpecified();
+ break;
+#endif
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (create)
+ {
+ if (log)
+ log->Printf ("PlatformiOSSimulator::%s() creating platform", __FUNCTION__);
+
+ return PlatformSP(new PlatformiOSSimulator ());
+ }
+
+ if (log)
+ log->Printf ("PlatformiOSSimulator::%s() aborting creation of platform", __FUNCTION__);
+
+ return PlatformSP();
+}
+
+
+lldb_private::ConstString
+PlatformiOSSimulator::GetPluginNameStatic ()
+{
+ static ConstString g_name("ios-simulator");
+ return g_name;
+}
+
+const char *
+PlatformiOSSimulator::GetDescriptionStatic()
+{
+ return "iOS simulator platform plug-in.";
+}
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformiOSSimulator::PlatformiOSSimulator () :
+PlatformAppleSimulator (),
+m_sdk_directory ()
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformiOSSimulator::~PlatformiOSSimulator()
+{
+}
+
+
+void
+PlatformiOSSimulator::GetStatus (Stream &strm)
+{
+ Platform::GetStatus (strm);
+ const char *sdk_directory = GetSDKDirectoryAsCString();
+ if (sdk_directory)
+ strm.Printf (" SDK Path: \"%s\"\n", sdk_directory);
+ else
+ strm.PutCString (" SDK Path: error: unable to locate SDK\n");
+ PlatformAppleSimulator::GetStatus(strm);
+}
+
+
+Error
+PlatformiOSSimulator::ResolveExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ ModuleSpec resolved_module_spec(module_spec);
+
+ // If we have "ls" as the exe_file, resolve the executable loation based on
+ // the current path variables
+ // TODO: resolve bare executables in the Platform SDK
+ // if (!resolved_exe_file.Exists())
+ // resolved_exe_file.ResolveExecutableLocation ();
+
+ // Resolve any executable within a bundle on MacOSX
+ // TODO: verify that this handles shallow bundles, if not then implement one ourselves
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ return error;
+ exe_module_sp.reset();
+ }
+ // No valid architecture was specified or the exact ARM slice wasn't
+ // found so ask the platform for the architectures that we should be
+ // using (in the correct order) and see if we can find a match that way
+ StreamString arch_names;
+ ArchSpec platform_arch;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ // Only match x86 with x86 and x86_64 with x86_64...
+ if (!module_spec.GetArchitecture().IsValid() || module_spec.GetArchitecture().GetCore() == resolved_module_spec.GetArchitecture().GetCore())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ NULL,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (platform_arch.GetArchitectureName());
+ }
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("'%s' does not exist",
+ module_spec.GetFileSpec().GetPath().c_str());
+ }
+
+ return error;
+}
+
+static FileSpec::EnumerateDirectoryResult
+EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const FileSpec &file_spec)
+{
+ if (file_type == FileSpec::eFileTypeDirectory)
+ {
+ const char *filename = file_spec.GetFilename().GetCString();
+ if (filename && strncmp(filename, "iPhoneSimulator", strlen ("iPhoneSimulator")) == 0)
+ {
+ ::snprintf ((char *)baton, PATH_MAX, "%s", filename);
+ return FileSpec::eEnumerateDirectoryResultQuit;
+ }
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+}
+
+
+
+const char *
+PlatformiOSSimulator::GetSDKDirectoryAsCString()
+{
+ Mutex::Locker locker (m_mutex);
+ if (m_sdk_directory.empty())
+ {
+ const char *developer_dir = GetDeveloperDirectory();
+ if (developer_dir)
+ {
+ char sdks_directory[PATH_MAX];
+ char sdk_dirname[PATH_MAX];
+ sdk_dirname[0] = '\0';
+ snprintf (sdks_directory,
+ sizeof(sdks_directory),
+ "%s/Platforms/iPhoneSimulator.platform/Developer/SDKs",
+ developer_dir);
+ FileSpec simulator_sdk_spec;
+ bool find_directories = true;
+ bool find_files = false;
+ bool find_other = false;
+ FileSpec::EnumerateDirectory (sdks_directory,
+ find_directories,
+ find_files,
+ find_other,
+ EnumerateDirectoryCallback,
+ sdk_dirname);
+
+ if (sdk_dirname[0])
+ {
+ m_sdk_directory = sdks_directory;
+ m_sdk_directory.append (1, '/');
+ m_sdk_directory.append (sdk_dirname);
+ return m_sdk_directory.c_str();
+ }
+ }
+ // Assign a single NULL character so we know we tried to find the device
+ // support directory and we don't keep trying to find it over and over.
+ m_sdk_directory.assign (1, '\0');
+ }
+
+ // We should have put a single NULL character into m_sdk_directory
+ // or it should have a valid path if the code gets here
+ assert (m_sdk_directory.empty() == false);
+ if (m_sdk_directory[0])
+ return m_sdk_directory.c_str();
+ return NULL;
+}
+
+Error
+PlatformiOSSimulator::GetSymbolFile (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ Error error;
+ char platform_file_path[PATH_MAX];
+ if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path)))
+ {
+ char resolved_path[PATH_MAX];
+
+ const char * sdk_dir = GetSDKDirectoryAsCString();
+ if (sdk_dir)
+ {
+ ::snprintf (resolved_path,
+ sizeof(resolved_path),
+ "%s/%s",
+ sdk_dir,
+ platform_file_path);
+
+ // First try in the SDK and see if the file is in there
+ local_file.SetFile(resolved_path, true);
+ if (local_file.Exists())
+ return error;
+
+ // Else fall back to the actual path itself
+ local_file.SetFile(platform_file_path, true);
+ if (local_file.Exists())
+ return error;
+
+ }
+ error.SetErrorStringWithFormat ("unable to locate a platform file for '%s' in platform '%s'",
+ platform_file_path,
+ GetPluginName().GetCString());
+ }
+ else
+ {
+ error.SetErrorString ("invalid platform file argument");
+ }
+ return error;
+}
+
+Error
+PlatformiOSSimulator::GetSharedModule (const ModuleSpec &module_spec,
+ Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ // For iOS, the SDK files are all cached locally on the host
+ // system. So first we ask for the file in the cached SDK,
+ // then we attempt to get a shared module for the right architecture
+ // with the right UUID.
+ Error error;
+ ModuleSpec platform_module_spec (module_spec);
+ const FileSpec &platform_file = module_spec.GetFileSpec();
+ error = GetSymbolFile (platform_file, module_spec.GetUUIDPtr(), platform_module_spec.GetFileSpec());
+ if (error.Success())
+ {
+ error = ResolveExecutable (platform_module_spec, module_sp, module_search_paths_ptr);
+ }
+ else
+ {
+ const bool always_create = false;
+ error = ModuleList::GetSharedModule (module_spec,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr,
+ always_create);
+
+ }
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(platform_file);
+
+ return error;
+}
+
+
+uint32_t
+PlatformiOSSimulator::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ ProcessInstanceInfoList all_osx_process_infos;
+ // First we get all OSX processes
+ const uint32_t n = Host::FindProcesses (match_info, all_osx_process_infos);
+
+ // Now we filter them down to only the iOS triples
+ for (uint32_t i=0; i<n; ++i)
+ {
+ const ProcessInstanceInfo &proc_info = all_osx_process_infos.GetProcessInfoAtIndex(i);
+ if (proc_info.GetArchitecture().GetTriple().getOS() == llvm::Triple::IOS) {
+ process_infos.Append(proc_info);
+ }
+ }
+ return process_infos.GetSize();
+}
+
+bool
+PlatformiOSSimulator::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ static const ArchSpec platform_arch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
+ static const ArchSpec platform_arch64(HostInfo::GetArchitecture(HostInfo::eArchKind64));
+
+ if (idx == 0)
+ {
+ arch = platform_arch;
+ if (arch.IsValid())
+ {
+ arch.GetTriple().setOS (llvm::Triple::IOS);
+ return true;
+ }
+ }
+ else
+ {
+ if (platform_arch.IsExactMatch(platform_arch64))
+ {
+ // This macosx platform supports both 32 and 64 bit.
+ if (idx == 1)
+ {
+ // 32/64: return "x86_64-apple-macosx" for architecture 1
+ arch = platform_arch64;
+ return true;
+ }
+ else if (idx == 2 || idx == 3)
+ {
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
+ if (arch.IsValid())
+ {
+ if (idx == 2)
+ arch.GetTriple().setOS (llvm::Triple::IOS);
+ // 32/64: return "i386-apple-ios" for architecture 2
+ // 32/64: return "i386-apple-macosx" for architecture 3
+ return true;
+ }
+ }
+ }
+ else if (idx == 1)
+ {
+ // This macosx platform supports only 32 bit, so return the *-apple-macosx version
+ arch = platform_arch;
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
new file mode 100644
index 0000000000000..f84d04b9c4856
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
@@ -0,0 +1,116 @@
+//===-- PlatformiOSSimulator.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_PlatformiOSSimulator_h_
+#define liblldb_PlatformiOSSimulator_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "PlatformAppleSimulator.h"
+
+class PlatformiOSSimulator : public PlatformAppleSimulator
+{
+public:
+ PlatformiOSSimulator ();
+
+ ~PlatformiOSSimulator() override;
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static lldb_private::ConstString
+ GetPluginNameStatic ();
+
+ static const char *
+ GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ lldb_private::Error
+ ResolveExecutable (const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic();
+ }
+
+ void
+ GetStatus (lldb_private::Stream &strm) override;
+
+ virtual lldb_private::Error
+ GetSymbolFile (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
+
+ lldb_private::Error
+ GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ uint32_t
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos) override;
+
+ bool
+ GetSupportedArchitectureAtIndex (uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+ void
+ AddClangModuleCompilationOptions (lldb_private::Target *target, std::vector<std::string> &options) override
+ {
+ return PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(target, options, PlatformDarwin::SDKType::iPhoneSimulator);
+ }
+
+protected:
+ std::string m_sdk_directory;
+ std::string m_build_update;
+
+ const char *
+ GetSDKDirectoryAsCString();
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformiOSSimulator);
+};
+
+#endif // liblldb_PlatformiOSSimulator_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h
new file mode 100644
index 0000000000000..8393ea3049063
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.h
@@ -0,0 +1,315 @@
+//===-- PlatformiOSSimulatorCoreSimulatorSupport.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_PlatformiOSSimulatorCoreSimulatorSupport_h_
+#define liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_
+
+// C Includes
+// C++ Includes
+#include <functional>
+#include <string>
+#include <ostream>
+#include <vector>
+// Other libraries and framework includes
+#ifdef __APPLE__
+#include <objc/objc.h>
+#else
+typedef void *id;
+#endif
+// Project includes
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+#include "llvm/ADT/Optional.h"
+
+// And now the actual magic
+namespace CoreSimulatorSupport
+{
+ class Process
+ {
+ public:
+ lldb::pid_t
+ GetPID ()
+ {
+ return m_pid;
+ }
+
+ explicit operator bool ()
+ {
+ return m_pid != LLDB_INVALID_PROCESS_ID;
+ }
+
+ lldb_private::Error
+ GetError ()
+ {
+ return m_error;
+ }
+
+ private:
+ Process (lldb::pid_t p);
+
+ Process(lldb_private::Error error);
+
+ Process (lldb::pid_t p, lldb_private::Error error);
+
+ lldb::pid_t m_pid;
+ lldb_private::Error m_error;
+
+ friend class Device;
+ };
+
+ class ModelIdentifier {
+ public:
+ ModelIdentifier (const std::string& mi);
+ ModelIdentifier ();
+
+ explicit operator bool () const
+ {
+ return !m_versions.empty();
+ }
+
+ size_t
+ GetNumVersions () const
+ {
+ return m_versions.size();
+ }
+
+ unsigned int
+ GetVersionAtIndex (size_t idx) const
+ {
+ return m_versions[idx];
+ }
+
+ std::string
+ GetFamily () const
+ {
+ return m_family.c_str();
+ }
+
+ private:
+ std::string m_family;
+ std::vector<unsigned int> m_versions;
+ };
+
+ class DeviceType
+ {
+ public:
+ enum class ProductFamilyID : int32_t
+ {
+ iPhone = 1,
+ iPad = 2,
+ appleTV = 3,
+ appleWatch = 4
+ };
+
+ DeviceType ();
+
+ DeviceType (id d);
+
+ explicit operator bool ();
+
+ std::string
+ GetName ();
+
+ lldb_private::ConstString
+ GetIdentifier ();
+
+ ModelIdentifier
+ GetModelIdentifier ();
+
+ lldb_private::ConstString
+ GetProductFamily ();
+
+ ProductFamilyID
+ GetProductFamilyID ();
+
+ private:
+ id m_dev;
+ llvm::Optional<ModelIdentifier> m_model_identifier;
+ };
+
+ class OSVersion {
+ public:
+ OSVersion (const std::string& ver,
+ const std::string& build);
+
+ OSVersion ();
+
+ explicit operator bool () const
+ {
+ return !m_versions.empty();
+ }
+
+ size_t
+ GetNumVersions () const
+ {
+ return m_versions.size();
+ }
+
+ unsigned int
+ GetVersionAtIndex (size_t idx) const
+ {
+ return m_versions[idx];
+ }
+
+ const char*
+ GetBuild () const
+ {
+ return m_build.c_str();
+ }
+
+ private:
+ std::vector<unsigned int> m_versions;
+ std::string m_build;
+ };
+
+ class DeviceRuntime
+ {
+ public:
+ DeviceRuntime ();
+
+ DeviceRuntime (id d);
+
+ explicit operator bool ();
+
+ OSVersion
+ GetVersion ();
+
+ bool
+ IsAvailable ();
+
+ private:
+ id m_dev;
+ llvm::Optional<OSVersion> m_os_version;
+ };
+
+ class Device
+ {
+ private:
+ typedef unsigned long int NSUInteger;
+
+ public:
+ enum class State : NSUInteger
+ {
+ Creating,
+ Shutdown,
+ Booting,
+ Booted,
+ ShuttingDown
+ };
+
+ Device ();
+
+ Device (id d);
+
+ explicit operator bool ();
+
+ std::string
+ GetName () const;
+
+ DeviceType
+ GetDeviceType ();
+
+ DeviceRuntime
+ GetDeviceRuntime ();
+
+ State
+ GetState ();
+
+ bool
+ Boot (lldb_private::Error &err);
+
+ bool
+ Shutdown (lldb_private::Error &err);
+
+ std::string
+ GetUDID () const;
+
+ Process
+ Spawn (lldb_private::ProcessLaunchInfo& launch_info);
+
+ private:
+ id m_dev;
+ llvm::Optional<DeviceType> m_dev_type;
+ llvm::Optional<DeviceRuntime> m_dev_runtime;
+
+ friend class DeviceSet;
+ };
+
+ bool
+ operator > (const OSVersion& lhs,
+ const OSVersion& rhs);
+
+ bool
+ operator > (const ModelIdentifier& lhs,
+ const ModelIdentifier& rhs);
+
+ bool
+ operator < (const OSVersion& lhs,
+ const OSVersion& rhs);
+
+ bool
+ operator < (const ModelIdentifier& lhs,
+ const ModelIdentifier& rhs);
+
+ bool
+ operator == (const OSVersion& lhs,
+ const OSVersion& rhs);
+
+ bool
+ operator == (const ModelIdentifier& lhs,
+ const ModelIdentifier& rhs);
+
+ bool
+ operator != (const OSVersion& lhs,
+ const OSVersion& rhs);
+
+ bool
+ operator != (const ModelIdentifier& lhs,
+ const ModelIdentifier& rhs);
+
+ class DeviceSet
+ {
+ public:
+ static DeviceSet
+ GetAllDevices ();
+
+ static DeviceSet
+ GetAvailableDevices ();
+
+ size_t
+ GetNumDevices ();
+
+ Device
+ GetDeviceAtIndex (size_t idx);
+
+ void
+ ForEach (std::function<bool(const Device &)> f);
+
+ DeviceSet
+ GetDevicesIf (std::function<bool(Device)> f);
+
+ DeviceSet
+ GetDevices (DeviceType::ProductFamilyID dev_id);
+
+ Device
+ GetFanciest (DeviceType::ProductFamilyID dev_id);
+
+ private:
+ DeviceSet (id arr) : m_dev(arr)
+ {
+ }
+
+ id m_dev;
+ };
+}
+
+#endif // liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm
new file mode 100644
index 0000000000000..7075de5525296
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulatorCoreSimulatorSupport.mm
@@ -0,0 +1,773 @@
+//===-- PlatformiOSSimulatorCoreSimulatorSupport.cpp ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformiOSSimulatorCoreSimulatorSupport.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include <CoreFoundation/CoreFoundation.h>
+#include <Foundation/Foundation.h>
+// Project includes
+#include "lldb/Target/FileAction.h"
+#include "lldb/Utility/PseudoTerminal.h"
+
+#include "llvm/ADT/StringRef.h"
+
+using namespace lldb_private;
+using namespace lldb_utility;
+// CoreSimulator lives as part of Xcode, which means we can't really link against it, so we dlopen()
+// it at runtime, and error out nicely if that fails
+@interface SimDeviceSet
+{}
++ (id) defaultSet;
+@end
+// However, the drawback is that the compiler will not know about the selectors we're trying to use
+// until runtime; to appease clang in this regard, define a fake protocol on NSObject that exposes
+// the needed interface names for us
+@protocol LLDBCoreSimulatorSupport <NSObject>
+- (NSArray *) devices;
+- (id) deviceType;
+- (NSString *) name;
+- (NSString *) identifier;
+- (NSString *) modelIdentifier;
+- (NSString *) productFamily;
+- (int32_t) productFamilyID;
+- (id) runtime;
+- (BOOL) available;
+- (NSString *) versionString;
+- (NSString *) buildVersionString;
+- (BOOL) bootWithOptions:(NSDictionary *)options error:(NSError**)error;
+- (NSUInteger) state;
+- (BOOL) shutdownWithError:(NSError **)error;
+- (NSUUID *) UDID;
+- (pid_t) spawnWithPath:(NSString *)path options:(NSDictionary *)options terminationHandler:(void (^)(int status)) terminationHandler error:(NSError **)error;
+@end
+
+CoreSimulatorSupport::Process::Process (lldb::pid_t p) :
+ m_pid (p),
+ m_error ()
+{
+}
+
+CoreSimulatorSupport::Process::Process(Error error) :
+ m_pid (LLDB_INVALID_PROCESS_ID),
+ m_error (error)
+{
+}
+
+CoreSimulatorSupport::Process::Process (lldb::pid_t p, Error error) :
+ m_pid (p),
+ m_error (error)
+{
+}
+
+
+CoreSimulatorSupport::DeviceType::DeviceType () :
+ m_dev (nil),
+ m_model_identifier ()
+{
+}
+
+CoreSimulatorSupport::DeviceType::DeviceType (id d) :
+ m_dev (d),
+ m_model_identifier ()
+{
+}
+
+CoreSimulatorSupport::DeviceType::operator bool ()
+{
+ return m_dev != nil;
+}
+
+ConstString
+CoreSimulatorSupport::DeviceType::GetIdentifier ()
+{
+ return ConstString( [[m_dev identifier] UTF8String] );
+}
+
+ConstString
+CoreSimulatorSupport::DeviceType::GetProductFamily ()
+{
+ return ConstString( [[m_dev productFamily] UTF8String] );
+}
+
+CoreSimulatorSupport::DeviceType::ProductFamilyID
+CoreSimulatorSupport::DeviceType::GetProductFamilyID ()
+{
+ return ProductFamilyID([m_dev productFamilyID]);
+}
+
+CoreSimulatorSupport::DeviceRuntime::DeviceRuntime () :
+ m_dev (nil),
+ m_os_version ()
+{
+}
+
+CoreSimulatorSupport::DeviceRuntime::DeviceRuntime (id d) :
+ m_dev (d),
+ m_os_version ()
+{
+}
+
+CoreSimulatorSupport::DeviceRuntime::operator bool ()
+{
+ return m_dev != nil;
+}
+
+bool
+CoreSimulatorSupport::DeviceRuntime::IsAvailable ()
+{
+ return [m_dev available];
+}
+
+CoreSimulatorSupport::Device::Device () :
+ m_dev (nil),
+ m_dev_type (),
+ m_dev_runtime ()
+{
+}
+
+CoreSimulatorSupport::Device::Device (id d) :
+ m_dev (d),
+ m_dev_type (),
+ m_dev_runtime ()
+{
+}
+
+CoreSimulatorSupport::Device::operator bool ()
+{
+ return m_dev != nil;
+}
+
+CoreSimulatorSupport::Device::State
+CoreSimulatorSupport::Device::GetState ()
+{
+ return (State)([m_dev state]);
+}
+
+CoreSimulatorSupport::ModelIdentifier::ModelIdentifier (const std::string& mi) :
+ m_family (),
+ m_versions ()
+{
+ bool any = false;
+ bool first_digit = false;
+ unsigned int val = 0;
+
+ for (char c : mi)
+ {
+ any = true;
+ if (::isdigit(c))
+ {
+ if (!first_digit)
+ first_digit = true;
+ val = 10*val + (c - '0');
+ }
+ else if (c == ',')
+ {
+ if (first_digit)
+ {
+ m_versions.push_back(val);
+ val = 0;
+ }
+ else
+ m_family.push_back(c);
+ }
+ else
+ {
+ if (first_digit)
+ {
+ m_family.clear();
+ m_versions.clear();
+ return;
+ }
+ else
+ {
+ m_family.push_back(c);
+ }
+ }
+ }
+
+ if (first_digit)
+ m_versions.push_back(val);
+}
+
+CoreSimulatorSupport::ModelIdentifier::ModelIdentifier () :
+ModelIdentifier("")
+{
+}
+
+CoreSimulatorSupport::OSVersion::OSVersion (const std::string& ver,
+ const std::string& build) :
+ m_versions (),
+ m_build (build)
+{
+ bool any = false;
+ unsigned int val = 0;
+ for (char c : ver)
+ {
+ if (c == '.')
+ {
+ m_versions.push_back(val);
+ val = 0;
+ }
+ else if (::isdigit(c))
+ {
+ val = 10*val + (c - '0');
+ any = true;
+ }
+ else
+ {
+ m_versions.clear();
+ return;
+ }
+ }
+ if (any)
+ m_versions.push_back(val);
+}
+
+CoreSimulatorSupport::OSVersion::OSVersion () :
+ OSVersion("","")
+{
+}
+
+CoreSimulatorSupport::ModelIdentifier
+CoreSimulatorSupport::DeviceType::GetModelIdentifier ()
+{
+ if (!m_model_identifier.hasValue())
+ {
+ auto utf8_model_id = [[m_dev modelIdentifier] UTF8String];
+ if (utf8_model_id && *utf8_model_id)
+ m_model_identifier = ModelIdentifier (utf8_model_id);
+ }
+
+ if (m_model_identifier.hasValue())
+ return m_model_identifier.getValue();
+ else
+ return ModelIdentifier();
+}
+
+CoreSimulatorSupport::OSVersion
+CoreSimulatorSupport::DeviceRuntime::GetVersion ()
+{
+ if (!m_os_version.hasValue())
+ {
+ auto utf8_ver_string = [[m_dev versionString] UTF8String];
+ auto utf8_build_ver = [[m_dev buildVersionString] UTF8String];
+ if (utf8_ver_string && *utf8_ver_string &&
+ utf8_build_ver && *utf8_build_ver)
+ {
+ m_os_version = OSVersion(utf8_ver_string, utf8_build_ver);
+ }
+ }
+
+ if (m_os_version.hasValue())
+ return m_os_version.getValue();
+ return OSVersion();
+}
+
+std::string
+CoreSimulatorSupport::DeviceType::GetName ()
+{
+ auto utf8_name = [[m_dev name] UTF8String];
+ if (utf8_name)
+ return std::string(utf8_name);
+ return "";
+}
+
+std::string
+CoreSimulatorSupport::Device::GetName () const
+{
+ auto utf8_name = [[m_dev name] UTF8String];
+ if (utf8_name)
+ return std::string(utf8_name);
+ return "";
+}
+
+std::string
+CoreSimulatorSupport::Device::GetUDID () const
+{
+ auto utf8_udid = [ [[m_dev UDID] UUIDString] UTF8String];
+ if (utf8_udid)
+ return std::string(utf8_udid);
+ else
+ return std::string();
+}
+
+CoreSimulatorSupport::DeviceType
+CoreSimulatorSupport::Device::GetDeviceType ()
+{
+ if (!m_dev_type.hasValue())
+ m_dev_type = DeviceType([m_dev deviceType]);
+
+ return m_dev_type.getValue();
+}
+
+CoreSimulatorSupport::DeviceRuntime
+CoreSimulatorSupport::Device::GetDeviceRuntime ()
+{
+ if (!m_dev_runtime.hasValue())
+ m_dev_runtime = DeviceRuntime([m_dev runtime]);
+
+ return m_dev_runtime.getValue();
+}
+
+bool
+CoreSimulatorSupport::operator > (const CoreSimulatorSupport::OSVersion& lhs,
+ const CoreSimulatorSupport::OSVersion& rhs)
+{
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l > r)
+ return true;
+ }
+ return false;
+}
+
+bool
+CoreSimulatorSupport::operator > (const CoreSimulatorSupport::ModelIdentifier& lhs,
+ const CoreSimulatorSupport::ModelIdentifier& rhs)
+{
+ if (lhs.GetFamily() != rhs.GetFamily())
+ return false;
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l > r)
+ return true;
+ }
+ return false;
+}
+
+bool
+CoreSimulatorSupport::operator < (const CoreSimulatorSupport::OSVersion& lhs,
+ const CoreSimulatorSupport::OSVersion& rhs)
+{
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l < r)
+ return true;
+ }
+ return false;
+}
+
+bool
+CoreSimulatorSupport::operator < (const CoreSimulatorSupport::ModelIdentifier& lhs,
+ const CoreSimulatorSupport::ModelIdentifier& rhs)
+{
+ if (lhs.GetFamily() != rhs.GetFamily())
+ return false;
+
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l < r)
+ return true;
+ }
+ return false;
+}
+
+bool
+CoreSimulatorSupport::operator == (const CoreSimulatorSupport::OSVersion& lhs,
+ const CoreSimulatorSupport::OSVersion& rhs)
+{
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l != r)
+ return false;
+ }
+ return true;
+}
+
+bool
+CoreSimulatorSupport::operator == (const CoreSimulatorSupport::ModelIdentifier& lhs,
+ const CoreSimulatorSupport::ModelIdentifier& rhs)
+{
+ if (lhs.GetFamily() != rhs.GetFamily())
+ return false;
+
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l != r)
+ return false;
+ }
+ return true;
+}
+
+bool
+CoreSimulatorSupport::operator != (const CoreSimulatorSupport::OSVersion& lhs,
+ const CoreSimulatorSupport::OSVersion& rhs)
+{
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l != r)
+ return true;
+ }
+ return false;
+}
+
+bool
+CoreSimulatorSupport::operator != (const CoreSimulatorSupport::ModelIdentifier& lhs,
+ const CoreSimulatorSupport::ModelIdentifier& rhs)
+{
+ if (lhs.GetFamily() != rhs.GetFamily())
+ return false;
+
+ for (size_t i = 0;
+ i < rhs.GetNumVersions();
+ i++)
+ {
+ unsigned int l = lhs.GetVersionAtIndex(i);
+ unsigned int r = rhs.GetVersionAtIndex(i);
+ if (l != r)
+ return true;
+ }
+ return false;
+}
+
+bool
+CoreSimulatorSupport::Device::Boot (Error &err)
+{
+ if (m_dev == nil)
+ {
+ err.SetErrorString("no valid simulator instance");
+ return false;
+ }
+
+#define kSimDeviceBootEnv @"env" /* An NSDictionary of "extra" environment key/values */
+#define kSimDeviceBootPersist @"persist" /* An NSNumber (boolean) indicating whether or not the session should outlive the calling process (default false) */
+#define kSimDeviceBootDisabledJobs @"disabled_jobs" /* An NSDictionary of NSStrings -> NSNumbers, each string is the name of a job, and the value is the corresponding state (true if disabled) */
+
+ NSDictionary *options = @{
+ kSimDeviceBootPersist : @NO,
+ kSimDeviceBootDisabledJobs : @{@"com.apple.backboardd" : @YES}
+ };
+
+#undef kSimDeviceBootEnv
+#undef kSimDeviceBootPersist
+#undef kSimDeviceBootDisabledJobs
+
+ NSError* nserror;
+ if ([m_dev bootWithOptions:options error:&nserror])
+ {
+ err.Clear();
+ return true;
+ }
+ else
+ {
+ err.SetErrorString([[nserror description] UTF8String]);
+ return false;
+ }
+}
+
+bool
+CoreSimulatorSupport::Device::Shutdown (Error &err)
+{
+ NSError* nserror;
+ if ([m_dev shutdownWithError:&nserror])
+ {
+ err.Clear();
+ return true;
+ }
+ else
+ {
+ err.SetErrorString([[nserror description] UTF8String]);
+ return false;
+ }
+}
+
+
+static Error
+HandleFileAction(ProcessLaunchInfo& launch_info,
+ NSMutableDictionary *options,
+ NSString *key,
+ const int fd,
+ File &file)
+{
+ Error error;
+ const FileAction *file_action = launch_info.GetFileActionForFD (fd);
+ if (file_action)
+ {
+ switch (file_action->GetAction())
+ {
+ case FileAction::eFileActionNone:
+ break;
+
+ case FileAction::eFileActionClose:
+ error.SetErrorStringWithFormat ("close file action for %i not supported", fd);
+ break;
+
+ case FileAction::eFileActionDuplicate:
+ error.SetErrorStringWithFormat ("duplication file action for %i not supported", fd);
+ break;
+
+ case FileAction::eFileActionOpen:
+ {
+ FileSpec file_spec = file_action->GetFileSpec();
+ if (file_spec)
+ {
+ const int master_fd = launch_info.GetPTY().GetMasterFileDescriptor();
+ if (master_fd != PseudoTerminal::invalid_fd)
+ {
+ // Check in case our file action open wants to open the slave
+ const char *slave_path = launch_info.GetPTY().GetSlaveName(NULL, 0);
+ if (slave_path)
+ {
+ FileSpec slave_spec(slave_path, false);
+ if (file_spec == slave_spec)
+ {
+ int slave_fd = launch_info.GetPTY().GetSlaveFileDescriptor();
+ if (slave_fd == PseudoTerminal::invalid_fd)
+ slave_fd = launch_info.GetPTY().OpenSlave(O_RDWR, nullptr, 0);
+ if (slave_fd == PseudoTerminal::invalid_fd)
+ {
+ error.SetErrorStringWithFormat("unable to open slave pty '%s'", slave_path);
+ return error; // Failure
+ }
+ [options setValue:[NSNumber numberWithInteger:slave_fd] forKey:key];
+ return error; // Success
+ }
+ }
+ }
+ Error posix_error;
+ int created_fd = open(file_spec.GetPath().c_str(), file_action->GetActionArgument(), S_IRUSR | S_IWUSR);
+ if (created_fd >= 0)
+ {
+ file.SetDescriptor(created_fd, true);
+ [options setValue:[NSNumber numberWithInteger:created_fd] forKey:key];
+ return error; // Success
+ }
+ else
+ {
+ posix_error.SetErrorToErrno();
+ error.SetErrorStringWithFormat("unable to open file '%s': %s", file_spec.GetPath().c_str(), posix_error.AsCString());
+ }
+ }
+ }
+ break;
+ }
+ }
+ return error; // Success, no file action, nothing to do
+}
+
+CoreSimulatorSupport::Process
+CoreSimulatorSupport::Device::Spawn (ProcessLaunchInfo& launch_info)
+{
+#define kSimDeviceSpawnEnvironment @"environment" /* An NSDictionary (NSStrings -> NSStrings) of environment key/values */
+#define kSimDeviceSpawnStdin @"stdin" /* An NSNumber corresponding to a fd */
+#define kSimDeviceSpawnStdout @"stdout" /* An NSNumber corresponding to a fd */
+#define kSimDeviceSpawnStderr @"stderr" /* An NSNumber corresponding to a fd */
+#define kSimDeviceSpawnArguments @"arguments" /* An NSArray of strings to use as the argv array. If not provided, path will be argv[0] */
+#define kSimDeviceSpawnWaitForDebugger @"wait_for_debugger" /* An NSNumber (bool) */
+
+ NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
+
+ if (launch_info.GetFlags().Test(lldb::eLaunchFlagDebug))
+ [options setObject:@YES forKey:kSimDeviceSpawnWaitForDebugger];
+
+ if (launch_info.GetArguments().GetArgumentCount())
+ {
+ const Args& args(launch_info.GetArguments());
+ NSMutableArray *args_array = [[NSMutableArray alloc] init];
+ for (size_t idx = 0;
+ idx < args.GetArgumentCount();
+ idx++)
+ [args_array addObject:[NSString stringWithUTF8String:args.GetArgumentAtIndex(idx)]];
+
+ [options setObject:args_array forKey:kSimDeviceSpawnArguments];
+ }
+
+ if (launch_info.GetEnvironmentEntries().GetArgumentCount())
+ {
+ const Args& envs(launch_info.GetEnvironmentEntries());
+ NSMutableDictionary *env_dict = [[NSMutableDictionary alloc] init];
+ for (size_t idx = 0;
+ idx < envs.GetArgumentCount();
+ idx++)
+ {
+ llvm::StringRef arg_sr(envs.GetArgumentAtIndex(idx));
+ auto first_eq = arg_sr.find('=');
+ if (first_eq == llvm::StringRef::npos)
+ continue;
+ llvm::StringRef key = arg_sr.substr(0, first_eq);
+ llvm::StringRef value = arg_sr.substr(first_eq+1);
+
+ NSString *key_ns = [NSString stringWithUTF8String:key.str().c_str()];
+ NSString *value_ns = [NSString stringWithUTF8String:value.str().c_str()];
+
+ [env_dict setValue:value_ns forKey:key_ns];
+ }
+
+ [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment];
+ }
+
+ Error error;
+ File stdin_file;
+ File stdout_file;
+ File stderr_file;
+ error = HandleFileAction(launch_info, options, kSimDeviceSpawnStdin, STDIN_FILENO, stdin_file);
+
+ if (error.Fail())
+ return CoreSimulatorSupport::Process(error);
+
+ error = HandleFileAction(launch_info, options, kSimDeviceSpawnStdout, STDOUT_FILENO, stdout_file);
+
+ if (error.Fail())
+ return CoreSimulatorSupport::Process(error);
+
+ error = HandleFileAction(launch_info, options, kSimDeviceSpawnStderr, STDERR_FILENO, stderr_file);
+
+ if (error.Fail())
+ return CoreSimulatorSupport::Process(error);
+
+#undef kSimDeviceSpawnEnvironment
+#undef kSimDeviceSpawnStdin
+#undef kSimDeviceSpawnStdout
+#undef kSimDeviceSpawnStderr
+#undef kSimDeviceSpawnWaitForDebugger
+#undef kSimDeviceSpawnArguments
+
+ NSError* nserror;
+
+ pid_t pid = [m_dev spawnWithPath: [NSString stringWithUTF8String: launch_info.GetExecutableFile().GetPath().c_str()]
+ options: options
+ terminationHandler: nil
+ error: &nserror];
+
+
+ if (pid < 0)
+ {
+ const char* nserror_string = [[nserror description] UTF8String];
+ error.SetErrorString(nserror_string ? nserror_string : "unable to launch");
+ }
+
+ return CoreSimulatorSupport::Process (pid, error);
+}
+
+CoreSimulatorSupport::DeviceSet
+CoreSimulatorSupport::DeviceSet::GetAllDevices ()
+{
+ return DeviceSet([[NSClassFromString(@"SimDeviceSet") defaultSet] devices]);
+}
+
+CoreSimulatorSupport::DeviceSet
+CoreSimulatorSupport::DeviceSet::GetAvailableDevices ()
+{
+ return GetAllDevices().GetDevicesIf( [] (Device d) -> bool {
+ return (d && d.GetDeviceType() && d.GetDeviceRuntime() && d.GetDeviceRuntime().IsAvailable());
+ });
+}
+
+size_t
+CoreSimulatorSupport::DeviceSet::GetNumDevices ()
+{
+ return [m_dev count];
+}
+
+CoreSimulatorSupport::Device
+CoreSimulatorSupport::DeviceSet::GetDeviceAtIndex (size_t idx)
+{
+ if (idx < GetNumDevices())
+ return Device([m_dev objectAtIndex:idx]);
+ return Device();
+}
+
+CoreSimulatorSupport::DeviceSet
+CoreSimulatorSupport::DeviceSet::GetDevicesIf (std::function<bool(CoreSimulatorSupport::Device)> f)
+{
+ NSMutableArray *array = [[NSMutableArray alloc] init];
+ for (NSUInteger i = 0;
+ i < GetNumDevices();
+ i++)
+ {
+ Device d(GetDeviceAtIndex(i));
+ if (f(d))
+ [array addObject:(id)d.m_dev];
+ }
+
+ return DeviceSet(array);
+}
+
+void
+CoreSimulatorSupport::DeviceSet::ForEach (std::function<bool(const Device &)> f)
+{
+ const size_t n = GetNumDevices();
+ for (NSUInteger i = 0; i < n; ++i)
+ {
+ if (f(GetDeviceAtIndex(i)) == false)
+ break;
+ }
+}
+
+CoreSimulatorSupport::DeviceSet
+CoreSimulatorSupport::DeviceSet::GetDevices (CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id)
+{
+ NSMutableArray *array = [[NSMutableArray alloc] init];
+ const size_t n = GetNumDevices();
+ for (NSUInteger i = 0; i < n; ++i)
+ {
+ Device d(GetDeviceAtIndex(i));
+ if (d && d.GetDeviceType() && d.GetDeviceType().GetProductFamilyID() == dev_id)
+ [array addObject:(id)d.m_dev];
+ }
+
+ return DeviceSet(array);
+}
+
+CoreSimulatorSupport::Device
+CoreSimulatorSupport::DeviceSet::GetFanciest (CoreSimulatorSupport::DeviceType::ProductFamilyID dev_id)
+{
+ Device dev;
+
+ for (NSUInteger i = 0;
+ i < GetNumDevices();
+ i++)
+ {
+ Device d(GetDeviceAtIndex(i));
+ if (d && d.GetDeviceType() && d.GetDeviceType().GetProductFamilyID() == dev_id)
+ {
+ if (!dev)
+ dev = d;
+ else
+ {
+ if ((d.GetDeviceType().GetModelIdentifier() > dev.GetDeviceType().GetModelIdentifier()) ||
+ d.GetDeviceRuntime().GetVersion() > dev.GetDeviceRuntime().GetVersion())
+ dev = d;
+ }
+ }
+ }
+
+ return dev;
+}
diff --git a/source/Plugins/Platform/Makefile b/source/Plugins/Platform/Makefile
new file mode 100644
index 0000000000000..572b08644074c
--- /dev/null
+++ b/source/Plugins/Platform/Makefile
@@ -0,0 +1,36 @@
+##===- source/Plugins/Platform/Makefile --------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../..
+
+include $(LLDB_LEVEL)/../../Makefile.config
+
+PARALLEL_DIRS := gdb-server MacOSX Linux FreeBSD NetBSD POSIX Windows Kalimba Android
+
+# ifeq ($(HOST_OS),Darwin)
+# DIRS += MacOSX
+# endif
+#
+# ifeq ($(HOST_OS),Linux)
+# DIRS += Linux
+# endif
+#
+# ifeq ($(HOST_OS),FreeBSD)
+# DIRS += FreeBSD
+# endif
+#
+# ifeq ($(HOST_OS),GNU/kFreeBSD)
+# DIRS += FreeBSD
+# endif
+#
+# ifeq ($(HOST_OS),NetBSD)
+# DIRS += NetBSD
+# endif
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/NetBSD/CMakeLists.txt b/source/Plugins/Platform/NetBSD/CMakeLists.txt
new file mode 100644
index 0000000000000..c70b419b98b43
--- /dev/null
+++ b/source/Plugins/Platform/NetBSD/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginPlatformNetBSD
+ PlatformNetBSD.cpp
+ )
diff --git a/source/Plugins/Platform/NetBSD/Makefile b/source/Plugins/Platform/NetBSD/Makefile
new file mode 100644
index 0000000000000..2c480bdbe8dac
--- /dev/null
+++ b/source/Plugins/Platform/NetBSD/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/NetBSD/Makefile ------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformNetBSD
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/POSIX/CMakeLists.txt b/source/Plugins/Platform/POSIX/CMakeLists.txt
new file mode 100644
index 0000000000000..c23e68155c2b0
--- /dev/null
+++ b/source/Plugins/Platform/POSIX/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginPlatformPOSIX
+ PlatformPOSIX.cpp
+ )
diff --git a/source/Plugins/Platform/POSIX/Makefile b/source/Plugins/Platform/POSIX/Makefile
new file mode 100644
index 0000000000000..eca927720ba87
--- /dev/null
+++ b/source/Plugins/Platform/POSIX/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/POSIX/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformPOSIX
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/Windows/CMakeLists.txt b/source/Plugins/Platform/Windows/CMakeLists.txt
new file mode 100644
index 0000000000000..09fbc11d33f25
--- /dev/null
+++ b/source/Plugins/Platform/Windows/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginPlatformWindows
+ PlatformWindows.cpp
+ )
diff --git a/source/Plugins/Platform/Windows/Makefile b/source/Plugins/Platform/Windows/Makefile
new file mode 100644
index 0000000000000..b78cd7bfd080f
--- /dev/null
+++ b/source/Plugins/Platform/Windows/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/Windows/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformWindows
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile
diff --git a/source/Plugins/Platform/Windows/PlatformWindows.cpp b/source/Plugins/Platform/Windows/PlatformWindows.cpp
new file mode 100644
index 0000000000000..4172f80176d31
--- /dev/null
+++ b/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -0,0 +1,753 @@
+//===-- PlatformWindows.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformWindows.h"
+
+// C Includes
+#include <stdio.h>
+#if defined (_WIN32)
+#include "lldb/Host/windows/windows.h"
+#include <winsock2.h>
+#endif
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointSite.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static uint32_t g_initialize_count = 0;
+
+namespace
+{
+ class SupportedArchList
+ {
+ public:
+ SupportedArchList()
+ {
+ AddArch(ArchSpec("i686-pc-windows"));
+ AddArch(HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
+ AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind32));
+ AddArch(HostInfo::GetArchitecture(HostInfo::eArchKind64));
+ AddArch(ArchSpec("i386-pc-windows"));
+ }
+
+ size_t Count() const { return m_archs.size(); }
+
+ const ArchSpec& operator[](int idx) { return m_archs[idx]; }
+
+ private:
+ void AddArch(const ArchSpec& spec)
+ {
+ auto iter = std::find_if(
+ m_archs.begin(), m_archs.end(),
+ [spec](const ArchSpec& rhs) { return spec.IsExactMatch(rhs); });
+ if (iter != m_archs.end())
+ return;
+ if (spec.IsValid())
+ m_archs.push_back(spec);
+ }
+
+ std::vector<ArchSpec> m_archs;
+ };
+} // anonymous namespace
+
+PlatformSP
+PlatformWindows::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
+{
+ // The only time we create an instance is when we are creating a remote
+ // windows platform
+ const bool is_host = false;
+
+ 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;
+
+ case llvm::Triple::UnknownArch:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+
+ default:
+ break;
+ }
+
+ if (create)
+ {
+ switch (triple.getOS())
+ {
+ case llvm::Triple::Win32:
+ break;
+
+ case llvm::Triple::UnknownOS:
+ create = arch->TripleOSWasSpecified();
+ break;
+
+ default:
+ create = false;
+ break;
+ }
+ }
+ }
+ if (create)
+ return PlatformSP(new PlatformWindows (is_host));
+ return PlatformSP();
+}
+
+lldb_private::ConstString
+PlatformWindows::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-windows");
+ return g_remote_name;
+ }
+}
+
+const char *
+PlatformWindows::GetPluginDescriptionStatic(bool is_host)
+{
+ return is_host ?
+ "Local Windows user platform plug-in." :
+ "Remote Windows user platform plug-in.";
+}
+
+lldb_private::ConstString
+PlatformWindows::GetPluginName()
+{
+ return GetPluginNameStatic(IsHost());
+}
+
+void
+PlatformWindows::Initialize()
+{
+ Platform::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+#if defined (_WIN32)
+ WSADATA dummy;
+ WSAStartup(MAKEWORD(2,2), &dummy);
+ // Force a host flag to true for the default platform object.
+ PlatformSP default_platform_sp (new PlatformWindows(true));
+ default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
+ Platform::SetHostPlatform (default_platform_sp);
+#endif
+ PluginManager::RegisterPlugin(PlatformWindows::GetPluginNameStatic(false),
+ PlatformWindows::GetPluginDescriptionStatic(false),
+ PlatformWindows::CreateInstance);
+ }
+}
+
+void
+PlatformWindows::Terminate( void )
+{
+ if (g_initialize_count > 0)
+ {
+ if (--g_initialize_count == 0)
+ {
+#ifdef _WIN32
+ WSACleanup();
+#endif
+ PluginManager::UnregisterPlugin (PlatformWindows::CreateInstance);
+ }
+ }
+
+ Platform::Terminate ();
+}
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformWindows::PlatformWindows (bool is_host) :
+ Platform(is_host)
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformWindows::~PlatformWindows() = default;
+
+bool
+PlatformWindows::GetModuleSpec (const FileSpec& module_file_spec,
+ const ArchSpec& arch,
+ ModuleSpec &module_spec)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec);
+
+ return Platform::GetModuleSpec (module_file_spec, arch, module_spec);
+}
+
+Error
+PlatformWindows::ResolveExecutable (const ModuleSpec &ms,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ char exe_path[PATH_MAX];
+ ModuleSpec resolved_module_spec(ms);
+
+ if (IsHost())
+ {
+ // if we cant resolve the executable loation based on the current path variables
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ {
+ resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ }
+
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ {
+ ms.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ {
+ error = GetCachedExecutable (resolved_module_spec, exe_module_sp, nullptr, *m_remote_platform_sp);
+ }
+ else
+ {
+ // We may connect to a process and use the provided executable (Don't use local $PATH).
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
+ }
+ }
+
+ if (error.Success())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule(resolved_module_spec,
+ exe_module_sp,
+ nullptr,
+ nullptr,
+ nullptr);
+
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == nullptr)
+ {
+ exe_module_sp.reset();
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+ }
+ else
+ {
+ // No valid architecture was specified, ask the platform for
+ // the architectures that we should be using (in the correct order)
+ // and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule(resolved_module_spec,
+ exe_module_sp,
+ nullptr,
+ nullptr,
+ nullptr);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ }
+
+ return error;
+}
+
+size_t
+PlatformWindows::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
+{
+ ArchSpec arch = target.GetArchitecture();
+ const uint8_t *trap_opcode = nullptr;
+ size_t trap_opcode_size = 0;
+
+ switch (arch.GetMachine())
+ {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ static const uint8_t g_i386_opcode[] = { 0xCC };
+ trap_opcode = g_i386_opcode;
+ trap_opcode_size = sizeof(g_i386_opcode);
+ }
+ break;
+
+ case llvm::Triple::hexagon:
+ {
+ static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 };
+ trap_opcode = g_hex_opcode;
+ trap_opcode_size = sizeof(g_hex_opcode);
+ }
+ break;
+ default:
+ llvm_unreachable("Unhandled architecture in PlatformWindows::GetSoftwareBreakpointTrapOpcode()");
+ break;
+ }
+
+ if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+ return trap_opcode_size;
+
+ return 0;
+}
+
+bool
+PlatformWindows::GetRemoteOSVersion ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetOSVersion (m_major_os_version,
+ m_minor_os_version,
+ m_update_os_version);
+ return false;
+}
+
+bool
+PlatformWindows::GetRemoteOSBuildString (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSBuildString (s);
+ s.clear();
+ return false;
+}
+
+bool
+PlatformWindows::GetRemoteOSKernelDescription (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
+ s.clear();
+ return false;
+}
+
+// Remote Platform subclasses need to override this function
+ArchSpec
+PlatformWindows::GetRemoteSystemArchitecture ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteSystemArchitecture ();
+ return ArchSpec();
+}
+
+const char *
+PlatformWindows::GetHostname ()
+{
+ if (IsHost())
+ return Platform::GetHostname();
+
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetHostname ();
+ return nullptr;
+}
+
+bool
+PlatformWindows::IsConnected () const
+{
+ if (IsHost())
+ return true;
+ else if (m_remote_platform_sp)
+ return m_remote_platform_sp->IsConnected();
+ return false;
+}
+
+Error
+PlatformWindows::ConnectRemote (Args& args)
+{
+ Error error;
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().AsCString() );
+ }
+ else
+ {
+ if (!m_remote_platform_sp)
+ m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);
+
+ if (m_remote_platform_sp)
+ {
+ if (error.Success())
+ {
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->ConnectRemote (args);
+ }
+ else
+ {
+ error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
+ }
+ }
+ }
+ else
+ error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
+
+ if (error.Fail())
+ m_remote_platform_sp.reset();
+ }
+
+ return error;
+}
+
+Error
+PlatformWindows::DisconnectRemote ()
+{
+ Error error;
+
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().AsCString() );
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->DisconnectRemote ();
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+bool
+PlatformWindows::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ bool success = false;
+ if (IsHost())
+ {
+ success = Platform::GetProcessInfo (pid, process_info);
+ }
+ else if (m_remote_platform_sp)
+ {
+ success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+ }
+ return success;
+}
+
+uint32_t
+PlatformWindows::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ uint32_t match_count = 0;
+ if (IsHost())
+ {
+ // Let the base class figure out the host details
+ match_count = Platform::FindProcesses (match_info, process_infos);
+ }
+ else
+ {
+ // If we are remote, we can only return results if we are connected
+ if (m_remote_platform_sp)
+ match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
+ }
+ return match_count;
+}
+
+Error
+PlatformWindows::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error 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;
+}
+
+ProcessSP
+PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, Target *target, Error &error)
+{
+ // Windows has special considerations that must be followed when launching or attaching to a process. The
+ // key requirement is that when launching or attaching to a process, you must do it from the same the thread
+ // that will go into a permanent loop which will then receive debug events from the process. In particular,
+ // this means we can't use any of LLDB's generic mechanisms to do it for us, because it doesn't have the
+ // special knowledge required for setting up the background thread or passing the right flags.
+ //
+ // Another problem is that that LLDB's standard model for debugging a process is to first launch it, have
+ // it stop at the entry point, and then attach to it. In Windows this doesn't quite work, you have to
+ // specify as an argument to CreateProcess() that you're going to debug the process. So we override DebugProcess
+ // here to handle this. Launch operations go directly to the process plugin, and attach operations almost go
+ // directly to the process plugin (but we hijack the events first). In essence, we encapsulate all the logic
+ // of Launching and Attaching in the process plugin, and PlatformWindows::DebugProcess is just a pass-through
+ // to get to the process plugin.
+
+ if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ {
+ // This is a process attach. Don't need to launch anything.
+ ProcessAttachInfo attach_info(launch_info);
+ return Attach(attach_info, debugger, target, error);
+ }
+ else
+ {
+ ProcessSP process_sp = target->CreateProcess(launch_info.GetListenerForProcess(debugger),
+ launch_info.GetProcessPluginName(),
+ nullptr);
+
+ // We need to launch and attach to the process.
+ launch_info.GetFlags().Set(eLaunchFlagDebug);
+ if (process_sp)
+ error = process_sp->Launch(launch_info);
+
+ return process_sp;
+ }
+}
+
+lldb::ProcessSP
+PlatformWindows::Attach(ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target,
+ Error &error)
+{
+ error.Clear();
+ lldb::ProcessSP process_sp;
+ if (!IsHost())
+ {
+ 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;
+ }
+
+ if (target == nullptr)
+ {
+ TargetSP new_target_sp;
+ FileSpec emptyFileSpec;
+ ArchSpec emptyArchSpec;
+
+ error = debugger.GetTargetList().CreateTarget(debugger,
+ nullptr,
+ nullptr,
+ false,
+ nullptr,
+ new_target_sp);
+ target = new_target_sp.get();
+ }
+
+ if (!target || error.Fail())
+ return process_sp;
+
+ debugger.GetTargetList().SetSelectedTarget(target);
+
+ const char *plugin_name = attach_info.GetProcessPluginName();
+ process_sp = target->CreateProcess(attach_info.GetListenerForProcess(debugger), plugin_name, nullptr);
+
+ process_sp->HijackProcessEvents(attach_info.GetHijackListener().get());
+ if (process_sp)
+ error = process_sp->Attach (attach_info);
+
+ return process_sp;
+}
+
+const char *
+PlatformWindows::GetUserName (uint32_t uid)
+{
+ // Check the cache in Platform in case we have already looked this uid up
+ const char *user_name = Platform::GetUserName(uid);
+ if (user_name)
+ return user_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetUserName(uid);
+ return nullptr;
+}
+
+const char *
+PlatformWindows::GetGroupName (uint32_t gid)
+{
+ const char *group_name = Platform::GetGroupName(gid);
+ if (group_name)
+ return group_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetGroupName(gid);
+ return nullptr;
+}
+
+Error
+PlatformWindows::GetFileWithUUID (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
+ }
+
+ // Default to the local case
+ local_file = platform_file;
+ return Error();
+}
+
+Error
+PlatformWindows::GetSharedModule (const ModuleSpec &module_spec,
+ Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ Error error;
+ module_sp.reset();
+
+ if (IsRemote())
+ {
+ // If we have a remote platform always, let it try and locate
+ // the shared module first.
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+ }
+ }
+
+ if (!module_sp)
+ {
+ // Fall back to the local platform and find the file locally
+ error = Platform::GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+ }
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+ return error;
+}
+
+bool
+PlatformWindows::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ static SupportedArchList architectures;
+
+ if (idx >= architectures.Count())
+ return false;
+ arch = architectures[idx];
+ return true;
+}
+
+void
+PlatformWindows::GetStatus (Stream &strm)
+{
+ Platform::GetStatus(strm);
+
+#ifdef _WIN32
+ uint32_t major;
+ uint32_t minor;
+ uint32_t update;
+ if (!HostInfo::GetOSVersion(major, minor, update))
+ {
+ strm << "Windows";
+ return;
+ }
+
+ strm << "Host: Windows " << major
+ << '.' << minor
+ << " Build: " << update << '\n';
+#endif
+}
+
+bool
+PlatformWindows::CanDebugProcess()
+{
+ return true;
+}
+
+size_t
+PlatformWindows::GetEnvironment(StringList &env)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetEnvironment(env);
+ return 0;
+ }
+
+ return Host::GetEnvironment(env);
+}
+
+ConstString
+PlatformWindows::GetFullNameForDylib (ConstString basename)
+{
+ if (basename.IsEmpty())
+ return basename;
+
+ StreamString stream;
+ stream.Printf("%s.dll", basename.GetCString());
+ return ConstString(stream.GetData());
+}
diff --git a/source/Plugins/Platform/Windows/PlatformWindows.h b/source/Plugins/Platform/Windows/PlatformWindows.h
new file mode 100644
index 0000000000000..e9a04b4cc33d3
--- /dev/null
+++ b/source/Plugins/Platform/Windows/PlatformWindows.h
@@ -0,0 +1,169 @@
+//===-- PlatformWindows.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_PlatformWindows_h_
+#define liblldb_PlatformWindows_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Platform.h"
+
+namespace lldb_private
+{
+
+class PlatformWindows : public Platform
+{
+public:
+ PlatformWindows(bool is_host);
+
+ ~PlatformWindows() 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
+ //------------------------------------------------------------
+ bool
+ GetModuleSpec (const lldb_private::FileSpec& module_file_spec,
+ const lldb_private::ArchSpec& arch,
+ lldb_private::ModuleSpec &module_spec) override;
+
+ Error
+ ResolveExecutable(const lldb_private::ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr) override;
+
+ const char *
+ GetDescription() override
+ {
+ return GetPluginDescriptionStatic(IsHost());
+ }
+
+ size_t
+ GetSoftwareBreakpointTrapOpcode(lldb_private::Target &target,
+ lldb_private::BreakpointSite *bp_site) override;
+
+ bool
+ GetRemoteOSVersion() override;
+
+ bool
+ GetRemoteOSBuildString(std::string &s) override;
+
+ bool
+ GetRemoteOSKernelDescription(std::string &s) override;
+
+ // Remote Platform subclasses need to override this function
+ lldb_private::ArchSpec
+ GetRemoteSystemArchitecture() override;
+
+ bool
+ IsConnected() const override;
+
+ lldb_private::Error
+ ConnectRemote(lldb_private::Args& args) override;
+
+ lldb_private::Error
+ DisconnectRemote() override;
+
+ const char *
+ GetHostname() override;
+
+ const char *
+ GetUserName(uint32_t uid) override;
+
+ const char *
+ GetGroupName(uint32_t gid) override;
+
+ bool
+ GetProcessInfo(lldb::pid_t pid,
+ lldb_private::ProcessInstanceInfo &proc_info) override;
+
+ uint32_t
+ FindProcesses(const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos) override;
+
+ lldb_private::Error
+ LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override;
+
+ lldb::ProcessSP
+ DebugProcess(lldb_private::ProcessLaunchInfo &launch_info, lldb_private::Debugger &debugger,
+ lldb_private::Target *target, lldb_private::Error &error) override;
+
+ lldb::ProcessSP
+ Attach(lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger,
+ lldb_private::Target *target, lldb_private::Error &error) override;
+
+ lldb_private::Error
+ GetFileWithUUID(const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID* uuid, lldb_private::FileSpec &local_file) override;
+
+ lldb_private::Error
+ GetSharedModule(const lldb_private::ModuleSpec &module_spec,
+ lldb_private::Process* process,
+ lldb::ModuleSP &module_sp,
+ const lldb_private::FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ bool
+ GetSupportedArchitectureAtIndex(uint32_t idx, lldb_private::ArchSpec &arch) override;
+
+ void
+ GetStatus(lldb_private::Stream &strm) override;
+
+ bool CanDebugProcess() override;
+
+ size_t GetEnvironment(StringList &env) override;
+
+ // FIXME not sure what the _sigtramp equivalent would be on this platform
+ void
+ CalculateTrapHandlerSymbolNames () override
+ {
+ }
+
+ ConstString
+ GetFullNameForDylib (ConstString basename) override;
+
+protected:
+ lldb::PlatformSP m_remote_platform_sp;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformWindows);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_PlatformWindows_h_
diff --git a/source/Plugins/Platform/gdb-server/CMakeLists.txt b/source/Plugins/Platform/gdb-server/CMakeLists.txt
new file mode 100644
index 0000000000000..b0b669e5b8b7d
--- /dev/null
+++ b/source/Plugins/Platform/gdb-server/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginPlatformGDB
+ PlatformRemoteGDBServer.cpp
+ )
diff --git a/source/Plugins/Platform/gdb-server/Makefile b/source/Plugins/Platform/gdb-server/Makefile
new file mode 100644
index 0000000000000..c56613b2a6536
--- /dev/null
+++ b/source/Plugins/Platform/gdb-server/Makefile
@@ -0,0 +1,14 @@
+##===- source/Plugins/Platform/gdb-server/Makefile ---------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LLDB_LEVEL := ../../../..
+LIBRARYNAME := lldbPluginPlatformGDB
+BUILD_ARCHIVE = 1
+
+include $(LLDB_LEVEL)/Makefile