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 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 specific 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 whether 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 previously 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__) || defined (__aarch64__)
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 registers 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 characters 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 register 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 
2330             if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
2331                 ostrm << std::hex << "name:" << thread_name << ';';
2332             else
2333             {
2334                 // the thread name contains special chars, send as hex bytes
2335                 ostrm << std::hex << "hexname:";
2336                 uint8_t *u_thread_name = (uint8_t *)thread_name;
2337                 for (int i = 0; i < thread_name_len; i++)
2338                     ostrm << RAWHEX8(u_thread_name[i]);
2339                 ostrm << ';';
2340             }
2341         }
2342 
2343         thread_identifier_info_data_t thread_ident_info;
2344         if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
2345         {
2346             if (thread_ident_info.dispatch_qaddr != 0)
2347                 ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
2348         }
2349 
2350         // If a 'QListThreadsInStopReply' was sent to enable this feature, we
2351         // will send all thread IDs back in the "threads" key whose value is
2352         // a list of hex thread IDs separated by commas:
2353         //  "threads:10a,10b,10c;"
2354         // This will save the debugger from having to send a pair of qfThreadInfo
2355         // and qsThreadInfo packets, but it also might take a lot of room in the
2356         // stop reply packet, so it must be enabled only on systems where there
2357         // are no limits on packet lengths.
2358 
2359         if (m_list_threads_in_stop_reply)
2360         {
2361             const nub_size_t numthreads = DNBProcessGetNumThreads (pid);
2362             if (numthreads > 0)
2363             {
2364                 ostrm << std::hex << "threads:";
2365                 for (nub_size_t i = 0; i < numthreads; ++i)
2366                 {
2367                     nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
2368                     if (i > 0)
2369                         ostrm << ',';
2370                     ostrm << std::hex << th;
2371                 }
2372                 ostrm << ';';
2373             }
2374         }
2375 
2376         if (g_num_reg_entries == 0)
2377             InitializeRegisters ();
2378 
2379         if (g_reg_entries != NULL)
2380         {
2381             DNBRegisterValue reg_value;
2382             for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2383             {
2384                 // Expedite all registers in the first register set that aren't
2385                 // contained in other registers
2386                 if (g_reg_entries[reg].nub_info.set == 1 &&
2387                     g_reg_entries[reg].nub_info.value_regs == NULL)
2388                 {
2389                     if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, &reg_value))
2390                         continue;
2391 
2392                     gdb_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg], &reg_value);
2393                 }
2394             }
2395         }
2396 
2397         if (did_exec)
2398         {
2399             ostrm << "reason:exec;";
2400         }
2401         else if (tid_stop_info.details.exception.type)
2402         {
2403             ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
2404             ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
2405             for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i)
2406                 ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";";
2407         }
2408         return SendPacket (ostrm.str ());
2409     }
2410     return SendPacket("E51");
2411 }
2412 
2413 /* '?'
2414  The stop reply packet - tell gdb what the status of the inferior is.
2415  Often called the questionmark_packet.  */
2416 
2417 rnb_err_t
2418 RNBRemote::HandlePacket_last_signal (const char *unused)
2419 {
2420     if (!m_ctx.HasValidProcessID())
2421     {
2422         // Inferior is not yet specified/running
2423         return SendPacket ("E02");
2424     }
2425 
2426     nub_process_t pid = m_ctx.ProcessID();
2427     nub_state_t pid_state = DNBProcessGetState (pid);
2428 
2429     switch (pid_state)
2430     {
2431         case eStateAttaching:
2432         case eStateLaunching:
2433         case eStateRunning:
2434         case eStateStepping:
2435         case eStateDetached:
2436             return rnb_success;  // Ignore
2437 
2438         case eStateSuspended:
2439         case eStateStopped:
2440         case eStateCrashed:
2441             {
2442                 nub_thread_t tid = DNBProcessGetCurrentThread (pid);
2443                 // Make sure we set the current thread so g and p packets return
2444                 // the data the gdb will expect.
2445                 SetCurrentThread (tid);
2446 
2447                 SendStopReplyPacketForThread (tid);
2448             }
2449             break;
2450 
2451         case eStateInvalid:
2452         case eStateUnloaded:
2453         case eStateExited:
2454             {
2455                 char pid_exited_packet[16] = "";
2456                 int pid_status = 0;
2457                 // Process exited with exit status
2458                 if (!DNBProcessGetExitStatus(pid, &pid_status))
2459                     pid_status = 0;
2460 
2461                 if (pid_status)
2462                 {
2463                     if (WIFEXITED (pid_status))
2464                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
2465                     else if (WIFSIGNALED (pid_status))
2466                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
2467                     else if (WIFSTOPPED (pid_status))
2468                         snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
2469                 }
2470 
2471                 // If we have an empty exit packet, lets fill one in to be safe.
2472                 if (!pid_exited_packet[0])
2473                 {
2474                     strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
2475                     pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
2476                 }
2477 
2478                 const char *exit_info = DNBProcessGetExitInfo (pid);
2479                 if (exit_info != NULL && *exit_info != '\0')
2480                 {
2481                     std::ostringstream exit_packet;
2482                     exit_packet << pid_exited_packet;
2483                     exit_packet << ';';
2484                     exit_packet << RAW_HEXBASE << "description";
2485                     exit_packet << ':';
2486                     for (size_t i = 0; exit_info[i] != '\0'; i++)
2487                         exit_packet << RAWHEX8(exit_info[i]);
2488                     exit_packet << ';';
2489                     return SendPacket (exit_packet.str());
2490                 }
2491                 else
2492                     return SendPacket (pid_exited_packet);
2493             }
2494             break;
2495     }
2496     return rnb_success;
2497 }
2498 
2499 rnb_err_t
2500 RNBRemote::HandlePacket_M (const char *p)
2501 {
2502     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2503     {
2504         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet");
2505     }
2506 
2507     char *c;
2508     p++;
2509     errno = 0;
2510     nub_addr_t addr = strtoull (p, &c, 16);
2511     if (errno != 0 && addr == 0)
2512     {
2513         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet");
2514     }
2515     if (*c != ',')
2516     {
2517         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet");
2518     }
2519 
2520     /* Advance 'p' to the length part of the packet.  */
2521     p += (c - p) + 1;
2522 
2523     errno = 0;
2524     uint32_t length = strtoul (p, &c, 16);
2525     if (errno != 0 && length == 0)
2526     {
2527         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet");
2528     }
2529     if (length == 0)
2530     {
2531         return SendPacket ("OK");
2532     }
2533 
2534     if (*c != ':')
2535     {
2536         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet");
2537     }
2538     /* Advance 'p' to the data part of the packet.  */
2539     p += (c - p) + 1;
2540 
2541     int datalen = strlen (p);
2542     if (datalen & 0x1)
2543     {
2544         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet");
2545     }
2546     if (datalen == 0)
2547     {
2548         return SendPacket ("OK");
2549     }
2550 
2551     uint8_t *buf = (uint8_t *) alloca (datalen / 2);
2552     uint8_t *i = buf;
2553 
2554     while (*p != '\0' && *(p + 1) != '\0')
2555     {
2556         char hexbuf[3];
2557         hexbuf[0] = *p;
2558         hexbuf[1] = *(p + 1);
2559         hexbuf[2] = '\0';
2560         errno = 0;
2561         uint8_t byte = strtoul (hexbuf, NULL, 16);
2562         if (errno != 0 && byte == 0)
2563         {
2564             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet");
2565         }
2566         *i++ = byte;
2567         p += 2;
2568     }
2569 
2570     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf);
2571     if (wrote != length)
2572         return SendPacket ("E09");
2573     else
2574         return SendPacket ("OK");
2575 }
2576 
2577 
2578 rnb_err_t
2579 RNBRemote::HandlePacket_m (const char *p)
2580 {
2581     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2582     {
2583         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet");
2584     }
2585 
2586     char *c;
2587     p++;
2588     errno = 0;
2589     nub_addr_t addr = strtoull (p, &c, 16);
2590     if (errno != 0 && addr == 0)
2591     {
2592         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet");
2593     }
2594     if (*c != ',')
2595     {
2596         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet");
2597     }
2598 
2599     /* Advance 'p' to the length part of the packet.  */
2600     p += (c - p) + 1;
2601 
2602     errno = 0;
2603     uint32_t length = strtoul (p, NULL, 16);
2604     if (errno != 0 && length == 0)
2605     {
2606         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
2607     }
2608     if (length == 0)
2609     {
2610         return SendPacket ("");
2611     }
2612 
2613     std::string buf(length, '\0');
2614     if (buf.empty())
2615     {
2616         return SendPacket ("E78");
2617     }
2618     int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
2619     if (bytes_read == 0)
2620     {
2621         return SendPacket ("E08");
2622     }
2623 
2624     // "The reply may contain fewer bytes than requested if the server was able
2625     //  to read only part of the region of memory."
2626     length = bytes_read;
2627 
2628     std::ostringstream ostrm;
2629     for (int i = 0; i < length; i++)
2630         ostrm << RAWHEX8(buf[i]);
2631     return SendPacket (ostrm.str ());
2632 }
2633 
2634 // Read memory, sent it up as binary data.
2635 // Usage:  xADDR,LEN
2636 // ADDR and LEN are both base 16.
2637 
2638 // Responds with 'OK' for zero-length request
2639 // or
2640 //
2641 // DATA
2642 //
2643 // where DATA is the binary data payload.
2644 
2645 rnb_err_t
2646 RNBRemote::HandlePacket_x (const char *p)
2647 {
2648     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2649     {
2650         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
2651     }
2652 
2653     char *c;
2654     p++;
2655     errno = 0;
2656     nub_addr_t addr = strtoull (p, &c, 16);
2657     if (errno != 0)
2658     {
2659         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
2660     }
2661     if (*c != ',')
2662     {
2663         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
2664     }
2665 
2666     /* Advance 'p' to the number of bytes to be read.  */
2667     p += (c - p) + 1;
2668 
2669     errno = 0;
2670     int length = strtoul (p, NULL, 16);
2671     if (errno != 0)
2672     {
2673         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in x packet");
2674     }
2675 
2676     // zero length read means this is a test of whether that packet is implemented or not.
2677     if (length == 0)
2678     {
2679         return SendPacket ("OK");
2680     }
2681 
2682     std::vector<uint8_t> buf (length);
2683 
2684     if (buf.capacity() != length)
2685     {
2686         return SendPacket ("E79");
2687     }
2688     int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
2689     if (bytes_read == 0)
2690     {
2691         return SendPacket ("E80");
2692     }
2693 
2694     std::vector<uint8_t> buf_quoted;
2695     buf_quoted.reserve (bytes_read + 30);
2696     for (int i = 0; i < bytes_read; i++)
2697     {
2698         if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*')
2699         {
2700             buf_quoted.push_back(0x7d);
2701             buf_quoted.push_back(buf[i] ^ 0x20);
2702         }
2703         else
2704         {
2705             buf_quoted.push_back(buf[i]);
2706         }
2707     }
2708     length = buf_quoted.size();
2709 
2710     std::ostringstream ostrm;
2711     for (int i = 0; i < length; i++)
2712         ostrm << buf_quoted[i];
2713 
2714     return SendPacket (ostrm.str ());
2715 }
2716 
2717 rnb_err_t
2718 RNBRemote::HandlePacket_X (const char *p)
2719 {
2720     if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2721     {
2722         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
2723     }
2724 
2725     char *c;
2726     p++;
2727     errno = 0;
2728     nub_addr_t addr = strtoull (p, &c, 16);
2729     if (errno != 0 && addr == 0)
2730     {
2731         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
2732     }
2733     if (*c != ',')
2734     {
2735         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
2736     }
2737 
2738     /* Advance 'p' to the length part of the packet.  NB this is the length of the packet
2739        including any escaped chars.  The data payload may be a little bit smaller after
2740        decoding.  */
2741     p += (c - p) + 1;
2742 
2743     errno = 0;
2744     int length = strtoul (p, NULL, 16);
2745     if (errno != 0 && length == 0)
2746     {
2747         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in X packet");
2748     }
2749 
2750     // I think gdb sends a zero length write request to test whether this
2751     // packet is accepted.
2752     if (length == 0)
2753     {
2754         return SendPacket ("OK");
2755     }
2756 
2757     std::vector<uint8_t> data = decode_binary_data (c, -1);
2758     std::vector<uint8_t>::const_iterator it;
2759     uint8_t *buf = (uint8_t *) alloca (data.size ());
2760     uint8_t *i = buf;
2761     for (it = data.begin (); it != data.end (); ++it)
2762     {
2763         *i++ = *it;
2764     }
2765 
2766     nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf);
2767     if (wrote != data.size ())
2768         return SendPacket ("E08");
2769     return SendPacket ("OK");
2770 }
2771 
2772 /* 'g' -- read registers
2773  Get the contents of the registers for the current thread,
2774  send them to gdb.
2775  Should the setting of the Hg packet determine which thread's registers
2776  are returned?  */
2777 
2778 rnb_err_t
2779 RNBRemote::HandlePacket_g (const char *p)
2780 {
2781     std::ostringstream ostrm;
2782     if (!m_ctx.HasValidProcessID())
2783     {
2784         return SendPacket ("E11");
2785     }
2786 
2787     if (g_num_reg_entries == 0)
2788         InitializeRegisters ();
2789 
2790     nub_process_t pid = m_ctx.ProcessID ();
2791     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
2792     if (tid == INVALID_NUB_THREAD)
2793         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2794 
2795     // Get the register context size first by calling with NULL buffer
2796     nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2797     if (reg_ctx_size)
2798     {
2799         // Now allocate enough space for the entire register context
2800         std::vector<uint8_t> reg_ctx;
2801         reg_ctx.resize(reg_ctx_size);
2802         // Now read the register context
2803         reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
2804         if (reg_ctx_size)
2805         {
2806             append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false);
2807             return SendPacket (ostrm.str ());
2808         }
2809     }
2810     return SendPacket ("E74");
2811 }
2812 
2813 /* 'G XXX...' -- write registers
2814  How is the thread for these specified, beyond "the current thread"?
2815  Does gdb actually use the Hg packet to set this?  */
2816 
2817 rnb_err_t
2818 RNBRemote::HandlePacket_G (const char *p)
2819 {
2820     if (!m_ctx.HasValidProcessID())
2821     {
2822         return SendPacket ("E11");
2823     }
2824 
2825     if (g_num_reg_entries == 0)
2826         InitializeRegisters ();
2827 
2828     StringExtractor packet(p);
2829     packet.SetFilePos(1); // Skip the 'G'
2830 
2831     nub_process_t pid = m_ctx.ProcessID();
2832     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
2833     if (tid == INVALID_NUB_THREAD)
2834         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
2835 
2836     // Get the register context size first by calling with NULL buffer
2837     nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2838     if (reg_ctx_size)
2839     {
2840         // Now allocate enough space for the entire register context
2841         std::vector<uint8_t> reg_ctx;
2842         reg_ctx.resize(reg_ctx_size);
2843 
2844         const nub_size_t bytes_extracted = packet.GetHexBytes (&reg_ctx[0], reg_ctx.size(), 0xcc);
2845         if (bytes_extracted == reg_ctx.size())
2846         {
2847             // Now write the register context
2848             reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
2849             if (reg_ctx_size == reg_ctx.size())
2850                 return SendPacket ("OK");
2851             else
2852                 return SendPacket ("E55");
2853         }
2854         else
2855         {
2856             DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu bytes, size mismatch\n", p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size);
2857             return SendPacket ("E64");
2858         }
2859     }
2860     return SendPacket ("E65");
2861 }
2862 
2863 static bool
2864 RNBRemoteShouldCancelCallback (void *not_used)
2865 {
2866     RNBRemoteSP remoteSP(g_remoteSP);
2867     if (remoteSP.get() != NULL)
2868     {
2869         RNBRemote* remote = remoteSP.get();
2870         if (remote->Comm().IsConnected())
2871             return false;
2872         else
2873             return true;
2874     }
2875     return true;
2876 }
2877 
2878 
2879 // FORMAT: _MXXXXXX,PPP
2880 //      XXXXXX: big endian hex chars
2881 //      PPP: permissions can be any combo of r w x chars
2882 //
2883 // RESPONSE: XXXXXX
2884 //      XXXXXX: hex address of the newly allocated memory
2885 //      EXX: error code
2886 //
2887 // EXAMPLES:
2888 //      _M123000,rw
2889 //      _M123000,rwx
2890 //      _M123000,xw
2891 
2892 rnb_err_t
2893 RNBRemote::HandlePacket_AllocateMemory (const char *p)
2894 {
2895     StringExtractor packet (p);
2896     packet.SetFilePos(2); // Skip the "_M"
2897 
2898     nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0);
2899     if (size != 0)
2900     {
2901         if (packet.GetChar() == ',')
2902         {
2903             uint32_t permissions = 0;
2904             char ch;
2905             bool success = true;
2906             while (success && (ch = packet.GetChar()) != '\0')
2907             {
2908                 switch (ch)
2909                 {
2910                 case 'r':   permissions |= eMemoryPermissionsReadable; break;
2911                 case 'w':   permissions |= eMemoryPermissionsWritable; break;
2912                 case 'x':   permissions |= eMemoryPermissionsExecutable; break;
2913                 default:    success = false; break;
2914                 }
2915             }
2916 
2917             if (success)
2918             {
2919                 nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions);
2920                 if (addr != INVALID_NUB_ADDRESS)
2921                 {
2922                     std::ostringstream ostrm;
2923                     ostrm << RAW_HEXBASE << addr;
2924                     return SendPacket (ostrm.str ());
2925                 }
2926             }
2927         }
2928     }
2929     return SendPacket ("E53");
2930 }
2931 
2932 // FORMAT: _mXXXXXX
2933 //      XXXXXX: address that was previously allocated
2934 //
2935 // RESPONSE: XXXXXX
2936 //      OK: address was deallocated
2937 //      EXX: error code
2938 //
2939 // EXAMPLES:
2940 //      _m123000
2941 
2942 rnb_err_t
2943 RNBRemote::HandlePacket_DeallocateMemory (const char *p)
2944 {
2945     StringExtractor packet (p);
2946     packet.SetFilePos(2); // Skip the "_m"
2947     nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS);
2948 
2949     if (addr != INVALID_NUB_ADDRESS)
2950     {
2951         if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr))
2952             return SendPacket ("OK");
2953     }
2954     return SendPacket ("E54");
2955 }
2956 
2957 
2958 // FORMAT: QSaveRegisterState;thread:TTTT;  (when thread suffix is supported)
2959 // FORMAT: QSaveRegisterState               (when thread suffix is NOT supported)
2960 //      TTTT: thread ID in hex
2961 //
2962 // RESPONSE:
2963 //      SAVEID: Where SAVEID is a decimal number that represents the save ID
2964 //              that can be passed back into a "QRestoreRegisterState" packet
2965 //      EXX: error code
2966 //
2967 // EXAMPLES:
2968 //      QSaveRegisterState;thread:1E34;     (when thread suffix is supported)
2969 //      QSaveRegisterState                  (when thread suffix is NOT supported)
2970 
2971 rnb_err_t
2972 RNBRemote::HandlePacket_SaveRegisterState (const char *p)
2973 {
2974     nub_process_t pid = m_ctx.ProcessID ();
2975     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
2976     if (tid == INVALID_NUB_THREAD)
2977     {
2978         if (m_thread_suffix_supported)
2979             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in QSaveRegisterState packet");
2980         else
2981             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread was is set with the Hg packet");
2982     }
2983 
2984     // Get the register context size first by calling with NULL buffer
2985     const uint32_t save_id = DNBThreadSaveRegisterState(pid, tid);
2986     if (save_id != 0)
2987     {
2988         char response[64];
2989         snprintf (response, sizeof(response), "%u", save_id);
2990         return SendPacket (response);
2991     }
2992     else
2993     {
2994         return SendPacket ("E75");
2995     }
2996 }
2997 // FORMAT: QRestoreRegisterState:SAVEID;thread:TTTT;  (when thread suffix is supported)
2998 // FORMAT: QRestoreRegisterState:SAVEID               (when thread suffix is NOT supported)
2999 //      TTTT: thread ID in hex
3000 //      SAVEID: a decimal number that represents the save ID that was
3001 //              returned from a call to "QSaveRegisterState"
3002 //
3003 // RESPONSE:
3004 //      OK: successfully restored registers for the specified thread
3005 //      EXX: error code
3006 //
3007 // EXAMPLES:
3008 //      QRestoreRegisterState:1;thread:1E34;     (when thread suffix is supported)
3009 //      QRestoreRegisterState:1                  (when thread suffix is NOT supported)
3010 
3011 rnb_err_t
3012 RNBRemote::HandlePacket_RestoreRegisterState (const char *p)
3013 {
3014     nub_process_t pid = m_ctx.ProcessID ();
3015     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
3016     if (tid == INVALID_NUB_THREAD)
3017     {
3018         if (m_thread_suffix_supported)
3019             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in QSaveRegisterState packet");
3020         else
3021             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread was is set with the Hg packet");
3022     }
3023 
3024     StringExtractor packet (p);
3025     packet.SetFilePos(strlen("QRestoreRegisterState:")); // Skip the "QRestoreRegisterState:"
3026     const uint32_t save_id = packet.GetU32(0);
3027 
3028     if (save_id != 0)
3029     {
3030         // Get the register context size first by calling with NULL buffer
3031         if (DNBThreadRestoreRegisterState(pid, tid, save_id))
3032             return SendPacket ("OK");
3033         else
3034             return SendPacket ("E77");
3035     }
3036     return SendPacket ("E76");
3037 }
3038 
3039 static bool
3040 GetProcessNameFrom_vAttach (const char *&p, std::string &attach_name)
3041 {
3042     bool return_val = true;
3043     while (*p != '\0')
3044     {
3045         char smallbuf[3];
3046         smallbuf[0] = *p;
3047         smallbuf[1] = *(p + 1);
3048         smallbuf[2] = '\0';
3049 
3050         errno = 0;
3051         int ch = strtoul (smallbuf, NULL, 16);
3052         if (errno != 0 && ch == 0)
3053         {
3054             return_val = false;
3055             break;
3056         }
3057 
3058         attach_name.push_back(ch);
3059         p += 2;
3060     }
3061     return return_val;
3062 }
3063 
3064 rnb_err_t
3065 RNBRemote::HandlePacket_qSupported (const char *p)
3066 {
3067     uint32_t max_packet_size = 128 * 1024;  // 128KBytes is a reasonable max packet size--debugger can always use less
3068     char buf[64];
3069     snprintf (buf, sizeof(buf), "PacketSize=%x", max_packet_size);
3070     return SendPacket (buf);
3071 }
3072 
3073 /*
3074  vAttach;pid
3075 
3076  Attach to a new process with the specified process ID. pid is a hexadecimal integer
3077  identifying the process. If the stub is currently controlling a process, it is
3078  killed. The attached process is stopped.This packet is only available in extended
3079  mode (see extended mode).
3080 
3081  Reply:
3082  "ENN"                      for an error
3083  "Any Stop Reply Packet"     for success
3084  */
3085 
3086 rnb_err_t
3087 RNBRemote::HandlePacket_v (const char *p)
3088 {
3089     if (strcmp (p, "vCont;c") == 0)
3090     {
3091         // Simple continue
3092         return RNBRemote::HandlePacket_c("c");
3093     }
3094     else if (strcmp (p, "vCont;s") == 0)
3095     {
3096         // Simple step
3097         return RNBRemote::HandlePacket_s("s");
3098     }
3099     else if (strstr (p, "vCont") == p)
3100     {
3101         typedef struct
3102         {
3103             nub_thread_t tid;
3104             char action;
3105             int signal;
3106         } vcont_action_t;
3107 
3108         DNBThreadResumeActions thread_actions;
3109         char *c = (char *)(p += strlen("vCont"));
3110         char *c_end = c + strlen(c);
3111         if (*c == '?')
3112             return SendPacket ("vCont;c;C;s;S");
3113 
3114         while (c < c_end && *c == ';')
3115         {
3116             ++c;    // Skip the semi-colon
3117             DNBThreadResumeAction thread_action;
3118             thread_action.tid = INVALID_NUB_THREAD;
3119             thread_action.state = eStateInvalid;
3120             thread_action.signal = 0;
3121             thread_action.addr = INVALID_NUB_ADDRESS;
3122 
3123             char action = *c++;
3124 
3125             switch (action)
3126             {
3127                 case 'C':
3128                     errno = 0;
3129                     thread_action.signal = strtoul (c, &c, 16);
3130                     if (errno != 0)
3131                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3132                     // Fall through to next case...
3133 
3134                 case 'c':
3135                     // Continue
3136                     thread_action.state = eStateRunning;
3137                     break;
3138 
3139                 case 'S':
3140                     errno = 0;
3141                     thread_action.signal = strtoul (c, &c, 16);
3142                     if (errno != 0)
3143                         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
3144                     // Fall through to next case...
3145 
3146                 case 's':
3147                     // Step
3148                     thread_action.state = eStateStepping;
3149                     break;
3150 
3151                 default:
3152                     HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet");
3153                     break;
3154             }
3155             if (*c == ':')
3156             {
3157                 errno = 0;
3158                 thread_action.tid = strtoul (++c, &c, 16);
3159                 if (errno != 0)
3160                     return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet");
3161             }
3162 
3163             thread_actions.Append (thread_action);
3164         }
3165 
3166         // If a default action for all other threads wasn't mentioned
3167         // then we should stop the threads
3168         thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3169         DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize());
3170         return rnb_success;
3171     }
3172     else if (strstr (p, "vAttach") == p)
3173     {
3174         nub_process_t attach_pid = INVALID_NUB_PROCESS;
3175         char err_str[1024]={'\0'};
3176 
3177         if (strstr (p, "vAttachWait;") == p)
3178         {
3179             p += strlen("vAttachWait;");
3180             std::string attach_name;
3181             if (!GetProcessNameFrom_vAttach(p, attach_name))
3182             {
3183                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
3184             }
3185             const bool ignore_existing = true;
3186             attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3187 
3188         }
3189         else if (strstr (p, "vAttachOrWait;") == p)
3190         {
3191             p += strlen("vAttachOrWait;");
3192             std::string attach_name;
3193             if (!GetProcessNameFrom_vAttach(p, attach_name))
3194             {
3195                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt");
3196             }
3197             const bool ignore_existing = false;
3198             attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
3199         }
3200         else if (strstr (p, "vAttachName;") == p)
3201         {
3202             p += strlen("vAttachName;");
3203             std::string attach_name;
3204             if (!GetProcessNameFrom_vAttach(p, attach_name))
3205             {
3206                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt");
3207             }
3208 
3209             attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
3210 
3211         }
3212         else if (strstr (p, "vAttach;") == p)
3213         {
3214             p += strlen("vAttach;");
3215             char *end = NULL;
3216             attach_pid = strtoul (p, &end, 16);    // PID will be in hex, so use base 16 to decode
3217             if (p != end && *end == '\0')
3218             {
3219                 // Wait at most 30 second for attach
3220                 struct timespec attach_timeout_abstime;
3221                 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
3222                 attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str));
3223             }
3224         }
3225         else
3226         {
3227             return HandlePacket_UNIMPLEMENTED(p);
3228         }
3229 
3230 
3231         if (attach_pid != INVALID_NUB_PROCESS)
3232         {
3233             if (m_ctx.ProcessID() != attach_pid)
3234                 m_ctx.SetProcessID(attach_pid);
3235             // Send a stop reply packet to indicate we successfully attached!
3236             NotifyThatProcessStopped ();
3237             return rnb_success;
3238         }
3239         else
3240         {
3241             m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
3242             if (err_str[0])
3243                 m_ctx.LaunchStatus().SetErrorString(err_str);
3244             else
3245                 m_ctx.LaunchStatus().SetErrorString("attach failed");
3246             SendPacket ("E01");  // E01 is our magic error value for attach failed.
3247             DNBLogError ("Attach failed: \"%s\".", err_str);
3248             return rnb_err;
3249         }
3250     }
3251 
3252     // All other failures come through here
3253     return HandlePacket_UNIMPLEMENTED(p);
3254 }
3255 
3256 /* 'T XX' -- status of thread
3257  Check if the specified thread is alive.
3258  The thread number is in hex?  */
3259 
3260 rnb_err_t
3261 RNBRemote::HandlePacket_T (const char *p)
3262 {
3263     p++;
3264     if (p == NULL || *p == '\0')
3265     {
3266         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet");
3267     }
3268     if (!m_ctx.HasValidProcessID())
3269     {
3270         return SendPacket ("E15");
3271     }
3272     errno = 0;
3273     nub_thread_t tid = strtoul (p, NULL, 16);
3274     if (errno != 0 && tid == 0)
3275     {
3276         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet");
3277     }
3278 
3279     nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid);
3280     if (state == eStateInvalid || state == eStateExited || state == eStateCrashed)
3281     {
3282         return SendPacket ("E16");
3283     }
3284 
3285     return SendPacket ("OK");
3286 }
3287 
3288 
3289 rnb_err_t
3290 RNBRemote::HandlePacket_z (const char *p)
3291 {
3292     if (p == NULL || *p == '\0')
3293         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet");
3294 
3295     if (!m_ctx.HasValidProcessID())
3296         return SendPacket ("E15");
3297 
3298     char packet_cmd = *p++;
3299     char break_type = *p++;
3300 
3301     if (*p++ != ',')
3302         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
3303 
3304     char *c = NULL;
3305     nub_process_t pid = m_ctx.ProcessID();
3306     errno = 0;
3307     nub_addr_t addr = strtoull (p, &c, 16);
3308     if (errno != 0 && addr == 0)
3309         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet");
3310     p = c;
3311     if (*p++ != ',')
3312         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
3313 
3314     errno = 0;
3315     uint32_t byte_size = strtoul (p, &c, 16);
3316     if (errno != 0 && byte_size == 0)
3317         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet");
3318 
3319     if (packet_cmd == 'Z')
3320     {
3321         // set
3322         switch (break_type)
3323         {
3324             case '0':   // set software breakpoint
3325             case '1':   // set hardware breakpoint
3326                 {
3327                     // gdb can send multiple Z packets for the same address and
3328                     // these calls must be ref counted.
3329                     bool hardware = (break_type == '1');
3330 
3331                     if (DNBBreakpointSet (pid, addr, byte_size, hardware))
3332                     {
3333                         // We successfully created a breakpoint, now lets full out
3334                         // a ref count structure with the breakID and add it to our
3335                         // map.
3336                         return SendPacket ("OK");
3337                     }
3338                     else
3339                     {
3340                         // We failed to set the software breakpoint
3341                         return SendPacket ("E09");
3342                     }
3343                 }
3344                 break;
3345 
3346             case '2':   // set write watchpoint
3347             case '3':   // set read watchpoint
3348             case '4':   // set access watchpoint
3349                 {
3350                     bool hardware = true;
3351                     uint32_t watch_flags = 0;
3352                     if (break_type == '2')
3353                         watch_flags = WATCH_TYPE_WRITE;
3354                     else if (break_type == '3')
3355                         watch_flags = WATCH_TYPE_READ;
3356                     else
3357                         watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
3358 
3359                     if (DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware))
3360                     {
3361                         return SendPacket ("OK");
3362                     }
3363                     else
3364                     {
3365                         // We failed to set the watchpoint
3366                         return SendPacket ("E09");
3367                     }
3368                 }
3369                 break;
3370 
3371             default:
3372                 break;
3373         }
3374     }
3375     else if (packet_cmd == 'z')
3376     {
3377         // remove
3378         switch (break_type)
3379         {
3380             case '0':   // remove software breakpoint
3381             case '1':   // remove hardware breakpoint
3382                 if (DNBBreakpointClear (pid, addr))
3383                 {
3384                     return SendPacket ("OK");
3385                 }
3386                 else
3387                 {
3388                     return SendPacket ("E08");
3389                 }
3390                 break;
3391 
3392             case '2':   // remove write watchpoint
3393             case '3':   // remove read watchpoint
3394             case '4':   // remove access watchpoint
3395                 if (DNBWatchpointClear (pid, addr))
3396                 {
3397                     return SendPacket ("OK");
3398                 }
3399                 else
3400                 {
3401                     return SendPacket ("E08");
3402                 }
3403                 break;
3404 
3405             default:
3406                 break;
3407         }
3408     }
3409     return HandlePacket_UNIMPLEMENTED(p);
3410 }
3411 
3412 // Extract the thread number from the thread suffix that might be appended to
3413 // thread specific packets. This will only be enabled if m_thread_suffix_supported
3414 // is true.
3415 nub_thread_t
3416 RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
3417 {
3418     if (m_thread_suffix_supported)
3419     {
3420         nub_thread_t tid = INVALID_NUB_THREAD;
3421         if (p)
3422         {
3423             const char *tid_cstr = strstr (p, "thread:");
3424             if (tid_cstr)
3425             {
3426                 tid_cstr += strlen ("thread:");
3427                 tid = strtoul(tid_cstr, NULL, 16);
3428             }
3429         }
3430         return tid;
3431     }
3432     return GetCurrentThread();
3433 
3434 }
3435 
3436 /* 'p XX'
3437  print the contents of register X */
3438 
3439 rnb_err_t
3440 RNBRemote::HandlePacket_p (const char *p)
3441 {
3442     if (g_num_reg_entries == 0)
3443         InitializeRegisters ();
3444 
3445     if (p == NULL || *p == '\0')
3446     {
3447         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3448     }
3449     if (!m_ctx.HasValidProcessID())
3450     {
3451         return SendPacket ("E15");
3452     }
3453     nub_process_t pid = m_ctx.ProcessID();
3454     errno = 0;
3455     char *tid_cstr = NULL;
3456     uint32_t reg = strtoul (p + 1, &tid_cstr, 16);
3457     if (errno != 0 && reg == 0)
3458     {
3459         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet");
3460     }
3461 
3462     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
3463     if (tid == INVALID_NUB_THREAD)
3464         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3465 
3466     const register_map_entry_t *reg_entry;
3467 
3468     if (reg < g_num_reg_entries)
3469         reg_entry = &g_reg_entries[reg];
3470     else
3471         reg_entry = NULL;
3472 
3473     std::ostringstream ostrm;
3474     if (reg_entry == NULL)
3475     {
3476         DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg);
3477         ostrm << "00000000";
3478     }
3479     else if (reg_entry->nub_info.reg == -1)
3480     {
3481         if (reg_entry->nub_info.size > 0)
3482         {
3483             std::basic_string<uint8_t> zeros(reg_entry->nub_info.size, '\0');
3484             append_hex_value(ostrm, zeros.data(), zeros.size(), false);
3485         }
3486     }
3487     else
3488     {
3489         register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry, NULL);
3490     }
3491     return SendPacket (ostrm.str());
3492 }
3493 
3494 /* 'Pnn=rrrrr'
3495  Set register number n to value r.
3496  n and r are hex strings.  */
3497 
3498 rnb_err_t
3499 RNBRemote::HandlePacket_P (const char *p)
3500 {
3501     if (g_num_reg_entries == 0)
3502         InitializeRegisters ();
3503 
3504     if (p == NULL || *p == '\0')
3505     {
3506         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet");
3507     }
3508     if (!m_ctx.HasValidProcessID())
3509     {
3510         return SendPacket ("E28");
3511     }
3512 
3513     nub_process_t pid = m_ctx.ProcessID();
3514 
3515     StringExtractor packet (p);
3516 
3517     const char cmd_char = packet.GetChar();
3518     // Register ID is always in big endian
3519     const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX);
3520     const char equal_char = packet.GetChar();
3521 
3522     if (cmd_char != 'P')
3523         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet");
3524 
3525     if (reg == UINT32_MAX)
3526         return SendPacket ("E29");
3527 
3528     if (equal_char != '=')
3529         return SendPacket ("E30");
3530 
3531     const register_map_entry_t *reg_entry;
3532 
3533     if (reg >= g_num_reg_entries)
3534         return SendPacket("E47");
3535 
3536     reg_entry = &g_reg_entries[reg];
3537 
3538     if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1)
3539     {
3540         DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg);
3541         return SendPacket("E48");
3542     }
3543 
3544     DNBRegisterValue reg_value;
3545     reg_value.info = reg_entry->nub_info;
3546     packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->nub_info.size, 0xcc);
3547 
3548     nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
3549     if (tid == INVALID_NUB_THREAD)
3550         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
3551 
3552     if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
3553     {
3554         return SendPacket ("E32");
3555     }
3556     return SendPacket ("OK");
3557 }
3558 
3559 /* 'c [addr]'
3560  Continue, optionally from a specified address. */
3561 
3562 rnb_err_t
3563 RNBRemote::HandlePacket_c (const char *p)
3564 {
3565     const nub_process_t pid = m_ctx.ProcessID();
3566 
3567     if (pid == INVALID_NUB_PROCESS)
3568         return SendPacket ("E23");
3569 
3570     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3571 
3572     if (*(p + 1) != '\0')
3573     {
3574         action.tid = GetContinueThread();
3575         errno = 0;
3576         action.addr = strtoull (p + 1, NULL, 16);
3577         if (errno != 0 && action.addr == 0)
3578             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet");
3579     }
3580 
3581     DNBThreadResumeActions thread_actions;
3582     thread_actions.Append(action);
3583     thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
3584     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3585         return SendPacket ("E25");
3586     // Don't send an "OK" packet; response is the stopped/exited message.
3587     return rnb_success;
3588 }
3589 
3590 rnb_err_t
3591 RNBRemote::HandlePacket_MemoryRegionInfo (const char *p)
3592 {
3593     /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code)
3594        for the memory region containing a given address and return that information.
3595 
3596        Users of this packet must be prepared for three results:
3597 
3598            Region information is returned
3599            Region information is unavailable for this address because the address is in unmapped memory
3600            Region lookup cannot be performed on this platform or process is not yet launched
3601            This packet isn't implemented
3602 
3603        Examples of use:
3604           qMemoryRegionInfo:3a55140
3605           start:3a50000,size:100000,permissions:rwx
3606 
3607           qMemoryRegionInfo:0
3608           error:address in unmapped region
3609 
3610           qMemoryRegionInfo:3a551140   (on a different platform)
3611           error:region lookup cannot be performed
3612 
3613           qMemoryRegionInfo
3614           OK                   // this packet is implemented by the remote nub
3615     */
3616 
3617     p += sizeof ("qMemoryRegionInfo") - 1;
3618     if (*p == '\0')
3619        return SendPacket ("OK");
3620     if (*p++ != ':')
3621        return SendPacket ("E67");
3622     if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
3623        p += 2;
3624 
3625     errno = 0;
3626     uint64_t address = strtoul (p, NULL, 16);
3627     if (errno != 0 && address == 0)
3628     {
3629         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet");
3630     }
3631 
3632     DNBRegionInfo region_info = { 0, 0, 0 };
3633     DNBProcessMemoryRegionInfo (m_ctx.ProcessID(), address, &region_info);
3634     std::ostringstream ostrm;
3635 
3636         // start:3a50000,size:100000,permissions:rwx
3637     ostrm << "start:" << std::hex << region_info.addr << ';';
3638 
3639     if (region_info.size > 0)
3640         ostrm << "size:"  << std::hex << region_info.size << ';';
3641 
3642     if (region_info.permissions)
3643     {
3644         ostrm << "permissions:";
3645 
3646         if (region_info.permissions & eMemoryPermissionsReadable)
3647             ostrm << 'r';
3648         if (region_info.permissions & eMemoryPermissionsWritable)
3649             ostrm << 'w';
3650         if (region_info.permissions & eMemoryPermissionsExecutable)
3651             ostrm << 'x';
3652         ostrm << ';';
3653     }
3654     return SendPacket (ostrm.str());
3655 }
3656 
3657 // qGetProfileData;scan_type:0xYYYYYYY
3658 rnb_err_t
3659 RNBRemote::HandlePacket_GetProfileData (const char *p)
3660 {
3661     nub_process_t pid = m_ctx.ProcessID();
3662     if (pid == INVALID_NUB_PROCESS)
3663         return SendPacket ("OK");
3664 
3665     StringExtractor packet(p += sizeof ("qGetProfileData"));
3666     DNBProfileDataScanType scan_type = eProfileAll;
3667     std::string name;
3668     std::string value;
3669     while (packet.GetNameColonValue(name, value))
3670     {
3671         if (name.compare ("scan_type") == 0)
3672         {
3673             std::istringstream iss(value);
3674             uint32_t int_value = 0;
3675             if (iss >> std::hex >> int_value)
3676             {
3677                 scan_type = (DNBProfileDataScanType)int_value;
3678             }
3679         }
3680     }
3681 
3682     std::string data = DNBProcessGetProfileData(pid, scan_type);
3683     if (!data.empty())
3684     {
3685         return SendPacket (data.c_str());
3686     }
3687     else
3688     {
3689         return SendPacket ("OK");
3690     }
3691 }
3692 
3693 // QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY
3694 rnb_err_t
3695 RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p)
3696 {
3697     nub_process_t pid = m_ctx.ProcessID();
3698     if (pid == INVALID_NUB_PROCESS)
3699         return SendPacket ("OK");
3700 
3701     StringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling"));
3702     bool enable = false;
3703     uint64_t interval_usec = 0;
3704     DNBProfileDataScanType scan_type = eProfileAll;
3705     std::string name;
3706     std::string value;
3707     while (packet.GetNameColonValue(name, value))
3708     {
3709         if (name.compare ("enable") == 0)
3710         {
3711             enable  = strtoul(value.c_str(), NULL, 10) > 0;
3712         }
3713         else if (name.compare ("interval_usec") == 0)
3714         {
3715             interval_usec  = strtoul(value.c_str(), NULL, 10);
3716         }
3717         else if (name.compare ("scan_type") == 0)
3718         {
3719             std::istringstream iss(value);
3720             uint32_t int_value = 0;
3721             if (iss >> std::hex >> int_value)
3722             {
3723                 scan_type = (DNBProfileDataScanType)int_value;
3724             }
3725         }
3726     }
3727 
3728     if (interval_usec == 0)
3729     {
3730         enable = 0;
3731     }
3732 
3733     DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type);
3734     return SendPacket ("OK");
3735 }
3736 
3737 
3738 rnb_err_t
3739 RNBRemote::HandlePacket_qSpeedTest (const char *p)
3740 {
3741     p += strlen ("qSpeedTest:response_size:");
3742     char *end = NULL;
3743     errno = 0;
3744     uint64_t response_size = ::strtoul (p, &end, 16);
3745     if (errno != 0)
3746         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Didn't find response_size value at right offset");
3747     else if (*end == ';')
3748     {
3749         static char g_data[4*1024*1024+16] = "data:";
3750         memset(g_data + 5, 'a', response_size);
3751         g_data[response_size + 5] = '\0';
3752         return SendPacket (g_data);
3753     }
3754     else
3755     {
3756         return SendPacket ("E79");
3757     }
3758 }
3759 
3760 rnb_err_t
3761 RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p)
3762 {
3763     /* This packet simply returns the number of supported hardware watchpoints.
3764 
3765        Examples of use:
3766           qWatchpointSupportInfo:
3767           num:4
3768 
3769           qWatchpointSupportInfo
3770           OK                   // this packet is implemented by the remote nub
3771     */
3772 
3773     p += sizeof ("qWatchpointSupportInfo") - 1;
3774     if (*p == '\0')
3775        return SendPacket ("OK");
3776     if (*p++ != ':')
3777        return SendPacket ("E67");
3778 
3779     errno = 0;
3780     uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID());
3781     std::ostringstream ostrm;
3782 
3783     // size:4
3784     ostrm << "num:" << std::dec << num << ';';
3785     return SendPacket (ostrm.str());
3786 }
3787 
3788 /* 'C sig [;addr]'
3789  Resume with signal sig, optionally at address addr.  */
3790 
3791 rnb_err_t
3792 RNBRemote::HandlePacket_C (const char *p)
3793 {
3794     const nub_process_t pid = m_ctx.ProcessID();
3795 
3796     if (pid == INVALID_NUB_PROCESS)
3797         return SendPacket ("E36");
3798 
3799     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3800     int process_signo = -1;
3801     if (*(p + 1) != '\0')
3802     {
3803         action.tid = GetContinueThread();
3804         char *end = NULL;
3805         errno = 0;
3806         process_signo = strtoul (p + 1, &end, 16);
3807         if (errno != 0)
3808             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet");
3809         else if (*end == ';')
3810         {
3811             errno = 0;
3812             action.addr = strtoull (end + 1, NULL, 16);
3813             if (errno != 0 && action.addr == 0)
3814                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet");
3815         }
3816     }
3817 
3818     DNBThreadResumeActions thread_actions;
3819     thread_actions.Append (action);
3820     thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal);
3821     if (!DNBProcessSignal(pid, process_signo))
3822         return SendPacket ("E52");
3823     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3824         return SendPacket ("E38");
3825     /* Don't send an "OK" packet; response is the stopped/exited message.  */
3826     return rnb_success;
3827 }
3828 
3829 //----------------------------------------------------------------------
3830 // 'D' packet
3831 // Detach from gdb.
3832 //----------------------------------------------------------------------
3833 rnb_err_t
3834 RNBRemote::HandlePacket_D (const char *p)
3835 {
3836     if (m_ctx.HasValidProcessID())
3837     {
3838         if (DNBProcessDetach(m_ctx.ProcessID()))
3839             SendPacket ("OK");
3840         else
3841             SendPacket ("E");
3842     }
3843     else
3844     {
3845         SendPacket ("E");
3846     }
3847     return rnb_success;
3848 }
3849 
3850 /* 'k'
3851  Kill the inferior process.  */
3852 
3853 rnb_err_t
3854 RNBRemote::HandlePacket_k (const char *p)
3855 {
3856     DNBLog ("Got a 'k' packet, killing the inferior process.");
3857     // No response to should be sent to the kill packet
3858     if (m_ctx.HasValidProcessID())
3859         DNBProcessKill (m_ctx.ProcessID());
3860     SendPacket ("X09");
3861     return rnb_success;
3862 }
3863 
3864 rnb_err_t
3865 RNBRemote::HandlePacket_stop_process (const char *p)
3866 {
3867 //#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test exiting on interrupt
3868 #if defined(TEST_EXIT_ON_INTERRUPT)
3869     rnb_err_t err = HandlePacket_k (p);
3870     m_comm.Disconnect(true);
3871     return err;
3872 #else
3873     if (!DNBProcessInterrupt(m_ctx.ProcessID()))
3874     {
3875         // If we failed to interrupt the process, then send a stop
3876         // reply packet as the process was probably already stopped
3877         HandlePacket_last_signal (NULL);
3878     }
3879     return rnb_success;
3880 #endif
3881 }
3882 
3883 /* 's'
3884  Step the inferior process.  */
3885 
3886 rnb_err_t
3887 RNBRemote::HandlePacket_s (const char *p)
3888 {
3889     const nub_process_t pid = m_ctx.ProcessID();
3890     if (pid == INVALID_NUB_PROCESS)
3891         return SendPacket ("E32");
3892 
3893     // Hardware supported stepping not supported on arm
3894     nub_thread_t tid = GetContinueThread ();
3895     if (tid == 0 || tid == -1)
3896         tid = GetCurrentThread();
3897 
3898     if (tid == INVALID_NUB_THREAD)
3899         return SendPacket ("E33");
3900 
3901     DNBThreadResumeActions thread_actions;
3902     thread_actions.AppendAction(tid, eStateStepping);
3903 
3904     // Make all other threads stop when we are stepping
3905     thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3906     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3907         return SendPacket ("E49");
3908     // Don't send an "OK" packet; response is the stopped/exited message.
3909     return rnb_success;
3910 }
3911 
3912 /* 'S sig [;addr]'
3913  Step with signal sig, optionally at address addr.  */
3914 
3915 rnb_err_t
3916 RNBRemote::HandlePacket_S (const char *p)
3917 {
3918     const nub_process_t pid = m_ctx.ProcessID();
3919     if (pid == INVALID_NUB_PROCESS)
3920         return SendPacket ("E36");
3921 
3922     DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
3923 
3924     if (*(p + 1) != '\0')
3925     {
3926         char *end = NULL;
3927         errno = 0;
3928         action.signal = strtoul (p + 1, &end, 16);
3929         if (errno != 0)
3930             return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
3931         else if (*end == ';')
3932         {
3933             errno = 0;
3934             action.addr = strtoull (end + 1, NULL, 16);
3935             if (errno != 0 && action.addr == 0)
3936             {
3937                 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
3938             }
3939         }
3940     }
3941 
3942     action.tid = GetContinueThread ();
3943     if (action.tid == 0 || action.tid == -1)
3944         return SendPacket ("E40");
3945 
3946     nub_state_t tstate = DNBThreadGetState (pid, action.tid);
3947     if (tstate == eStateInvalid || tstate == eStateExited)
3948         return SendPacket ("E37");
3949 
3950 
3951     DNBThreadResumeActions thread_actions;
3952     thread_actions.Append (action);
3953 
3954     // Make all other threads stop when we are stepping
3955     thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3956     if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3957         return SendPacket ("E39");
3958 
3959     // Don't send an "OK" packet; response is the stopped/exited message.
3960     return rnb_success;
3961 }
3962 
3963 rnb_err_t
3964 RNBRemote::HandlePacket_qHostInfo (const char *p)
3965 {
3966     std::ostringstream strm;
3967 
3968     uint32_t cputype, is_64_bit_capable;
3969     size_t len = sizeof(cputype);
3970     bool promoted_to_64 = false;
3971     if  (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
3972     {
3973         len = sizeof (is_64_bit_capable);
3974         if  (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
3975         {
3976             if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
3977             {
3978                 promoted_to_64 = true;
3979                 cputype |= CPU_ARCH_ABI64;
3980             }
3981         }
3982 
3983         strm << "cputype:" << std::dec << cputype << ';';
3984     }
3985 
3986     uint32_t cpusubtype;
3987     len = sizeof(cpusubtype);
3988     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
3989     {
3990         if (promoted_to_64 &&
3991             cputype == CPU_TYPE_X86_64 &&
3992             cpusubtype == CPU_SUBTYPE_486)
3993             cpusubtype = CPU_SUBTYPE_X86_64_ALL;
3994 
3995         strm << "cpusubtype:" << std::dec << cpusubtype << ';';
3996     }
3997 
3998     // The OS in the triple should be "ios" or "macosx" which doesn't match our
3999     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4000     // this for now.
4001     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
4002     {
4003         strm << "ostype:ios;";
4004         // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
4005         strm << "watchpoint_exceptions_received:before;";
4006     }
4007     else
4008     {
4009         strm << "ostype:macosx;";
4010         strm << "watchpoint_exceptions_received:after;";
4011     }
4012 //    char ostype[64];
4013 //    len = sizeof(ostype);
4014 //    if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
4015 //    {
4016 //        len = strlen(ostype);
4017 //        std::transform (ostype, ostype + len, ostype, tolower);
4018 //        strm << "ostype:" << std::dec << ostype << ';';
4019 //    }
4020 
4021     strm << "vendor:apple;";
4022 
4023 #if defined (__LITTLE_ENDIAN__)
4024     strm << "endian:little;";
4025 #elif defined (__BIG_ENDIAN__)
4026     strm << "endian:big;";
4027 #elif defined (__PDP_ENDIAN__)
4028     strm << "endian:pdp;";
4029 #endif
4030 
4031     if (promoted_to_64)
4032         strm << "ptrsize:8;";
4033     else
4034         strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
4035     return SendPacket (strm.str());
4036 }
4037 
4038 rnb_err_t
4039 RNBRemote::HandlePacket_qGDBServerVersion (const char *p)
4040 {
4041     std::ostringstream strm;
4042 
4043     if (DEBUGSERVER_PROGRAM_NAME)
4044         strm << "name:" DEBUGSERVER_PROGRAM_NAME ";";
4045     else
4046         strm << "name:debugserver;";
4047     strm << "version:" << DEBUGSERVER_VERSION_STR << ";";
4048 
4049     return SendPacket (strm.str());
4050 }
4051 
4052 // A helper function that retrieves a single integer value from
4053 // a one-level-deep JSON dictionary of key-value pairs.  e.g.
4054 // jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
4055 //
4056 uint64_t
4057 get_integer_value_for_key_name_from_json (const char *key, const char *json_string)
4058 {
4059     uint64_t retval = INVALID_NUB_ADDRESS;
4060     std::string key_with_quotes = "\"";
4061     key_with_quotes += key;
4062     key_with_quotes += "\":";
4063     const char *c = strstr (json_string, key_with_quotes.c_str());
4064     if (c)
4065     {
4066         c += key_with_quotes.size();
4067         errno = 0;
4068         retval = strtoul (c, NULL, 10);
4069         if (errno != 0)
4070         {
4071             retval = INVALID_NUB_ADDRESS;
4072         }
4073     }
4074     return retval;
4075 
4076 }
4077 
4078 rnb_err_t
4079 RNBRemote::HandlePacket_jThreadExtendedInfo (const char *p)
4080 {
4081     nub_process_t pid;
4082     std::ostringstream json;
4083     std::ostringstream reply_strm;
4084     // If we haven't run the process yet, return an error.
4085     if (!m_ctx.HasValidProcessID())
4086     {
4087         return SendPacket ("E81");
4088     }
4089 
4090     pid = m_ctx.ProcessID();
4091 
4092     const char thread_extended_info_str[] = { "jThreadExtendedInfo:{" };
4093     if (strncmp (p, thread_extended_info_str, sizeof (thread_extended_info_str) - 1) == 0)
4094     {
4095         p += strlen (thread_extended_info_str);
4096 
4097         uint64_t tid = get_integer_value_for_key_name_from_json ("thread", p);
4098         uint64_t plo_pthread_tsd_base_address_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_address_offset", p);
4099         uint64_t plo_pthread_tsd_base_offset = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_base_offset", p);
4100         uint64_t plo_pthread_tsd_entry_size = get_integer_value_for_key_name_from_json ("plo_pthread_tsd_entry_size", p);
4101         uint64_t dti_qos_class_index = get_integer_value_for_key_name_from_json ("dti_qos_class_index", p);
4102         // Commented out the two variables below as they are not being used
4103 //        uint64_t dti_queue_index = get_integer_value_for_key_name_from_json ("dti_queue_index", p);
4104 //        uint64_t dti_voucher_index = get_integer_value_for_key_name_from_json ("dti_voucher_index", p);
4105 
4106         if (tid != INVALID_NUB_ADDRESS)
4107         {
4108             nub_addr_t pthread_t_value = DNBGetPThreadT (pid, tid);
4109 
4110             uint64_t tsd_address = INVALID_NUB_ADDRESS;
4111             if (plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS
4112                 && plo_pthread_tsd_base_offset != INVALID_NUB_ADDRESS
4113                 && plo_pthread_tsd_entry_size != INVALID_NUB_ADDRESS)
4114             {
4115                 tsd_address = DNBGetTSDAddressForThread (pid, tid, plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset, plo_pthread_tsd_entry_size);
4116             }
4117 
4118             bool timed_out = false;
4119             Genealogy::ThreadActivitySP thread_activity_sp;
4120 
4121             // If the pthread_t value is invalid, or if we were able to fetch the thread's TSD base
4122             // and got an invalid value back, then we have a thread in early startup or shutdown and
4123             // it's possible that gathering the genealogy information for this thread go badly.
4124             // Ideally fetching this info for a thread in these odd states shouldn't matter - but
4125             // we've seen some problems with these new SPI and threads in edge-casey states.
4126 
4127             double genealogy_fetch_time = 0;
4128             if (pthread_t_value != INVALID_NUB_ADDRESS && tsd_address != INVALID_NUB_ADDRESS)
4129             {
4130                 DNBTimer timer(false);
4131                 thread_activity_sp = DNBGetGenealogyInfoForThread (pid, tid, timed_out);
4132                 genealogy_fetch_time = timer.ElapsedMicroSeconds(false) / 1000000.0;
4133             }
4134 
4135             std::unordered_set<uint32_t> process_info_indexes; // an array of the process info #'s seen
4136 
4137             json << "{";
4138 
4139             bool need_to_print_comma = false;
4140 
4141             if (thread_activity_sp && timed_out == false)
4142             {
4143                 const Genealogy::Activity *activity = &thread_activity_sp->current_activity;
4144                 bool need_vouchers_comma_sep = false;
4145                 json << "\"activity_query_timed_out\":false,";
4146                 if (genealogy_fetch_time != 0)
4147                 {
4148                     //  If we append the floating point value with << we'll get it in scientific
4149                     //  notation.
4150                     char floating_point_ascii_buffer[64];
4151                     floating_point_ascii_buffer[0] = '\0';
4152                     snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time);
4153                     if (strlen (floating_point_ascii_buffer) > 0)
4154                     {
4155                         if (need_to_print_comma)
4156                             json << ",";
4157                         need_to_print_comma = true;
4158                         json << "\"activity_query_duration\":" << floating_point_ascii_buffer;
4159                     }
4160                 }
4161                 if (activity->activity_id != 0)
4162                 {
4163                     if (need_to_print_comma)
4164                         json << ",";
4165                     need_to_print_comma = true;
4166                     need_vouchers_comma_sep = true;
4167                     json << "\"activity\":{";
4168                     json <<    "\"start\":" << activity->activity_start << ",";
4169                     json <<    "\"id\":" << activity->activity_id << ",";
4170                     json <<    "\"parent_id\":" << activity->parent_id << ",";
4171                     json <<    "\"name\":\"" << json_string_quote_metachars (activity->activity_name) << "\",";
4172                     json <<    "\"reason\":\"" << json_string_quote_metachars (activity->reason) << "\"";
4173                     json << "}";
4174                 }
4175                 if (thread_activity_sp->messages.size() > 0)
4176                 {
4177                     need_to_print_comma = true;
4178                     if (need_vouchers_comma_sep)
4179                         json << ",";
4180                     need_vouchers_comma_sep = true;
4181                     json << "\"trace_messages\":[";
4182                     bool printed_one_message = false;
4183                     for (auto iter = thread_activity_sp->messages.begin() ; iter != thread_activity_sp->messages.end(); ++iter)
4184                     {
4185                         if (printed_one_message)
4186                             json << ",";
4187                         else
4188                             printed_one_message = true;
4189                         json << "{";
4190                         json <<   "\"timestamp\":" << iter->timestamp << ",";
4191                         json <<   "\"activity_id\":" << iter->activity_id << ",";
4192                         json <<   "\"trace_id\":" << iter->trace_id << ",";
4193                         json <<   "\"thread\":" << iter->thread << ",";
4194                         json <<   "\"type\":" << (int) iter->type << ",";
4195                         json <<   "\"process_info_index\":" << iter->process_info_index << ",";
4196                         process_info_indexes.insert (iter->process_info_index);
4197                         json <<   "\"message\":\"" << json_string_quote_metachars (iter->message) << "\"";
4198                         json << "}";
4199                     }
4200                     json << "]";
4201                 }
4202                 if (thread_activity_sp->breadcrumbs.size() == 1)
4203                 {
4204                     need_to_print_comma = true;
4205                     if (need_vouchers_comma_sep)
4206                         json << ",";
4207                     need_vouchers_comma_sep = true;
4208                     json << "\"breadcrumb\":{";
4209                     for (auto iter = thread_activity_sp->breadcrumbs.begin() ; iter != thread_activity_sp->breadcrumbs.end(); ++iter)
4210                     {
4211                         json <<   "\"breadcrumb_id\":" << iter->breadcrumb_id << ",";
4212                         json <<   "\"activity_id\":" << iter->activity_id << ",";
4213                         json <<   "\"timestamp\":" << iter->timestamp << ",";
4214                         json <<   "\"name\":\"" << json_string_quote_metachars (iter->name) << "\"";
4215                     }
4216                     json << "}";
4217                 }
4218                 if (process_info_indexes.size() > 0)
4219                 {
4220                     need_to_print_comma = true;
4221                     if (need_vouchers_comma_sep)
4222                         json << ",";
4223                     need_vouchers_comma_sep = true;
4224                     json << "\"process_infos\":[";
4225                     bool printed_one_process_info = false;
4226                     for (auto iter = process_info_indexes.begin(); iter != process_info_indexes.end(); ++iter)
4227                     {
4228                         if (printed_one_process_info)
4229                             json << ",";
4230                         else
4231                             printed_one_process_info = true;
4232                         Genealogy::ProcessExecutableInfoSP image_info_sp;
4233                         uint32_t idx = *iter;
4234                         image_info_sp = DNBGetGenealogyImageInfo (pid, idx);
4235                         json << "{";
4236                         char uuid_buf[37];
4237                         uuid_unparse_upper (image_info_sp->image_uuid, uuid_buf);
4238                         json <<   "\"process_info_index\":" << idx << ",";
4239                         json <<  "\"image_path\":\"" << json_string_quote_metachars (image_info_sp->image_path) << "\",";
4240                         json <<  "\"image_uuid\":\"" << uuid_buf <<"\"";
4241                         json << "}";
4242                     }
4243                     json << "]";
4244                 }
4245             }
4246             else
4247             {
4248                 if (timed_out)
4249                 {
4250                     if (need_to_print_comma)
4251                         json << ",";
4252                     need_to_print_comma = true;
4253                     json << "\"activity_query_timed_out\":true";
4254                     if (genealogy_fetch_time != 0)
4255                     {
4256                         //  If we append the floating point value with << we'll get it in scientific
4257                         //  notation.
4258                         char floating_point_ascii_buffer[64];
4259                         floating_point_ascii_buffer[0] = '\0';
4260                         snprintf (floating_point_ascii_buffer, sizeof (floating_point_ascii_buffer), "%f", genealogy_fetch_time);
4261                         if (strlen (floating_point_ascii_buffer) > 0)
4262                         {
4263                             json << ",";
4264                             json << "\"activity_query_duration\":" << floating_point_ascii_buffer;
4265                         }
4266                     }
4267                 }
4268             }
4269 
4270             if (tsd_address != INVALID_NUB_ADDRESS)
4271             {
4272                 if (need_to_print_comma)
4273                     json << ",";
4274                 need_to_print_comma = true;
4275                 json << "\"tsd_address\":" << tsd_address;
4276 
4277                 if (dti_qos_class_index != 0 && dti_qos_class_index != UINT64_MAX)
4278                 {
4279                     ThreadInfo::QoS requested_qos = DNBGetRequestedQoSForThread (pid, tid, tsd_address, dti_qos_class_index);
4280                     if (requested_qos.IsValid())
4281                     {
4282                         if (need_to_print_comma)
4283                             json << ",";
4284                         need_to_print_comma = true;
4285                         json << "\"requested_qos\":{";
4286                         json <<    "\"enum_value\":" << requested_qos.enum_value << ",";
4287                         json <<    "\"constant_name\":\"" << json_string_quote_metachars (requested_qos.constant_name) << "\",";
4288                         json <<    "\"printable_name\":\"" << json_string_quote_metachars (requested_qos.printable_name) << "\"";
4289                         json << "}";
4290                     }
4291                 }
4292             }
4293 
4294             if (pthread_t_value != INVALID_NUB_ADDRESS)
4295             {
4296                 if (need_to_print_comma)
4297                     json << ",";
4298                 need_to_print_comma = true;
4299                 json << "\"pthread_t\":" << pthread_t_value;
4300             }
4301 
4302             nub_addr_t dispatch_queue_t_value = DNBGetDispatchQueueT (pid, tid);
4303             if (dispatch_queue_t_value != INVALID_NUB_ADDRESS)
4304             {
4305                 if (need_to_print_comma)
4306                     json << ",";
4307                 need_to_print_comma = true;
4308                 json << "\"dispatch_queue_t\":" << dispatch_queue_t_value;
4309             }
4310 
4311             json << "}";
4312             std::string json_quoted = binary_encode_string (json.str());
4313             reply_strm << json_quoted;
4314             return SendPacket (reply_strm.str());
4315         }
4316     }
4317     return SendPacket ("OK");
4318 }
4319 
4320 // Note that all numeric values returned by qProcessInfo are hex encoded,
4321 // including the pid and the cpu type.
4322 
4323 rnb_err_t
4324 RNBRemote::HandlePacket_qProcessInfo (const char *p)
4325 {
4326     nub_process_t pid;
4327     std::ostringstream rep;
4328 
4329     // If we haven't run the process yet, return an error.
4330     if (!m_ctx.HasValidProcessID())
4331         return SendPacket ("E68");
4332 
4333     pid = m_ctx.ProcessID();
4334 
4335     rep << "pid:" << std::hex << pid << ";";
4336 
4337     int procpid_mib[4];
4338     procpid_mib[0] = CTL_KERN;
4339     procpid_mib[1] = KERN_PROC;
4340     procpid_mib[2] = KERN_PROC_PID;
4341     procpid_mib[3] = pid;
4342     struct kinfo_proc proc_kinfo;
4343     size_t proc_kinfo_size = sizeof(struct kinfo_proc);
4344 
4345     if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0)
4346     {
4347         if (proc_kinfo_size > 0)
4348         {
4349             rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";";
4350             rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";";
4351             rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";";
4352             rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";";
4353             if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
4354                 rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";";
4355         }
4356     }
4357 
4358     cpu_type_t cputype = DNBProcessGetCPUType (pid);
4359     if (cputype == 0)
4360     {
4361         DNBLog ("Unable to get the process cpu_type, making a best guess.");
4362         cputype = best_guess_cpu_type();
4363     }
4364 
4365     if (cputype != 0)
4366     {
4367         rep << "cputype:" << std::hex << cputype << ";";
4368     }
4369 
4370     bool host_cpu_is_64bit;
4371     uint32_t is64bit_capable;
4372     size_t is64bit_capable_len = sizeof (is64bit_capable);
4373     if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable, &is64bit_capable_len, NULL, 0) == 0)
4374         host_cpu_is_64bit = true;
4375     else
4376         host_cpu_is_64bit = false;
4377 
4378     uint32_t cpusubtype;
4379     size_t cpusubtype_len = sizeof(cpusubtype);
4380     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0)
4381     {
4382         // If a process is CPU_TYPE_X86, then ignore the cpusubtype that we detected
4383         // from the host and use CPU_SUBTYPE_I386_ALL because we don't want the
4384         // CPU_SUBTYPE_X86_ARCH1 or CPU_SUBTYPE_X86_64_H to be used as the cpu subtype
4385         // for i386...
4386         if (host_cpu_is_64bit)
4387         {
4388             if (cputype == CPU_TYPE_X86)
4389             {
4390                 cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
4391             }
4392             else if (cputype == CPU_TYPE_ARM)
4393             {
4394                 // We can query a process' cputype but we cannot query a process' cpusubtype.
4395                 // If the process has cputype CPU_TYPE_ARM, then it is an armv7 (32-bit process) and we
4396                 // need to override the host cpusubtype (which is in the CPU_SUBTYPE_ARM64 subtype namespace)
4397                 // with a reasonable CPU_SUBTYPE_ARMV7 subtype.
4398                 cpusubtype = 11; // CPU_SUBTYPE_ARM_V7S
4399             }
4400         }
4401         rep << "cpusubtype:" << std::hex << cpusubtype << ';';
4402     }
4403 
4404     // The OS in the triple should be "ios" or "macosx" which doesn't match our
4405     // "Darwin" which gets returned from "kern.ostype", so we need to hardcode
4406     // this for now.
4407     if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
4408         rep << "ostype:ios;";
4409     else
4410     {
4411         bool is_ios_simulator = false;
4412         if (cputype == CPU_TYPE_X86 || cputype == CPU_TYPE_X86_64)
4413         {
4414             // Check for iOS simulator binaries by getting the process argument
4415             // and environment and checking for SIMULATOR_UDID in the environment
4416             int proc_args_mib[3] = { CTL_KERN, KERN_PROCARGS2, (int)pid };
4417 
4418             uint8_t arg_data[8192];
4419             size_t arg_data_size = sizeof(arg_data);
4420             if (::sysctl (proc_args_mib, 3, arg_data, &arg_data_size , NULL, 0) == 0)
4421             {
4422                 DNBDataRef data (arg_data, arg_data_size, false);
4423                 DNBDataRef::offset_t offset = 0;
4424                 uint32_t argc = data.Get32 (&offset);
4425                 const char *cstr;
4426 
4427                 cstr = data.GetCStr (&offset);
4428                 if (cstr)
4429                 {
4430                     // Skip NULLs
4431                     while (1)
4432                     {
4433                         const char *p = data.PeekCStr(offset);
4434                         if ((p == NULL) || (*p != '\0'))
4435                             break;
4436                         ++offset;
4437                     }
4438                     // Now skip all arguments
4439                     for (int i=0; i<static_cast<int>(argc); ++i)
4440                     {
4441                         cstr = data.GetCStr(&offset);
4442                     }
4443 
4444                     // Now iterate across all environment variables
4445                     while ((cstr = data.GetCStr(&offset)))
4446                     {
4447                         if (strncmp(cstr, "SIMULATOR_UDID=", strlen("SIMULATOR_UDID=")) == 0)
4448                         {
4449                             is_ios_simulator = true;
4450                             break;
4451                         }
4452                         if (cstr[0] == '\0')
4453                             break;
4454 
4455                     }
4456                 }
4457             }
4458         }
4459         if (is_ios_simulator)
4460             rep << "ostype:ios;";
4461         else
4462             rep << "ostype:macosx;";
4463     }
4464 
4465     rep << "vendor:apple;";
4466 
4467 #if defined (__LITTLE_ENDIAN__)
4468     rep << "endian:little;";
4469 #elif defined (__BIG_ENDIAN__)
4470     rep << "endian:big;";
4471 #elif defined (__PDP_ENDIAN__)
4472     rep << "endian:pdp;";
4473 #endif
4474 
4475 #if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE)
4476     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
4477     kern_return_t kr;
4478     x86_thread_state_t gp_regs;
4479     mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT;
4480     kr = thread_get_state (thread, x86_THREAD_STATE,
4481                            (thread_state_t) &gp_regs, &gp_count);
4482     if (kr == KERN_SUCCESS)
4483     {
4484         if (gp_regs.tsh.flavor == x86_THREAD_STATE64)
4485             rep << "ptrsize:8;";
4486         else
4487             rep << "ptrsize:4;";
4488     }
4489 #elif defined (__arm__)
4490     rep << "ptrsize:4;";
4491 #elif (defined (__arm64__) || defined (__aarch64__)) && defined (ARM_UNIFIED_THREAD_STATE)
4492     nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid);
4493     kern_return_t kr;
4494     arm_unified_thread_state_t gp_regs;
4495     mach_msg_type_number_t gp_count = ARM_UNIFIED_THREAD_STATE_COUNT;
4496     kr = thread_get_state (thread, ARM_UNIFIED_THREAD_STATE,
4497                            (thread_state_t) &gp_regs, &gp_count);
4498     if (kr == KERN_SUCCESS)
4499     {
4500         if (gp_regs.ash.flavor == ARM_THREAD_STATE64)
4501             rep << "ptrsize:8;";
4502         else
4503             rep << "ptrsize:4;";
4504     }
4505 #endif
4506 
4507     return SendPacket (rep.str());
4508 }
4509 
4510