mirror of
https://github.com/intel/llvm.git
synced 2026-01-22 23:49:22 +08:00
Move ADB communications to AdbClient class - to make it accessible by other components.
http://reviews.llvm.org/D8535 llvm-svn: 233021
This commit is contained in:
@@ -100,6 +100,8 @@
|
||||
254FBBA51A91670E00BD6378 /* SBAttachInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */; };
|
||||
257E47171AA56C2000A62F81 /* ModuleCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 257E47151AA56C2000A62F81 /* ModuleCache.cpp */; };
|
||||
257E47181AA56C2000A62F81 /* ModuleCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 257E47161AA56C2000A62F81 /* ModuleCache.h */; };
|
||||
25EF23781AC09B3700908DF0 /* AdbClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25EF23751AC09AD800908DF0 /* AdbClient.cpp */; };
|
||||
25EF23791AC09B4200908DF0 /* AdbClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 25EF23761AC09AD800908DF0 /* AdbClient.h */; };
|
||||
260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
|
||||
260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
|
||||
2606EDDF184E68A10034641B /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; };
|
||||
@@ -1221,6 +1223,8 @@
|
||||
254FBBA61A91672800BD6378 /* SBAttachInfo.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBAttachInfo.i; sourceTree = "<group>"; };
|
||||
257E47151AA56C2000A62F81 /* ModuleCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleCache.cpp; path = source/Utility/ModuleCache.cpp; sourceTree = "<group>"; };
|
||||
257E47161AA56C2000A62F81 /* ModuleCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ModuleCache.h; path = source/Utility/ModuleCache.h; sourceTree = "<group>"; };
|
||||
25EF23751AC09AD800908DF0 /* AdbClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AdbClient.cpp; sourceTree = "<group>"; };
|
||||
25EF23761AC09AD800908DF0 /* AdbClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AdbClient.h; sourceTree = "<group>"; };
|
||||
260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = "<absolute>"; };
|
||||
260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = "<group>"; };
|
||||
260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = "<group>"; };
|
||||
@@ -4971,6 +4975,8 @@
|
||||
6D55BAE61A8CD08C00A70529 /* Android */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
25EF23751AC09AD800908DF0 /* AdbClient.cpp */,
|
||||
25EF23761AC09AD800908DF0 /* AdbClient.h */,
|
||||
6D55BAE91A8CD08C00A70529 /* PlatformAndroid.cpp */,
|
||||
6D55BAEA1A8CD08C00A70529 /* PlatformAndroid.h */,
|
||||
6D55BAEB1A8CD08C00A70529 /* PlatformAndroidRemoteGDBServer.cpp */,
|
||||
@@ -5306,6 +5312,7 @@
|
||||
26CFDCA11861638D000E63E5 /* Editline.h in Headers */,
|
||||
26BC17B018C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.h in Headers */,
|
||||
6D55BAF01A8CD0BD00A70529 /* PlatformAndroidRemoteGDBServer.h in Headers */,
|
||||
25EF23791AC09B4200908DF0 /* AdbClient.h in Headers */,
|
||||
AF9B8F34182DB52900DA866F /* SystemRuntimeMacOSX.h in Headers */,
|
||||
26474CB518D0CB180073DEBA /* RegisterContextLinux_x86_64.h in Headers */,
|
||||
26D1804716CEE12C00EDFB5B /* TimeSpecTimeout.h in Headers */,
|
||||
@@ -6086,6 +6093,7 @@
|
||||
268900C113353E5F00698AC0 /* DWARFDebugPubnames.cpp in Sources */,
|
||||
268900C213353E5F00698AC0 /* DWARFDebugPubnamesSet.cpp in Sources */,
|
||||
268900C313353E5F00698AC0 /* DWARFDebugRanges.cpp in Sources */,
|
||||
25EF23781AC09B3700908DF0 /* AdbClient.cpp in Sources */,
|
||||
94380B8219940B0A00BFE4A8 /* StringLexer.cpp in Sources */,
|
||||
268900C413353E5F00698AC0 /* DWARFDefines.cpp in Sources */,
|
||||
94D0B10C16D5535900EA9C70 /* LibCxx.cpp in Sources */,
|
||||
|
||||
187
lldb/source/Plugins/Platform/Android/AdbClient.cpp
Normal file
187
lldb/source/Plugins/Platform/Android/AdbClient.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
//===-- 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/Host/ConnectionFileDescriptor.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
// Project includes
|
||||
#include "AdbClient.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kConnTimeout = 10000; // 10 ms
|
||||
const char * kOKAY = "OKAY";
|
||||
const char * kFAIL = "FAIL";
|
||||
|
||||
} // namespace
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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::string in_buffer;
|
||||
error = ReadMessage (in_buffer);
|
||||
|
||||
llvm::StringRef response (in_buffer);
|
||||
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 port)
|
||||
{
|
||||
char message[48];
|
||||
snprintf (message, sizeof (message), "forward:tcp:%d;tcp:%d", port, port);
|
||||
|
||||
const auto error = SendDeviceMessage (message);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
return ReadResponseStatus ();
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::DeletePortForwarding (const uint16_t port)
|
||||
{
|
||||
char message[32];
|
||||
snprintf (message, sizeof (message), "killforward:tcp:%d", port);
|
||||
|
||||
const auto error = SendDeviceMessage (message);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
return ReadResponseStatus ();
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::SendMessage (const std::string &packet)
|
||||
{
|
||||
auto error = Connect ();
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
char length_buffer[5];
|
||||
snprintf (length_buffer, sizeof (length_buffer), "%04zx", 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::string &message)
|
||||
{
|
||||
message.clear ();
|
||||
|
||||
char buffer[5];
|
||||
buffer[4] = 0;
|
||||
|
||||
Error error;
|
||||
ConnectionStatus status;
|
||||
|
||||
m_conn.Read (buffer, 4, kConnTimeout, status, &error);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
size_t packet_len = 0;
|
||||
sscanf (buffer, "%zx", &packet_len);
|
||||
std::string result (packet_len, 0);
|
||||
m_conn.Read (&result[0], packet_len, kConnTimeout, status, &error);
|
||||
if (error.Success ())
|
||||
result.swap (message);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
AdbClient::ReadResponseStatus()
|
||||
{
|
||||
char buffer[5];
|
||||
|
||||
static const size_t packet_len = 4;
|
||||
buffer[packet_len] = 0;
|
||||
|
||||
Error error;
|
||||
ConnectionStatus status;
|
||||
|
||||
m_conn.Read (buffer, packet_len, kConnTimeout, status, &error);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
if (strncmp (buffer, kOKAY, packet_len) != 0)
|
||||
{
|
||||
if (strncmp (buffer, kFAIL, packet_len) == 0)
|
||||
{
|
||||
std::string error_message;
|
||||
error = ReadMessage (error_message);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
error.SetErrorString (error_message.c_str ());
|
||||
}
|
||||
else
|
||||
error.SetErrorStringWithFormat ("\"%s\" expected from adb, received: \"%s\"", kOKAY, buffer);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
69
lldb/source/Plugins/Platform/Android/AdbClient.h
Normal file
69
lldb/source/Plugins/Platform/Android/AdbClient.h
Normal file
@@ -0,0 +1,69 @@
|
||||
//===-- 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>
|
||||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
|
||||
#include "lldb/Core/Error.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class AdbClient
|
||||
{
|
||||
public:
|
||||
using DeviceIDList = std::list<std::string>;
|
||||
|
||||
AdbClient () = default;
|
||||
explicit AdbClient (const std::string &device_id);
|
||||
|
||||
void
|
||||
SetDeviceID (const std::string& device_id);
|
||||
|
||||
Error
|
||||
GetDevices (DeviceIDList &device_list);
|
||||
|
||||
Error
|
||||
SetPortForwarding (const uint16_t port);
|
||||
|
||||
Error
|
||||
DeletePortForwarding (const uint16_t port);
|
||||
|
||||
private:
|
||||
Error
|
||||
Connect ();
|
||||
|
||||
Error
|
||||
SendMessage (const std::string &packet);
|
||||
|
||||
Error
|
||||
SendDeviceMessage (const std::string &packet);
|
||||
|
||||
Error
|
||||
ReadMessage (std::string &message);
|
||||
|
||||
Error
|
||||
ReadResponseStatus ();
|
||||
|
||||
std::string m_device_id;
|
||||
ConnectionFileDescriptor m_conn;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_AdbClient_h_
|
||||
@@ -1,6 +1,7 @@
|
||||
set(LLVM_NO_RTTI 1)
|
||||
|
||||
add_lldb_library(lldbPluginPlatformAndroid
|
||||
AdbClient.cpp
|
||||
PlatformAndroid.cpp
|
||||
PlatformAndroidRemoteGDBServer.cpp
|
||||
)
|
||||
|
||||
@@ -9,10 +9,12 @@
|
||||
|
||||
// Other libraries and framework includes
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Host/ConnectionFileDescriptor.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
// Project includes
|
||||
#include "AdbClient.h"
|
||||
#include "PlatformAndroidRemoteGDBServer.h"
|
||||
#include "Utility/UriParser.h"
|
||||
|
||||
@@ -20,130 +22,37 @@ 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;
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM));
|
||||
|
||||
{
|
||||
// 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;
|
||||
// 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
|
||||
AdbClient adb;
|
||||
|
||||
SendMessageToAdb (*conn, "host:devices", error);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
std::string in_buffer = ReadMessageFromAdb (*conn, true, error);
|
||||
AdbClient::DeviceIDList connect_devices;
|
||||
auto error = adb.GetDevices (connect_devices);
|
||||
if (error.Fail ())
|
||||
return 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;
|
||||
}
|
||||
if (connect_devices.size () != 1)
|
||||
return Error ("Expected a single connected device, got instead %" PRIu64, connect_devices.size ());
|
||||
|
||||
device_id = devices.first.split ('\t').first;
|
||||
}
|
||||
device_id = connect_devices.front ();
|
||||
if (log)
|
||||
log->Printf("Connected to Android device \"%s\"", device_id.c_str ());
|
||||
|
||||
{
|
||||
// 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;
|
||||
adb.SetDeviceID (device_id);
|
||||
return adb.SetPortForwarding (port);
|
||||
}
|
||||
|
||||
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;
|
||||
AdbClient adb (device_id);
|
||||
return adb.DeletePortForwarding (port);
|
||||
}
|
||||
|
||||
PlatformAndroidRemoteGDBServer::PlatformAndroidRemoteGDBServer ()
|
||||
|
||||
Reference in New Issue
Block a user