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