1 //===-- RNBRemote.cpp -------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Created by Greg Clayton on 12/12/07.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "RNBRemote.h"
15 
16 #include <errno.h>
17 #include <unistd.h>
18 #include <signal.h>
19 #include <mach/exception_types.h>
20 #include <sys/stat.h>
21 #include <sys/sysctl.h>
22 
23 #include "DNB.h"
24 #include "DNBLog.h"
25 #include "DNBThreadResumeActions.h"
26 #include "RNBContext.h"
27 #include "RNBServices.h"
28 #include "RNBSocket.h"
29 #include "Utility/StringExtractor.h"
30 
31 #include <iomanip>
32 #include <sstream>
33 #include <TargetConditionals.h> // for endianness predefines
34 
35 //----------------------------------------------------------------------
36 // std::iostream formatting macros
37 //----------------------------------------------------------------------
38 #define RAW_HEXBASE     std::setfill('0') << std::hex << std::right
39 #define HEXBASE         '0' << 'x' << RAW_HEXBASE
40 #define RAWHEX8(x)      RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x))
41 #define RAWHEX16        RAW_HEXBASE << std::setw(4)
42 #define RAWHEX32        RAW_HEXBASE << std::setw(8)
43 #define RAWHEX64        RAW_HEXBASE << std::setw(16)
44 #define HEX8(x)         HEXBASE << std::setw(2) << ((uint32_t)(x))
45 #define HEX16           HEXBASE << std::setw(4)
46 #define HEX32           HEXBASE << std::setw(8)
47 #define HEX64           HEXBASE << std::setw(16)
48 #define RAW_HEX(x)      RAW_HEXBASE << std::setw(sizeof(x)*2) << (x)
49 #define HEX(x)          HEXBASE << std::setw(sizeof(x)*2) << (x)
50 #define RAWHEX_SIZE(x, sz)  RAW_HEXBASE << std::setw((sz)) << (x)
51 #define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x)
52 #define STRING_WIDTH(w) std::setfill(' ') << std::setw(w)
53 #define LEFT_STRING_WIDTH(s, w) std::left << std::setfill(' ') << std::setw(w) << (s) << std::right
54 #define DECIMAL         std::dec << std::setfill(' ')
55 #define DECIMAL_WIDTH(w) DECIMAL << std::setw(w)
56 #define FLOAT(n, d)     std::setfill(' ') << std::setw((n)+(d)+1) << std::setprecision(d) << std::showpoint << std::fixed
57 #define INDENT_WITH_SPACES(iword_idx)   std::setfill(' ') << std::setw((iword_idx)) << ""
58 #define INDENT_WITH_TABS(iword_idx)     std::setfill('\t') << std::setw((iword_idx)) << ""
59 // Class to handle communications via gdb remote protocol.
60 
61 extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
62 
RNBRemote()63 RNBRemote::RNBRemote () :
64     m_ctx (),
65     m_comm (),
66     m_continue_thread(-1),
67     m_thread(-1),
68     m_mutex(),
69     m_packets_recvd(0),
70     m_packets(),
71     m_rx_packets(),
72     m_rx_partial_data(),
73     m_rx_pthread(0),
74     m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
75     m_extended_mode(false),
76     m_noack_mode(false),
77     m_use_native_regs (false),
78     m_thread_suffix_supported (false),
79     m_list_threads_in_stop_reply (false)
80 {
81     DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
82     CreatePacketTable ();
83 }
84 
85 
~RNBRemote()86 RNBRemote::~RNBRemote()
87 {
88     DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
89     StopReadRemoteDataThread();
90 }
91 
92 void
CreatePacketTable()93 RNBRemote::CreatePacketTable  ()
94 {
95     // Step required to add new packets:
96     // 1 - Add new enumeration to RNBRemote::PacketEnum
97     // 2 - Create a the RNBRemote::HandlePacket_ function if a new function is needed
98     // 3 - Register the Packet definition with any needed callbacks in this function
99     //          - If no response is needed for a command, then use NULL for the normal callback
100     //          - If the packet is not supported while the target is running, use NULL for the async callback
101     // 4 - If the packet is a standard packet (starts with a '$' character
102     //      followed by the payload and then '#' and checksum, then you are done
103     //      else go on to step 5
104     // 5 - if the packet is a fixed length packet:
105     //      - modify the switch statement for the first character in the payload
106     //        in RNBRemote::CommDataReceived so it doesn't reject the new packet
107     //        type as invalid
108     //      - modify the switch statement for the first character in the payload
109     //        in RNBRemote::GetPacketPayload and make sure the payload of the packet
110     //        is returned correctly
111 
112     std::vector <Packet> &t = m_packets;
113     t.push_back (Packet (ack,                           NULL,                                   NULL, "+", "ACK"));
114     t.push_back (Packet (nack,                          NULL,                                   NULL, "-", "!ACK"));
115     t.push_back (Packet (read_memory,                   &RNBRemote::HandlePacket_m,             NULL, "m", "Read memory"));
116     t.push_back (Packet (read_register,                 &RNBRemote::HandlePacket_p,             NULL, "p", "Read one register"));
117     t.push_back (Packet (read_general_regs,             &RNBRemote::HandlePacket_g,             NULL, "g", "Read registers"));
118     t.push_back (Packet (write_memory,                  &RNBRemote::HandlePacket_M,             NULL, "M", "Write memory"));
119     t.push_back (Packet (write_register,                &RNBRemote::HandlePacket_P,             NULL, "P", "Write one register"));
120     t.push_back (Packet (write_general_regs,            &RNBRemote::HandlePacket_G,             NULL, "G", "Write registers"));
121     t.push_back (Packet (insert_mem_bp,                 &RNBRemote::HandlePacket_z,             NULL, "Z0", "Insert memory breakpoint"));
122     t.push_back (Packet (remove_mem_bp,                 &RNBRemote::HandlePacket_z,             NULL, "z0", "Remove memory breakpoint"));
123     t.push_back (Packet (single_step,                   &RNBRemote::HandlePacket_s,             NULL, "s", "Single step"));
124     t.push_back (Packet (cont,                          &RNBRemote::HandlePacket_c,             NULL, "c", "continue"));
125     t.push_back (Packet (single_step_with_sig,          &RNBRemote::HandlePacket_S,             NULL, "S", "Single step with signal"));
126     t.push_back (Packet (set_thread,                    &RNBRemote::HandlePacket_H,             NULL, "H", "Set thread"));
127     t.push_back (Packet (halt,                          &RNBRemote::HandlePacket_last_signal,   &RNBRemote::HandlePacket_stop_process, "\x03", "^C"));
128 //  t.push_back (Packet (use_extended_mode,             &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode"));
129     t.push_back (Packet (why_halted,                    &RNBRemote::HandlePacket_last_signal,   NULL, "?", "Why did target halt"));
130     t.push_back (Packet (set_argv,                      &RNBRemote::HandlePacket_A,             NULL, "A", "Set argv"));
131 //  t.push_back (Packet (set_bp,                        &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear breakpoint"));
132     t.push_back (Packet (continue_with_sig,             &RNBRemote::HandlePacket_C,             NULL, "C", "Continue with signal"));
133     t.push_back (Packet (detach,                        &RNBRemote::HandlePacket_D,             NULL, "D", "Detach gdb from remote system"));
134 //  t.push_back (Packet (step_inferior_one_cycle,       &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one clock cycle"));
135 //  t.push_back (Packet (signal_and_step_inf_one_cycle, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then step one clock cyle"));
136     t.push_back (Packet (kill,                          &RNBRemote::HandlePacket_k,             NULL, "k", "Kill"));
137 //  t.push_back (Packet (restart,                       &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior"));
138 //  t.push_back (Packet (search_mem_backwards,          &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory backwards"));
139     t.push_back (Packet (thread_alive_p,                &RNBRemote::HandlePacket_T,             NULL, "T", "Is thread alive"));
140     t.push_back (Packet (vattach,                       &RNBRemote::HandlePacket_v,             NULL, "vAttach", "Attach to a new process"));
141     t.push_back (Packet (vattachwait,                   &RNBRemote::HandlePacket_v,             NULL, "vAttachWait", "Wait for a process to start up then attach to it"));
142     t.push_back (Packet (vattachorwait,                 &RNBRemote::HandlePacket_v,             NULL, "vAttachOrWait", "Attach to the process or if it doesn't exist, wait for the process to start up then attach to it"));
143     t.push_back (Packet (vattachname,                   &RNBRemote::HandlePacket_v,             NULL, "vAttachName", "Attach to an existing process by name"));
144     t.push_back (Packet (vcont_list_actions,            &RNBRemote::HandlePacket_v,             NULL, "vCont;", "Verbose resume with thread actions"));
145     t.push_back (Packet (vcont_list_actions,            &RNBRemote::HandlePacket_v,             NULL, "vCont?", "List valid continue-with-thread-actions actions"));
146     // The X packet doesn't currently work. If/when it does, remove the line above and uncomment out the line below
147 //  t.push_back (Packet (write_data_to_memory,          &RNBRemote::HandlePacket_X,             NULL, "X", "Write data to memory"));
148 //  t.push_back (Packet (insert_hardware_bp,            &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware breakpoint"));
149 //  t.push_back (Packet (remove_hardware_bp,            &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware breakpoint"));
150     t.push_back (Packet (insert_write_watch_bp,         &RNBRemote::HandlePacket_z,             NULL, "Z2", "Insert write watchpoint"));
151     t.push_back (Packet (remove_write_watch_bp,         &RNBRemote::HandlePacket_z,             NULL, "z2", "Remove write watchpoint"));
152     t.push_back (Packet (insert_read_watch_bp,          &RNBRemote::HandlePacket_z,             NULL, "Z3", "Insert read watchpoint"));
153     t.push_back (Packet (remove_read_watch_bp,          &RNBRemote::HandlePacket_z,             NULL, "z3", "Remove read watchpoint"));
154     t.push_back (Packet (insert_access_watch_bp,        &RNBRemote::HandlePacket_z,             NULL, "Z4", "Insert access watchpoint"));
155     t.push_back (Packet (remove_access_watch_bp,        &RNBRemote::HandlePacket_z,             NULL, "z4", "Remove access watchpoint"));
156     t.push_back (Packet (query_monitor,                 &RNBRemote::HandlePacket_qRcmd,          NULL, "qRcmd", "Monitor command"));
157     t.push_back (Packet (query_current_thread_id,       &RNBRemote::HandlePacket_qC,            NULL, "qC", "Query current thread ID"));
158     t.push_back (Packet (query_get_pid,                 &RNBRemote::HandlePacket_qGetPid,       NULL, "qGetPid", "Query process id"));
159     t.push_back (Packet (query_thread_ids_first,        &RNBRemote::HandlePacket_qThreadInfo,   NULL, "qfThreadInfo", "Get list of active threads (first req)"));
160     t.push_back (Packet (query_thread_ids_subsequent,   &RNBRemote::HandlePacket_qThreadInfo,   NULL, "qsThreadInfo", "Get list of active threads (subsequent req)"));
161     // APPLE LOCAL: qThreadStopInfo
162     // syntax: qThreadStopInfoTTTT
163     //  TTTT is hex thread ID
164     t.push_back (Packet (query_thread_stop_info,        &RNBRemote::HandlePacket_qThreadStopInfo,   NULL, "qThreadStopInfo", "Get detailed info on why the specified thread stopped"));
165     t.push_back (Packet (query_thread_extra_info,       &RNBRemote::HandlePacket_qThreadExtraInfo,NULL, "qThreadExtraInfo", "Get printable status of a thread"));
166 //  t.push_back (Packet (query_image_offsets,           &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset of loaded program"));
167     t.push_back (Packet (query_launch_success,          &RNBRemote::HandlePacket_qLaunchSuccess,NULL, "qLaunchSuccess", "Report the success or failure of the launch attempt"));
168     t.push_back (Packet (query_register_info,           &RNBRemote::HandlePacket_qRegisterInfo, NULL, "qRegisterInfo", "Dynamically discover remote register context information."));
169     t.push_back (Packet (query_shlib_notify_info_addr,  &RNBRemote::HandlePacket_qShlibInfoAddr,NULL, "qShlibInfoAddr", "Returns the address that contains info needed for getting shared library notifications"));
170     t.push_back (Packet (query_step_packet_supported,   &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported."));
171     t.push_back (Packet (query_vattachorwait_supported, &RNBRemote::HandlePacket_qVAttachOrWaitSupported,NULL, "qVAttachOrWaitSupported", "Replys with OK if the 'vAttachOrWait' packet is supported."));
172     t.push_back (Packet (query_sync_thread_state_supported, &RNBRemote::HandlePacket_qSyncThreadStateSupported,NULL, "qSyncThreadStateSupported", "Replys with OK if the 'QSyncThreadState:' packet is supported."));
173     t.push_back (Packet (query_host_info,               &RNBRemote::HandlePacket_qHostInfo,     NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
174     t.push_back (Packet (query_process_info,            &RNBRemote::HandlePacket_qProcessInfo,     NULL, "qProcessInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
175 //  t.push_back (Packet (query_symbol_lookup,           &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qSymbol", "Notify that host debugger is ready to do symbol lookups"));
176     t.push_back (Packet (start_noack_mode,              &RNBRemote::HandlePacket_QStartNoAckMode        , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
177     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"));
178     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"));
179     t.push_back (Packet (set_max_packet_size,           &RNBRemote::HandlePacket_QSetMaxPacketSize      , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
180     t.push_back (Packet (set_max_payload_size,          &RNBRemote::HandlePacket_QSetMaxPayloadSize     , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle"));
181     t.push_back (Packet (set_environment_variable,      &RNBRemote::HandlePacket_QEnvironment           , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment"));
182     t.push_back (Packet (set_environment_variable_hex,  &RNBRemote::HandlePacket_QEnvironmentHexEncoded , NULL, "QEnvironmentHexEncoded:", "Add an environment variable to the inferior's environment"));
183     t.push_back (Packet (set_launch_arch,               &RNBRemote::HandlePacket_QLaunchArch            , NULL, "QLaunchArch:", "Set the architecture to use when launching a process for hosts that can run multiple architecture slices from universal files."));
184     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"));
185     t.push_back (Packet (set_stdin,                     &RNBRemote::HandlePacket_QSetSTDIO              , NULL, "QSetSTDIN:", "Set the standard input for a process to be launched with the 'A' packet"));
186     t.push_back (Packet (set_stdout,                    &RNBRemote::HandlePacket_QSetSTDIO              , NULL, "QSetSTDOUT:", "Set the standard output for a process to be launched with the 'A' packet"));
187     t.push_back (Packet (set_stderr,                    &RNBRemote::HandlePacket_QSetSTDIO              , NULL, "QSetSTDERR:", "Set the standard error for a process to be launched with the 'A' packet"));
188     t.push_back (Packet (set_working_dir,               &RNBRemote::HandlePacket_QSetWorkingDir         , NULL, "QSetWorkingDir:", "Set the working directory for a process to be launched with the 'A' packet"));
189     t.push_back (Packet (set_list_threads_in_stop_reply,&RNBRemote::HandlePacket_QListThreadsInStopReply , NULL, "QListThreadsInStopReply", "Set if the 'threads' key should be added to the stop reply packets with a list of all thread IDs."));
190     t.push_back (Packet (sync_thread_state,             &RNBRemote::HandlePacket_QSyncThreadState , NULL, "QSyncThreadState:", "Do whatever is necessary to make sure 'thread' is in a safe state to call functions on."));
191 //  t.push_back (Packet (pass_signals_to_inferior,      &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior"));
192     t.push_back (Packet (allocate_memory,               &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process."));
193     t.push_back (Packet (deallocate_memory,             &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process."));
194     t.push_back (Packet (memory_region_info,            &RNBRemote::HandlePacket_MemoryRegionInfo, NULL, "qMemoryRegionInfo", "Return size and attributes of a memory region that contains the given address"));
195     t.push_back (Packet (get_profile_data,              &RNBRemote::HandlePacket_GetProfileData, NULL, "qGetProfileData", "Return profiling data of the current target."));
196     t.push_back (Packet (set_enable_profiling,          &RNBRemote::HandlePacket_SetEnableAsyncProfiling, NULL, "QSetEnableAsyncProfiling", "Enable or disable the profiling of current target."));
197     t.push_back (Packet (watchpoint_support_info,       &RNBRemote::HandlePacket_WatchpointSupportInfo, NULL, "qWatchpointSupportInfo", "Return the number of supported hardware watchpoints"));
198 
199 }
200 
201 
202 void
FlushSTDIO()203 RNBRemote::FlushSTDIO ()
204 {
205     if (m_ctx.HasValidProcessID())
206     {
207         nub_process_t pid = m_ctx.ProcessID();
208         char buf[256];
209         nub_size_t count;
210         do
211         {
212             count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf));
213             if (count > 0)
214             {
215                 SendSTDOUTPacket (buf, count);
216             }
217         } while (count > 0);
218 
219         do
220         {
221             count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf));
222             if (count > 0)
223             {
224                 SendSTDERRPacket (buf, count);
225             }
226         } while (count > 0);
227     }
228 }
229 
230 void
SendAsyncProfileData()231 RNBRemote::SendAsyncProfileData ()
232 {
233     if (m_ctx.HasValidProcessID())
234     {
235         nub_process_t pid = m_ctx.ProcessID();
236         char buf[1024];
237         nub_size_t count;
238         do
239         {
240             count = DNBProcessGetAvailableProfileData(pid, buf, sizeof(buf));
241             if (count > 0)
242             {
243                 SendAsyncProfileDataPacket (buf, count);
244             }
245         } while (count > 0);
246     }
247 }
248 
249 rnb_err_t
SendHexEncodedBytePacket(const char * header,const void * buf,size_t buf_len,const char * footer)250 RNBRemote::SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer)
251 {
252     std::ostringstream packet_sstrm;
253     // Append the header cstr if there was one
254     if (header && header[0])
255         packet_sstrm << header;
256     nub_size_t i;
257     const uint8_t *ubuf8 = (const uint8_t *)buf;
258     for (i=0; i<buf_len; i++)
259     {
260         packet_sstrm << RAWHEX8(ubuf8[i]);
261     }
262     // Append the footer cstr if there was one
263     if (footer && footer[0])
264         packet_sstrm << footer;
265 
266     return SendPacket(packet_sstrm.str());
267 }
268 
269 rnb_err_t
SendSTDOUTPacket(char * buf,nub_size_t buf_size)270 RNBRemote::SendSTDOUTPacket (char *buf, nub_size_t buf_size)
271 {
272     if (buf_size == 0)
273         return rnb_success;
274     return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
275 }
276 
277 rnb_err_t
SendSTDERRPacket(char * buf,nub_size_t buf_size)278 RNBRemote::SendSTDERRPacket (char *buf, nub_size_t buf_size)
279 {
280     if (buf_size == 0)
281         return rnb_success;
282     return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
283 }
284 
285 // This makes use of asynchronous bit 'A' in the gdb remote protocol.
286 rnb_err_t
SendAsyncProfileDataPacket(char * buf,nub_size_t buf_size)287 RNBRemote::SendAsyncProfileDataPacket (char *buf, nub_size_t buf_size)
288 {
289     if (buf_size == 0)
290         return rnb_success;
291 
292     std::string packet("A");
293     packet.append(buf, buf_size);
294     return SendPacket(packet);
295 }
296 
297 rnb_err_t
SendPacket(const std::string & s)298 RNBRemote::SendPacket (const std::string &s)
299 {
300     DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, s.c_str());
301     std::string sendpacket = "$" + s + "#";
302     int cksum = 0;
303     char hexbuf[5];
304 
305     if (m_noack_mode)
306     {
307         sendpacket += "00";
308     }
309     else
310     {
311         for (int i = 0; i != s.size(); ++i)
312             cksum += s[i];
313         snprintf (hexbuf, sizeof hexbuf, "%02x", cksum & 0xff);
314         sendpacket += hexbuf;
315     }
316 
317     rnb_err_t err = m_comm.Write (sendpacket.c_str(), sendpacket.size());
318     if (err != rnb_success)
319         return err;
320 
321     if (m_noack_mode)
322         return rnb_success;
323 
324     std::string reply;
325     RNBRemote::Packet packet;
326     err = GetPacket (reply, packet, true);
327 
328     if (err != rnb_success)
329     {
330         DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s (%s) got error trying to get reply...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str());
331         return err;
332     }
333 
334     DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) got reply: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, sendpacket.c_str(), reply.c_str());
335 
336     if (packet.type == ack)
337         return rnb_success;
338 
339     // Should we try to resend the packet at this layer?
340     //  if (packet.command == nack)
341     return rnb_err;
342 }
343 
344 /* Get a packet via gdb remote protocol.
345  Strip off the prefix/suffix, verify the checksum to make sure
346  a valid packet was received, send an ACK if they match.  */
347 
348 rnb_err_t
GetPacketPayload(std::string & return_packet)349 RNBRemote::GetPacketPayload (std::string &return_packet)
350 {
351     //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
352 
353     PThreadMutex::Locker locker(m_mutex);
354     if (m_rx_packets.empty())
355     {
356         // Only reset the remote command available event if we have no more packets
357         m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
358         //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
359         return rnb_err;
360     }
361 
362     //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, m_rx_packets.size());
363     return_packet.swap(m_rx_packets.front());
364     m_rx_packets.pop_front();
365     locker.Reset(); // Release our lock on the mutex
366 
367     if (m_rx_packets.empty())
368     {
369         // Reset the remote command available event if we have no more packets
370         m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
371     }
372 
373     //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
374 
375     switch (return_packet[0])
376     {
377         case '+':
378         case '-':
379         case '\x03':
380             break;
381 
382         case '$':
383         {
384             int packet_checksum = 0;
385             if (!m_noack_mode)
386             {
387                 for (int i = return_packet.size() - 2; i < return_packet.size(); ++i)
388                 {
389                     char checksum_char = tolower (return_packet[i]);
390                     if (!isxdigit (checksum_char))
391                     {
392                         m_comm.Write ("-", 1);
393                         DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s error: packet with invalid checksum characters: %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
394                         return rnb_err;
395                     }
396                 }
397                 packet_checksum = strtol (&return_packet[return_packet.size() - 2], NULL, 16);
398             }
399 
400             return_packet.erase(0,1);           // Strip the leading '$'
401             return_packet.erase(return_packet.size() - 3);// Strip the #XX checksum
402 
403             if (!m_noack_mode)
404             {
405                 // Compute the checksum
406                 int computed_checksum = 0;
407                 for (std::string::iterator it = return_packet.begin ();
408                      it != return_packet.end ();
409                      ++it)
410                 {
411                     computed_checksum += *it;
412                 }
413 
414                 if (packet_checksum == (computed_checksum & 0xff))
415                 {
416                     //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
417                     m_comm.Write ("+", 1);
418                 }
419                 else
420                 {
421                     DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: packet checksum mismatch  (0x%2.2x != 0x%2.2x))",
422                                       (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
423                                       __FUNCTION__,
424                                       return_packet.c_str(),
425                                       packet_checksum,
426                                       computed_checksum);
427                     m_comm.Write ("-", 1);
428                     return rnb_err;
429                 }
430             }
431         }
432         break;
433 
434         default:
435             DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s tossing unexpected packet???? %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
436             if (!m_noack_mode)
437                 m_comm.Write ("-", 1);
438             return rnb_err;
439     }
440 
441     return rnb_success;
442 }
443 
444 rnb_err_t
HandlePacket_UNIMPLEMENTED(const char * p)445 RNBRemote::HandlePacket_UNIMPLEMENTED (const char* p)
446 {
447     DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p ? p : "NULL");
448     return SendPacket ("");
449 }
450 
451 rnb_err_t
HandlePacket_ILLFORMED(const char * file,int line,const char * p,const char * description)452 RNBRemote::HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description)
453 {
454     DNBLogThreadedIf (LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file, line, __FUNCTION__, p);
455     return SendPacket ("E03");
456 }
457 
458 rnb_err_t
GetPacket(std::string & packet_payload,RNBRemote::Packet & packet_info,bool wait)459 RNBRemote::GetPacket (std::string &packet_payload, RNBRemote::Packet& packet_info, bool wait)
460 {
461     std::string payload;
462     rnb_err_t err = GetPacketPayload (payload);
463     if (err != rnb_success)
464     {
465         PThreadEvent& events = m_ctx.Events();
466         nub_event_t set_events = events.GetEventBits();
467         // TODO: add timeout version of GetPacket?? We would then need to pass
468         // that timeout value along to DNBProcessTimedWaitForEvent.
469         if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0))
470             return err;
471 
472         const nub_event_t events_to_wait_for = RNBContext::event_read_packet_available | RNBContext::event_read_thread_exiting;
473 
474         while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0)
475         {
476             if (set_events & RNBContext::event_read_packet_available)
477             {
478                 // Try the queue again now that we got an event
479                 err = GetPacketPayload (payload);
480                 if (err == rnb_success)
481                     break;
482             }
483 
484             if (set_events & RNBContext::event_read_thread_exiting)
485                 err = rnb_not_connected;
486 
487             if (err == rnb_not_connected)
488                 return err;
489 
490         } while (err == rnb_err);
491 
492         if (set_events == 0)
493             err = rnb_not_connected;
494     }
495 
496     if (err == rnb_success)
497     {
498         Packet::iterator it;
499         for (it = m_packets.begin (); it != m_packets.end (); ++it)
500         {
501             if (payload.compare (0, it->abbrev.size(), it->abbrev) == 0)
502                 break;
503         }
504 
505         // A packet we don't have an entry for. This can happen when we
506         // get a packet that we don't know about or support. We just reply
507         // accordingly and go on.
508         if (it == m_packets.end ())
509         {
510             DNBLogThreadedIf (LOG_RNB_PACKETS, "unimplemented packet: '%s'", payload.c_str());
511             HandlePacket_UNIMPLEMENTED(payload.c_str());
512             return rnb_err;
513         }
514         else
515         {
516             packet_info = *it;
517             packet_payload = payload;
518         }
519     }
520     return err;
521 }
522 
523 rnb_err_t
HandleAsyncPacket(PacketEnum * type)524 RNBRemote::HandleAsyncPacket(PacketEnum *type)
525 {
526     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
527     static DNBTimer g_packetTimer(true);
528     rnb_err_t err = rnb_err;
529     std::string packet_data;
530     RNBRemote::Packet packet_info;
531     err = GetPacket (packet_data, packet_info, false);
532 
533     if (err == rnb_success)
534     {
535         if (!packet_data.empty() && isprint(packet_data[0]))
536             DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (\"%s\");", packet_data.c_str());
537         else
538             DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (%s);", packet_info.printable_name.c_str());
539 
540         HandlePacketCallback packet_callback = packet_info.async;
541         if (packet_callback != NULL)
542         {
543             if (type != NULL)
544                 *type = packet_info.type;
545             return (this->*packet_callback)(packet_data.c_str());
546         }
547     }
548 
549     return err;
550 }
551 
552 rnb_err_t
HandleReceivedPacket(PacketEnum * type)553 RNBRemote::HandleReceivedPacket(PacketEnum *type)
554 {
555     static DNBTimer g_packetTimer(true);
556 
557     //  DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
558     rnb_err_t err = rnb_err;
559     std::string packet_data;
560     RNBRemote::Packet packet_info;
561     err = GetPacket (packet_data, packet_info, false);
562 
563     if (err == rnb_success)
564     {
565         DNBLogThreadedIf (LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");", packet_data.c_str());
566         HandlePacketCallback packet_callback = packet_info.normal;
567         if (packet_callback != NULL)
568         {
569             if (type != NULL)
570                 *type = packet_info.type;
571             return (this->*packet_callback)(packet_data.c_str());
572         }
573         else
574         {
575             // Do not fall through to end of this function, if we have valid
576             // packet_info and it has a NULL callback, then we need to respect
577             // that it may not want any response or anything to be done.
578             return err;
579         }
580     }
581     return rnb_err;
582 }
583 
584 void
CommDataReceived(const std::string & new_data)585 RNBRemote::CommDataReceived(const std::string& new_data)
586 {
587     //  DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
588     {
589         // Put the packet data into the buffer in a thread safe fashion
590         PThreadMutex::Locker locker(m_mutex);
591 
592         std::string data;
593         // See if we have any left over data from a previous call to this
594         // function?
595         if (!m_rx_partial_data.empty())
596         {
597             // We do, so lets start with that data
598             data.swap(m_rx_partial_data);
599         }
600         // Append the new incoming data
601         data += new_data;
602 
603         // Parse up the packets into gdb remote packets
604         uint32_t idx = 0;
605         const size_t data_size = data.size();
606 
607         while (idx < data_size)
608         {
609             // end_idx must be one past the last valid packet byte. Start
610             // it off with an invalid value that is the same as the current
611             // index.
612             size_t end_idx = idx;
613 
614             switch (data[idx])
615             {
616                 case '+':       // Look for ack
617                 case '-':       // Look for cancel
618                 case '\x03':    // ^C to halt target
619                     end_idx = idx + 1;  // The command is one byte long...
620                     break;
621 
622                 case '$':
623                     // Look for a standard gdb packet?
624                     end_idx = data.find('#',  idx + 1);
625                     if (end_idx == std::string::npos || end_idx + 3 > data_size)
626                     {
627                         end_idx = std::string::npos;
628                     }
629                     else
630                     {
631                         // Add two for the checksum bytes and 1 to point to the
632                         // byte just past the end of this packet
633                         end_idx += 3;
634                     }
635                     break;
636 
637                 default:
638                     break;
639             }
640 
641             if (end_idx == std::string::npos)
642             {
643                 // Not all data may be here for the packet yet, save it for
644                 // next time through this function.
645                 m_rx_partial_data += data.substr(idx);
646                 //DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s saving data for later[%u, npos): '%s'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, idx, m_rx_partial_data.c_str());
647                 idx = end_idx;
648             }
649             else
650                 if (idx < end_idx)
651                 {
652                     m_packets_recvd++;
653                     // Hack to get rid of initial '+' ACK???
654                     if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+')
655                     {
656                         //DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first ACK away....[%u, npos): '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, idx);
657                     }
658                     else
659                     {
660                         // We have a valid packet...
661                         m_rx_packets.push_back(data.substr(idx, end_idx - idx));
662                         DNBLogThreadedIf (LOG_RNB_PACKETS, "getpkt: %s", m_rx_packets.back().c_str());
663                     }
664                     idx = end_idx;
665                 }
666                 else
667                 {
668                     DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s tossing junk byte at %c",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, data[idx]);
669                     idx = idx + 1;
670                 }
671         }
672     }
673 
674     if (!m_rx_packets.empty())
675     {
676         // Let the main thread know we have received a packet
677 
678         //DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s   called events.SetEvent(RNBContext::event_read_packet_available)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
679         PThreadEvent& events = m_ctx.Events();
680         events.SetEvents (RNBContext::event_read_packet_available);
681     }
682 }
683 
684 rnb_err_t
GetCommData()685 RNBRemote::GetCommData ()
686 {
687     //  DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
688     std::string comm_data;
689     rnb_err_t err = m_comm.Read (comm_data);
690     if (err == rnb_success)
691     {
692         if (!comm_data.empty())
693             CommDataReceived (comm_data);
694     }
695     return err;
696 }
697 
698 void
StartReadRemoteDataThread()699 RNBRemote::StartReadRemoteDataThread()
700 {
701     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
702     PThreadEvent& events = m_ctx.Events();
703     if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0)
704     {
705         events.ResetEvents (RNBContext::event_read_thread_exiting);
706         int err = ::pthread_create (&m_rx_pthread, NULL, ThreadFunctionReadRemoteData, this);
707         if (err == 0)
708         {
709             // Our thread was successfully kicked off, wait for it to
710             // set the started event so we can safely continue
711             events.WaitForSetEvents (RNBContext::event_read_thread_running);
712         }
713         else
714         {
715             events.ResetEvents (RNBContext::event_read_thread_running);
716             events.SetEvents (RNBContext::event_read_thread_exiting);
717         }
718     }
719 }
720 
721 void
StopReadRemoteDataThread()722 RNBRemote::StopReadRemoteDataThread()
723 {
724     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
725     PThreadEvent& events = m_ctx.Events();
726     if ((events.GetEventBits() & RNBContext::event_read_thread_running) == RNBContext::event_read_thread_running)
727     {
728         m_comm.Disconnect(true);
729         struct timespec timeout_abstime;
730         DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0);
731 
732         // Wait for 2 seconds for the remote data thread to exit
733         if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting, &timeout_abstime) == 0)
734         {
735             // Kill the remote data thread???
736         }
737     }
738 }
739 
740 
741 void*
ThreadFunctionReadRemoteData(void * arg)742 RNBRemote::ThreadFunctionReadRemoteData(void *arg)
743 {
744     // Keep a shared pointer reference so this doesn't go away on us before the thread is killed.
745     DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...", __FUNCTION__, arg);
746     RNBRemoteSP remoteSP(g_remoteSP);
747     if (remoteSP.get() != NULL)
748     {
749         RNBRemote* remote = remoteSP.get();
750         PThreadEvent& events = remote->Context().Events();
751         events.SetEvents (RNBContext::event_read_thread_running);
752         // START: main receive remote command thread loop
753         bool done = false;
754         while (!done)
755         {
756             rnb_err_t err = remote->GetCommData();
757 
758             switch (err)
759             {
760                 case rnb_success:
761                     break;
762 
763                 default:
764                 case rnb_err:
765                     DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned error %u", err);
766                     done = true;
767                     break;
768 
769                 case rnb_not_connected:
770                     DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned not connected...");
771                     done = true;
772                     break;
773             }
774         }
775         // START: main receive remote command thread loop
776         events.ResetEvents (RNBContext::event_read_thread_running);
777         events.SetEvents (RNBContext::event_read_thread_exiting);
778     }
779     DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...", __FUNCTION__, arg);
780     return NULL;
781 }
782 
783 
784 // If we fail to get back a valid CPU type for the remote process,
785 // make a best guess for the CPU type based on the currently running
786 // debugserver binary -- the debugger may not handle the case of an
787 // un-specified process CPU type correctly.
788 
789 static cpu_type_t
best_guess_cpu_type()790 best_guess_cpu_type ()
791 {
792 #if defined (__arm__)
793     return CPU_TYPE_ARM;
794 #elif defined (__i386__) || defined (__x86_64__)
795     if (sizeof (char*) == 8)
796     {
797         return CPU_TYPE_X86_64;
798     }
799     else
800     {
801         return CPU_TYPE_I386;
802     }
803 #endif
804     return 0;
805 }
806 
807 
808 /* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes
809  (8-bit bytes).
810  This encoding uses 0x7d ('}') as an escape character for 0x7d ('}'),
811  0x23 ('#'), and 0x24 ('$').
812  LEN is the number of bytes to be processed.  If a character is escaped,
813  it is 2 characters for LEN.  A LEN of -1 means encode-until-nul-byte
814  (end of string).  */
815 
816 std::vector<uint8_t>
decode_binary_data(const char * str,int len)817 decode_binary_data (const char *str, int len)
818 {
819     std::vector<uint8_t> bytes;
820     if (len == 0)
821     {
822         return bytes;
823     }
824     if (len == -1)
825         len = strlen (str);
826 
827     while (len--)
828     {
829         unsigned char c = *str;
830         if (c == 0x7d && len > 0)
831         {
832             len--;
833             str++;
834             c ^= 0x20;
835         }
836         bytes.push_back (c);
837     }
838     return bytes;
839 }
840 
841 typedef struct register_map_entry
842 {
843     uint32_t        gdb_regnum; // gdb register number
844     uint32_t        gdb_size;   // gdb register size in bytes (can be greater than or less than to debugnub size...)
845     const char *    gdb_name;   // gdb register name
846     DNBRegisterInfo nub_info;   // debugnub register info
847     const uint8_t*  fail_value; // Value to print if case we fail to reg this register (if this is NULL, we will return an error)
848     int             expedite;   // expedite delivery of this register in last stop reply packets
849 } register_map_entry_t;
850 
851 
852 
853 // If the notion of registers differs from what is handed out by the
854 // architecture, then flavors can be defined here.
855 
856 static const uint32_t MAX_REGISTER_BYTE_SIZE = 16;
857 static const uint8_t k_zero_bytes[MAX_REGISTER_BYTE_SIZE] = {0};
858 static std::vector<register_map_entry_t> g_dynamic_register_map;
859 static register_map_entry_t *g_reg_entries = NULL;
860 static size_t g_num_reg_entries = 0;
861 
862 static void
RegisterEntryNotAvailable(register_map_entry_t * reg_entry)863 RegisterEntryNotAvailable (register_map_entry_t *reg_entry)
864 {
865     reg_entry->fail_value = k_zero_bytes;
866     reg_entry->nub_info.set = INVALID_NUB_REGNUM;
867     reg_entry->nub_info.reg = INVALID_NUB_REGNUM;
868     reg_entry->nub_info.name = NULL;
869     reg_entry->nub_info.alt = NULL;
870     reg_entry->nub_info.type = InvalidRegType;
871     reg_entry->nub_info.format = InvalidRegFormat;
872     reg_entry->nub_info.size = 0;
873     reg_entry->nub_info.offset = 0;
874     reg_entry->nub_info.reg_gcc = INVALID_NUB_REGNUM;
875     reg_entry->nub_info.reg_dwarf = INVALID_NUB_REGNUM;
876     reg_entry->nub_info.reg_generic = INVALID_NUB_REGNUM;
877     reg_entry->nub_info.reg_gdb = INVALID_NUB_REGNUM;
878 }
879 
880 
881 //----------------------------------------------------------------------
882 // ARM regiseter sets as gdb knows them
883 //----------------------------------------------------------------------
884 register_map_entry_t
885 g_gdb_register_map_arm[] =
886 {
887     {  0,  4,  "r0",    {0}, NULL, 1},
888     {  1,  4,  "r1",    {0}, NULL, 1},
889     {  2,  4,  "r2",    {0}, NULL, 1},
890     {  3,  4,  "r3",    {0}, NULL, 1},
891     {  4,  4,  "r4",    {0}, NULL, 1},
892     {  5,  4,  "r5",    {0}, NULL, 1},
893     {  6,  4,  "r6",    {0}, NULL, 1},
894     {  7,  4,  "r7",    {0}, NULL, 1},
895     {  8,  4,  "r8",    {0}, NULL, 1},
896     {  9,  4,  "r9",    {0}, NULL, 1},
897     { 10,  4, "r10",    {0}, NULL, 1},
898     { 11,  4, "r11",    {0}, NULL, 1},
899     { 12,  4, "r12",    {0}, NULL, 1},
900     { 13,  4,  "sp",    {0}, NULL, 1},
901     { 14,  4,  "lr",    {0}, NULL, 1},
902     { 15,  4,  "pc",    {0}, NULL, 1},
903     { 16,  4,"cpsr",    {0}, NULL, 1},               // current program status register
904     { 17,  4,  "s0",    {0}, NULL, 0},
905     { 18,  4,  "s1",    {0}, NULL, 0},
906     { 19,  4,  "s2",    {0}, NULL, 0},
907     { 20,  4,  "s3",    {0}, NULL, 0},
908     { 21,  4,  "s4",    {0}, NULL, 0},
909     { 22,  4,  "s5",    {0}, NULL, 0},
910     { 23,  4,  "s6",    {0}, NULL, 0},
911     { 24,  4,  "s7",    {0}, NULL, 0},
912     { 25,  4,  "s8",    {0}, NULL, 0},
913     { 26,  4,  "s9",    {0}, NULL, 0},
914     { 27,  4, "s10",    {0}, NULL, 0},
915     { 28,  4, "s11",    {0}, NULL, 0},
916     { 29,  4, "s12",    {0}, NULL, 0},
917     { 30,  4, "s13",    {0}, NULL, 0},
918     { 31,  4, "s14",    {0}, NULL, 0},
919     { 32,  4, "s15",    {0}, NULL, 0},
920     { 33,  4, "s16",    {0}, NULL, 0},
921     { 34,  4, "s17",    {0}, NULL, 0},
922     { 35,  4, "s18",    {0}, NULL, 0},
923     { 36,  4, "s19",    {0}, NULL, 0},
924     { 37,  4, "s20",    {0}, NULL, 0},
925     { 38,  4, "s21",    {0}, NULL, 0},
926     { 39,  4, "s22",    {0}, NULL, 0},
927     { 40,  4, "s23",    {0}, NULL, 0},
928     { 41,  4, "s24",    {0}, NULL, 0},
929     { 42,  4, "s25",    {0}, NULL, 0},
930     { 43,  4, "s26",    {0}, NULL, 0},
931     { 44,  4, "s27",    {0}, NULL, 0},
932     { 45,  4, "s28",    {0}, NULL, 0},
933     { 46,  4, "s29",    {0}, NULL, 0},
934     { 47,  4, "s30",    {0}, NULL, 0},
935     { 48,  4, "s31",    {0}, NULL, 0},
936     { 49,  8, "d0",     {0}, NULL, 0},
937     { 50,  8, "d1",     {0}, NULL, 0},
938     { 51,  8, "d2",     {0}, NULL, 0},
939     { 52,  8, "d3",     {0}, NULL, 0},
940     { 53,  8, "d4",     {0}, NULL, 0},
941     { 54,  8, "d5",     {0}, NULL, 0},
942     { 55,  8, "d6",     {0}, NULL, 0},
943     { 56,  8, "d7",     {0}, NULL, 0},
944     { 57,  8, "d8",     {0}, NULL, 0},
945     { 58,  8, "d9",     {0}, NULL, 0},
946     { 59,  8, "d10",    {0}, NULL, 0},
947     { 60,  8, "d11",    {0}, NULL, 0},
948     { 61,  8, "d12",    {0}, NULL, 0},
949     { 62,  8, "d13",    {0}, NULL, 0},
950     { 63,  8, "d14",    {0}, NULL, 0},
951     { 64,  8, "d15",    {0}, NULL, 0},
952     { 65,  8, "d16",    {0}, NULL, 0},
953     { 66,  8, "d17",    {0}, NULL, 0},
954     { 67,  8, "d18",    {0}, NULL, 0},
955     { 68,  8, "d19",    {0}, NULL, 0},
956     { 69,  8, "d20",    {0}, NULL, 0},
957     { 70,  8, "d21",    {0}, NULL, 0},
958     { 71,  8, "d22",    {0}, NULL, 0},
959     { 72,  8, "d23",    {0}, NULL, 0},
960     { 73,  8, "d24",    {0}, NULL, 0},
961     { 74,  8, "d25",    {0}, NULL, 0},
962     { 75,  8, "d26",    {0}, NULL, 0},
963     { 76,  8, "d27",    {0}, NULL, 0},
964     { 77,  8, "d28",    {0}, NULL, 0},
965     { 78,  8, "d29",    {0}, NULL, 0},
966     { 79,  8, "d30",    {0}, NULL, 0},
967     { 80,  8, "d31",    {0}, NULL, 0},
968     { 81, 16, "q0",     {0}, NULL, 0},
969     { 82, 16, "q1",     {0}, NULL, 0},
970     { 83, 16, "q2",     {0}, NULL, 0},
971     { 84, 16, "q3",     {0}, NULL, 0},
972     { 85, 16, "q4",     {0}, NULL, 0},
973     { 86, 16, "q5",     {0}, NULL, 0},
974     { 87, 16, "q6",     {0}, NULL, 0},
975     { 88, 16, "q7",     {0}, NULL, 0},
976     { 89, 16, "q8",     {0}, NULL, 0},
977     { 90, 16, "q9",     {0}, NULL, 0},
978     { 91, 16, "q10",    {0}, NULL, 0},
979     { 92, 16, "q11",    {0}, NULL, 0},
980     { 93, 16, "q12",    {0}, NULL, 0},
981     { 94, 16, "q13",    {0}, NULL, 0},
982     { 95, 16, "q14",    {0}, NULL, 0},
983     { 96, 16, "q15",    {0}, NULL, 0},
984     { 97,  4, "fpscr",  {0}, NULL, 0}
985 };
986 
987 register_map_entry_t
988 g_gdb_register_map_i386[] =
989 {
990     {  0,   4, "eax"    , {0}, NULL, 0 },
991     {  1,   4, "ecx"    , {0}, NULL, 0 },
992     {  2,   4, "edx"    , {0}, NULL, 0 },
993     {  3,   4, "ebx"    , {0}, NULL, 0 },
994     {  4,   4, "esp"    , {0}, NULL, 1 },
995     {  5,   4, "ebp"    , {0}, NULL, 1 },
996     {  6,   4, "esi"    , {0}, NULL, 0 },
997     {  7,   4, "edi"    , {0}, NULL, 0 },
998     {  8,   4, "eip"    , {0}, NULL, 1 },
999     {  9,   4, "eflags" , {0}, NULL, 0 },
1000     { 10,   4, "cs"     , {0}, NULL, 0 },
1001     { 11,   4, "ss"     , {0}, NULL, 0 },
1002     { 12,   4, "ds"     , {0}, NULL, 0 },
1003     { 13,   4, "es"     , {0}, NULL, 0 },
1004     { 14,   4, "fs"     , {0}, NULL, 0 },
1005     { 15,   4, "gs"     , {0}, NULL, 0 },
1006     { 16,  10, "stmm0"  , {0}, NULL, 0 },
1007     { 17,  10, "stmm1"  , {0}, NULL, 0 },
1008     { 18,  10, "stmm2"  , {0}, NULL, 0 },
1009     { 19,  10, "stmm3"  , {0}, NULL, 0 },
1010     { 20,  10, "stmm4"  , {0}, NULL, 0 },
1011     { 21,  10, "stmm5"  , {0}, NULL, 0 },
1012     { 22,  10, "stmm6"  , {0}, NULL, 0 },
1013     { 23,  10, "stmm7"  , {0}, NULL, 0 },
1014     { 24,   4, "fctrl"  , {0}, NULL, 0 },
1015     { 25,   4, "fstat"  , {0}, NULL, 0 },
1016     { 26,   4, "ftag"   , {0}, NULL, 0 },
1017     { 27,   4, "fiseg"  , {0}, NULL, 0 },
1018     { 28,   4, "fioff"  , {0}, NULL, 0 },
1019     { 29,   4, "foseg"  , {0}, NULL, 0 },
1020     { 30,   4, "fooff"  , {0}, NULL, 0 },
1021     { 31,   4, "fop"    , {0}, NULL, 0 },
1022     { 32,  16, "xmm0"   , {0}, NULL, 0 },
1023     { 33,  16, "xmm1"   , {0}, NULL, 0 },
1024     { 34,  16, "xmm2"   , {0}, NULL, 0 },
1025     { 35,  16, "xmm3"   , {0}, NULL, 0 },
1026     { 36,  16, "xmm4"   , {0}, NULL, 0 },
1027     { 37,  16, "xmm5"   , {0}, NULL, 0 },
1028     { 38,  16, "xmm6"   , {0}, NULL, 0 },
1029     { 39,  16, "xmm7"   , {0}, NULL, 0 },
1030     { 40,   4, "mxcsr"  , {0}, NULL, 0 },
1031 };
1032 
1033 register_map_entry_t
1034 g_gdb_register_map_x86_64[] =
1035 {
1036     {  0,   8, "rax"   , {0}, NULL, 0 },
1037     {  1,   8, "rbx"   , {0}, NULL, 0 },
1038     {  2,   8, "rcx"   , {0}, NULL, 0 },
1039     {  3,   8, "rdx"   , {0}, NULL, 0 },
1040     {  4,   8, "rsi"   , {0}, NULL, 0 },
1041     {  5,   8, "rdi"   , {0}, NULL, 0 },
1042     {  6,   8, "rbp"   , {0}, NULL, 1 },
1043     {  7,   8, "rsp"   , {0}, NULL, 1 },
1044     {  8,   8, "r8"    , {0}, NULL, 0 },
1045     {  9,   8, "r9"    , {0}, NULL, 0 },
1046     { 10,   8, "r10"   , {0}, NULL, 0 },
1047     { 11,   8, "r11"   , {0}, NULL, 0 },
1048     { 12,   8, "r12"   , {0}, NULL, 0 },
1049     { 13,   8, "r13"   , {0}, NULL, 0 },
1050     { 14,   8, "r14"   , {0}, NULL, 0 },
1051     { 15,   8, "r15"   , {0}, NULL, 0 },
1052     { 16,   8, "rip"   , {0}, NULL, 1 },
1053     { 17,   4, "rflags", {0}, NULL, 0 },
1054     { 18,   4, "cs"    , {0}, NULL, 0 },
1055     { 19,   4, "ss"    , {0}, NULL, 0 },
1056     { 20,   4, "ds"    , {0}, NULL, 0 },
1057     { 21,   4, "es"    , {0}, NULL, 0 },
1058     { 22,   4, "fs"    , {0}, NULL, 0 },
1059     { 23,   4, "gs"    , {0}, NULL, 0 },
1060     { 24,  10, "stmm0" , {0}, NULL, 0 },
1061     { 25,  10, "stmm1" , {0}, NULL, 0 },
1062     { 26,  10, "stmm2" , {0}, NULL, 0 },
1063     { 27,  10, "stmm3" , {0}, NULL, 0 },
1064     { 28,  10, "stmm4" , {0}, NULL, 0 },
1065     { 29,  10, "stmm5" , {0}, NULL, 0 },
1066     { 30,  10, "stmm6" , {0}, NULL, 0 },
1067     { 31,  10, "stmm7" , {0}, NULL, 0 },
1068     { 32,   4, "fctrl" , {0}, NULL, 0 },
1069     { 33,   4, "fstat" , {0}, NULL, 0 },
1070     { 34,   4, "ftag"  , {0}, NULL, 0 },
1071     { 35,   4, "fiseg" , {0}, NULL, 0 },
1072     { 36,   4, "fioff" , {0}, NULL, 0 },
1073     { 37,   4, "foseg" , {0}, NULL, 0 },
1074     { 38,   4, "fooff" , {0}, NULL, 0 },
1075     { 39,   4, "fop"   , {0}, NULL, 0 },
1076     { 40,  16, "xmm0"  , {0}, NULL, 0 },
1077     { 41,  16, "xmm1"  , {0}, NULL, 0 },
1078     { 42,  16, "xmm2"  , {0}, NULL, 0 },
1079     { 43,  16, "xmm3"  , {0}, NULL, 0 },
1080     { 44,  16, "xmm4"  , {0}, NULL, 0 },
1081     { 45,  16, "xmm5"  , {0}, NULL, 0 },
1082     { 46,  16, "xmm6"  , {0}, NULL, 0 },
1083     { 47,  16, "xmm7"  , {0}, NULL, 0 },
1084     { 48,  16, "xmm8"  , {0}, NULL, 0 },
1085     { 49,  16, "xmm9"  , {0}, NULL, 0 },
1086     { 50,  16, "xmm10" , {0}, NULL, 0 },
1087     { 51,  16, "xmm11" , {0}, NULL, 0 },
1088     { 52,  16, "xmm12" , {0}, NULL, 0 },
1089     { 53,  16, "xmm13" , {0}, NULL, 0 },
1090     { 54,  16, "xmm14" , {0}, NULL, 0 },
1091     { 55,  16, "xmm15" , {0}, NULL, 0 },
1092     { 56,   4, "mxcsr" , {0}, NULL, 0 }
1093 };
1094 
1095 
1096 void
Initialize()1097 RNBRemote::Initialize()
1098 {
1099     DNBInitialize();
1100 }
1101 
1102 
1103 bool
InitializeRegisters(bool force)1104 RNBRemote::InitializeRegisters (bool force)
1105 {
1106     pid_t pid = m_ctx.ProcessID();
1107     if (pid == INVALID_NUB_PROCESS)
1108         return false;
1109 
1110     if (m_use_native_regs)
1111     {
1112         DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface", __FUNCTION__);
1113         // Discover the registers by querying the DNB interface and letting it
1114         // state the registers that it would like to export. This allows the
1115         // registers to be discovered using multiple qRegisterInfo calls to get
1116         // all register information after the architecture for the process is
1117         // determined.
1118         if (force)
1119         {
1120             g_dynamic_register_map.clear();
1121             g_reg_entries = NULL;
1122             g_num_reg_entries = 0;
1123         }
1124 
1125         if (g_dynamic_register_map.empty())
1126         {
1127             nub_size_t num_reg_sets = 0;
1128             const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
1129 
1130             assert (num_reg_sets > 0 && reg_sets != NULL);
1131 
1132             uint32_t regnum = 0;
1133             for (nub_size_t set = 0; set < num_reg_sets; ++set)
1134             {
1135                 if (reg_sets[set].registers == NULL)
1136                     continue;
1137 
1138                 for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg)
1139                 {
1140                     register_map_entry_t reg_entry = {
1141                         regnum++,                           // register number starts at zero and goes up with no gaps
1142                         reg_sets[set].registers[reg].size,  // register size in bytes
1143                         reg_sets[set].registers[reg].name,  // register name
1144                         reg_sets[set].registers[reg],       // DNBRegisterInfo
1145                         NULL,                               // Value to print if case we fail to reg this register (if this is NULL, we will return an error)
1146                         reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM};
1147 
1148                     g_dynamic_register_map.push_back (reg_entry);
1149                 }
1150             }
1151             g_reg_entries = g_dynamic_register_map.data();
1152             g_num_reg_entries = g_dynamic_register_map.size();
1153         }
1154         return true;
1155     }
1156     else
1157     {
1158         uint32_t cpu_type = DNBProcessGetCPUType (pid);
1159         if (cpu_type == 0)
1160         {
1161             DNBLog ("Unable to get the process cpu_type, making a best guess.");
1162             cpu_type = best_guess_cpu_type ();
1163         }
1164 
1165         DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers(%s)", __FUNCTION__, m_arch.c_str());
1166 #if defined (__i386__) || defined (__x86_64__)
1167         if (cpu_type == CPU_TYPE_X86_64)
1168         {
1169             const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
1170             for (uint32_t i=0; i<num_regs; ++i)
1171             {
1172                 if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info))
1173                 {
1174                     RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]);
1175                     assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE);
1176                 }
1177             }
1178             g_reg_entries = g_gdb_register_map_x86_64;
1179             g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
1180             return true;
1181         }
1182         else if (cpu_type == CPU_TYPE_I386)
1183         {
1184             const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
1185             for (uint32_t i=0; i<num_regs; ++i)
1186             {
1187                 if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info))
1188                 {
1189                     RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]);
1190                     assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
1191                 }
1192             }
1193             g_reg_entries = g_gdb_register_map_i386;
1194             g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
1195             return true;
1196         }
1197 #elif defined (__arm__)
1198         if (cpu_type == CPU_TYPE_ARM)
1199         {
1200             const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
1201             for (uint32_t i=0; i<num_regs; ++i)
1202             {
1203                 if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info))
1204                 {
1205                     RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]);
1206                     assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
1207                 }
1208             }
1209             g_reg_entries = g_gdb_register_map_arm;
1210             g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
1211             return true;
1212         }
1213 #endif
1214     }
1215     return false;
1216 }
1217 
1218 /* The inferior has stopped executing; send a packet
1219  to gdb to let it know.  */
1220 
1221 void
NotifyThatProcessStopped(void)1222 RNBRemote::NotifyThatProcessStopped (void)
1223 {
1224     RNBRemote::HandlePacket_last_signal (NULL);
1225     return;
1226 }
1227 
1228 
1229 /* 'A arglen,argnum,arg,...'
1230  Update the inferior context CTX with the program name and arg
1231  list.
1232  The documentation for this packet is underwhelming but my best reading
1233  of this is that it is a series of (len, position #, arg)'s, one for
1234  each argument with "arg" hex encoded (two 0-9a-f chars?).
1235  Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either
1236  is sufficient to get around the "," position separator escape issue.
1237 
1238  e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is
1239 
1240  6,0,676462,4,1,2d71,10,2,612e6f7574
1241 
1242  Note that "argnum" and "arglen" are numbers in base 10.  Again, that's
1243  not documented either way but I'm assuming it's so.  */
1244 
1245 rnb_err_t
HandlePacket_A(const char * p)1246 RNBRemote::HandlePacket_A (const char *p)
1247 {
1248     if (p == NULL || *p == '\0')
1249     {
1250         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Null packet for 'A' pkt");
1251     }
1252     p++;
1253     if (p == '\0' || !isdigit (*p))
1254     {
1255         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not specified on 'A' pkt");
1256     }
1257 
1258     /* I promise I don't modify it anywhere in this function.  strtoul()'s
1259      2nd arg has to be non-const which makes it problematic to step
1260      through the string easily.  */
1261     char *buf = const_cast<char *>(p);
1262 
1263     RNBContext& ctx = Context();
1264 
1265     while (*buf != '\0')
1266     {
1267         int arglen, argnum;
1268         std::string arg;
1269         char *c;
1270 
1271         errno = 0;
1272         arglen = strtoul (buf, &c, 10);
1273         if (errno != 0 && arglen == 0)
1274         {
1275             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not a number on 'A' pkt");
1276         }
1277         if (*c != ',')
1278         {
1279             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
1280         }
1281         buf = c + 1;
1282 
1283         errno = 0;
1284         argnum = strtoul (buf, &c, 10);
1285         if (errno != 0 && argnum == 0)
1286         {
1287             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "argnum not a number on 'A' pkt");
1288         }
1289         if (*c != ',')
1290         {
1291             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
1292         }
1293         buf = c + 1;
1294 
1295         c = buf;
1296         buf = buf + arglen;
1297         while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0')
1298         {
1299             char smallbuf[3];
1300             smallbuf[0] = *c;
1301             smallbuf[1] = *(c + 1);
1302             smallbuf[2] = '\0';
1303 
1304             errno = 0;
1305             int ch = strtoul (smallbuf, NULL, 16);
1306             if (errno != 0 && ch == 0)
1307             {
1308                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'A' pkt");
1309             }
1310 
1311             arg.push_back(ch);
1312             c += 2;
1313         }
1314 
1315         ctx.PushArgument (arg.c_str());
1316         if (*buf == ',')
1317             buf++;
1318     }
1319     SendPacket ("OK");
1320 
1321     return rnb_success;
1322 }
1323 
1324 /* 'H c t'
1325  Set the thread for subsequent actions; 'c' for step/continue ops,
1326  'g' for other ops.  -1 means all threads, 0 means any thread.  */
1327 
1328 rnb_err_t
HandlePacket_H(const char * p)1329 RNBRemote::HandlePacket_H (const char *p)
1330 {
1331     p++;  // skip 'H'
1332     if (*p != 'c' && *p != 'g')
1333     {
1334         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing 'c' or 'g' type in H packet");
1335     }
1336 
1337     if (!m_ctx.HasValidProcessID())
1338     {
1339         // We allow gdb to connect to a server that hasn't started running
1340         // the target yet.  gdb still wants to ask questions about it and
1341         // freaks out if it gets an error.  So just return OK here.
1342     }
1343 
1344     errno = 0;
1345     nub_thread_t tid = strtoul (p + 1, NULL, 16);
1346     if (errno != 0 && tid == 0)
1347     {
1348         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in H packet");
1349     }
1350     if (*p == 'c')
1351         SetContinueThread (tid);
1352     if (*p == 'g')
1353         SetCurrentThread (tid);
1354 
1355     return SendPacket ("OK");
1356 }
1357 
1358 
1359 rnb_err_t
HandlePacket_qLaunchSuccess(const char * p)1360 RNBRemote::HandlePacket_qLaunchSuccess (const char *p)
1361 {
1362     if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0)
1363         return SendPacket("OK");
1364     std::ostringstream ret_str;
1365     std::string status_str;
1366     ret_str << "E" << m_ctx.LaunchStatusAsString(status_str);
1367 
1368     return SendPacket (ret_str.str());
1369 }
1370 
1371 rnb_err_t
HandlePacket_qShlibInfoAddr(const char * p)1372 RNBRemote::HandlePacket_qShlibInfoAddr (const char *p)
1373 {
1374     if (m_ctx.HasValidProcessID())
1375     {
1376         nub_addr_t shlib_info_addr = DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID());
1377         if (shlib_info_addr != INVALID_NUB_ADDRESS)
1378         {
1379             std::ostringstream ostrm;
1380             ostrm << RAW_HEXBASE << shlib_info_addr;
1381             return SendPacket (ostrm.str ());
1382         }
1383     }
1384     return SendPacket ("E44");
1385 }
1386 
1387 rnb_err_t
HandlePacket_qStepPacketSupported(const char * p)1388 RNBRemote::HandlePacket_qStepPacketSupported (const char *p)
1389 {
1390     // Normally the "s" packet is mandatory, yet in gdb when using ARM, they
1391     // get around the need for this packet by implementing software single
1392     // stepping from gdb. Current versions of debugserver do support the "s"
1393     // packet, yet some older versions do not. We need a way to tell if this
1394     // packet is supported so we can disable software single stepping in gdb
1395     // for remote targets (so the "s" packet will get used).
1396     return SendPacket("OK");
1397 }
1398 
1399 rnb_err_t
HandlePacket_qSyncThreadStateSupported(const char * p)1400 RNBRemote::HandlePacket_qSyncThreadStateSupported (const char *p)
1401 {
1402     // We support attachOrWait meaning attach if the process exists, otherwise wait to attach.
1403     return SendPacket("OK");
1404 }
1405 
1406 rnb_err_t
HandlePacket_qVAttachOrWaitSupported(const char * p)1407 RNBRemote::HandlePacket_qVAttachOrWaitSupported (const char *p)
1408 {
1409     // We support attachOrWait meaning attach if the process exists, otherwise wait to attach.
1410     return SendPacket("OK");
1411 }
1412 
1413 rnb_err_t
HandlePacket_qThreadStopInfo(const char * p)1414 RNBRemote::HandlePacket_qThreadStopInfo (const char *p)
1415 {
1416     p += strlen ("qThreadStopInfo");
1417     nub_thread_t tid = strtoul(p, 0, 16);
1418     return SendStopReplyPacketForThread (tid);
1419 }
1420 
1421 rnb_err_t
HandlePacket_qThreadInfo(const char * p)1422 RNBRemote::HandlePacket_qThreadInfo (const char *p)
1423 {
1424     // We allow gdb to connect to a server that hasn't started running
1425     // the target yet.  gdb still wants to ask questions about it and
1426     // freaks out if it gets an error.  So just return OK here.
1427     nub_process_t pid = m_ctx.ProcessID();
1428     if (pid == INVALID_NUB_PROCESS)
1429         return SendPacket ("OK");
1430 
1431     // Only "qfThreadInfo" and "qsThreadInfo" get into this function so
1432     // we only need to check the second byte to tell which is which
1433     if (p[1] == 'f')
1434     {
1435         nub_size_t numthreads = DNBProcessGetNumThreads (pid);
1436         std::ostringstream ostrm;
1437         ostrm << "m";
1438         bool first = true;
1439         for (nub_size_t i = 0; i < numthreads; ++i)
1440         {
1441             if (first)
1442                 first = false;
1443             else
1444                 ostrm << ",";
1445             nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
1446             ostrm << std::hex << th;
1447         }
1448         return SendPacket (ostrm.str ());
1449     }
1450     else
1451     {
1452         return SendPacket ("l");
1453     }
1454 }
1455 
1456 rnb_err_t
HandlePacket_qThreadExtraInfo(const char * p)1457 RNBRemote::HandlePacket_qThreadExtraInfo (const char *p)
1458 {
1459     // We allow gdb to connect to a server that hasn't started running
1460     // the target yet.  gdb still wants to ask questions about it and
1461     // freaks out if it gets an error.  So just return OK here.
1462     nub_process_t pid = m_ctx.ProcessID();
1463     if (pid == INVALID_NUB_PROCESS)
1464         return SendPacket ("OK");
1465 
1466     /* This is supposed to return a string like 'Runnable' or
1467      'Blocked on Mutex'.
1468      The returned string is formatted like the "A" packet - a
1469      sequence of letters encoded in as 2-hex-chars-per-letter.  */
1470     p += strlen ("qThreadExtraInfo");
1471     if (*p++ != ',')
1472         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Illformed qThreadExtraInfo packet");
1473     errno = 0;
1474     nub_thread_t tid = strtoul (p, NULL, 16);
1475     if (errno != 0 && tid == 0)
1476     {
1477         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in qThreadExtraInfo packet");
1478     }
1479 
1480     const char * threadInfo = DNBThreadGetInfo(pid, tid);
1481     if (threadInfo != NULL && threadInfo[0])
1482     {
1483         return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL);
1484     }
1485     else
1486     {
1487         // "OK" == 4f6b
1488         // Return "OK" as a ASCII hex byte stream if things go wrong
1489         return SendPacket ("4f6b");
1490     }
1491 
1492     return SendPacket ("");
1493 }
1494 
1495 
1496 const char *k_space_delimiters = " \t";
1497 static void
skip_spaces(std::string & line)1498 skip_spaces (std::string &line)
1499 {
1500     if (!line.empty())
1501     {
1502         size_t space_pos = line.find_first_not_of (k_space_delimiters);
1503         if (space_pos > 0)
1504             line.erase(0, space_pos);
1505     }
1506 }
1507 
1508 static std::string
get_identifier(std::string & line)1509 get_identifier (std::string &line)
1510 {
1511     std::string word;
1512     skip_spaces (line);
1513     const size_t line_size = line.size();
1514     size_t end_pos;
1515     for (end_pos = 0; end_pos < line_size; ++end_pos)
1516     {
1517         if (end_pos == 0)
1518         {
1519             if (isalpha(line[end_pos]) || line[end_pos] == '_')
1520                 continue;
1521         }
1522         else if (isalnum(line[end_pos]) || line[end_pos] == '_')
1523             continue;
1524         break;
1525     }
1526     word.assign (line, 0, end_pos);
1527     line.erase(0, end_pos);
1528     return word;
1529 }
1530 
1531 static std::string
get_operator(std::string & line)1532 get_operator (std::string &line)
1533 {
1534     std::string op;
1535     skip_spaces (line);
1536     if (!line.empty())
1537     {
1538         if (line[0] == '=')
1539         {
1540             op = '=';
1541             line.erase(0,1);
1542         }
1543     }
1544     return op;
1545 }
1546 
1547 static std::string
get_value(std::string & line)1548 get_value (std::string &line)
1549 {
1550     std::string value;
1551     skip_spaces (line);
1552     if (!line.empty())
1553     {
1554         value.swap(line);
1555     }
1556     return value;
1557 }
1558 
1559 extern void FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
1560 extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
1561 
1562 rnb_err_t
HandlePacket_qRcmd(const char * p)1563 RNBRemote::HandlePacket_qRcmd (const char *p)
1564 {
1565     const char *c = p + strlen("qRcmd,");
1566     std::string line;
1567     while (c[0] && c[1])
1568     {
1569         char smallbuf[3] = { c[0], c[1], '\0' };
1570         errno = 0;
1571         int ch = strtoul (smallbuf, NULL, 16);
1572         if (errno != 0 && ch == 0)
1573             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in payload of qRcmd packet");
1574         line.push_back(ch);
1575         c += 2;
1576     }
1577     if (*c == '\0')
1578     {
1579         std::string command = get_identifier(line);
1580         if (command.compare("set") == 0)
1581         {
1582             std::string variable = get_identifier (line);
1583             std::string op = get_operator (line);
1584             std::string value = get_value (line);
1585             if (variable.compare("logfile") == 0)
1586             {
1587                 FILE *log_file = fopen(value.c_str(), "w");
1588                 if (log_file)
1589                 {
1590                     DNBLogSetLogCallback(FileLogCallback, log_file);
1591                     return SendPacket ("OK");
1592                 }
1593                 return SendPacket ("E71");
1594             }
1595             else if (variable.compare("logmask") == 0)
1596             {
1597                 char *end;
1598                 errno = 0;
1599                 uint32_t logmask = strtoul (value.c_str(), &end, 0);
1600                 if (errno == 0 && end && *end == '\0')
1601                 {
1602                     DNBLogSetLogMask (logmask);
1603                     if (!DNBLogGetLogCallback())
1604                         DNBLogSetLogCallback(ASLLogCallback, NULL);
1605                     return SendPacket ("OK");
1606                 }
1607                 errno = 0;
1608                 logmask = strtoul (value.c_str(), &end, 16);
1609                 if (errno == 0 && end && *end == '\0')
1610                 {
1611                     DNBLogSetLogMask (logmask);
1612                     return SendPacket ("OK");
1613                 }
1614                 return SendPacket ("E72");
1615             }
1616             return SendPacket ("E70");
1617         }
1618         return SendPacket ("E69");
1619     }
1620     return SendPacket ("E73");
1621 }
1622 
1623 rnb_err_t
HandlePacket_qC(const char * p)1624 RNBRemote::HandlePacket_qC (const char *p)
1625 {
1626     nub_process_t pid;
1627     std::ostringstream rep;
1628     // If we haven't run the process yet, we tell the debugger the
1629     // pid is 0.  That way it can know to tell use to run later on.
1630     if (m_ctx.HasValidProcessID())
1631         pid = m_ctx.ProcessID();
1632     else
1633         pid = 0;
1634     rep << "QC" << std::hex << pid;
1635     return SendPacket (rep.str());
1636 }
1637 
1638 rnb_err_t
HandlePacket_qGetPid(const char * p)1639 RNBRemote::HandlePacket_qGetPid (const char *p)
1640 {
1641     nub_process_t pid;
1642     std::ostringstream rep;
1643     // If we haven't run the process yet, we tell the debugger the
1644     // pid is 0.  That way it can know to tell use to run later on.
1645     if (m_ctx.HasValidProcessID())
1646         pid = m_ctx.ProcessID();
1647     else
1648         pid = 0;
1649     rep << std::hex << pid;
1650     return SendPacket (rep.str());
1651 }
1652 
1653 rnb_err_t
HandlePacket_qRegisterInfo(const char * p)1654 RNBRemote::HandlePacket_qRegisterInfo (const char *p)
1655 {
1656     if (g_num_reg_entries == 0)
1657         InitializeRegisters ();
1658 
1659     p += strlen ("qRegisterInfo");
1660 
1661     nub_size_t num_reg_sets = 0;
1662     const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1663     uint32_t reg_num = strtoul(p, 0, 16);
1664 
1665     if (reg_num < g_num_reg_entries)
1666     {
1667         const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
1668         std::ostringstream ostrm;
1669         ostrm << "name:" << reg_entry->gdb_name << ';';
1670 
1671         if (reg_entry->nub_info.name && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.name))
1672             ostrm << "alt-name:" << reg_entry->nub_info.name << ';';
1673         else if (reg_entry->nub_info.alt && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.alt))
1674             ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
1675 
1676         ostrm << "bitsize:" << std::dec << reg_entry->gdb_size * 8 << ';';
1677         ostrm << "offset:" << std::dec << reg_entry->nub_info.offset << ';';
1678 
1679         switch (reg_entry->nub_info.type)
1680         {
1681             case Uint:      ostrm << "encoding:uint;"; break;
1682             case Sint:      ostrm << "encoding:sint;"; break;
1683             case IEEE754:   ostrm << "encoding:ieee754;"; break;
1684             case Vector:    ostrm << "encoding:vector;"; break;
1685         }
1686 
1687         switch (reg_entry->nub_info.format)
1688         {
1689             case Binary:            ostrm << "format:binary;"; break;
1690             case Decimal:           ostrm << "format:decimal;"; break;
1691             case Hex:               ostrm << "format:hex;"; break;
1692             case Float:             ostrm << "format:float;"; break;
1693             case VectorOfSInt8:     ostrm << "format:vector-sint8;"; break;
1694             case VectorOfUInt8:     ostrm << "format:vector-uint8;"; break;
1695             case VectorOfSInt16:    ostrm << "format:vector-sint16;"; break;
1696             case VectorOfUInt16:    ostrm << "format:vector-uint16;"; break;
1697             case VectorOfSInt32:    ostrm << "format:vector-sint32;"; break;
1698             case VectorOfUInt32:    ostrm << "format:vector-uint32;"; break;
1699             case VectorOfFloat32:   ostrm << "format:vector-float32;"; break;
1700             case VectorOfUInt128:   ostrm << "format:vector-uint128;"; break;
1701         };
1702 
1703         if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
1704             ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
1705 
1706 
1707         if (g_reg_entries != g_dynamic_register_map.data())
1708         {
1709             if (reg_entry->nub_info.reg_gdb != INVALID_NUB_REGNUM && reg_entry->nub_info.reg_gdb != reg_num)
1710             {
1711                 printf("register %s is getting gdb reg_num of %u when the register info says %u\n",
1712                        reg_entry->gdb_name, reg_num, reg_entry->nub_info.reg_gdb);
1713             }
1714         }
1715 
1716         if (reg_entry->nub_info.reg_gcc != INVALID_NUB_REGNUM)
1717             ostrm << "gcc:" << std::dec << reg_entry->nub_info.reg_gcc << ';';
1718 
1719         if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
1720             ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
1721 
1722 
1723         switch (reg_entry->nub_info.reg_generic)
1724         {
1725             case GENERIC_REGNUM_FP:     ostrm << "generic:fp;"; break;
1726             case GENERIC_REGNUM_PC:     ostrm << "generic:pc;"; break;
1727             case GENERIC_REGNUM_SP:     ostrm << "generic:sp;"; break;
1728             case GENERIC_REGNUM_RA:     ostrm << "generic:ra;"; break;
1729             case GENERIC_REGNUM_FLAGS:  ostrm << "generic:flags;"; break;
1730             case GENERIC_REGNUM_ARG1:   ostrm << "generic:arg1;"; break;
1731             case GENERIC_REGNUM_ARG2:   ostrm << "generic:arg2;"; break;
1732             case GENERIC_REGNUM_ARG3:   ostrm << "generic:arg3;"; break;
1733             case GENERIC_REGNUM_ARG4:   ostrm << "generic:arg4;"; break;
1734             case GENERIC_REGNUM_ARG5:   ostrm << "generic:arg5;"; break;
1735             case GENERIC_REGNUM_ARG6:   ostrm << "generic:arg6;"; break;
1736             case GENERIC_REGNUM_ARG7:   ostrm << "generic:arg7;"; break;
1737             case GENERIC_REGNUM_ARG8:   ostrm << "generic:arg8;"; break;
1738             default: break;
1739         }
1740 
1741         if (reg_entry->nub_info.pseudo_regs && reg_entry->nub_info.pseudo_regs[0] != INVALID_NUB_REGNUM)
1742         {
1743             ostrm << "container-regs:";
1744             for (unsigned i=0; reg_entry->nub_info.pseudo_regs[i] != INVALID_NUB_REGNUM; ++i)
1745             {
1746                 if (i > 0)
1747                     ostrm << ',';
1748                 ostrm << RAW_HEXBASE << reg_entry->nub_info.pseudo_regs[i];
1749             }
1750             ostrm << ';';
1751         }
1752 
1753         if (reg_entry->nub_info.update_regs && reg_entry->nub_info.update_regs[0] != INVALID_NUB_REGNUM)
1754         {
1755             ostrm << "invalidate-regs:";
1756             for (unsigned i=0; reg_entry->nub_info.update_regs[i] != INVALID_NUB_REGNUM; ++i)
1757             {
1758                 if (i > 0)
1759                     ostrm << ',';
1760                 ostrm << RAW_HEXBASE << reg_entry->nub_info.update_regs[i];
1761             }
1762             ostrm << ';';
1763         }
1764 
1765         return SendPacket (ostrm.str ());
1766     }
1767     return SendPacket ("E45");
1768 }
1769 
1770 
1771 /* This expects a packet formatted like
1772 
1773  QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
1774 
1775  with the "QSetLogging:" already removed from the start.  Maybe in the
1776  future this packet will include other keyvalue pairs like
1777 
1778  QSetLogging:bitmask=LOG_ALL;mode=asl;
1779  */
1780 
1781 rnb_err_t
set_logging(const char * p)1782 set_logging (const char *p)
1783 {
1784     int bitmask = 0;
1785     while (p && *p != '\0')
1786     {
1787         if (strncmp (p, "bitmask=", sizeof ("bitmask=") - 1) == 0)
1788         {
1789             p += sizeof ("bitmask=") - 1;
1790             while (p && *p != '\0' && *p != ';')
1791             {
1792                 if (*p == '|')
1793                     p++;
1794 
1795 // to regenerate the LOG_ entries (not including the LOG_RNB entries)
1796 // $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v 'LOG_HI|LOG_LO' | awk '{print $2}'`
1797 // do
1798 //   echo "                else if (strncmp (p, \"$logname\", sizeof (\"$logname\") - 1) == 0)"
1799 //   echo "                {"
1800 //   echo "                    p += sizeof (\"$logname\") - 1;"
1801 //   echo "                    bitmask |= $logname;"
1802 //   echo "                }"
1803 // done
1804                 if (strncmp (p, "LOG_VERBOSE", sizeof ("LOG_VERBOSE") - 1) == 0)
1805                 {
1806                     p += sizeof ("LOG_VERBOSE") - 1;
1807                     bitmask |= LOG_VERBOSE;
1808                 }
1809                 else if (strncmp (p, "LOG_PROCESS", sizeof ("LOG_PROCESS") - 1) == 0)
1810                 {
1811                     p += sizeof ("LOG_PROCESS") - 1;
1812                     bitmask |= LOG_PROCESS;
1813                 }
1814                 else if (strncmp (p, "LOG_THREAD", sizeof ("LOG_THREAD") - 1) == 0)
1815                 {
1816                     p += sizeof ("LOG_THREAD") - 1;
1817                     bitmask |= LOG_THREAD;
1818                 }
1819                 else if (strncmp (p, "LOG_EXCEPTIONS", sizeof ("LOG_EXCEPTIONS") - 1) == 0)
1820                 {
1821                     p += sizeof ("LOG_EXCEPTIONS") - 1;
1822                     bitmask |= LOG_EXCEPTIONS;
1823                 }
1824                 else if (strncmp (p, "LOG_SHLIB", sizeof ("LOG_SHLIB") - 1) == 0)
1825                 {
1826                     p += sizeof ("LOG_SHLIB") - 1;
1827                     bitmask |= LOG_SHLIB;
1828                 }
1829                 else if (strncmp (p, "LOG_MEMORY", sizeof ("LOG_MEMORY") - 1) == 0)
1830                 {
1831                     p += sizeof ("LOG_MEMORY") - 1;
1832                     bitmask |= LOG_MEMORY;
1833                 }
1834                 else if (strncmp (p, "LOG_MEMORY_DATA_SHORT", sizeof ("LOG_MEMORY_DATA_SHORT") - 1) == 0)
1835                 {
1836                     p += sizeof ("LOG_MEMORY_DATA_SHORT") - 1;
1837                     bitmask |= LOG_MEMORY_DATA_SHORT;
1838                 }
1839                 else if (strncmp (p, "LOG_MEMORY_DATA_LONG", sizeof ("LOG_MEMORY_DATA_LONG") - 1) == 0)
1840                 {
1841                     p += sizeof ("LOG_MEMORY_DATA_LONG") - 1;
1842                     bitmask |= LOG_MEMORY_DATA_LONG;
1843                 }
1844                 else if (strncmp (p, "LOG_MEMORY_PROTECTIONS", sizeof ("LOG_MEMORY_PROTECTIONS") - 1) == 0)
1845                 {
1846                     p += sizeof ("LOG_MEMORY_PROTECTIONS") - 1;
1847                     bitmask |= LOG_MEMORY_PROTECTIONS;
1848                 }
1849                 else if (strncmp (p, "LOG_BREAKPOINTS", sizeof ("LOG_BREAKPOINTS") - 1) == 0)
1850                 {
1851                     p += sizeof ("LOG_BREAKPOINTS") - 1;
1852                     bitmask |= LOG_BREAKPOINTS;
1853                 }
1854                 else if (strncmp (p, "LOG_EVENTS", sizeof ("LOG_EVENTS") - 1) == 0)
1855                 {
1856                     p += sizeof ("LOG_EVENTS") - 1;
1857                     bitmask |= LOG_EVENTS;
1858                 }
1859                 else if (strncmp (p, "LOG_WATCHPOINTS", sizeof ("LOG_WATCHPOINTS") - 1) == 0)
1860                 {
1861                     p += sizeof ("LOG_WATCHPOINTS") - 1;
1862                     bitmask |= LOG_WATCHPOINTS;
1863                 }
1864                 else if (strncmp (p, "LOG_STEP", sizeof ("LOG_STEP") - 1) == 0)
1865                 {
1866                     p += sizeof ("LOG_STEP") - 1;
1867                     bitmask |= LOG_STEP;
1868                 }
1869                 else if (strncmp (p, "LOG_TASK", sizeof ("LOG_TASK") - 1) == 0)
1870                 {
1871                     p += sizeof ("LOG_TASK") - 1;
1872                     bitmask |= LOG_TASK;
1873                 }
1874                 else if (strncmp (p, "LOG_ALL", sizeof ("LOG_ALL") - 1) == 0)
1875                 {
1876                     p += sizeof ("LOG_ALL") - 1;
1877                     bitmask |= LOG_ALL;
1878                 }
1879                 else if (strncmp (p, "LOG_DEFAULT", sizeof ("LOG_DEFAULT") - 1) == 0)
1880                 {
1881                     p += sizeof ("LOG_DEFAULT") - 1;
1882                     bitmask |= LOG_DEFAULT;
1883                 }
1884 // end of auto-generated entries
1885 
1886                 else if (strncmp (p, "LOG_NONE", sizeof ("LOG_NONE") - 1) == 0)
1887                 {
1888                     p += sizeof ("LOG_NONE") - 1;
1889                     bitmask = 0;
1890                 }
1891                 else if (strncmp (p, "LOG_RNB_MINIMAL", sizeof ("LOG_RNB_MINIMAL") - 1) == 0)
1892                 {
1893                     p += sizeof ("LOG_RNB_MINIMAL") - 1;
1894                     bitmask |= LOG_RNB_MINIMAL;
1895                 }
1896                 else if (strncmp (p, "LOG_RNB_MEDIUM", sizeof ("LOG_RNB_MEDIUM") - 1) == 0)
1897                 {
1898                     p += sizeof ("LOG_RNB_MEDIUM") - 1;
1899                     bitmask |= LOG_RNB_MEDIUM;
1900                 }
1901                 else if (strncmp (p, "LOG_RNB_MAX", sizeof ("LOG_RNB_MAX") - 1) == 0)
1902                 {
1903                     p += sizeof ("LOG_RNB_MAX") - 1;
1904                     bitmask |= LOG_RNB_MAX;
1905                 }
1906                 else if (strncmp (p, "LOG_RNB_COMM", sizeof ("LOG_RNB_COMM") - 1) == 0)
1907                 {
1908                     p += sizeof ("LOG_RNB_COMM") - 1;
1909                     bitmask |= LOG_RNB_COMM;
1910                 }
1911                 else if (strncmp (p, "LOG_RNB_REMOTE", sizeof ("LOG_RNB_REMOTE") - 1) == 0)
1912                 {
1913                     p += sizeof ("LOG_RNB_REMOTE") - 1;
1914                     bitmask |= LOG_RNB_REMOTE;
1915                 }
1916                 else if (strncmp (p, "LOG_RNB_EVENTS", sizeof ("LOG_RNB_EVENTS") - 1) == 0)
1917                 {
1918                     p += sizeof ("LOG_RNB_EVENTS") - 1;
1919                     bitmask |= LOG_RNB_EVENTS;
1920                 }
1921                 else if (strncmp (p, "LOG_RNB_PROC", sizeof ("LOG_RNB_PROC") - 1) == 0)
1922                 {
1923                     p += sizeof ("LOG_RNB_PROC") - 1;
1924                     bitmask |= LOG_RNB_PROC;
1925                 }
1926                 else if (strncmp (p, "LOG_RNB_PACKETS", sizeof ("LOG_RNB_PACKETS") - 1) == 0)
1927                 {
1928                     p += sizeof ("LOG_RNB_PACKETS") - 1;
1929                     bitmask |= LOG_RNB_PACKETS;
1930                 }
1931                 else if (strncmp (p, "LOG_RNB_ALL", sizeof ("LOG_RNB_ALL") - 1) == 0)
1932                 {
1933                     p += sizeof ("LOG_RNB_ALL") - 1;
1934                     bitmask |= LOG_RNB_ALL;
1935                 }
1936                 else if (strncmp (p, "LOG_RNB_DEFAULT", sizeof ("LOG_RNB_DEFAULT") - 1) == 0)
1937                 {
1938                     p += sizeof ("LOG_RNB_DEFAULT") - 1;
1939                     bitmask |= LOG_RNB_DEFAULT;
1940                 }
1941                 else if (strncmp (p, "LOG_RNB_NONE", sizeof ("LOG_RNB_NONE") - 1) == 0)
1942                 {
1943                     p += sizeof ("LOG_RNB_NONE") - 1;
1944                     bitmask = 0;
1945                 }
1946                 else
1947                 {
1948                     /* Unrecognized logging bit; ignore it.  */
1949                     const char *c = strchr (p, '|');
1950                     if (c)
1951                     {
1952                         p = c;
1953                     }
1954                     else
1955                     {
1956                         c = strchr (p, ';');
1957                         if (c)
1958                         {
1959                             p = c;
1960                         }
1961                         else
1962                         {
1963                             // Improperly terminated word; just go to end of str
1964                             p = strchr (p, '\0');
1965                         }
1966                     }
1967                 }
1968             }
1969             // Did we get a properly formatted logging bitmask?
1970             if (p && *p == ';')
1971             {
1972                 // Enable DNB logging
1973                 DNBLogSetLogCallback(ASLLogCallback, NULL);
1974                 DNBLogSetLogMask (bitmask);
1975                 p++;
1976             }
1977         }
1978         // We're not going to support logging to a file for now.  All logging
1979         // goes through ASL.
1980 #if 0
1981         else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
1982         {
1983             p += sizeof ("mode=") - 1;
1984             if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
1985             {
1986                 DNBLogToASL ();
1987                 p += sizeof ("asl;") - 1;
1988             }
1989             else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
1990             {
1991                 DNBLogToFile ();
1992                 p += sizeof ("file;") - 1;
1993             }
1994             else
1995             {
1996                 // Ignore unknown argument
1997                 const char *c = strchr (p, ';');
1998                 if (c)
1999                     p = c + 1;
2000                 else
2001                     p = strchr (p, '\0');
2002             }
2003         }
2004         else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
2005         {
2006             p += sizeof ("filename=") - 1;
2007             const char *c = strchr (p, ';');
2008             if (c == NULL)
2009             {
2010                 c = strchr (p, '\0');
2011                 continue;
2012             }
2013             char *fn = (char *) alloca (c - p + 1);
2014             strncpy (fn, p, c - p);
2015             fn[c - p] = '\0';
2016 
2017             // A file name of "asl" is special and is another way to indicate
2018             // that logging should be done via ASL, not by file.
2019             if (strcmp (fn, "asl") == 0)
2020             {
2021                 DNBLogToASL ();
2022             }
2023             else
2024             {
2025                 FILE *f = fopen (fn, "w");
2026                 if (f)
2027                 {
2028                     DNBLogSetLogFile (f);
2029                     DNBEnableLogging (f, DNBLogGetLogMask ());
2030                     DNBLogToFile ();
2031                 }
2032             }
2033             p = c + 1;
2034         }
2035 #endif /* #if 0 to enforce ASL logging only.  */
2036         else
2037         {
2038             // Ignore unknown argument
2039             const char *c = strchr (p, ';');
2040             if (c)
2041                 p = c + 1;
2042             else
2043                 p = strchr (p, '\0');
2044         }
2045     }
2046 
2047     return rnb_success;
2048 }
2049 
2050 rnb_err_t
HandlePacket_QThreadSuffixSupported(const char * p)2051 RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p)
2052 {
2053     m_thread_suffix_supported = true;
2054     return SendPacket ("OK");
2055 }
2056 
2057 rnb_err_t
HandlePacket_QStartNoAckMode(const char * p)2058 RNBRemote::HandlePacket_QStartNoAckMode (const char *p)
2059 {
2060     // Send the OK packet first so the correct checksum is appended...
2061     rnb_err_t result = SendPacket ("OK");
2062     m_noack_mode = true;
2063     return result;
2064 }
2065 
2066 
2067 rnb_err_t
HandlePacket_QSetLogging(const char * p)2068 RNBRemote::HandlePacket_QSetLogging (const char *p)
2069 {
2070     p += sizeof ("QSetLogging:") - 1;
2071     rnb_err_t result = set_logging (p);
2072     if (result == rnb_success)
2073         return SendPacket ("OK");
2074     else
2075         return SendPacket ("E35");
2076 }
2077 
2078 rnb_err_t
HandlePacket_QSetDisableASLR(const char * p)2079 RNBRemote::HandlePacket_QSetDisableASLR (const char *p)
2080 {
2081     extern int g_disable_aslr;
2082     p += sizeof ("QSetDisableASLR:") - 1;
2083     switch (*p)
2084     {
2085     case '0': g_disable_aslr = 0; break;
2086     case '1': g_disable_aslr = 1; break;
2087     default:
2088         return SendPacket ("E56");
2089     }
2090     return SendPacket ("OK");
2091 }
2092 
2093 rnb_err_t
HandlePacket_QSetSTDIO(const char * p)2094 RNBRemote::HandlePacket_QSetSTDIO (const char *p)
2095 {
2096     // Only set stdin/out/err if we don't already have a process
2097     if (!m_ctx.HasValidProcessID())
2098     {
2099         bool success = false;
2100         // Check the seventh character since the packet will be one of:
2101         // QSetSTDIN
2102         // QSetSTDOUT
2103         // QSetSTDERR
2104         StringExtractor packet(p);
2105         packet.SetFilePos (7);
2106         char ch = packet.GetChar();
2107         while (packet.GetChar() != ':')
2108             /* Do nothing. */;
2109 
2110         switch (ch)
2111         {
2112             case 'I': // STDIN
2113                 packet.GetHexByteString (m_ctx.GetSTDIN());
2114                 success = !m_ctx.GetSTDIN().empty();
2115                 break;
2116 
2117             case 'O': // STDOUT
2118                 packet.GetHexByteString (m_ctx.GetSTDOUT());
2119                 success = !m_ctx.GetSTDOUT().empty();
2120                 break;
2121 
2122             case 'E': // STDERR
2123                 packet.GetHexByteString (m_ctx.GetSTDERR());
2124                 success = !m_ctx.GetSTDERR().empty();
2125                 break;
2126 
2127             default:
2128                 break;
2129         }
2130         if (success)
2131             return SendPacket ("OK");
2132         return SendPacket ("E57");
2133     }
2134     return SendPacket ("E58");
2135 }
2136 
2137 rnb_err_t
HandlePacket_QSetWorkingDir(const char * p)2138 RNBRemote::HandlePacket_QSetWorkingDir (const char *p)
2139 {
2140     // Only set the working directory if we don't already have a process
2141     if (!m_ctx.HasValidProcessID())
2142     {
2143         StringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1);
2144         if (packet.GetHexByteString (m_ctx.GetWorkingDir()))
2145         {
2146             struct stat working_dir_stat;
2147             if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1)
2148             {
2149                 m_ctx.GetWorkingDir().clear();
2150                 return SendPacket ("E61");    // Working directory doesn't exist...
2151             }
2152             else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR)
2153             {
2154                 return SendPacket ("OK");
2155             }
2156             else
2157             {
2158                 m_ctx.GetWorkingDir().clear();
2159                 return SendPacket ("E62");    // Working directory isn't a directory...
2160             }
2161         }
2162         return SendPacket ("E59");  // Invalid path
2163     }
2164     return SendPacket ("E60"); // Already had a process, too late to set working dir
2165 }
2166 
2167 rnb_err_t
HandlePacket_QSyncThreadState(const char * p)2168 RNBRemote::HandlePacket_QSyncThreadState (const char *p)
2169 {
2170     if (!m_ctx.HasValidProcessID())
2171     {
2172         // We allow gdb to connect to a server that hasn't started running
2173         // the target yet.  gdb still wants to ask questions about it and
2174         // freaks out if it gets an error.  So just return OK here.
2175         return SendPacket ("OK");
2176     }
2177 
2178     errno = 0;
2179     p += strlen("QSyncThreadState:");
2180     nub_thread_t tid = strtoul (p, NULL, 16);
2181     if (errno != 0 && tid == 0)
2182     {
2183         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in QSyncThreadState packet");
2184     }
2185     if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid))
2186         return SendPacket("OK");
2187     else
2188         return SendPacket ("E61");
2189 }
2190 
2191 rnb_err_t
HandlePacket_QListThreadsInStopReply(const char * p)2192 RNBRemote::HandlePacket_QListThreadsInStopReply (const char *p)
2193 {
2194     // If this packet is received, it allows us to send an extra key/value
2195     // pair in the stop reply packets where we will list all of the thread IDs
2196     // separated by commas:
2197     //
2198     //  "threads:10a,10b,10c;"
2199     //
2200     // This will get included in the stop reply packet as something like:
2201     //
2202     //  "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;"
2203     //
2204     // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and
2205     // speed things up a bit.
2206     //
2207     // Send the OK packet first so the correct checksum is appended...
2208     rnb_err_t result = SendPacket ("OK");
2209     m_list_threads_in_stop_reply = true;
2210     return result;
2211 }
2212 
2213 
2214 rnb_err_t
HandlePacket_QSetMaxPayloadSize(const char * p)2215 RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
2216 {
2217     /* The number of characters in a packet payload that gdb is
2218      prepared to accept.  The packet-start char, packet-end char,
2219      2 checksum chars and terminating null character are not included
2220      in this size.  */
2221     p += sizeof ("QSetMaxPayloadSize:") - 1;
2222     errno = 0;
2223     uint32_t size = strtoul (p, NULL, 16);
2224     if (errno != 0 && size == 0)
2225     {
2226         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
2227     }
2228     m_max_payload_size = size;
2229     return SendPacket ("OK");
2230 }
2231 
2232 rnb_err_t
HandlePacket_QSetMaxPacketSize(const char * p)2233 RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p)
2234 {
2235     /* This tells us the largest packet that gdb can handle.
2236      i.e. the size of gdb's packet-reading buffer.
2237      QSetMaxPayloadSize is preferred because it is less ambiguous.  */
2238     p += sizeof ("QSetMaxPacketSize:") - 1;
2239     errno = 0;
2240     uint32_t size = strtoul (p, NULL, 16);
2241     if (errno != 0 && size == 0)
2242     {
2243         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPacketSize packet");
2244     }
2245     m_max_payload_size = size - 5;
2246     return SendPacket ("OK");
2247 }
2248 
2249 
2250 
2251 
2252 rnb_err_t
HandlePacket_QEnvironment(const char * p)2253 RNBRemote::HandlePacket_QEnvironment (const char *p)
2254 {
2255     /* This sets the environment for the target program.  The packet is of the form:
2256 
2257      QEnvironment:VARIABLE=VALUE
2258 
2259      */
2260 
2261     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
2262                       (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
2263 
2264     p += sizeof ("QEnvironment:") - 1;
2265     RNBContext& ctx = Context();
2266 
2267     ctx.PushEnvironment (p);
2268     return SendPacket ("OK");
2269 }
2270 
2271 rnb_err_t
HandlePacket_QEnvironmentHexEncoded(const char * p)2272 RNBRemote::HandlePacket_QEnvironmentHexEncoded (const char *p)
2273 {
2274     /* This sets the environment for the target program.  The packet is of the form:
2275 
2276         QEnvironmentHexEncoded:VARIABLE=VALUE
2277 
2278         The VARIABLE=VALUE part is sent hex-encoded so chracters like '#' with special
2279         meaning in the remote protocol won't break it.
2280     */
2281 
2282     DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"",
2283         (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
2284 
2285     p += sizeof ("QEnvironmentHexEncoded:") - 1;
2286 
2287     std::string arg;
2288     const char *c;
2289     c = p;
2290     while (*c != '\0')
2291       {
2292         if (*(c + 1) == '\0')
2293         {
2294             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2295         }
2296         char smallbuf[3];
2297         smallbuf[0] = *c;
2298         smallbuf[1] = *(c + 1);
2299         smallbuf[2] = '\0';
2300         errno = 0;
2301         int ch = strtoul (smallbuf, NULL, 16);
2302         if (errno != 0 && ch == 0)
2303           {
2304             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt");
2305           }
2306         arg.push_back(ch);
2307         c += 2;
2308       }
2309 
2310     RNBContext& ctx = Context();
2311     if (arg.length() > 0)
2312       ctx.PushEnvironment (arg.c_str());
2313 
2314     return SendPacket ("OK");
2315 }
2316 
2317 
2318 rnb_err_t
HandlePacket_QLaunchArch(const char * p)2319 RNBRemote::HandlePacket_QLaunchArch (const char *p)
2320 {
2321     p += sizeof ("QLaunchArch:") - 1;
2322     if (DNBSetArchitecture(p))
2323         return SendPacket ("OK");
2324     return SendPacket ("E63");
2325 }
2326 
2327 void
append_hex_value(std::ostream & ostrm,const uint8_t * buf,size_t buf_size,bool swap)2328 append_hex_value (std::ostream& ostrm, const uint8_t* buf, size_t buf_size, bool swap)
2329 {
2330     int i;
2331     if (swap)
2332     {
2333         for (i = buf_size-1; i >= 0; i--)
2334             ostrm << RAWHEX8(buf[i]);
2335     }
2336     else
2337     {
2338         for (i = 0; i < buf_size; i++)
2339             ostrm << RAWHEX8(buf[i]);
2340     }
2341 }
2342 
2343 
2344 void
register_value_in_hex_fixed_width(std::ostream & ostrm,nub_process_t pid,nub_thread_t tid,const register_map_entry_t * reg,const DNBRegisterValue * reg_value_ptr)2345 register_value_in_hex_fixed_width (std::ostream& ostrm,
2346                                    nub_process_t pid,
2347                                    nub_thread_t tid,
2348                                    const register_map_entry_t* reg,
2349                                    const DNBRegisterValue *reg_value_ptr)
2350 {
2351     if (reg != NULL)
2352     {
2353         DNBRegisterValue reg_value;
2354         if (reg_value_ptr == NULL)
2355         {
2356             if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, &reg_value))
2357                 reg_value_ptr = &reg_value;
2358         }
2359 
2360         if (reg_value_ptr)
2361         {
2362             append_hex_value (ostrm, reg_value_ptr->value.v_uint8, reg->gdb_size, false);
2363         }
2364         else
2365         {
2366             // If we fail to read a regiser value, check if it has a default
2367             // fail value. If it does, return this instead in case some of
2368             // the registers are not available on the current system.
2369             if (reg->gdb_size > 0)
2370             {
2371                 if (reg->fail_value != NULL)
2372                 {
2373                     append_hex_value (ostrm, reg->fail_value, reg->gdb_size, false);
2374                 }
2375                 else
2376                 {
2377                     std::basic_string<uint8_t> zeros(reg->gdb_size, '\0');
2378                     append_hex_value (ostrm, zeros.data(), zeros.size(), false);
2379                 }
2380             }
2381         }
2382     }
2383 }
2384 
2385 
2386 void
gdb_regnum_with_fixed_width_hex_register_value(std::ostream & ostrm,nub_process_t pid,nub_thread_t tid,const register_map_entry_t * reg,const DNBRegisterValue * reg_value_ptr)2387 gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm,
2388                                                 nub_process_t pid,
2389                                                 nub_thread_t tid,
2390                                                 const register_map_entry_t* reg,
2391                                                 const DNBRegisterValue *reg_value_ptr)
2392 {
2393     // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
2394     // gdb register number, and VVVVVVVV is the correct number of hex bytes
2395     // as ASCII for the register value.
2396     if (reg != NULL)
2397     {
2398         ostrm << RAWHEX8(reg->gdb_regnum) << ':';
2399         register_value_in_hex_fixed_width (ostrm, pid, tid, reg, reg_value_ptr);
2400         ostrm << ';';
2401     }
2402 }
2403 
2404 rnb_err_t
SendStopReplyPacketForThread(nub_thread_t tid)2405 RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
2406 {
2407     const nub_process_t pid = m_ctx.ProcessID();
2408     if (pid == INVALID_NUB_PROCESS)
2409         return SendPacket("E50");
2410 
2411     struct DNBThreadStopInfo tid_stop_info;
2412 
2413     /* Fill the remaining space in this packet with as many registers
2414      as we can stuff in there.  */
2415 
2416     if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
2417     {
2418         const bool did_exec = tid_stop_info.reason == eStopTypeExec;
2419         if (did_exec)
2420             RNBRemote::InitializeRegisters(true);
2421 
2422         std::ostringstream ostrm;
2423         // Output the T packet with the thread
2424         ostrm << 'T';
2425         int signum = tid_stop_info.details.signal.signo;
2426         DNBLogThreadedIf (LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, signum, tid_stop_info.details.exception.type);
2427 
2428         // Translate any mach exceptions to gdb versions, unless they are
2429         // common exceptions like a breakpoint or a soft signal.
2430         switch (tid_stop_info.details.exception.type)
2431         {
2432             default:                    signum = 0; break;
2433             case EXC_BREAKPOINT:        signum = SIGTRAP; break;
2434             case EXC_BAD_ACCESS:        signum = TARGET_EXC_BAD_ACCESS; break;
2435             case EXC_BAD_INSTRUCTION:   signum = TARGET_EXC_BAD_INSTRUCTION; break;
2436             case EXC_ARITHMETIC:        signum = TARGET_EXC_ARITHMETIC; break;
2437             case EXC_EMULATION:         signum = TARGET_EXC_EMULATION; break;
2438             case EXC_SOFTWARE:
2439                 if (tid_stop_info.details.exception.data_count == 2 &&
2440                     tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
2441                     signum = tid_stop_info.details.exception.data[1];
2442                 else
2443                     signum = TARGET_EXC_SOFTWARE;
2444                 break;
2445         }
2446 
2447         ostrm << RAWHEX8(signum & 0xff);
2448 
2449         ostrm << std::hex << "thread:" << tid << ';';
2450 
2451         const char *thread_name = DNBThreadGetName (pid, tid);
2452         if (thread_name && thread_name[0])
2453         {
2454             size_t thread_name_len = strlen(thread_name);
2455 
2456             if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
2457                 ostrm << std::hex << "name:" << thread_name << ';';
2458             else
2459             {
2460                 // the thread name contains special chars, send as hex bytes
2461                 ostrm << std::hex << "hexname:";
2462                 uint8_t *u_thread_name = (uint8_t *)thread_name;
2463                 for (int i = 0; i < thread_name_len; i++)
2464                     ostrm << RAWHEX8(u_thread_name[i]);
2465                 ostrm << ';';
2466             }
2467         }
2468 
2469         thread_identifier_info_data_t thread_ident_info;
2470         if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
2471         {
2472             if (thread_ident_info.dispatch_qaddr != 0)
2473                 ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
2474         }
2475 
2476         // If a 'QListThreadsInStopReply' was sent to enable this feature, we
2477         // will send all thread IDs back in the "threads" key whose value is
2478         // a listc of hex thread IDs separated by commas:
2479         //  "threads:10a,10b,10c;"
2480         // This will save the debugger from having to send a pair of qfThreadInfo
2481         // and qsThreadInfo packets, but it also might take a lot of room in the
2482         // stop reply packet, so it must be enabled only on systems where there
2483         // are no limits on packet lengths.
2484 
2485         if (m_list_threads_in_stop_reply)
2486         {
2487             const nub_size_t numthreads = DNBProcessGetNumThreads (pid);
2488             if (numthreads > 0)
2489             {
2490                 ostrm << std::hex << "threads:";
2491                 for (nub_size_t i = 0; i < numthreads; ++i)
2492                 {
2493                     nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
2494                     if (i > 0)
2495                         ostrm << ',';
2496                     ostrm << std::hex << th;
2497                 }
2498                 ostrm << ';';
2499             }
2500         }
2501 
2502         if (g_num_reg_entries == 0)
2503             InitializeRegisters ();
2504 
2505         if (g_reg_entries != NULL)
2506         {
2507             DNBRegisterValue reg_value;
2508             for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2509             {
2510                 if (g_reg_entries[reg].expedite)
2511                 {
2512                     if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, &reg_value))
2513                         continue;
2514 
2515                     gdb_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg], &reg_value);
2516                 }
2517             }
2518         }
2519 
2520         if (did_exec)
2521         {
2522             ostrm << "reason:exec;";
2523         }
2524         else if (tid_stop_info.details.exception.type)
2525         {
2526             ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
2527             ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
2528             for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i)
2529                 ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";";
2530         }
2531         return SendPacket (ostrm.str ());
2532     }
2533     return SendPacket("E51");
2534 }
2535 
2536 /* '?'
2537  The stop reply packet - tell gdb what the status of the inferior is.
2538  Often called the questionmark_packet.  */
2539 
2540 rnb_err_t
HandlePacket_last_signal(const char * unused)2541 RNBRemote::HandlePacket_last_signal (const char *unused)
2542 {
2543     if (!m_ctx.HasValidProcessID())
2544     {
2545         // Inferior is not yet specified/running
2546         return SendPacket ("E02");
2547     }
2548 
2549     nub_process_t pid = m_ctx.ProcessID();
2550     nub_state_t pid_state = DNBProcessGetState (pid);
2551 
2552     switch (pid_state)
2553     {
2554         case eStateAttaching:
2555         case eStateLaunching:
2556         case eStateRunning:
2557         case eStateStepping:
2558         case eStateDetached:
2559             return rnb_success;  // Ignore
2560 
2561         case eStateSuspended:
2562         case eStateStopped:
2563         case eStateCrashed:
2564             {
2565                 nub_thread_t tid = DNBProcessGetCurrentThread (pid);
2566                 // Make sure we set the current thread so g and p packets return
2567                 // the data the gdb will expect.
2568                 SetCurrentThread (tid);
2569 
2570                 SendStopReplyPacketForThread (tid);
2571             }
2572             break;
2573 
2574         case eStateInvalid:
2575         case eStateUnloaded:
2576         case eStateExited:
2577             {
2578                 char pid_exited_packet[16] = "";
2579                 int pid_status = 0;
2580                 // Process exited with exit status
2581                 if (!DNBProcessGetExitStatus(pid, &pid_status))
2582                     pid_status = 0;
2583 
2584                 if (pid_status)
2585                 {
2586                     if (WIFEXITED (pid_status))
2587                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
2588                     else if (WIFSIGNALED (pid_status))
2589                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
2590                     else if (WIFSTOPPED (pid_status))
2591                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
2592                 }
2593 
2594                 // If we have an empty exit packet, lets fill one in to be safe.
2595                 if (!pid_exited_packet[0])
2596                 {
2597                     strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
2598                     pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
2599                 }
2600 
2601                 return SendPacket (pid_exited_packet);
2602             }
2603             break;
2604     }
2605     return rnb_success;
2606 }
2607 
2608 rnb_err_t
HandlePacket_M(const char * p)2609 RNBRemote::HandlePacket_M (const char *p)
2610 {
2611     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2612     {
2613         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet");
2614     }
2615 
2616     char *c;
2617     p++;
2618     errno = 0;
2619     nub_addr_t addr = strtoull (p, &c, 16);
2620     if (errno != 0 && addr == 0)
2621     {
2622         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet");
2623     }
2624     if (*c != ',')
2625     {
2626         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet");
2627     }
2628 
2629     /* Advance 'p' to the length part of the packet.  */
2630     p += (c - p) + 1;
2631 
2632     errno = 0;
2633     uint32_t length = strtoul (p, &c, 16);
2634     if (errno != 0 && length == 0)
2635     {
2636         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet");
2637     }
2638     if (length == 0)
2639     {
2640         return SendPacket ("OK");
2641     }
2642 
2643     if (*c != ':')
2644     {
2645         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet");
2646     }
2647     /* Advance 'p' to the data part of the packet.  */
2648     p += (c - p) + 1;
2649 
2650     int datalen = strlen (p);
2651     if (datalen & 0x1)
2652     {
2653         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet");
2654     }
2655     if (datalen == 0)
2656     {
2657         return SendPacket ("OK");
2658     }
2659 
2660     uint8_t *buf = (uint8_t *) alloca (datalen / 2);
2661     uint8_t *i = buf;
2662 
2663     while (*p != '\0' && *(p + 1) != '\0')
2664     {
2665         char hexbuf[3];
2666         hexbuf[0] = *p;
2667         hexbuf[1] = *(p + 1);
2668         hexbuf[2] = '\0';
2669         errno = 0;
2670         uint8_t byte = strtoul (hexbuf, NULL, 16);
2671         if (errno != 0 && byte == 0)
2672         {
2673             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet");
2674         }
2675         *i++ = byte;
2676         p += 2;
2677     }
2678 
2679     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf);
2680     if (wrote != length)
2681         return SendPacket ("E09");
2682     else
2683         return SendPacket ("OK");
2684 }
2685 
2686 
2687 rnb_err_t
HandlePacket_m(const char * p)2688 RNBRemote::HandlePacket_m (const char *p)
2689 {
2690     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2691     {
2692         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet");
2693     }
2694 
2695     char *c;
2696     p++;
2697     errno = 0;
2698     nub_addr_t addr = strtoull (p, &c, 16);
2699     if (errno != 0 && addr == 0)
2700     {
2701         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet");
2702     }
2703     if (*c != ',')
2704     {
2705         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet");
2706     }
2707 
2708     /* Advance 'p' to the length part of the packet.  */
2709     p += (c - p) + 1;
2710 
2711     errno = 0;
2712     uint32_t length = strtoul (p, NULL, 16);
2713     if (errno != 0 && length == 0)
2714     {
2715         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2716     }
2717     if (length == 0)
2718     {
2719         return SendPacket ("");
2720     }
2721 
2722     uint8_t buf[length];
2723     int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, length, buf);
2724     if (bytes_read == 0)
2725     {
2726         return SendPacket ("E08");
2727     }
2728 
2729     // "The reply may contain fewer bytes than requested if the server was able
2730     //  to read only part of the region of memory."
2731     length = bytes_read;
2732 
2733     std::ostringstream ostrm;
2734     for (int i = 0; i < length; i++)
2735         ostrm << RAWHEX8(buf[i]);
2736     return SendPacket (ostrm.str ());
2737 }
2738 
2739 rnb_err_t
HandlePacket_X(const char * p)2740 RNBRemote::HandlePacket_X (const char *p)
2741 {
2742     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2743     {
2744         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
2745     }
2746 
2747     char *c;
2748     p++;
2749     errno = 0;
2750     nub_addr_t addr = strtoull (p, &c, 16);
2751     if (errno != 0 && addr == 0)
2752     {
2753         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
2754     }
2755     if (*c != ',')
2756     {
2757         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
2758     }
2759 
2760     /* Advance 'p' to the length part of the packet.  */
2761     p += (c - p) + 1;
2762 
2763     errno = 0;
2764     int length = strtoul (p, NULL, 16);
2765     if (errno != 0 && length == 0)
2766     {
2767         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2768     }
2769 
2770     // I think gdb sends a zero length write request to test whether this
2771     // packet is accepted.
2772     if (length == 0)
2773     {
2774         return SendPacket ("OK");
2775     }
2776 
2777     std::vector<uint8_t> data = decode_binary_data (c, -1);
2778     std::vector<uint8_t>::const_iterator it;
2779     uint8_t *buf = (uint8_t *) alloca (data.size ());
2780     uint8_t *i = buf;
2781     for (it = data.begin (); it != data.end (); ++it)
2782     {
2783         *i++ = *it;
2784     }
2785 
2786     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf);
2787     if (wrote != data.size ())
2788         return SendPacket ("E08");
2789     return SendPacket ("OK");
2790 }
2791 
2792 /* 'g' -- read registers
2793  Get the contents of the registers for the current thread,
2794  send them to gdb.
2795  Should the setting of the Hg packet determine which thread's registers
2796  are returned?  */
2797 
2798 rnb_err_t
HandlePacket_g(const char * p)2799 RNBRemote::HandlePacket_g (const char *p)
2800 {
2801     std::ostringstream ostrm;
2802     if (!m_ctx.HasValidProcessID())
2803     {
2804         return SendPacket ("E11");
2805     }
2806 
2807     if (g_num_reg_entries == 0)
2808         InitializeRegisters ();
2809 
2810     nub_process_t pid = m_ctx.ProcessID ();
2811     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
2812     if (tid == INVALID_NUB_THREAD)
2813         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2814 
2815     if (m_use_native_regs)
2816     {
2817         // Get the register context size first by calling with NULL buffer
2818         nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2819         if (reg_ctx_size)
2820         {
2821             // Now allocate enough space for the entire register context
2822             std::vector<uint8_t> reg_ctx;
2823             reg_ctx.resize(reg_ctx_size);
2824             // Now read the register context
2825             reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
2826             if (reg_ctx_size)
2827             {
2828                 append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false);
2829                 return SendPacket (ostrm.str ());
2830             }
2831         }
2832     }
2833 
2834     for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2835         register_value_in_hex_fixed_width (ostrm, pid, tid, &g_reg_entries[reg], NULL);
2836 
2837     return SendPacket (ostrm.str ());
2838 }
2839 
2840 /* 'G XXX...' -- write registers
2841  How is the thread for these specified, beyond "the current thread"?
2842  Does gdb actually use the Hg packet to set this?  */
2843 
2844 rnb_err_t
HandlePacket_G(const char * p)2845 RNBRemote::HandlePacket_G (const char *p)
2846 {
2847     if (!m_ctx.HasValidProcessID())
2848     {
2849         return SendPacket ("E11");
2850     }
2851 
2852     if (g_num_reg_entries == 0)
2853         InitializeRegisters ();
2854 
2855     StringExtractor packet(p);
2856     packet.SetFilePos(1); // Skip the 'G'
2857 
2858     nub_process_t pid = m_ctx.ProcessID();
2859     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
2860     if (tid == INVALID_NUB_THREAD)
2861         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2862 
2863     if (m_use_native_regs)
2864     {
2865         // Get the register context size first by calling with NULL buffer
2866         nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2867         if (reg_ctx_size)
2868         {
2869             // Now allocate enough space for the entire register context
2870             std::vector<uint8_t> reg_ctx;
2871             reg_ctx.resize(reg_ctx_size);
2872 
2873             const nub_size_t bytes_extracted = packet.GetHexBytes (&reg_ctx[0], reg_ctx.size(), 0xcc);
2874             if (bytes_extracted == reg_ctx.size())
2875             {
2876                 // Now write the register context
2877                 reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
2878                 if (reg_ctx_size == reg_ctx.size())
2879                     return SendPacket ("OK");
2880                 else
2881                     return SendPacket ("E55");
2882             }
2883             else
2884             {
2885                 DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu bytes, size mismatch\n", p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
2886                 return SendPacket ("E64");
2887             }
2888         }
2889         else
2890             return SendPacket ("E65");
2891     }
2892 
2893 
2894     DNBRegisterValue reg_value;
2895     for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2896     {
2897         const register_map_entry_t *reg_entry = &g_reg_entries[reg];
2898 
2899         reg_value.info = reg_entry->nub_info;
2900         if (packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc) != reg_entry->gdb_size)
2901             break;
2902 
2903         if (reg_entry->fail_value == NULL)
2904         {
2905             if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
2906                 return SendPacket ("E15");
2907         }
2908     }
2909     return SendPacket ("OK");
2910 }
2911 
2912 static bool
RNBRemoteShouldCancelCallback(void * not_used)2913 RNBRemoteShouldCancelCallback (void *not_used)
2914 {
2915     RNBRemoteSP remoteSP(g_remoteSP);
2916     if (remoteSP.get() != NULL)
2917     {
2918         RNBRemote* remote = remoteSP.get();
2919         if (remote->Comm().IsConnected())
2920             return false;
2921         else
2922             return true;
2923     }
2924     return true;
2925 }
2926 
2927 
2928 // FORMAT: _MXXXXXX,PPP
2929 //      XXXXXX: big endian hex chars
2930 //      PPP: permissions can be any combo of r w x chars
2931 //
2932 // RESPONSE: XXXXXX
2933 //      XXXXXX: hex address of the newly allocated memory
2934 //      EXX: error code
2935 //
2936 // EXAMPLES:
2937 //      _M123000,rw
2938 //      _M123000,rwx
2939 //      _M123000,xw
2940 
2941 rnb_err_t
HandlePacket_AllocateMemory(const char * p)2942 RNBRemote::HandlePacket_AllocateMemory (const char *p)
2943 {
2944     StringExtractor packet (p);
2945     packet.SetFilePos(2); // Skip the "_M"
2946 
2947     nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0);
2948     if (size != 0)
2949     {
2950         if (packet.GetChar() == ',')
2951         {
2952             uint32_t permissions = 0;
2953             char ch;
2954             bool success = true;
2955             while (success && (ch = packet.GetChar()) != '\0')
2956             {
2957                 switch (ch)
2958                 {
2959                 case 'r':   permissions |= eMemoryPermissionsReadable; break;
2960                 case 'w':   permissions |= eMemoryPermissionsWritable; break;
2961                 case 'x':   permissions |= eMemoryPermissionsExecutable; break;
2962                 default:    success = false; break;
2963                 }
2964             }
2965 
2966             if (success)
2967             {
2968                 nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions);
2969                 if (addr != INVALID_NUB_ADDRESS)
2970                 {
2971                     std::ostringstream ostrm;
2972                     ostrm << RAW_HEXBASE << addr;
2973                     return SendPacket (ostrm.str ());
2974                 }
2975             }
2976         }
2977     }
2978     return SendPacket ("E53");
2979 }
2980 
2981 // FORMAT: _mXXXXXX
2982 //      XXXXXX: address that was previosly allocated
2983 //
2984 // RESPONSE: XXXXXX
2985 //      OK: address was deallocated
2986 //      EXX: error code
2987 //
2988 // EXAMPLES:
2989 //      _m123000
2990 
2991 rnb_err_t
HandlePacket_DeallocateMemory(const char * p)2992 RNBRemote::HandlePacket_DeallocateMemory (const char *p)
2993 {
2994     StringExtractor packet (p);
2995     packet.SetFilePos(2); // Skip the "_m"
2996     nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS);
2997 
2998     if (addr != INVALID_NUB_ADDRESS)
2999     {
3000         if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr))
3001             return SendPacket ("OK");
3002     }
3003     return SendPacket ("E54");
3004 }
3005 
3006 static bool
GetProcessNameFrom_vAttach(const char * & p,std::string & attach_name)3007 GetProcessNameFrom_vAttach (const char *&p, std::string &attach_name)
3008 {
3009     bool return_val = true;
3010     while (*p != '\0')
3011     {
3012         char smallbuf[3];
3013         smallbuf[0] = *p;
3014         smallbuf[1] = *(p + 1);
3015         smallbuf[2] = '\0';
3016 
3017         errno = 0;
3018         int ch = strtoul (smallbuf, NULL, 16);
3019         if (errno != 0 && ch == 0)
3020         {
3021             return_val = false;
3022             break;
3023         }
3024 
3025         attach_name.push_back(ch);
3026         p += 2;
3027     }
3028     return return_val;
3029 }
3030 
3031 /*
3032  vAttach;pid
3033 
3034  Attach to a new process with the specified process ID. pid is a hexadecimal integer
3035  identifying the process. If the stub is currently controlling a process, it is
3036  killed. The attached process is stopped.This packet is only available in extended
3037  mode (see extended mode).
3038 
3039  Reply:
3040  "ENN"                      for an error
3041  "Any Stop Reply Packet"     for success
3042  */
3043 
3044 rnb_err_t
HandlePacket_v(const char * p)3045 RNBRemote::HandlePacket_v (const char *p)
3046 {
3047     if (strcmp (p, "vCont;c") == 0)
3048     {
3049         // Simple continue
3050         return RNBRemote::HandlePacket_c("c");
3051     }
3052     else if (strcmp (p, "vCont;s") == 0)
3053     {
3054         // Simple step
3055         return RNBRemote::HandlePacket_s("s");
3056     }
3057     else if (strstr (p, "vCont") == p)
3058     {
3059         typedef struct
3060         {
3061             nub_thread_t tid;
3062             char action;
3063             int signal;
3064         } vcont_action_t;
3065 
3066         DNBThreadResumeActions thread_actions;
3067         char *c = (char *)(p += strlen("vCont"));
3068         char *c_end = c + strlen(c);
3069         if (*c == '?')
3070             return SendPacket ("vCont;c;C;s;S");
3071 
3072         while (c < c_end && *c == ';')
3073         {
3074             ++c;    // Skip the semi-colon
3075             DNBThreadResumeAction thread_action;
3076             thread_action.tid = INVALID_NUB_THREAD;
3077             thread_action.state = eStateInvalid;
3078             thread_action.signal = 0;
3079             thread_action.addr = INVALID_NUB_ADDRESS;
3080 
3081             char action = *c++;
3082 
3083             switch (action)
3084             {
3085                 case 'C':
3086                     errno = 0;
3087                     thread_action.signal = strtoul (c, &c, 16);
3088                     if (errno != 0)
3089                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3090                     // Fall through to next case...
3091 
3092                 case 'c':
3093                     // Continue
3094                     thread_action.state = eStateRunning;
3095                     break;
3096 
3097                 case 'S':
3098                     errno = 0;
3099                     thread_action.signal = strtoul (c, &c, 16);
3100                     if (errno != 0)
3101                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3102                     // Fall through to next case...
3103 
3104                 case 's':
3105                     // Step
3106                     thread_action.state = eStateStepping;
3107                     break;
3108 
3109                 default:
3110                     HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet");
3111                     break;
3112             }
3113             if (*c == ':')
3114             {
3115                 errno = 0;
3116                 thread_action.tid = strtoul (++c, &c, 16);
3117                 if (errno != 0)
3118                     return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet");
3119             }
3120 
3121             thread_actions.Append (thread_action);
3122         }
3123 
3124         // If a default action for all other threads wasn't mentioned
3125         // then we should stop the threads
3126         thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3127         DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize());
3128         return rnb_success;
3129     }
3130     else if (strstr (p, "vAttach") == p)
3131     {
3132         nub_process_t attach_pid = INVALID_NUB_PROCESS;
3133         char err_str[1024]={'\0'};
3134 
3135         if (strstr (p, "vAttachWait;") == p)
3136         {
3137             p += strlen("vAttachWait;");
3138             std::string attach_name;
3139             if (!GetProcessNameFrom_vAttach(p, attach_name))
3140             {
3141                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
3142             }
3143             const bool ignore_existing = true;
3144             attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3145 
3146         }
3147         else if (strstr (p, "vAttachOrWait;") == p)
3148         {
3149             p += strlen("vAttachOrWait;");
3150             std::string attach_name;
3151             if (!GetProcessNameFrom_vAttach(p, attach_name))
3152             {
3153                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt");
3154             }
3155             const bool ignore_existing = false;
3156             attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3157         }
3158         else if (strstr (p, "vAttachName;") == p)
3159         {
3160             p += strlen("vAttachName;");
3161             std::string attach_name;
3162             if (!GetProcessNameFrom_vAttach(p, attach_name))
3163             {
3164                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
3165             }
3166 
3167             attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
3168 
3169         }
3170         else if (strstr (p, "vAttach;") == p)
3171         {
3172             p += strlen("vAttach;");
3173             char *end = NULL;
3174             attach_pid = strtoul (p, &end, 16);    // PID will be in hex, so use base 16 to decode
3175             if (p != end && *end == '\0')
3176             {
3177                 // Wait at most 30 second for attach
3178                 struct timespec attach_timeout_abstime;
3179                 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3180                 attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str));
3181             }
3182         }
3183         else
3184         {
3185             return HandlePacket_UNIMPLEMENTED(p);
3186         }
3187 
3188 
3189         if (attach_pid != INVALID_NUB_PROCESS)
3190         {
3191             if (m_ctx.ProcessID() != attach_pid)
3192                 m_ctx.SetProcessID(attach_pid);
3193             // Send a stop reply packet to indicate we successfully attached!
3194             NotifyThatProcessStopped ();
3195             return rnb_success;
3196         }
3197         else
3198         {
3199             m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3200             if (err_str[0])
3201                 m_ctx.LaunchStatus().SetErrorString(err_str);
3202             else
3203                 m_ctx.LaunchStatus().SetErrorString("attach failed");
3204             return SendPacket ("E01");  // E01 is our magic error value for attach failed.
3205         }
3206     }
3207 
3208     // All other failures come through here
3209     return HandlePacket_UNIMPLEMENTED(p);
3210 }
3211 
3212 /* 'T XX' -- status of thread
3213  Check if the specified thread is alive.
3214  The thread number is in hex?  */
3215 
3216 rnb_err_t
HandlePacket_T(const char * p)3217 RNBRemote::HandlePacket_T (const char *p)
3218 {
3219     p++;
3220     if (p == NULL || *p == '\0')
3221     {
3222         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet");
3223     }
3224     if (!m_ctx.HasValidProcessID())
3225     {
3226         return SendPacket ("E15");
3227     }
3228     errno = 0;
3229     nub_thread_t tid = strtoul (p, NULL, 16);
3230     if (errno != 0 && tid == 0)
3231     {
3232         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet");
3233     }
3234 
3235     nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid);
3236     if (state == eStateInvalid || state == eStateExited || state == eStateCrashed)
3237     {
3238         return SendPacket ("E16");
3239     }
3240 
3241     return SendPacket ("OK");
3242 }
3243 
3244 
3245 rnb_err_t
HandlePacket_z(const char * p)3246 RNBRemote::HandlePacket_z (const char *p)
3247 {
3248     if (p == NULL || *p == '\0')
3249         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet");
3250 
3251     if (!m_ctx.HasValidProcessID())
3252         return SendPacket ("E15");
3253 
3254     char packet_cmd = *p++;
3255     char break_type = *p++;
3256 
3257     if (*p++ != ',')
3258         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
3259 
3260     char *c = NULL;
3261     nub_process_t pid = m_ctx.ProcessID();
3262     errno = 0;
3263     nub_addr_t addr = strtoull (p, &c, 16);
3264     if (errno != 0 && addr == 0)
3265         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet");
3266     p = c;
3267     if (*p++ != ',')
3268         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
3269 
3270     errno = 0;
3271     uint32_t byte_size = strtoul (p, &c, 16);
3272     if (errno != 0 && byte_size == 0)
3273         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet");
3274 
3275     if (packet_cmd == 'Z')
3276     {
3277         // set
3278         switch (break_type)
3279         {
3280             case '0':   // set software breakpoint
3281             case '1':   // set hardware breakpoint
3282                 {
3283                     // gdb can send multiple Z packets for the same address and
3284                     // these calls must be ref counted.
3285                     bool hardware = (break_type == '1');
3286 
3287                     if (DNBBreakpointSet (pid, addr, byte_size, hardware))
3288                     {
3289                         // We successfully created a breakpoint, now lets full out
3290                         // a ref count structure with the breakID and add it to our
3291                         // map.
3292                         return SendPacket ("OK");
3293                     }
3294                     else
3295                     {
3296                         // We failed to set the software breakpoint
3297                         return SendPacket ("E09");
3298                     }
3299                 }
3300                 break;
3301 
3302             case '2':   // set write watchpoint
3303             case '3':   // set read watchpoint
3304             case '4':   // set access watchpoint
3305                 {
3306                     bool hardware = true;
3307                     uint32_t watch_flags = 0;
3308                     if (break_type == '2')
3309                         watch_flags = WATCH_TYPE_WRITE;
3310                     else if (break_type == '3')
3311                         watch_flags = WATCH_TYPE_READ;
3312                     else
3313                         watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
3314 
3315                     if (DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware))
3316                     {
3317                         return SendPacket ("OK");
3318                     }
3319                     else
3320                     {
3321                         // We failed to set the watchpoint
3322                         return SendPacket ("E09");
3323                     }
3324                 }
3325                 break;
3326 
3327             default:
3328                 break;
3329         }
3330     }
3331     else if (packet_cmd == 'z')
3332     {
3333         // remove
3334         switch (break_type)
3335         {
3336             case '0':   // remove software breakpoint
3337             case '1':   // remove hardware breakpoint
3338                 if (DNBBreakpointClear (pid, addr))
3339                 {
3340                     return SendPacket ("OK");
3341                 }
3342                 else
3343                 {
3344                     return SendPacket ("E08");
3345                 }
3346                 break;
3347 
3348             case '2':   // remove write watchpoint
3349             case '3':   // remove read watchpoint
3350             case '4':   // remove access watchpoint
3351                 if (DNBWatchpointClear (pid, addr))
3352                 {
3353                     return SendPacket ("OK");
3354                 }
3355                 else
3356                 {
3357                     return SendPacket ("E08");
3358                 }
3359                 break;
3360 
3361             default:
3362                 break;
3363         }
3364     }
3365     return HandlePacket_UNIMPLEMENTED(p);
3366 }
3367 
3368 // Extract the thread number from the thread suffix that might be appended to
3369 // thread specific packets. This will only be enabled if m_thread_suffix_supported
3370 // is true.
3371 nub_thread_t
ExtractThreadIDFromThreadSuffix(const char * p)3372 RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
3373 {
3374     if (m_thread_suffix_supported)
3375     {
3376         nub_thread_t tid = INVALID_NUB_THREAD;
3377         if (p)
3378         {
3379             const char *tid_cstr = strstr (p, "thread:");
3380             if (tid_cstr)
3381             {
3382                 tid_cstr += strlen ("thread:");
3383                 tid = strtoul(tid_cstr, NULL, 16);
3384             }
3385         }
3386         return tid;
3387     }
3388     return GetCurrentThread();
3389 
3390 }
3391 
3392 /* 'p XX'
3393  print the contents of register X */
3394 
3395 rnb_err_t
HandlePacket_p(const char * p)3396 RNBRemote::HandlePacket_p (const char *p)
3397 {
3398     if (g_num_reg_entries == 0)
3399         InitializeRegisters ();
3400 
3401     if (p == NULL || *p == '\0')
3402     {
3403         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3404     }
3405     if (!m_ctx.HasValidProcessID())
3406     {
3407         return SendPacket ("E15");
3408     }
3409     nub_process_t pid = m_ctx.ProcessID();
3410     errno = 0;
3411     char *tid_cstr = NULL;
3412     uint32_t reg = strtoul (p + 1, &tid_cstr, 16);
3413     if (errno != 0 && reg == 0)
3414     {
3415         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet");
3416     }
3417 
3418     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
3419     if (tid == INVALID_NUB_THREAD)
3420         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3421 
3422     const register_map_entry_t *reg_entry;
3423 
3424     if (reg < g_num_reg_entries)
3425         reg_entry = &g_reg_entries[reg];
3426     else
3427         reg_entry = NULL;
3428 
3429     std::ostringstream ostrm;
3430     if (reg_entry == NULL)
3431     {
3432         DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg);
3433         ostrm << "00000000";
3434     }
3435     else if (reg_entry->nub_info.reg == -1)
3436     {
3437         if (reg_entry->gdb_size > 0)
3438         {
3439             if (reg_entry->fail_value != NULL)
3440             {
3441                 append_hex_value(ostrm, reg_entry->fail_value, reg_entry->gdb_size, false);
3442             }
3443             else
3444             {
3445                 std::basic_string<uint8_t> zeros(reg_entry->gdb_size, '\0');
3446                 append_hex_value(ostrm, zeros.data(), zeros.size(), false);
3447             }
3448         }
3449     }
3450     else
3451     {
3452         register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry, NULL);
3453     }
3454     return SendPacket (ostrm.str());
3455 }
3456 
3457 /* 'Pnn=rrrrr'
3458  Set register number n to value r.
3459  n and r are hex strings.  */
3460 
3461 rnb_err_t
HandlePacket_P(const char * p)3462 RNBRemote::HandlePacket_P (const char *p)
3463 {
3464     if (g_num_reg_entries == 0)
3465         InitializeRegisters ();
3466 
3467     if (p == NULL || *p == '\0')
3468     {
3469         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet");
3470     }
3471     if (!m_ctx.HasValidProcessID())
3472     {
3473         return SendPacket ("E28");
3474     }
3475 
3476     nub_process_t pid = m_ctx.ProcessID();
3477 
3478     StringExtractor packet (p);
3479 
3480     const char cmd_char = packet.GetChar();
3481     // Register ID is always in big endian
3482     const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX);
3483     const char equal_char = packet.GetChar();
3484 
3485     if (cmd_char != 'P')
3486         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet");
3487 
3488     if (reg == UINT32_MAX)
3489         return SendPacket ("E29");
3490 
3491     if (equal_char != '=')
3492         return SendPacket ("E30");
3493 
3494     const register_map_entry_t *reg_entry;
3495 
3496     if (reg >= g_num_reg_entries)
3497         return SendPacket("E47");
3498 
3499     reg_entry = &g_reg_entries[reg];
3500 
3501     if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1)
3502     {
3503         DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg);
3504         return SendPacket("E48");
3505     }
3506 
3507     DNBRegisterValue reg_value;
3508     reg_value.info = reg_entry->nub_info;
3509     packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc);
3510 
3511     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
3512     if (tid == INVALID_NUB_THREAD)
3513         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3514 
3515     if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
3516     {
3517         return SendPacket ("E32");
3518     }
3519     return SendPacket ("OK");
3520 }
3521 
3522 /* 'c [addr]'
3523  Continue, optionally from a specified address. */
3524 
3525 rnb_err_t
HandlePacket_c(const char * p)3526 RNBRemote::HandlePacket_c (const char *p)
3527 {
3528     const nub_process_t pid = m_ctx.ProcessID();
3529 
3530     if (pid == INVALID_NUB_PROCESS)
3531         return SendPacket ("E23");
3532 
3533     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3534 
3535     if (*(p + 1) != '\0')
3536     {
3537         action.tid = GetContinueThread();
3538         errno = 0;
3539         action.addr = strtoull (p + 1, NULL, 16);
3540         if (errno != 0 && action.addr == 0)
3541             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet");
3542     }
3543 
3544     DNBThreadResumeActions thread_actions;
3545     thread_actions.Append(action);
3546     thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
3547     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3548         return SendPacket ("E25");
3549     // Don't send an "OK" packet; response is the stopped/exited message.
3550     return rnb_success;
3551 }
3552 
3553 rnb_err_t
HandlePacket_MemoryRegionInfo(const char * p)3554 RNBRemote::HandlePacket_MemoryRegionInfo (const char *p)
3555 {
3556     /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code)
3557        for the memory region containing a given address and return that information.
3558 
3559        Users of this packet must be prepared for three results:
3560 
3561            Region information is returned
3562            Region information is unavailable for this address because the address is in unmapped memory
3563            Region lookup cannot be performed on this platform or process is not yet launched
3564            This packet isn't implemented
3565 
3566        Examples of use:
3567           qMemoryRegionInfo:3a55140
3568           start:3a50000,size:100000,permissions:rwx
3569 
3570           qMemoryRegionInfo:0
3571           error:address in unmapped region
3572 
3573           qMemoryRegionInfo:3a551140   (on a different platform)
3574           error:region lookup cannot be performed
3575 
3576           qMemoryRegionInfo
3577           OK                   // this packet is implemented by the remote nub
3578     */
3579 
3580     p += sizeof ("qMemoryRegionInfo") - 1;
3581     if (*p == '\0')
3582        return SendPacket ("OK");
3583     if (*p++ != ':')
3584        return SendPacket ("E67");
3585     if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
3586        p += 2;
3587 
3588     errno = 0;
3589     uint64_t address = strtoul (p, NULL, 16);
3590     if (errno != 0 && address == 0)
3591     {
3592         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
3593     }
3594 
3595     DNBRegionInfo region_info = { 0, 0, 0 };
3596     DNBProcessMemoryRegionInfo (m_ctx.ProcessID(), address, &region_info);
3597     std::ostringstream ostrm;
3598 
3599         // start:3a50000,size:100000,permissions:rwx
3600     ostrm << "start:" << std::hex << region_info.addr << ';';
3601 
3602     if (region_info.size > 0)
3603         ostrm << "size:"  << std::hex << region_info.size << ';';
3604 
3605     if (region_info.permissions)
3606     {
3607         ostrm << "permissions:";
3608 
3609         if (region_info.permissions & eMemoryPermissionsReadable)
3610             ostrm << 'r';
3611         if (region_info.permissions & eMemoryPermissionsWritable)
3612             ostrm << 'w';
3613         if (region_info.permissions & eMemoryPermissionsExecutable)
3614             ostrm << 'x';
3615         ostrm << ';';
3616     }
3617     return SendPacket (ostrm.str());
3618 }
3619 
3620 // qGetProfileData;scan_type:0xYYYYYYY
3621 rnb_err_t
HandlePacket_GetProfileData(const char * p)3622 RNBRemote::HandlePacket_GetProfileData (const char *p)
3623 {
3624     nub_process_t pid = m_ctx.ProcessID();
3625     if (pid == INVALID_NUB_PROCESS)
3626         return SendPacket ("OK");
3627 
3628     StringExtractor packet(p += sizeof ("qGetProfileData"));
3629     DNBProfileDataScanType scan_type = eProfileAll;
3630     std::string name;
3631     std::string value;
3632     while (packet.GetNameColonValue(name, value))
3633     {
3634         if (name.compare ("scan_type") == 0)
3635         {
3636             std::istringstream iss(value);
3637             uint32_t int_value = 0;
3638             if (iss >> std::hex >> int_value)
3639             {
3640                 scan_type = (DNBProfileDataScanType)int_value;
3641             }
3642         }
3643     }
3644 
3645     std::string data = DNBProcessGetProfileData(pid, scan_type);
3646     if (!data.empty())
3647     {
3648         return SendPacket (data.c_str());
3649     }
3650     else
3651     {
3652         return SendPacket ("OK");
3653     }
3654 }
3655 
3656 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
3657 rnb_err_t
HandlePacket_SetEnableAsyncProfiling(const char * p)3658 RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p)
3659 {
3660     nub_process_t pid = m_ctx.ProcessID();
3661     if (pid == INVALID_NUB_PROCESS)
3662         return SendPacket ("OK");
3663 
3664     StringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling"));
3665     bool enable = false;
3666     uint64_t interval_usec = 0;
3667     DNBProfileDataScanType scan_type = eProfileAll;
3668     std::string name;
3669     std::string value;
3670     while (packet.GetNameColonValue(name, value))
3671     {
3672         if (name.compare ("enable") == 0)
3673         {
3674             enable  = strtoul(value.c_str(), NULL, 10) > 0;
3675         }
3676         else if (name.compare ("interval_usec") == 0)
3677         {
3678             interval_usec  = strtoul(value.c_str(), NULL, 10);
3679         }
3680         else if (name.compare ("scan_type") == 0)
3681         {
3682             std::istringstream iss(value);
3683             uint32_t int_value = 0;
3684             if (iss >> std::hex >> int_value)
3685             {
3686                 scan_type = (DNBProfileDataScanType)int_value;
3687             }
3688         }
3689     }
3690 
3691     if (interval_usec == 0)
3692     {
3693         enable = 0;
3694     }
3695 
3696     DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
3697     return SendPacket ("OK");
3698 }
3699 
3700 rnb_err_t
HandlePacket_WatchpointSupportInfo(const char * p)3701 RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p)
3702 {
3703     /* This packet simply returns the number of supported hardware watchpoints.
3704 
3705        Examples of use:
3706           qWatchpointSupportInfo:
3707           num:4
3708 
3709           qWatchpointSupportInfo
3710           OK                   // this packet is implemented by the remote nub
3711     */
3712 
3713     p += sizeof ("qWatchpointSupportInfo") - 1;
3714     if (*p == '\0')
3715        return SendPacket ("OK");
3716     if (*p++ != ':')
3717        return SendPacket ("E67");
3718 
3719     errno = 0;
3720     uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID());
3721     std::ostringstream ostrm;
3722 
3723     // size:4
3724     ostrm << "num:" << std::dec << num << ';';
3725     return SendPacket (ostrm.str());
3726 }
3727 
3728 /* 'C sig [;addr]'
3729  Resume with signal sig, optionally at address addr.  */
3730 
3731 rnb_err_t
HandlePacket_C(const char * p)3732 RNBRemote::HandlePacket_C (const char *p)
3733 {
3734     const nub_process_t pid = m_ctx.ProcessID();
3735 
3736     if (pid == INVALID_NUB_PROCESS)
3737         return SendPacket ("E36");
3738 
3739     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3740     int process_signo = -1;
3741     if (*(p + 1) != '\0')
3742     {
3743         action.tid = GetContinueThread();
3744         char *end = NULL;
3745         errno = 0;
3746         process_signo = strtoul (p + 1, &end, 16);
3747         if (errno != 0)
3748             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet");
3749         else if (*end == ';')
3750         {
3751             errno = 0;
3752             action.addr = strtoull (end + 1, NULL, 16);
3753             if (errno != 0 && action.addr == 0)
3754                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet");
3755         }
3756     }
3757 
3758     DNBThreadResumeActions thread_actions;
3759     thread_actions.Append (action);
3760     thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal);
3761     if (!DNBProcessSignal(pid, process_signo))
3762         return SendPacket ("E52");
3763     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3764         return SendPacket ("E38");
3765     /* Don't send an "OK" packet; response is the stopped/exited message.  */
3766     return rnb_success;
3767 }
3768 
3769 //----------------------------------------------------------------------
3770 // 'D' packet
3771 // Detach from gdb.
3772 //----------------------------------------------------------------------
3773 rnb_err_t
HandlePacket_D(const char * p)3774 RNBRemote::HandlePacket_D (const char *p)
3775 {
3776     SendPacket ("OK");
3777     if (m_ctx.HasValidProcessID())
3778         DNBProcessDetach(m_ctx.ProcessID());
3779     return rnb_success;
3780 }
3781 
3782 /* 'k'
3783  Kill the inferior process.  */
3784 
3785 rnb_err_t
HandlePacket_k(const char * p)3786 RNBRemote::HandlePacket_k (const char *p)
3787 {
3788     DNBLog ("Got a 'k' packet, killing the inferior process.");
3789     // No response to should be sent to the kill packet
3790     if (m_ctx.HasValidProcessID())
3791         DNBProcessKill (m_ctx.ProcessID());
3792     SendPacket ("W09");
3793     return rnb_success;
3794 }
3795 
3796 rnb_err_t
HandlePacket_stop_process(const char * p)3797 RNBRemote::HandlePacket_stop_process (const char *p)
3798 {
3799 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test exiting on interrupt
3800 #if defined(TEST_EXIT_ON_INTERRUPT)
3801     rnb_err_t err = HandlePacket_k (p);
3802     m_comm.Disconnect(true);
3803     return err;
3804 #else
3805     DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP);
3806     //DNBProcessSignal (m_ctx.ProcessID(), SIGINT);
3807     // Do not send any response packet! Wait for the stop reply packet to naturally happen
3808     return rnb_success;
3809 #endif
3810 }
3811 
3812 /* 's'
3813  Step the inferior process.  */
3814 
3815 rnb_err_t
HandlePacket_s(const char * p)3816 RNBRemote::HandlePacket_s (const char *p)
3817 {
3818     const nub_process_t pid = m_ctx.ProcessID();
3819     if (pid == INVALID_NUB_PROCESS)
3820         return SendPacket ("E32");
3821 
3822     // Hardware supported stepping not supported on arm
3823     nub_thread_t tid = GetContinueThread ();
3824     if (tid == 0 || tid == -1)
3825         tid = GetCurrentThread();
3826 
3827     if (tid == INVALID_NUB_THREAD)
3828         return SendPacket ("E33");
3829 
3830     DNBThreadResumeActions thread_actions;
3831     thread_actions.AppendAction(tid, eStateStepping);
3832 
3833     // Make all other threads stop when we are stepping
3834     thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3835     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3836         return SendPacket ("E49");
3837     // Don't send an "OK" packet; response is the stopped/exited message.
3838     return rnb_success;
3839 }
3840 
3841 /* 'S sig [;addr]'
3842  Step with signal sig, optionally at address addr.  */
3843 
3844 rnb_err_t
HandlePacket_S(const char * p)3845 RNBRemote::HandlePacket_S (const char *p)
3846 {
3847     const nub_process_t pid = m_ctx.ProcessID();
3848     if (pid == INVALID_NUB_PROCESS)
3849         return SendPacket ("E36");
3850 
3851     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
3852 
3853     if (*(p + 1) != '\0')
3854     {
3855         char *end = NULL;
3856         errno = 0;
3857         action.signal = strtoul (p + 1, &end, 16);
3858         if (errno != 0)
3859             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
3860         else if (*end == ';')
3861         {
3862             errno = 0;
3863             action.addr = strtoull (end + 1, NULL, 16);
3864             if (errno != 0 && action.addr == 0)
3865             {
3866                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
3867             }
3868         }
3869     }
3870 
3871     action.tid = GetContinueThread ();
3872     if (action.tid == 0 || action.tid == -1)
3873         return SendPacket ("E40");
3874 
3875     nub_state_t tstate = DNBThreadGetState (pid, action.tid);
3876     if (tstate == eStateInvalid || tstate == eStateExited)
3877         return SendPacket ("E37");
3878 
3879 
3880     DNBThreadResumeActions thread_actions;
3881     thread_actions.Append (action);
3882 
3883     // Make all other threads stop when we are stepping
3884     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3885     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3886         return SendPacket ("E39");
3887 
3888     // Don't send an "OK" packet; response is the stopped/exited message.
3889     return rnb_success;
3890 }
3891 
3892 rnb_err_t
HandlePacket_qHostInfo(const char * p)3893 RNBRemote::HandlePacket_qHostInfo (const char *p)
3894 {
3895     std::ostringstream strm;
3896 
3897     uint32_t cputype, is_64_bit_capable;
3898     size_t len = sizeof(cputype);
3899     bool promoted_to_64 = false;
3900     if  (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
3901     {
3902         len = sizeof (is_64_bit_capable);
3903         if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
3904         {
3905             if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
3906             {
3907                 promoted_to_64 = true;
3908                 cputype |= CPU_ARCH_ABI64;
3909             }
3910         }
3911 
3912         strm << "cputype:" << std::dec << cputype << ';';
3913     }
3914 
3915     uint32_t cpusubtype;
3916     len = sizeof(cpusubtype);
3917     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
3918     {
3919         if (promoted_to_64 &&
3920             cputype == CPU_TYPE_X86_64 &&
3921             cpusubtype == CPU_SUBTYPE_486)
3922             cpusubtype = CPU_SUBTYPE_X86_64_ALL;
3923 
3924         strm << "cpusubtype:" << std::dec << cpusubtype << ';';
3925     }
3926 
3927     // The OS in the triple should be "ios" or "macosx" which doesn't match our
3928     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
3929     // this for now.
3930     if (cputype == CPU_TYPE_ARM)
3931     {
3932         strm << "ostype:ios;";
3933         // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
3934         strm << "watchpoint_exceptions_received:before;";
3935     }
3936     else
3937     {
3938         strm << "ostype:macosx;";
3939         strm << "watchpoint_exceptions_received:after;";
3940     }
3941 //    char ostype[64];
3942 //    len = sizeof(ostype);
3943 //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
3944 //    {
3945 //        len = strlen(ostype);
3946 //        std::transform (ostype, ostype + len, ostype, tolower);
3947 //        strm << "ostype:" << std::dec << ostype << ';';
3948 //    }
3949 
3950     strm << "vendor:apple;";
3951 
3952 #if defined (__LITTLE_ENDIAN__)
3953     strm << "endian:little;";
3954 #elif defined (__BIG_ENDIAN__)
3955     strm << "endian:big;";
3956 #elif defined (__PDP_ENDIAN__)
3957     strm << "endian:pdp;";
3958 #endif
3959 
3960     if (promoted_to_64)
3961         strm << "ptrsize:8;";
3962     else
3963         strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
3964     return SendPacket (strm.str());
3965 }
3966 
3967 
3968 // Note that all numeric values returned by qProcessInfo are hex encoded,
3969 // including the pid and the cpu type.
3970 
3971 rnb_err_t
HandlePacket_qProcessInfo(const char * p)3972 RNBRemote::HandlePacket_qProcessInfo (const char *p)
3973 {
3974     nub_process_t pid;
3975     std::ostringstream rep;
3976 
3977     // If we haven't run the process yet, return an error.
3978     if (!m_ctx.HasValidProcessID())
3979         return SendPacket ("E68");
3980 
3981     pid = m_ctx.ProcessID();
3982 
3983     rep << "pid:" << std::hex << pid << ";";
3984 
3985     int procpid_mib[4];
3986     procpid_mib[0] = CTL_KERN;
3987     procpid_mib[1] = KERN_PROC;
3988     procpid_mib[2] = KERN_PROC_PID;
3989     procpid_mib[3] = pid;
3990     struct kinfo_proc proc_kinfo;
3991     size_t proc_kinfo_size = sizeof(struct kinfo_proc);
3992 
3993     if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
3994     {
3995         if (proc_kinfo_size > 0)
3996         {
3997             rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";";
3998             rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";";
3999             rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";";
4000             rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";";
4001             if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
4002                 rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";";
4003         }
4004     }
4005 
4006     cpu_type_t cputype = DNBProcessGetCPUType (pid);
4007     if (cputype == 0)
4008     {
4009         DNBLog ("Unable to get the process cpu_type, making a best guess.");
4010         cputype = best_guess_cpu_type();
4011     }
4012 
4013     if (cputype != 0)
4014     {
4015         rep << "cputype:" << std::hex << cputype << ";";
4016     }
4017 
4018     uint32_t cpusubtype;
4019     size_t cpusubtype_len = sizeof(cpusubtype);
4020     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0)
4021     {
4022         if (cputype == CPU_TYPE_X86_64 && cpusubtype == CPU_SUBTYPE_486)
4023         {
4024             cpusubtype = CPU_SUBTYPE_X86_64_ALL;
4025         }
4026 
4027         rep << "cpusubtype:" << std::hex << cpusubtype << ';';
4028     }
4029 
4030     // The OS in the triple should be "ios" or "macosx" which doesn't match our
4031     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4032     // this for now.
4033     if (cputype == CPU_TYPE_ARM)
4034         rep << "ostype:ios;";
4035     else
4036         rep << "ostype:macosx;";
4037 
4038     rep << "vendor:apple;";
4039 
4040 #if defined (__LITTLE_ENDIAN__)
4041     rep << "endian:little;";
4042 #elif defined (__BIG_ENDIAN__)
4043     rep << "endian:big;";
4044 #elif defined (__PDP_ENDIAN__)
4045     rep << "endian:pdp;";
4046 #endif
4047 
4048 #if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE)
4049     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
4050     kern_return_t kr;
4051     x86_thread_state_t gp_regs;
4052     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
4053     kr = thread_get_state (thread, x86_THREAD_STATE,
4054                            (thread_state_t) &gp_regs, &gp_count);
4055     if (kr == KERN_SUCCESS)
4056     {
4057         if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
4058             rep << "ptrsize:8;";
4059         else
4060             rep << "ptrsize:4;";
4061     }
4062 #elif defined (__arm__)
4063     rep << "ptrsize:4;";
4064 #endif
4065 
4066     return SendPacket (rep.str());
4067 }
4068 
4069