diff options
Diffstat (limited to 'lldb/tools/debugserver/source')
9 files changed, 209 insertions, 158 deletions
diff --git a/lldb/tools/debugserver/source/DNBThreadResumeActions.h b/lldb/tools/debugserver/source/DNBThreadResumeActions.h index f3fb8de6a82..81c7c43b722 100644 --- a/lldb/tools/debugserver/source/DNBThreadResumeActions.h +++ b/lldb/tools/debugserver/source/DNBThreadResumeActions.h @@ -85,6 +85,13 @@ public: { return m_actions.size(); } + + void + Clear() + { + m_actions.clear(); + m_signal_handled.clear(); + } protected: std::vector<DNBThreadResumeAction> m_actions; diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp index 10f86f91225..05298168037 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp @@ -101,6 +101,7 @@ MachProcess::MachProcess() : m_stdio_thread (0), m_stdio_mutex (PTHREAD_MUTEX_RECURSIVE), m_stdout_data (), + m_thread_actions (), m_thread_list (), m_exception_messages (), m_exception_messages_mutex (PTHREAD_MUTEX_RECURSIVE), @@ -314,7 +315,8 @@ MachProcess::Resume (const DNBThreadResumeActions& thread_actions) if (CanResume(state)) { - PrivateResume(thread_actions); + m_thread_actions = thread_actions; + PrivateResume(); return true; } else if (state == eStateRunning) @@ -337,7 +339,8 @@ MachProcess::Kill (const struct timespec *timeout_abstime) DNBError err; err.SetErrorToErrno(); DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Kill() DoSIGSTOP() ::ptrace (PT_KILL, pid=%u, 0, 0) => 0x%8.8x (%s)", err.Error(), err.AsString()); - PrivateResume (DNBThreadResumeActions (eStateRunning, 0)); + m_thread_actions = DNBThreadResumeActions (eStateRunning, 0); + PrivateResume (); return true; } @@ -392,7 +395,8 @@ MachProcess::DoSIGSTOP (bool clear_bps_and_wps, uint32_t *thread_idx_ptr) // No threads were stopped with a SIGSTOP, we need to run and halt the // process with a signal DNBLogThreadedIf(LOG_PROCESS, "MachProcess::DoSIGSTOP() state = %s -- resuming process", DNBStateAsString (state)); - PrivateResume (DNBThreadResumeActions (eStateRunning, 0)); + m_thread_actions = DNBThreadResumeActions (eStateRunning, 0); + PrivateResume (); // Reset the event that says we were indeed running m_events.ResetEvents(eEventProcessRunningStateChanged); @@ -428,20 +432,19 @@ MachProcess::Detach() DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Detach() DoSIGSTOP() returned %s", DNBStateAsString(state)); { - DNBThreadResumeActions thread_actions; + m_thread_actions.Clear(); DNBThreadResumeAction thread_action; thread_action.tid = m_thread_list.ThreadIDAtIndex (thread_idx); thread_action.state = eStateRunning; thread_action.signal = -1; thread_action.addr = INVALID_NUB_ADDRESS; - thread_actions.Append (thread_action); - - thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0); + m_thread_actions.Append (thread_action); + m_thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, 0); PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex); - ReplyToAllExceptions (thread_actions); + ReplyToAllExceptions (); } @@ -597,7 +600,7 @@ MachProcess::WriteMemory (nub_addr_t addr, nub_size_t size, const void *buf) void -MachProcess::ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions) +MachProcess::ReplyToAllExceptions () { PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex); if (m_exception_messages.empty() == false) @@ -610,13 +613,13 @@ MachProcess::ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions) DNBLogThreadedIf(LOG_EXCEPTIONS, "Replying to exception %d...", std::distance(begin, pos)); int thread_reply_signal = 0; - const DNBThreadResumeAction *action = thread_actions.GetActionForThread (pos->state.thread_port, false); + const DNBThreadResumeAction *action = m_thread_actions.GetActionForThread (pos->state.thread_port, false); if (action) { thread_reply_signal = action->signal; if (thread_reply_signal) - thread_actions.SetSignalHandledForThread (pos->state.thread_port); + m_thread_actions.SetSignalHandledForThread (pos->state.thread_port); } DNBError err (pos->Reply(this, thread_reply_signal)); @@ -630,20 +633,20 @@ MachProcess::ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions) } } void -MachProcess::PrivateResume (const DNBThreadResumeActions& thread_actions) +MachProcess::PrivateResume () { PTHREAD_MUTEX_LOCKER (locker, m_exception_messages_mutex); - ReplyToAllExceptions (thread_actions); + ReplyToAllExceptions (); // bool stepOverBreakInstruction = step; // Let the thread prepare to resume and see if any threads want us to // step over a breakpoint instruction (ProcessWillResume will modify // the value of stepOverBreakInstruction). - m_thread_list.ProcessWillResume (this, thread_actions); + m_thread_list.ProcessWillResume (this, m_thread_actions); // Set our state accordingly - if (thread_actions.NumActionsWithState(eStateStepping)) + if (m_thread_actions.NumActionsWithState(eStateStepping)) SetState (eStateStepping); else SetState (eStateRunning); @@ -1100,7 +1103,7 @@ MachProcess::ExceptionMessageBundleComplete() else { // Resume without checking our current state. - PrivateResume (DNBThreadResumeActions (eStateRunning, 0)); + PrivateResume (); } } else diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h index 04ad02eb634..8866187b56a 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -17,6 +17,7 @@ #include "DNBDefs.h" #include "DNBBreakpoint.h" #include "DNBError.h" +#include "DNBThreadResumeActions.h" //#include "MachDYLD.h" #include "MachException.h" #include "MachVMMemory.h" @@ -219,8 +220,8 @@ private: eMachProcessFlagsUsingSBS = (1 << 1) }; void Clear (); - void ReplyToAllExceptions (const DNBThreadResumeActions& thread_actions); - void PrivateResume (const DNBThreadResumeActions& thread_actions); + void ReplyToAllExceptions (); + void PrivateResume (); nub_size_t RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, uint8_t *buf) const; uint32_t Flags () const { return m_flags; } @@ -239,6 +240,7 @@ private: pthread_t m_stdio_thread; // Thread ID for the thread that watches for child process stdio PThreadMutex m_stdio_mutex; // Multithreaded protection for stdio std::string m_stdout_data; + DNBThreadResumeActions m_thread_actions; // The thread actions for the current MachProcess::Resume() call MachException::Message::collection m_exception_messages; // A collection of exception messages caught when listening to the exception port PThreadMutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index 7890c069a77..003a58b79d6 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -339,6 +339,12 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) m_stop_exception.Clear(); } +nub_break_t +MachThread::CurrentBreakpoint() +{ + return m_process->Breakpoints().FindIDByAddress(GetPC()); +} + bool MachThread::ShouldStop(bool &step_more) { @@ -394,14 +400,18 @@ MachThread::ShouldStop(bool &step_more) bool MachThread::IsStepping() { +#if ENABLE_AUTO_STEPPING_OVER_BP // Return true if this thread is currently being stepped. // MachThread::ThreadWillResume currently determines this by looking if we // have been asked to single step, or if we are at a breakpoint instruction // and have been asked to resume. In the latter case we need to disable the // breakpoint we are at, single step, re-enable and continue. nub_state_t state = GetState(); - return (state == eStateStepping) || - (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint())); + return ((state == eStateStepping) || + (state == eStateRunning && NUB_BREAK_ID_IS_VALID(CurrentBreakpoint()))); +#else + return GetState() == eStateStepping; +#endif } @@ -430,6 +440,7 @@ MachThread::ThreadDidStop() // Update the basic information for a thread MachThread::GetBasicInfo(m_tid, &m_basicInfo); +#if ENABLE_AUTO_STEPPING_OVER_BP // See if we were at a breakpoint when we last resumed that we disabled, // re-enable it. nub_break_t breakID = CurrentBreakpoint(); @@ -469,10 +480,12 @@ MachThread::ThreadDidStop() SetState(eStateStopped); } } - - - SetCurrentBreakpoint(INVALID_NUB_BREAK_ID); - +#else + if (m_basicInfo.suspend_count > 0) + SetState(eStateSuspended); + else + SetState(eStateStopped); +#endif return true; } @@ -496,30 +509,27 @@ MachThread::NotifyException(MachException::Data& exc) if (!handled) { handled = true; - nub_addr_t pc = GetPC(); - nub_break_t breakID = m_process->Breakpoints().FindIDByAddress(pc); - SetCurrentBreakpoint(breakID); - switch (exc.exc_type) - { - case EXC_BAD_ACCESS: - break; - case EXC_BAD_INSTRUCTION: - break; - case EXC_ARITHMETIC: - break; - case EXC_EMULATION: - break; - case EXC_SOFTWARE: - break; - case EXC_BREAKPOINT: - break; - case EXC_SYSCALL: - break; - case EXC_MACH_SYSCALL: - break; - case EXC_RPC_ALERT: - break; - } +// switch (exc.exc_type) +// { +// case EXC_BAD_ACCESS: +// break; +// case EXC_BAD_INSTRUCTION: +// break; +// case EXC_ARITHMETIC: +// break; +// case EXC_EMULATION: +// break; +// case EXC_SOFTWARE: +// break; +// case EXC_BREAKPOINT: +// break; +// case EXC_SYSCALL: +// break; +// case EXC_MACH_SYSCALL: +// break; +// case EXC_RPC_ALERT: +// break; +// } } return handled; } @@ -658,27 +668,6 @@ MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp) return false; } - -void -MachThread::NotifyBreakpointChanged (const DNBBreakpoint *bp) -{ - nub_break_t breakID = bp->GetID(); - if (bp->IsEnabled()) - { - if (bp->Address() == GetPC()) - { - SetCurrentBreakpoint(breakID); - } - } - else - { - if (CurrentBreakpoint() == breakID) - { - SetCurrentBreakpoint(INVALID_NUB_BREAK_ID); - } - } -} - bool MachThread::GetIdentifierInfo () { diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index 0b2a8bf1ff9..e7e18fe262c 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -60,8 +60,7 @@ public: bool SetPC(uint64_t value); // Set program counter uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer - nub_break_t CurrentBreakpoint() const { return m_breakID; } - void SetCurrentBreakpoint(nub_break_t breakID) { m_breakID = breakID; } + nub_break_t CurrentBreakpoint(); uint32_t EnableHardwareBreakpoint (const DNBBreakpoint *breakpoint); uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *watchpoint); bool DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint); @@ -88,7 +87,9 @@ public: bool SetRegisterValue ( uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value ); nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); nub_size_t SetRegisterContext (const void *buf, nub_size_t buf_len); - void NotifyBreakpointChanged (const DNBBreakpoint *bp); + void NotifyBreakpointChanged (const DNBBreakpoint *bp) + { + } bool IsUserReady(); struct thread_basic_info * diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index 1222b809904..411e91426e1 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -428,8 +428,6 @@ DNBArchImplI386::NotifyException(MachException::Data& exc) // Write the new PC back out SetGPRState (); } - - m_thread->SetCurrentBreakpoint(breakID); } return true; } diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index fde3be6ab5d..ce0e9c2c579 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -355,8 +355,6 @@ DNBArchImplX86_64::NotifyException(MachException::Data& exc) // Write the new PC back out SetGPRState (); } - - m_thread->SetCurrentBreakpoint(breakID); } return true; } diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 7fa05073d72..7ce808dbab4 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -76,6 +76,7 @@ RNBRemote::RNBRemote (bool use_native_regs, const char *arch) : m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4), m_extended_mode(false), m_noack_mode(false), + m_thread_suffix_supported (false), m_use_native_regs (use_native_regs) { DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); @@ -170,12 +171,13 @@ RNBRemote::CreatePacketTable () t.push_back (Packet (query_step_packet_supported, &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported.")); t.push_back (Packet (query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other.")); // t.push_back (Packet (query_symbol_lookup, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qSymbol", "Notify that host debugger is ready to do symbol lookups")); - t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_Q , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets")); - t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_Q , NULL, "QSetLogging:", "Request that the " DEBUGSERVER_PROGRAM_NAME " set its logging mode bits")); - t.push_back (Packet (set_max_packet_size, &RNBRemote::HandlePacket_Q , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle")); - t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_Q , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle")); - t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_Q , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment")); - t.push_back (Packet (set_disable_aslr, &RNBRemote::HandlePacket_Q , NULL, "QSetDisableASLR:", "Set wether to disable ASLR when launching the process with the set argv ('A') packet")); + t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets")); + t.push_back (Packet (prefix_reg_packets_with_tid, &RNBRemote::HandlePacket_QThreadSuffixSupported , NULL, "QThreadSuffixSupported", "Check if thread specifc packets (register packets 'g', 'G', 'p', and 'P') support having the thread ID appended to the end of the command")); + t.push_back (Packet (set_logging_mode, &RNBRemote::HandlePacket_QSetLogging , NULL, "QSetLogging:", "Check if register packets ('g', 'G', 'p', and 'P' support having the thread ID prefix")); + t.push_back (Packet (set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle")); + t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle")); + t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_QEnvironment , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment")); + t.push_back (Packet (set_disable_aslr, &RNBRemote::HandlePacket_QSetDisableASLR , NULL, "QSetDisableASLR:", "Set wether to disable ASLR when launching the process with the set argv ('A') packet")); // t.push_back (Packet (pass_signals_to_inferior, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior")); t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process.")); t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process.")); @@ -1702,104 +1704,105 @@ set_logging (const char *p) return rnb_success; } - +rnb_err_t +RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p) +{ + m_thread_suffix_supported = true; + return SendPacket ("OK"); +} rnb_err_t -RNBRemote::HandlePacket_Q (const char *p) +RNBRemote::HandlePacket_QStartNoAckMode (const char *p) { - if (p == NULL || strlen (p) <= 1) - { - return HandlePacket_ILLFORMED ("No subtype specified in Q packet"); - } + // Send the OK packet first so the correct checksum is appended... + rnb_err_t result = SendPacket ("OK"); + m_noack_mode = true; + return result; +} - /* Switch to no-ack protocol mode after the "OK" packet is sent - and the ack for that comes back from gdb. */ - if (strcmp (p, "QStartNoAckMode") == 0) - { - rnb_err_t result = SendPacket ("OK"); - m_noack_mode = true; - return result; - } +rnb_err_t +RNBRemote::HandlePacket_QSetLogging (const char *p) +{ + p += sizeof ("QSetLogging:") - 1; + rnb_err_t result = set_logging (p); + if (result == rnb_success) + return SendPacket ("OK"); + else + return SendPacket ("E35"); +} - if (strncmp (p, "QSetLogging:", sizeof ("QSetLogging:") - 1) == 0) +rnb_err_t +RNBRemote::HandlePacket_QSetDisableASLR (const char *p) +{ + extern int g_disable_aslr; + p += sizeof ("QSetDisableASLR:") - 1; + switch (*p) { - p += sizeof ("QSetLogging:") - 1; - rnb_err_t result = set_logging (p); - if (result == rnb_success) - return SendPacket ("OK"); - else - return SendPacket ("E35"); + case '0': g_disable_aslr = 0; break; + case '1': g_disable_aslr = 1; break; + default: + return SendPacket ("E56"); } + return SendPacket ("OK"); +} - if (strncmp (p, "QSetDisableASLR:", sizeof ("QSetDisableASLR:") - 1) == 0) - { - extern int g_disable_aslr; - p += sizeof ("QSetDisableASLR:") - 1; - switch (*p) - { - case '0': g_disable_aslr = 0; break; - case '1': g_disable_aslr = 1; break; - default: - return SendPacket ("E56"); - } - return SendPacket ("OK"); - } +rnb_err_t +RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p) +{ /* The number of characters in a packet payload that gdb is prepared to accept. The packet-start char, packet-end char, 2 checksum chars and terminating null character are not included in this size. */ - if (strncmp (p, "QSetMaxPayloadSize:", sizeof ("QSetMaxPayloadSize:") - 1) == 0) + p += sizeof ("QSetMaxPayloadSize:") - 1; + errno = 0; + uint32_t size = strtoul (p, NULL, 16); + if (errno != 0 && size == 0) { - p += sizeof ("QSetMaxPayloadSize:") - 1; - errno = 0; - uint32_t size = strtoul (p, NULL, 16); - if (errno != 0 && size == 0) - { - return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPayloadSize packet"); - } - m_max_payload_size = size; - return SendPacket ("OK"); + return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPayloadSize packet"); } + m_max_payload_size = size; + return SendPacket ("OK"); +} +rnb_err_t +RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p) +{ /* This tells us the largest packet that gdb can handle. i.e. the size of gdb's packet-reading buffer. QSetMaxPayloadSize is preferred because it is less ambiguous. */ - - if (strncmp (p, "QSetMaxPacketSize:", sizeof ("QSetMaxPacketSize:") - 1) == 0) + p += sizeof ("QSetMaxPacketSize:") - 1; + errno = 0; + uint32_t size = strtoul (p, NULL, 16); + if (errno != 0 && size == 0) { - p += sizeof ("QSetMaxPacketSize:") - 1; - errno = 0; - uint32_t size = strtoul (p, NULL, 16); - if (errno != 0 && size == 0) - { - return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPacketSize packet"); - } - m_max_payload_size = size - 5; - return SendPacket ("OK"); + return HandlePacket_ILLFORMED ("Invalid length in QSetMaxPacketSize packet"); } + m_max_payload_size = size - 5; + return SendPacket ("OK"); +} + + + +rnb_err_t +RNBRemote::HandlePacket_QEnvironment (const char *p) +{ /* This sets the environment for the target program. The packet is of the form: QEnvironment:VARIABLE=VALUE */ - if (strncmp (p, "QEnvironment:", sizeof ("QEnvironment:") - 1) == 0) - { - DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"", - (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); + DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"", + (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); - p += sizeof ("QEnvironment:") - 1; - RNBContext& ctx = Context(); - - ctx.PushEnvironment (p); - return SendPacket ("OK"); - } + p += sizeof ("QEnvironment:") - 1; + RNBContext& ctx = Context(); - // Unrecognized Q packet - return SendPacket (""); + ctx.PushEnvironment (p); + return SendPacket ("OK"); } void @@ -2245,7 +2248,9 @@ RNBRemote::HandlePacket_g (const char *p) InitializeRegisters (); nub_process_t pid = m_ctx.ProcessID (); - nub_thread_t tid = GetCurrentThread(); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED ("No thread specified in p packet"); if (m_use_native_regs) { @@ -2291,7 +2296,9 @@ RNBRemote::HandlePacket_G (const char *p) packet.SetFilePos(1); // Skip the 'G' nub_process_t pid = m_ctx.ProcessID(); - nub_thread_t tid = GetCurrentThread(); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED ("No thread specified in p packet"); if (m_use_native_regs) { @@ -2870,6 +2877,30 @@ RNBRemote::HandlePacket_z (const char *p) return HandlePacket_UNIMPLEMENTED(p); } +// Extract the thread number from the thread suffix that might be appended to +// thread specific packets. This will only be enabled if m_thread_suffix_supported +// is true. +nub_thread_t +RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p) +{ + if (m_thread_suffix_supported) + { + nub_thread_t tid = INVALID_NUB_THREAD; + if (p) + { + const char *tid_cstr = strstr (p, "thread:"); + if (tid_cstr) + { + tid_cstr += strlen ("thread:"); + tid = strtoul(tid_cstr, NULL, 16); + } + DNBLogThreadedIf (LOG_RNB_PACKETS, "RNBRemote::ExtractThreadIDFromThreadSuffix(%s) got thread 0x%4.4x", p, tid); + } + } + return GetCurrentThread(); + +} + /* `p XX' print the contents of register X */ @@ -2889,12 +2920,17 @@ RNBRemote::HandlePacket_p (const char *p) } nub_process_t pid = m_ctx.ProcessID(); errno = 0; - uint32_t reg = strtoul (p + 1, NULL, 16); + char *tid_cstr = NULL; + uint32_t reg = strtoul (p + 1, &tid_cstr, 16); if (errno != 0 && reg == 0) { - return HandlePacket_ILLFORMED ("Could not parse thread number in p packet"); + return HandlePacket_ILLFORMED ("Could not parse register number in p packet"); } + nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED ("No thread specified in p packet"); + const register_map_entry_t *reg_entry; if (reg < g_num_reg_entries) @@ -2925,7 +2961,6 @@ RNBRemote::HandlePacket_p (const char *p) } else { - nub_thread_t tid = GetCurrentThread(); register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry); } return SendPacket (ostrm.str()); @@ -2985,8 +3020,9 @@ RNBRemote::HandlePacket_P (const char *p) reg_value.info = reg_entry->nub_info; packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc); - nub_thread_t tid; - tid = GetCurrentThread (); + nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); + if (tid == INVALID_NUB_THREAD) + return HandlePacket_ILLFORMED ("No thread specified in p packet"); if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, ®_value)) { diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index fab42bc9693..82febf7d226 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -93,6 +93,7 @@ public: query_host_info, // 'qHostInfo' pass_signals_to_inferior, // 'QPassSignals' start_noack_mode, // 'QStartNoAckMode' + prefix_reg_packets_with_tid, // 'QPrefixRegisterPacketsWithThreadID set_logging_mode, // 'QSetLogging:' set_max_packet_size, // 'QSetMaxPacketSize:' set_max_payload_size, // 'QSetMaxPayloadSize:' @@ -156,7 +157,14 @@ public: rnb_err_t HandlePacket_qThreadExtraInfo (const char *p); rnb_err_t HandlePacket_qThreadStopInfo (const char *p); rnb_err_t HandlePacket_qHostInfo (const char *p); - rnb_err_t HandlePacket_Q (const char *p); + rnb_err_t HandlePacket_QStartNoAckMode (const char *p); + rnb_err_t HandlePacket_QThreadSuffixSupported (const char *p); + rnb_err_t HandlePacket_QSetLogging (const char *p); + rnb_err_t HandlePacket_QSetDisableASLR (const char *p); + rnb_err_t HandlePacket_QSetMaxPayloadSize (const char *p); + rnb_err_t HandlePacket_QSetMaxPacketSize (const char *p); + rnb_err_t HandlePacket_QEnvironment (const char *p); + rnb_err_t HandlePacket_QPrefixRegisterPacketsWithThreadID (const char *p); rnb_err_t HandlePacket_last_signal (const char *p); rnb_err_t HandlePacket_m (const char *p); rnb_err_t HandlePacket_M (const char *p); @@ -237,6 +245,9 @@ protected: void CreatePacketTable (); rnb_err_t GetPacketPayload (std::string &); + nub_thread_t + ExtractThreadIDFromThreadSuffix (const char *p); + // gdb can send multiple Z/z packets for the same address and // these calls must be ref counted. struct Breakpoint @@ -286,7 +297,13 @@ protected: uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb bool m_extended_mode:1, // are we in extended mode? m_noack_mode:1, // are we in no-ack mode? - m_use_native_regs:1; // Use native registers by querying DNB layer for register definitions? + m_noack_mode_just_enabled:1, // Did we just enable this and need to compute one more checksum? + m_use_native_regs:1, // Use native registers by querying DNB layer for register definitions? + m_thread_suffix_supported:1; // Set to true if the 'p', 'P', 'g', and 'G' packets should be prefixed with the thread ID and colon: + // "$pRR;thread:TTTT;" instead of "$pRR" + // "$PRR=VVVVVVVV;thread:TTTT;" instead of "$PRR=VVVVVVVV" + // "$g;thread:TTTT" instead of "$g" + // "$GVVVVVVVVVVVVVV;thread:TTTT;#00 instead of "$GVVVVVVVVVVVVVV" }; /* We translate the /usr/include/mach/exception_types.h exception types |

