Added a boolean to the pure virtual lldb_private::Process::CanDebug(...)
method so process plug-ins that are requested by name can answer yes when
asked if they can debug a target that might not have any file in the target.

Modified the ConnectionFileDescriptor to have both a read and a write file
descriptor. This allows us to support UDP, and eventually will allow us to
support pipes. The ConnectionFileDescriptor class also has a file descriptor
type for each of the read and write file decriptors so we can use the correct
read/recv/recvfrom call when reading, or write/send/sendto for writing.

Finished up an initial implementation of UDP where you can use the "udp://"
URL to specify a host and port to connect to:

(lldb) process connect --plugin kdp-remote udp://host:41139

This will cause a ConnectionFileDescriptor to be created that can send UDP
packets to "host:41139", and it will also bind to a localhost port that can
be given out to receive the connectionless UDP reply. 

Added the ability to get to the IPv4/IPv6 socket port number from a 
ConnectionFileDescriptor instance if either file descriptor is a socket.

The ProcessKDP can now successfully connect to a remote kernel and detach
using the above "processs connect" command!!! So far we have the following
packets working:
    KDP_CONNECT
    KDP_DISCONNECT
    KDP_HOSTINFO
    KDP_VERSION
    KDP_REATTACH

Now that the packets are working, adding new packets will go very quickly.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@135363 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
index 06096af..2d9522b 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
@@ -102,7 +102,7 @@
     Mutex::Locker locker(m_sequence_mutex);    
     if (SendRequestPacketNoLock(request_packet))
     {
-        if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, m_packet_timeout))
+        if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ()))
         {
             uint32_t offset = 0;
             const uint8_t reply_command = reply_packet.GetU8 (&offset);
@@ -131,9 +131,11 @@
         {
             PacketStreamType log_strm;
             
-            DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, 0);
+            DataExtractor::DumpHexBytes (&log_strm, packet_data, packet_size, UINT32_MAX, LLDB_INVALID_ADDRESS);
             
-            log->Printf("request packet: <%u>\n%s", packet_size, log_strm.GetData());
+            log->Printf("send kdp-packet: %.*s", 
+                        (uint32_t)log_strm.GetSize(), 
+                        log_strm.GetData());
         }
         ConnectionStatus status = eConnectionStatusSuccess;
 
@@ -239,7 +241,7 @@
         if (log && log->GetVerbose())
         {
             PacketStreamType log_strm;
-            DataExtractor::DumpHexBytes (&log_strm, src, src_len, 0);
+            DataExtractor::DumpHexBytes (&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS);
             log->Printf ("CommunicationKDP::%s adding %u bytes: %s",
                          __FUNCTION__, 
                          (uint32_t)src_len, 
@@ -292,6 +294,23 @@
                     // erase the bytes from our communcation buffer "m_bytes"
                     packet.SetData (DataBufferSP (new DataBufferHeap (&m_bytes[0], length)));
                     m_bytes.erase (0, length);
+                    
+                    if (log)
+                    {
+                        PacketStreamType log_strm;
+                        packet.Dump (&log_strm,             // Stream to dump to
+                                     0,                     // Offset into "packet"
+                                     eFormatBytes,          // Dump as hex bytes
+                                     1,                     // Size of each item is 1 for single bytes
+                                     length,                // Number of bytes
+                                     UINT32_MAX,            // Num bytes per line
+                                     LLDB_INVALID_ADDRESS,  // Base address
+                                     0, 0);                 // Bitfield info set to not do anything bitfield related
+                        
+                        log->Printf("recv kdp-packet: %.*s", 
+                                    (uint32_t)log_strm.GetSize(), 
+                                    log_strm.GetData());
+                    }
                     return true;
                 }
             }
@@ -313,22 +332,25 @@
 
 
 bool
-CommunicationKDP::Connect (uint16_t reply_port, 
-                           uint16_t exc_port, 
-                           const char *greeting)
+CommunicationKDP::SendRequestConnect (uint16_t reply_port, 
+                                      uint16_t exc_port, 
+                                      const char *greeting)
 {
     PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
     if (greeting == NULL)
         greeting = "";
 
     const CommandType command = eCommandTypeConnect;
-    // Length is 82 uint16_t and the length of the greeting C string
-    const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting);
+    // Length is 82 uint16_t and the length of the greeting C string with the terminating NULL
+    const uint32_t command_length = 8 + 2 + 2 + ::strlen(greeting) + 1;
     const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
-    request_packet.PutHex16(reply_port);
-    request_packet.PutHex16(exc_port);
-    request_packet.PutCString(greeting);
+    // Always send connect ports as little endian
+    request_packet.SetByteOrder (eByteOrderLittle);
+    request_packet.PutHex16 (reply_port);
+    request_packet.PutHex16 (exc_port);
+    request_packet.SetByteOrder (m_byte_order);
+    request_packet.PutCString (greeting);
     DataExtractor reply_packet;
     return SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet);
 }
@@ -345,7 +367,7 @@
 }
 
 bool
