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