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