-CommunicationKDP::Reattach (uint16_t reply_port)
+CommunicationKDP::SendRequestReattach (uint16_t reply_port)
 {
     PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
     const CommandType command = eCommandTypeReattach;
@@ -353,7 +375,10 @@
     const uint32_t command_length = 8 + 2;
     const uint32_t request_sequence_id = m_request_sequence_id;
     MakeRequestPacketHeader (command, request_packet, command_length);
+    // Always send connect ports as little endian
+    request_packet.SetByteOrder (eByteOrderLittle);
     request_packet.PutHex16(reply_port);
+    request_packet.SetByteOrder (m_byte_order);
     DataExtractor reply_packet;
     if (SendRequestAndGetReply (command, request_sequence_id, request_packet, reply_packet))
     {
@@ -448,7 +473,7 @@
 }
 
 bool
-CommunicationKDP::Disconnect ()
+CommunicationKDP::SendRequestDisconnect ()
 {
     PacketStreamType request_packet (Stream::eBinary, 4, m_byte_order);
     const CommandType command = eCommandTypeDisconnect;
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
index 4445608..83c8790 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
@@ -141,15 +141,15 @@
 
     
     bool
-    Connect (uint16_t reply_port, 
-             uint16_t exc_port, 
-             const char *greeting);
+    SendRequestConnect (uint16_t reply_port, 
+                        uint16_t exc_port, 
+                        const char *greeting);
 
     bool
-    Reattach (uint16_t reply_port);
+    SendRequestReattach (uint16_t reply_port);
 
     bool
-    Disconnect ();
+    SendRequestDisconnect ();
     
     uint32_t
     GetVersion ();
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 1e3158d..77d3d1c 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -13,6 +13,7 @@
 
 // C++ Includes
 // Other libraries and framework includes
+#include "lldb/Core/ConnectionFileDescriptor.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/State.h"
 #include "lldb/Host/Host.h"
@@ -53,7 +54,7 @@
 }
 
 bool
-ProcessKDP::CanDebug(Target &target)
+ProcessKDP::CanDebug(Target &target, bool plugin_specified_by_name)
 {
     // For now we are just making sure the file exists for a given module
     ModuleSP exe_module_sp(target.GetExecutableModule());
@@ -68,8 +69,10 @@
                 exe_objfile->GetStrata() == ObjectFile::eStrataKernel)
                 return true;
         }
+        return false;
     }
-    return false;
+    // No target executable, assume we can debug if our plug-in was specified by name
+    return plugin_specified_by_name;
 }
 
 //----------------------------------------------------------------------
@@ -143,7 +146,63 @@
 {
     // TODO: fill in the remote connection to the remote KDP here!
     Error error;
-    error.SetErrorString ("attaching to a by process name not supported in kdp-remote plug-in");
+    
+    if (remote_url == NULL || remote_url[0] == '\0')
+        remote_url = "udp://localhost:41139";
+
+    std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+    if (conn_ap.get())
+    {
+        // Only try once for now.
+        // TODO: check if we should be retrying?
+        const uint32_t max_retry_count = 1;
+        for (uint32_t retry_count = 0; retry_count < max_retry_count; ++retry_count)
+        {
+            if (conn_ap->Connect(remote_url, &error) == eConnectionStatusSuccess)
+                break;
+            usleep (100000);
+        }
+    }
+
+    if (conn_ap->IsConnected())
+    {
+        const uint16_t reply_port = conn_ap->GetReadPort ();
+
+        if (reply_port != 0)
+        {
+            m_comm.SetConnection(conn_ap.release());
+
+            if (m_comm.SendRequestReattach(reply_port))
+            {
+                if (m_comm.SendRequestConnect(reply_port, reply_port, "Greetings from LLDB..."))
+                {
+                    m_comm.GetVersion();
+                    uint32_t cpu = m_comm.GetCPUType();
+                    uint32_t sub = m_comm.GetCPUSubtype();
+                    ArchSpec kernel_arch;
+                    kernel_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
+                    m_target.SetArchitecture(kernel_arch);
+                    // TODO: thread registers based off of architecture...
+                }
+            }
+            else
+            {
+                error.SetErrorString("KDP reattach failed");
+            }
+        }
+        else
+        {
+            error.SetErrorString("invalid reply port from UDP connection");
+        }
+    }
+    else
+    {
+        if (error.Success())
+            error.SetErrorStringWithFormat ("failed to connect to '%s'", remote_url);
+    }
+    if (error.Fail())
+        m_comm.Disconnect();
+
     return error;
 }
 
@@ -414,13 +473,19 @@
     
     m_thread_list.DiscardThreadPlans();
     
-    size_t response_size = m_comm.Disconnect ();
-    if (log)
+    if (m_comm.IsConnected())
     {
-        if (response_size)
-            log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
-        else
-            log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+
+        m_comm.SendRequestDisconnect();
+
+        size_t response_size = m_comm.Disconnect ();
+        if (log)
+        {
+            if (response_size)
+                log->PutCString ("ProcessKDP::DoDetach() detach packet sent successfully");
+            else
+                log->PutCString ("ProcessKDP::DoDetach() detach packet send failed");
+        }
     }
     // Sleep for one second to let the process get all detached...
     StopAsyncThread ();
@@ -446,6 +511,8 @@
     // Interrupt if our inferior is running...
     if (m_comm.IsConnected())
     {
+        m_comm.SendRequestDisconnect();
+
         if (m_public_state.GetValue() == eStateAttaching)
         {
             // We are being asked to halt during an attach. We need to just close
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
index 1e2e87c..c967e2f 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
@@ -65,7 +65,8 @@
     // Check if a given Process
     //------------------------------------------------------------------
     virtual bool
-    CanDebug (lldb_private::Target &target);
+    CanDebug (lldb_private::Target &target,
+              bool plugin_specified_by_name);
     
     //    virtual uint32_t
     //    ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids);