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