diff options
| -rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 8 | ||||
| -rw-r--r-- | lldb/source/Plugins/Platform/Android/AdbClient.cpp | 187 | ||||
| -rw-r--r-- | lldb/source/Plugins/Platform/Android/AdbClient.h | 69 | ||||
| -rw-r--r-- | lldb/source/Plugins/Platform/Android/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp | 131 | 
5 files changed, 285 insertions, 111 deletions
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index c843e58eedd..336bfaf8247 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -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 */, diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.cpp b/lldb/source/Plugins/Platform/Android/AdbClient.cpp new file mode 100644 index 00000000000..eb094a17439 --- /dev/null +++ b/lldb/source/Plugins/Platform/Android/AdbClient.cpp @@ -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; +} diff --git a/lldb/source/Plugins/Platform/Android/AdbClient.h b/lldb/source/Plugins/Platform/Android/AdbClient.h new file mode 100644 index 00000000000..382e30455da --- /dev/null +++ b/lldb/source/Plugins/Platform/Android/AdbClient.h @@ -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_ diff --git a/lldb/source/Plugins/Platform/Android/CMakeLists.txt b/lldb/source/Plugins/Platform/Android/CMakeLists.txt index bdf72c0ee1e..44f0722d288 100644 --- a/lldb/source/Plugins/Platform/Android/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/Android/CMakeLists.txt @@ -1,6 +1,7 @@  set(LLVM_NO_RTTI 1)  add_lldb_library(lldbPluginPlatformAndroid +  AdbClient.cpp    PlatformAndroid.cpp    PlatformAndroidRemoteGDBServer.cpp    ) diff --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp index 8d782f4351a..e75e0cba9bb 100644 --- a/lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/Android/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) +static Error +ForwardPortWithAdb (uint16_t port, std::string& device_id)  { -    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 ""; -        } -    } +    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); -    conn.Read (buffer, 4, g_adb_timeout, status, &error); -    if (error.Fail()) -        return ""; +    // 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; -    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); +    AdbClient::DeviceIDList connect_devices; +    auto error = adb.GetDevices (connect_devices);      if (error.Fail ()) -        return ""; - -    return result; -} - -static Error -ForwardPortWithAdb (uint16_t port, std::string& device_id) -{ -    Error error; +        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 -        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; -    } +    if (connect_devices.size () != 1) +        return Error ("Expected a single connected device, got instead %" PRIu64, connect_devices.size ()); -    { -        // 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 ()); -    } +    device_id = connect_devices.front (); +    if (log) +        log->Printf("Connected to Android device \"%s\"", device_id.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 ()  | 

