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