summaryrefslogtreecommitdiffstats
path: root/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2014-02-25 21:42:16 +0000
committeremaste <emaste@FreeBSD.org>2014-02-25 21:42:16 +0000
commit788502c6f6261e2d84ef85d1052b41a6c5be31b3 (patch)
treee0f754ea0922908b0f1be8f01c4efbdfc20462eb /source/Plugins/Process/gdb-remote
parent6beac4fcf9e5327f07c0fefd527180124438096a (diff)
downloadFreeBSD-src-788502c6f6261e2d84ef85d1052b41a6c5be31b3.zip
FreeBSD-src-788502c6f6261e2d84ef85d1052b41a6c5be31b3.tar.gz
Import LLDB as of SVN r202189 (git 32871eb)
(A number of files not required for the FreeBSD build have been removed.) Sponsored by: DARPA, AFRL
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp7
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp134
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp157
3 files changed, 206 insertions, 92 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 1ec75a4..72600d8 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -497,6 +497,13 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
for (int i = 0; i < repeat_count; ++i)
packet_str.push_back(char_to_repeat);
}
+ else if (*c == 0x7d)
+ {
+ // 0x7d is the escape character. The next character is to
+ // be XOR'd with 0x20.
+ char escapee = *++c ^ 0x20;
+ packet_str.push_back(escapee);
+ }
else
{
packet_str.push_back(*c);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index aa60ec1..ab3bf7f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -136,6 +136,11 @@ GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
// a live connection to a remote GDB server...
if (QueryNoAckModeSupported())
{
+#if 0
+ // Set above line to "#if 1" to test packet speed if remote GDB server
+ // supports the qSpeedTest packet...
+ TestPacketSpeed(10000);
+#endif
return true;
}
else
@@ -2420,50 +2425,81 @@ GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets)
uint32_t i;
TimeValue start_time, end_time;
uint64_t total_time_nsec;
- float packets_per_second;
if (SendSpeedTestPacket (0, 0))
{
- for (uint32_t send_size = 0; send_size <= 1024; send_size *= 2)
+ static uint32_t g_send_sizes[] = { 0, 64, 128, 512, 1024 };
+ static uint32_t g_recv_sizes[] = { 0, 64, 128, 512, 1024 }; //, 4*1024, 8*1024, 16*1024, 32*1024, 48*1024, 64*1024, 96*1024, 128*1024 };
+ const size_t k_num_send_sizes = sizeof(g_send_sizes)/sizeof(uint32_t);
+ const size_t k_num_recv_sizes = sizeof(g_recv_sizes)/sizeof(uint32_t);
+ const uint64_t k_recv_amount = 4*1024*1024; // Receive 4MB
+ for (uint32_t send_idx = 0; send_idx < k_num_send_sizes; ++send_idx)
{
- for (uint32_t recv_size = 0; recv_size <= 1024; recv_size *= 2)
+ const uint32_t send_size = g_send_sizes[send_idx];
+ for (uint32_t recv_idx = 0; recv_idx < k_num_recv_sizes; ++recv_idx)
{
+ const uint32_t recv_size = g_recv_sizes[recv_idx];
+ StreamString packet;
+ packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size);
+ uint32_t bytes_left = send_size;
+ while (bytes_left > 0)
+ {
+ if (bytes_left >= 26)
+ {
+ packet.PutCString("abcdefghijklmnopqrstuvwxyz");
+ bytes_left -= 26;
+ }
+ else
+ {
+ packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz");
+ bytes_left = 0;
+ }
+ }
+
start_time = TimeValue::Now();
- for (i=0; i<num_packets; ++i)
+ if (recv_size == 0)
{
- SendSpeedTestPacket (send_size, recv_size);
+ for (i=0; i<num_packets; ++i)
+ {
+ StringExtractorGDBRemote response;
+ SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false);
+ }
+ }
+ else
+ {
+ uint32_t bytes_read = 0;
+ while (bytes_read < k_recv_amount)
+ {
+ StringExtractorGDBRemote response;
+ SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false);
+ bytes_read += recv_size;
+ }
}
end_time = TimeValue::Now();
total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
- packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
- printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n",
- num_packets,
- send_size,
- recv_size,
- total_time_nsec / TimeValue::NanoSecPerSec,
- total_time_nsec % TimeValue::NanoSecPerSec,
- packets_per_second);
if (recv_size == 0)
- recv_size = 32;
+ {
+ float packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
+ printf ("%u qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n",
+ num_packets,
+ send_size,
+ recv_size,
+ total_time_nsec / TimeValue::NanoSecPerSec,
+ total_time_nsec % TimeValue::NanoSecPerSec,
+ packets_per_second);
+ }
+ else
+ {
+ float mb_second = ((((float)k_recv_amount)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec) / (1024.0*1024.0);
+ printf ("%u qSpeedTest(send=%-7u, recv=%-7u) sent 4MB in %" PRIu64 ".%9.9" PRIu64 " sec for %f MB/sec.\n",
+ num_packets,
+ send_size,
+ recv_size,
+ total_time_nsec / TimeValue::NanoSecPerSec,
+ total_time_nsec % TimeValue::NanoSecPerSec,
+ mb_second);
+ }
}
- if (send_size == 0)
- send_size = 32;
- }
- }
- else
- {
- start_time = TimeValue::Now();
- for (i=0; i<num_packets; ++i)
- {
- GetCurrentProcessID ();
}
- end_time = TimeValue::Now();
- total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
- packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
- printf ("%u 'qC' packets packets in 0x%" PRIu64 "%9.9" PRIu64 " sec for %f packets/sec.\n",
- num_packets,
- total_time_nsec / TimeValue::NanoSecPerSec,
- total_time_nsec % TimeValue::NanoSecPerSec,
- packets_per_second);
}
}
@@ -2639,15 +2675,10 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
uint8_t
GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length)
{
- switch (type)
- {
- case eBreakpointSoftware: if (!m_supports_z0) return UINT8_MAX; break;
- case eBreakpointHardware: if (!m_supports_z1) return UINT8_MAX; break;
- case eWatchpointWrite: if (!m_supports_z2) return UINT8_MAX; break;
- case eWatchpointRead: if (!m_supports_z3) return UINT8_MAX; break;
- case eWatchpointReadWrite: if (!m_supports_z4) return UINT8_MAX; break;
- }
-
+ // Check if the stub is known not to support this breakpoint type
+ if (!SupportsGDBStoppointPacket(type))
+ return UINT8_MAX;
+ // Construct the breakpoint packet
char packet[64];
const int packet_len = ::snprintf (packet,
sizeof(packet),
@@ -2656,28 +2687,35 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type,
type,
addr,
length);
-
+ // Check we havent overwritten the end of the packet buffer
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
+ // Try to send the breakpoint packet, and check that it was correctly sent
if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == PacketResult::Success)
{
+ // Receive and OK packet when the breakpoint successfully placed
if (response.IsOKResponse())
return 0;
- else if (response.IsErrorResponse())
+
+ // Error while setting breakpoint, send back specific error
+ if (response.IsErrorResponse())
return response.GetError();
- }
- else
- {
- switch (type)
+
+ // Empty packet informs us that breakpoint is not supported
+ if (response.IsUnsupportedResponse())
{
+ // Disable this breakpoint type since it is unsupported
+ switch (type)
+ {
case eBreakpointSoftware: m_supports_z0 = false; break;
case eBreakpointHardware: m_supports_z1 = false; break;
case eWatchpointWrite: m_supports_z2 = false; break;
case eWatchpointRead: m_supports_z3 = false; break;
case eWatchpointReadWrite: m_supports_z4 = false; break;
+ }
}
}
-
+ // Signal generic faliure
return UINT8_MAX;
}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index e1989eb..1172222 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1645,6 +1645,21 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
}
}
+ // If the response is old style 'S' packet which does not provide us with thread information
+ // then update the thread list and choose the first one.
+ if (!thread_sp)
+ {
+ UpdateThreadIDList ();
+
+ if (!m_thread_ids.empty ())
+ {
+ Mutex::Locker locker (m_thread_list_real.GetMutex ());
+ thread_sp = m_thread_list_real.FindThreadByProtocolID (m_thread_ids.front (), false);
+ if (thread_sp)
+ gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get ());
+ }
+ }
+
if (thread_sp)
{
// Clear the stop info just in case we don't set it to anything
@@ -1720,7 +1735,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
}
}
- if (signo && did_exec == false)
+ if (!handled && signo && did_exec == false)
{
if (signo == SIGTRAP)
{
@@ -2007,6 +2022,24 @@ ProcessGDBRemote::DoDestroy ()
if (packet_cmd == 'W' || packet_cmd == 'X')
{
+#if defined(__APPLE__)
+ // For Native processes on Mac OS X, we launch through the Host Platform, then hand the process off
+ // to debugserver, which becomes the parent process through "PT_ATTACH". Then when we go to kill
+ // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we call waitpid which returns
+ // with no error and the correct status. But amusingly enough that doesn't seem to actually reap
+ // the process, but instead it is left around as a Zombie. Probably the kernel is in the process of
+ // switching ownership back to lldb which was the original parent, and gets confused in the handoff.
+ // Anyway, so call waitpid here to finally reap it.
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (platform_sp && platform_sp->IsHost())
+ {
+ int status;
+ ::pid_t reap_pid;
+ reap_pid = waitpid (GetID(), &status, WNOHANG);
+ if (log)
+ log->Printf ("Reaped pid: %d, status: %d.\n", reap_pid, status);
+ }
+#endif
SetLastStopPacket (response);
ClearThreadIDList ();
exit_status = response.GetHexU8();
@@ -2277,70 +2310,106 @@ Error
ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
{
Error error;
- assert (bp_site != NULL);
+ assert(bp_site != NULL);
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+ // Get logging info
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
user_id_t site_id = bp_site->GetID();
+
+ // Get the breakpoint address
const addr_t addr = bp_site->GetLoadAddress();
+
+ // Log that a breakpoint was requested
if (log)
- log->Printf ("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr);
+ log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr);
+ // Breakpoint already exists and is enabled
if (bp_site->IsEnabled())
{
if (log)
- log->Printf ("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
+ log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
return error;
}
- else
+
+ // Get the software breakpoint trap opcode size
+ const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
+
+ // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this breakpoint type
+ // is supported by the remote stub. These are set to true by default, and later set to false
+ // only after we receive an unimplemented response when sending a breakpoint packet. This means
+ // initially that unless we were specifically instructed to use a hardware breakpoint, LLDB will
+ // attempt to set a software breakpoint. HardwareRequired() also queries a boolean variable which
+ // indicates if the user specifically asked for hardware breakpoints. If true then we will
+ // skip over software breakpoints.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired()))
{
- const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
+ // Try to send off a software breakpoint packet ($Z0)
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
+ {
+ // The breakpoint was placed successfully
+ bp_site->SetEnabled(true);
+ bp_site->SetType(BreakpointSite::eExternal);
+ return error;
+ }
+
+ // SendGDBStoppointTypePacket() will return an error if it was unable to set this
+ // breakpoint. We need to differentiate between a error specific to placing this breakpoint
+ // or if we have learned that this breakpoint type is unsupported. To do this, we
+ // must test the support boolean for this breakpoint type to see if it now indicates that
+ // this breakpoint type is unsupported. If they are still supported then we should return
+ // with the error code. If they are now unsupported, then we would like to fall through
+ // and try another form of breakpoint.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
+ return error;
- if (bp_site->HardwareRequired())
+ // We reach here when software breakpoints have been found to be unsupported. For future
+ // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is
+ // known not to be supported.
+ if (log)
+ log->Printf("Software breakpoints are unsupported");
+
+ // So we will fall through and try a hardware breakpoint
+ }
+
+ // The process of setting a hardware breakpoint is much the same as above. We check the
+ // supported boolean for this breakpoint type, and if it is thought to be supported then we
+ // will try to set this breakpoint with a hardware breakpoint.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
+ {
+ // Try to send off a hardware breakpoint packet ($Z1)
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
{
- // Try and set hardware breakpoint, and if that fails, fall through
- // and set a software breakpoint?
- if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
- {
- if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
- {
- bp_site->SetEnabled(true);
- bp_site->SetType (BreakpointSite::eHardware);
- }
- else
- {
- error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)");
- }
- }
- else
- {
- error.SetErrorString("hardware breakpoints are not supported");
- }
+ // The breakpoint was placed successfully
+ bp_site->SetEnabled(true);
+ bp_site->SetType(BreakpointSite::eHardware);
return error;
}
- else if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
+
+ // Check if the error was something other then an unsupported breakpoint type
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
{
- if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
- {
- bp_site->SetEnabled(true);
- bp_site->SetType (BreakpointSite::eExternal);
- return error;
- }
+ // Unable to set this hardware breakpoint
+ error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)");
+ return error;
}
- return EnableSoftwareBreakpoint (bp_site);
+ // We will reach here when the stub gives an unsported response to a hardware breakpoint
+ if (log)
+ log->Printf("Hardware breakpoints are unsupported");
+
+ // Finally we will falling through to a #trap style breakpoint
}
- if (log)
+ // Don't fall through when hardware breakpoints were specifically requested
+ if (bp_site->HardwareRequired())
{
- const char *err_string = error.AsCString();
- log->Printf ("ProcessGDBRemote::EnableBreakpointSite () error for breakpoint at 0x%8.8" PRIx64 ": %s",
- bp_site->GetLoadAddress(),
- err_string ? err_string : "NULL");
+ error.SetErrorString("hardware breakpoints are not supported");
+ return error;
}
- // We shouldn't reach here on a successful breakpoint enable...
- if (error.Success())
- error.SetErrorToGenericError();
- return error;
+
+ // As a last resort we want to place a manual breakpoint. An instruction
+ // is placed into the process memory using memory write packets.
+ return EnableSoftwareBreakpoint(bp_site);
}
Error
@@ -2366,7 +2435,7 @@ ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site)
break;
case BreakpointSite::eHardware:
- if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, addr, bp_op_size))
error.SetErrorToGenericError();
break;
OpenPOWER on IntegriCloud