summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
diff options
context:
space:
mode:
authorTamas Berghammer <tberghammer@google.com>2015-02-12 18:13:44 +0000
committerTamas Berghammer <tberghammer@google.com>2015-02-12 18:13:44 +0000
commit00e305d281502a9b4d90dc02aa4c7dad819a9083 (patch)
tree39a3796bf30454182b8947b30e29e42f6eb3db0d /lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
parent97eac4089aa5e249143fbc7aa24984242eeea54b (diff)
downloadbcm5719-llvm-00e305d281502a9b4d90dc02aa4c7dad819a9083.tar.gz
bcm5719-llvm-00e305d281502a9b4d90dc02aa4c7dad819a9083.zip
Create new platform: remote-android
* Create new platform plugin for lldb * Create HostInfo class for android * Create ProcessLauncher for android Differential Revision: http://reviews.llvm.org/D7584 llvm-svn: 228943
Diffstat (limited to 'lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp')
-rw-r--r--lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
new file mode 100644
index 00000000000..8d782f4351a
--- /dev/null
+++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -0,0 +1,224 @@
+//===-- 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/Host/ConnectionFileDescriptor.h"
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "PlatformAndroidRemoteGDBServer.h"
+#include "Utility/UriParser.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const lldb::pid_t g_remote_platform_pid = 0; // Alias for the process id of lldb-platform
+static const uint32_t g_adb_timeout = 10000; // 10 ms
+
+static void
+SendMessageToAdb (Connection& conn, const std::string& packet, Error& error)
+{
+ ConnectionStatus status;
+
+ char length_buffer[5];
+ snprintf (length_buffer, sizeof (length_buffer), "%04zx", packet.size());
+
+ conn.Write (length_buffer, 4, status, &error);
+ if (error.Fail ())
+ return;
+
+ conn.Write (packet.c_str(), packet.size(), status, &error);
+}
+
+static std::string
+ReadMessageFromAdb (Connection& conn, bool has_okay, Error& error)
+{
+ ConnectionStatus status;
+
+ char buffer[5];
+ buffer[4] = 0;
+
+ if (has_okay)
+ {
+ conn.Read (buffer, 4, g_adb_timeout, status, &error);
+ if (error.Fail ())
+ return "";
+
+ if (strncmp (buffer, "OKAY", 4) != 0)
+ {
+ error.SetErrorStringWithFormat ("\"OKAY\" expected from adb, received: \"%s\"", buffer);
+ return "";
+ }
+ }
+
+ conn.Read (buffer, 4, g_adb_timeout, status, &error);
+ if (error.Fail())
+ return "";
+
+ size_t packet_len = 0;
+ sscanf(buffer, "%zx", &packet_len);
+ std::string result(packet_len, 0);
+ conn.Read (&result[0], packet_len, g_adb_timeout, status, &error);
+ if (error.Fail ())
+ return "";
+
+ return result;
+}
+
+static Error
+ForwardPortWithAdb (uint16_t port, std::string& device_id)
+{
+ Error error;
+
+ {
+ // Fetch the device list from ADB and if only 1 device found then use that device
+ // TODO: Handle the case when more device is available
+ std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ());
+ if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess)
+ return error;
+
+ SendMessageToAdb (*conn, "host:devices", error);
+ if (error.Fail ())
+ return error;
+ std::string in_buffer = ReadMessageFromAdb (*conn, true, error);
+
+ llvm::StringRef deviceList(in_buffer);
+ std::pair<llvm::StringRef, llvm::StringRef> devices = deviceList.split ('\n');
+ if (devices.first.size () == 0 || devices.second.size () > 0)
+ {
+ error.SetErrorString ("Wrong number of devices returned from ADB");
+ return error;
+ }
+
+ device_id = devices.first.split ('\t').first;
+ }
+
+ {
+ // Forward the port to the (only) connected device
+ std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ());
+ if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess)
+ return error;
+
+ char port_buffer[32];
+ snprintf (port_buffer, sizeof (port_buffer), "tcp:%d;tcp:%d", port, port);
+
+ std::string out_buffer = "host-serial:" + device_id + ":forward:" + port_buffer;
+ SendMessageToAdb (*conn, out_buffer, error);
+ if (error.Fail ())
+ return error;
+
+ std::string in_buffer = ReadMessageFromAdb (*conn, false, error);
+ if (in_buffer != "OKAY")
+ error.SetErrorString (in_buffer.c_str ());
+ }
+
+ return error;
+}
+
+static Error
+DeleteForwardPortWithAdb (uint16_t port, const std::string& device_id)
+{
+ Error error;
+
+ std::unique_ptr<ConnectionFileDescriptor> conn (new ConnectionFileDescriptor ());
+ if (conn->Connect ("connect://localhost:5037", &error) != eConnectionStatusSuccess)
+ return error;
+
+ char port_buffer[16];
+ snprintf (port_buffer, sizeof (port_buffer), "tcp:%d", port);
+
+ std::string out_buffer = "host-serial:" + device_id + ":killforward:" + port_buffer;
+ SendMessageToAdb (*conn, out_buffer, error);
+ if (error.Fail ())
+ return error;
+
+ std::string in_buffer = ReadMessageFromAdb (*conn, true, error);
+ if (in_buffer != "OKAY")
+ error.SetErrorString (in_buffer.c_str ());
+
+ return error;
+}
+
+PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer ()
+{
+}
+
+PlatformAndroidRemoteGDBServer::~PlatformAndroidRemoteGDBServer ()
+{
+ for (const auto& it : m_port_forwards)
+ {
+ DeleteForwardPortWithAdb (it.second.first, it.second.second);
+ }
+}
+
+uint16_t
+PlatformAndroidRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
+{
+ uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
+ if (port == 0)
+ return port;
+
+ std::string device_id;
+ Error error = ForwardPortWithAdb (port, device_id);
+ if (error.Fail ())
+ return 0;
+
+ m_port_forwards[pid] = std::make_pair (port, device_id);
+
+ return port;
+}
+
+bool
+PlatformAndroidRemoteGDBServer::KillSpawnedProcess (lldb::pid_t pid)
+{
+ auto it = m_port_forwards.find (pid);
+ if (it != m_port_forwards.end ())
+ {
+ DeleteForwardPortWithAdb (it->second.first, it->second.second);
+ m_port_forwards.erase (it);
+ }
+
+ return m_gdb_client.KillSpawnedProcess (pid);
+}
+
+Error
+PlatformAndroidRemoteGDBServer::ConnectRemote (Args& args)
+{
+ if (args.GetArgumentCount () != 1)
+ return Error ("\"platform connect\" takes a single argument: <connect-url>");
+
+ int port;
+ std::string scheme, host, path;
+ const char *url = args.GetArgumentAtIndex (0);
+ if (!UriParser::Parse (url, scheme, host, port, path))
+ return Error ("invalid uri");
+
+ std::string device_id;
+ Error error = ForwardPortWithAdb (port, device_id);
+ if (error.Fail ())
+ return error;
+
+ m_port_forwards[g_remote_platform_pid] = std::make_pair (port, device_id);
+
+ return PlatformRemoteGDBServer::ConnectRemote (args);
+}
+
+Error
+PlatformAndroidRemoteGDBServer::DisconnectRemote ()
+{
+ auto it = m_port_forwards.find (g_remote_platform_pid);
+ if (it != m_port_forwards.end ())
+ {
+ DeleteForwardPortWithAdb (it->second.first, it->second.second);
+ m_port_forwards.erase (it);
+ }
+
+ return PlatformRemoteGDBServer::DisconnectRemote ();
+}
OpenPOWER on IntegriCloud