blob: c980e79322634413a112d4f5b8d35ce1a00ebdd9 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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>
Greg Claytona2f74232011-02-24 22:24:29 +000020#include <sys/stat.h>
Chris Lattner24943d22010-06-08 16:52:24 +000021#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"
Greg Clayton54e7afa2010-07-09 20:39:50 +000029#include "Utility/StringExtractor.h"
Chris Lattner24943d22010-06-08 16:52:24 +000030
31#include <iomanip>
32#include <sstream>
33
34#include <TargetConditionals.h> // for endianness predefines
35
36//----------------------------------------------------------------------
37// std::iostream formatting macros
38//----------------------------------------------------------------------
39#define RAW_HEXBASE std::setfill('0') << std::hex << std::right
40#define HEXBASE '0' << 'x' << RAW_HEXBASE
41#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)((uint8_t)x))
42#define RAWHEX16 RAW_HEXBASE << std::setw(4)
43#define RAWHEX32 RAW_HEXBASE << std::setw(8)
44#define RAWHEX64 RAW_HEXBASE << std::setw(16)
45#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x))
46#define HEX16 HEXBASE << std::setw(4)
47#define HEX32 HEXBASE << std::setw(8)
48#define HEX64 HEXBASE << std::setw(16)
49#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x)*2) << (x)
50#define HEX(x) HEXBASE << std::setw(sizeof(x)*2) << (x)
51#define RAWHEX_SIZE(x, sz) RAW_HEXBASE << std::setw((sz)) << (x)
52#define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x)
53#define STRING_WIDTH(w) std::setfill(' ') << std::setw(w)
54#define LEFT_STRING_WIDTH(s, w) std::left << std::setfill(' ') << std::setw(w) << (s) << std::right
55#define DECIMAL std::dec << std::setfill(' ')
56#define DECIMAL_WIDTH(w) DECIMAL << std::setw(w)
57#define FLOAT(n, d) std::setfill(' ') << std::setw((n)+(d)+1) << std::setprecision(d) << std::showpoint << std::fixed
58#define INDENT_WITH_SPACES(iword_idx) std::setfill(' ') << std::setw((iword_idx)) << ""
59#define INDENT_WITH_TABS(iword_idx) std::setfill('\t') << std::setw((iword_idx)) << ""
60// Class to handle communications via gdb remote protocol.
61
62extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args);
63
Greg Claytona2f74232011-02-24 22:24:29 +000064RNBRemote::RNBRemote () :
Greg Clayton20d338f2010-11-18 05:57:03 +000065 m_ctx (),
66 m_comm (),
Chris Lattner24943d22010-06-08 16:52:24 +000067 m_continue_thread(-1),
68 m_thread(-1),
69 m_mutex(),
70 m_packets_recvd(0),
71 m_packets(),
72 m_rx_packets(),
73 m_rx_partial_data(),
74 m_rx_pthread(0),
75 m_breakpoints(),
76 m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4),
Greg Clayton20d338f2010-11-18 05:57:03 +000077 m_extended_mode(false),
78 m_noack_mode(false),
Greg Claytonc71899e2011-01-18 19:36:39 +000079 m_thread_suffix_supported (false),
Greg Claytona2f74232011-02-24 22:24:29 +000080 m_use_native_regs (false)
Chris Lattner24943d22010-06-08 16:52:24 +000081{
82 DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
83 CreatePacketTable ();
84}
85
86
87RNBRemote::~RNBRemote()
88{
89 DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__);
90 StopReadRemoteDataThread();
91}
92
93void
94RNBRemote::CreatePacketTable ()
95{
96 // Step required to add new packets:
97 // 1 - Add new enumeration to RNBRemote::PacketEnum
98 // 2 - Create a the RNBRemote::HandlePacket_ function if a new function is needed
99 // 3 - Register the Packet definition with any needed callbacks in this fucntion
100 // - If no response is needed for a command, then use NULL for the normal callback
101 // - If the packet is not supported while the target is running, use NULL for the async callback
102 // 4 - If the packet is a standard packet (starts with a '$' character
103 // followed by the payload and then '#' and checksum, then you are done
104 // else go on to step 5
105 // 5 - if the packet is a fixed length packet:
106 // - modify the switch statement for the first character in the payload
107 // in RNBRemote::CommDataReceived so it doesn't reject the new packet
108 // type as invalid
109 // - modify the switch statement for the first character in the payload
110 // in RNBRemote::GetPacketPayload and make sure the payload of the packet
111 // is returned correctly
112
113 std::vector <Packet> &t = m_packets;
114 t.push_back (Packet (ack, NULL, NULL, "+", "ACK"));
115 t.push_back (Packet (nack, NULL, NULL, "-", "!ACK"));
116 t.push_back (Packet (read_memory, &RNBRemote::HandlePacket_m, NULL, "m", "Read memory"));
117 t.push_back (Packet (read_register, &RNBRemote::HandlePacket_p, NULL, "p", "Read one register"));
118 t.push_back (Packet (read_general_regs, &RNBRemote::HandlePacket_g, NULL, "g", "Read registers"));
119 t.push_back (Packet (write_memory, &RNBRemote::HandlePacket_M, NULL, "M", "Write memory"));
120 t.push_back (Packet (write_register, &RNBRemote::HandlePacket_P, NULL, "P", "Write one register"));
121 t.push_back (Packet (write_general_regs, &RNBRemote::HandlePacket_G, NULL, "G", "Write registers"));
122 t.push_back (Packet (insert_mem_bp, &RNBRemote::HandlePacket_z, NULL, "Z0", "Insert memory breakpoint"));
123 t.push_back (Packet (remove_mem_bp, &RNBRemote::HandlePacket_z, NULL, "z0", "Remove memory breakpoint"));
124 t.push_back (Packet (single_step, &RNBRemote::HandlePacket_s, NULL, "s", "Single step"));
125 t.push_back (Packet (cont, &RNBRemote::HandlePacket_c, NULL, "c", "continue"));
126 t.push_back (Packet (single_step_with_sig, &RNBRemote::HandlePacket_S, NULL, "S", "Single step with signal"));
127 t.push_back (Packet (set_thread, &RNBRemote::HandlePacket_H, NULL, "H", "Set thread"));
128 t.push_back (Packet (halt, &RNBRemote::HandlePacket_last_signal, &RNBRemote::HandlePacket_stop_process, "\x03", "^C"));
129// t.push_back (Packet (use_extended_mode, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "!", "Use extended mode"));
130 t.push_back (Packet (why_halted, &RNBRemote::HandlePacket_last_signal, NULL, "?", "Why did target halt"));
131 t.push_back (Packet (set_argv, &RNBRemote::HandlePacket_A, NULL, "A", "Set argv"));
132// t.push_back (Packet (set_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "B", "Set/clear breakpoint"));
133 t.push_back (Packet (continue_with_sig, &RNBRemote::HandlePacket_C, NULL, "C", "Continue with signal"));
134 t.push_back (Packet (detach, &RNBRemote::HandlePacket_D, NULL, "D", "Detach gdb from remote system"));
135// t.push_back (Packet (step_inferior_one_cycle, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "i", "Step inferior by one clock cycle"));
136// t.push_back (Packet (signal_and_step_inf_one_cycle, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "I", "Signal inferior, then step one clock cyle"));
137 t.push_back (Packet (kill, &RNBRemote::HandlePacket_k, NULL, "k", "Kill"));
138// t.push_back (Packet (restart, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior"));
139// t.push_back (Packet (search_mem_backwards, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory backwards"));
140 t.push_back (Packet (thread_alive_p, &RNBRemote::HandlePacket_T, NULL, "T", "Is thread alive"));
141 t.push_back (Packet (vattach, &RNBRemote::HandlePacket_v, NULL, "vAttach", "Attach to a new process"));
142 t.push_back (Packet (vattachwait, &RNBRemote::HandlePacket_v, NULL, "vAttachWait", "Wait for a process to start up then attach to it"));
Greg Claytonc1d37752010-10-18 01:45:30 +0000143 t.push_back (Packet (vattachname, &RNBRemote::HandlePacket_v, NULL, "vAttachName", "Attach to an existing process by name"));
Chris Lattner24943d22010-06-08 16:52:24 +0000144 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_UNIMPLEMENTED, NULL, "Z2", "Insert write watchpoint"));
151// t.push_back (Packet (remove_write_watch_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z2", "Remove write watchpoint"));
152// t.push_back (Packet (insert_read_watch_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z3", "Insert read watchpoint"));
153// t.push_back (Packet (remove_read_watch_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z3", "Remove read watchpoint"));
154// t.push_back (Packet (insert_access_watch_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z4", "Insert access watchpoint"));
155// t.push_back (Packet (remove_access_watch_bp, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z4", "Remove access watchpoint"));
156 t.push_back (Packet (query_current_thread_id, &RNBRemote::HandlePacket_qC, NULL, "qC", "Query current thread ID"));
157// t.push_back (Packet (query_memory_crc, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qCRC:", "Compute CRC of memory region"));
158 t.push_back (Packet (query_thread_ids_first, &RNBRemote::HandlePacket_qThreadInfo, NULL, "qfThreadInfo", "Get list of active threads (first req)"));
159 t.push_back (Packet (query_thread_ids_subsequent, &RNBRemote::HandlePacket_qThreadInfo, NULL, "qsThreadInfo", "Get list of active threads (subsequent req)"));
160 // APPLE LOCAL: qThreadStopInfo
161 // syntax: qThreadStopInfoTTTT
162 // TTTT is hex thread ID
163 t.push_back (Packet (query_thread_stop_info, &RNBRemote::HandlePacket_qThreadStopInfo, NULL, "qThreadStopInfo", "Get detailed info on why the specified thread stopped"));
164 t.push_back (Packet (query_thread_extra_info, &RNBRemote::HandlePacket_qThreadExtraInfo,NULL, "qThreadExtraInfo", "Get printable status of a thread"));
165// t.push_back (Packet (query_image_offsets, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qOffsets", "Report offset of loaded program"));
166 t.push_back (Packet (query_launch_success, &RNBRemote::HandlePacket_qLaunchSuccess,NULL, "qLaunchSuccess", "Report the success or failure of the launch attempt"));
167 t.push_back (Packet (query_register_info, &RNBRemote::HandlePacket_qRegisterInfo, NULL, "qRegisterInfo", "Dynamically discover remote register context information."));
168 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"));
169 t.push_back (Packet (query_step_packet_supported, &RNBRemote::HandlePacket_qStepPacketSupported,NULL, "qStepPacketSupported", "Replys with OK if the 's' packet is supported."));
170 t.push_back (Packet (query_host_info, &RNBRemote::HandlePacket_qHostInfo, NULL, "qHostInfo", "Replies with multiple 'key:value;' tuples appended to each other."));
171// t.push_back (Packet (query_symbol_lookup, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "qSymbol", "Notify that host debugger is ready to do symbol lookups"));
Greg Claytonc71899e2011-01-18 19:36:39 +0000172 t.push_back (Packet (start_noack_mode, &RNBRemote::HandlePacket_QStartNoAckMode , NULL, "QStartNoAckMode", "Request that " DEBUGSERVER_PROGRAM_NAME " stop acking remote protocol packets"));
173 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"));
174 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"));
175 t.push_back (Packet (set_max_packet_size, &RNBRemote::HandlePacket_QSetMaxPacketSize , NULL, "QSetMaxPacketSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized packet gdb can handle"));
176 t.push_back (Packet (set_max_payload_size, &RNBRemote::HandlePacket_QSetMaxPayloadSize , NULL, "QSetMaxPayloadSize:", "Tell " DEBUGSERVER_PROGRAM_NAME " the max sized payload gdb can handle"));
177 t.push_back (Packet (set_environment_variable, &RNBRemote::HandlePacket_QEnvironment , NULL, "QEnvironment:", "Add an environment variable to the inferior's environment"));
178 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"));
Greg Claytona2f74232011-02-24 22:24:29 +0000179 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"));
180 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"));
181 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"));
182 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"));
Chris Lattner24943d22010-06-08 16:52:24 +0000183// t.push_back (Packet (pass_signals_to_inferior, &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "QPassSignals:", "Specify which signals are passed to the inferior"));
184 t.push_back (Packet (allocate_memory, &RNBRemote::HandlePacket_AllocateMemory, NULL, "_M", "Allocate memory in the inferior process."));
185 t.push_back (Packet (deallocate_memory, &RNBRemote::HandlePacket_DeallocateMemory, NULL, "_m", "Deallocate memory in the inferior process."));
186}
187
188
189void
190RNBRemote::FlushSTDIO ()
191{
192 if (m_ctx.HasValidProcessID())
193 {
194 nub_process_t pid = m_ctx.ProcessID();
195 char buf[256];
196 nub_size_t count;
197 do
198 {
199 count = DNBProcessGetAvailableSTDOUT(pid, buf, sizeof(buf));
200 if (count > 0)
201 {
202 SendSTDOUTPacket (buf, count);
203 }
204 } while (count > 0);
205
206 do
207 {
208 count = DNBProcessGetAvailableSTDERR(pid, buf, sizeof(buf));
209 if (count > 0)
210 {
211 SendSTDERRPacket (buf, count);
212 }
213 } while (count > 0);
214 }
215}
216
217rnb_err_t
218RNBRemote::SendHexEncodedBytePacket (const char *header, const void *buf, size_t buf_len, const char *footer)
219{
220 std::ostringstream packet_sstrm;
221 // Append the header cstr if there was one
222 if (header && header[0])
223 packet_sstrm << header;
224 nub_size_t i;
225 const uint8_t *ubuf8 = (const uint8_t *)buf;
226 for (i=0; i<buf_len; i++)
227 {
228 packet_sstrm << RAWHEX8(ubuf8[i]);
229 }
230 // Append the footer cstr if there was one
231 if (footer && footer[0])
232 packet_sstrm << footer;
233
234 return SendPacket(packet_sstrm.str());
235}
236
237rnb_err_t
238RNBRemote::SendSTDOUTPacket (char *buf, nub_size_t buf_size)
239{
240 if (buf_size == 0)
241 return rnb_success;
242 return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
243}
244
245rnb_err_t
246RNBRemote::SendSTDERRPacket (char *buf, nub_size_t buf_size)
247{
248 if (buf_size == 0)
249 return rnb_success;
250 return SendHexEncodedBytePacket("O", buf, buf_size, NULL);
251}
252
253rnb_err_t
254RNBRemote::SendPacket (const std::string &s)
255{
256 DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s (%s) called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, s.c_str());
257 std::string sendpacket = "$" + s + "#";
258 int cksum = 0;
259 char hexbuf[5];
260
261 if (m_noack_mode)
262 {
263 sendpacket += "00";
264 }
265 else
266 {
267 for (int i = 0; i != s.size(); ++i)
268 cksum += s[i];
269 snprintf (hexbuf, sizeof hexbuf, "%02x", cksum & 0xff);
270 sendpacket += hexbuf;
271 }
272
273 rnb_err_t err = m_comm.Write (sendpacket.c_str(), sendpacket.size());
274 if (err != rnb_success)
275 return err;
276
277 if (m_noack_mode)
278 return rnb_success;
279
280 std::string reply;
281 RNBRemote::Packet packet;
282 err = GetPacket (reply, packet, true);
283
284 if (err != rnb_success)
285 {
286 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());
287 return err;
288 }
289
290 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());
291
292 if (packet.type == ack)
293 return rnb_success;
294
295 // Should we try to resend the packet at this layer?
296 // if (packet.command == nack)
297 return rnb_err;
298}
299
300/* Get a packet via gdb remote protocol.
301 Strip off the prefix/suffix, verify the checksum to make sure
302 a valid packet was received, send an ACK if they match. */
303
304rnb_err_t
305RNBRemote::GetPacketPayload (std::string &return_packet)
306{
307 //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
308
309 PThreadMutex::Locker locker(m_mutex);
310 if (m_rx_packets.empty())
311 {
312 // Only reset the remote command available event if we have no more packets
313 m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
314 //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s error: no packets available...", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
315 return rnb_err;
316 }
317
318 //DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s has %u queued packets", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, m_rx_packets.size());
319 return_packet.swap(m_rx_packets.front());
320 m_rx_packets.pop_front();
321 locker.Reset(); // Release our lock on the mutex
322
323 if (m_rx_packets.empty())
324 {
325 // Reset the remote command available event if we have no more packets
326 m_ctx.Events().ResetEvents ( RNBContext::event_read_packet_available );
327 }
328
329 //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s: '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
330
331 switch (return_packet[0])
332 {
333 case '+':
334 case '-':
335 case '\x03':
336 break;
337
338 case '$':
339 {
340 int packet_checksum = 0;
341 if (!m_noack_mode)
342 {
343 for (int i = return_packet.size() - 2; i < return_packet.size(); ++i)
344 {
345 char checksum_char = tolower (return_packet[i]);
346 if (!isxdigit (checksum_char))
347 {
348 m_comm.Write ("-", 1);
349 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());
350 return rnb_err;
351 }
352 }
353 packet_checksum = strtol (&return_packet[return_packet.size() - 2], NULL, 16);
354 }
355
356 return_packet.erase(0,1); // Strip the leading '$'
357 return_packet.erase(return_packet.size() - 3);// Strip the #XX checksum
358
359 if (!m_noack_mode)
360 {
361 // Compute the checksum
362 int computed_checksum = 0;
363 for (std::string::iterator it = return_packet.begin ();
364 it != return_packet.end ();
365 ++it)
366 {
367 computed_checksum += *it;
368 }
369
370 if (packet_checksum == (computed_checksum & 0xff))
371 {
372 //DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s'", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
373 m_comm.Write ("+", 1);
374 }
375 else
376 {
377 DNBLogThreadedIf (LOG_RNB_MEDIUM, "%8u RNBRemote::%s sending ACK for '%s' (error: packet checksum mismatch (0x%2.2x != 0x%2.2x))",
378 (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true),
379 __FUNCTION__,
380 return_packet.c_str(),
381 packet_checksum,
382 computed_checksum);
383 m_comm.Write ("-", 1);
384 return rnb_err;
385 }
386 }
387 }
Greg Claytondb2bab42011-01-27 09:02:32 +0000388 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000389
390 default:
391 DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s tossing unexpected packet???? %s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, return_packet.c_str());
392 if (!m_noack_mode)
393 m_comm.Write ("-", 1);
394 return rnb_err;
395 }
396
397 return rnb_success;
398}
399
400rnb_err_t
401RNBRemote::HandlePacket_UNIMPLEMENTED (const char* p)
402{
403 DNBLogThreadedIf (LOG_RNB_MAX, "%8u RNBRemote::%s(\"%s\")", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p ? p : "NULL");
404 return SendPacket ("");
405}
406
407rnb_err_t
Greg Claytondb2bab42011-01-27 09:02:32 +0000408RNBRemote::HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description)
Chris Lattner24943d22010-06-08 16:52:24 +0000409{
Greg Claytondb2bab42011-01-27 09:02:32 +0000410 DNBLogThreadedIf (LOG_RNB_PACKETS, "%8u %s:%i ILLFORMED: '%s' (%s)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), file, line, __FUNCTION__, p);
Chris Lattner24943d22010-06-08 16:52:24 +0000411 return SendPacket ("E03");
412}
413
414rnb_err_t
415RNBRemote::GetPacket (std::string &packet_payload, RNBRemote::Packet& packet_info, bool wait)
416{
417 std::string payload;
418 rnb_err_t err = GetPacketPayload (payload);
419 if (err != rnb_success)
420 {
421 PThreadEvent& events = m_ctx.Events();
422 nub_event_t set_events = events.GetEventBits();
423 // TODO: add timeout version of GetPacket?? We would then need to pass
424 // that timeout value along to DNBProcessTimedWaitForEvent.
425 if (!wait || ((set_events & RNBContext::event_read_thread_running) == 0))
426 return err;
427
428 const nub_event_t events_to_wait_for = RNBContext::event_read_packet_available | RNBContext::event_read_thread_exiting;
429 set_events = 0;
430
431 while ((set_events = events.WaitForSetEvents(events_to_wait_for)) != 0)
432 {
433 if (set_events & RNBContext::event_read_packet_available)
434 {
435 // Try the queue again now that we got an event
436 err = GetPacketPayload (payload);
437 if (err == rnb_success)
438 break;
439 }
440
441 if (set_events & RNBContext::event_read_thread_exiting)
442 err = rnb_not_connected;
443
444 if (err == rnb_not_connected)
445 return err;
446
447 } while (err == rnb_err);
448
449 if (set_events == 0)
450 err = rnb_not_connected;
451 }
452
453 if (err == rnb_success)
454 {
455 Packet::iterator it;
456 for (it = m_packets.begin (); it != m_packets.end (); ++it)
457 {
458 if (payload.compare (0, it->abbrev.size(), it->abbrev) == 0)
459 break;
460 }
461
462 // A packet we don't have an entry for. This can happen when we
463 // get a packet that we don't know about or support. We just reply
464 // accordingly and go on.
465 if (it == m_packets.end ())
466 {
467 DNBLogThreadedIf (LOG_RNB_PACKETS, "unimplemented packet: '%s'", payload.c_str());
468 HandlePacket_UNIMPLEMENTED(payload.c_str());
469 return rnb_err;
470 }
471 else
472 {
473 packet_info = *it;
474 packet_payload = payload;
475 }
476 }
477 return err;
478}
479
480rnb_err_t
481RNBRemote::HandleAsyncPacket(PacketEnum *type)
482{
483 DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
484 static DNBTimer g_packetTimer(true);
485 rnb_err_t err = rnb_err;
486 std::string packet_data;
487 RNBRemote::Packet packet_info;
488 err = GetPacket (packet_data, packet_info, false);
489
490 if (err == rnb_success)
491 {
492 if (!packet_data.empty() && isprint(packet_data[0]))
493 DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (\"%s\");", packet_data.c_str());
494 else
495 DNBLogThreadedIf (LOG_RNB_REMOTE | LOG_RNB_PACKETS, "HandleAsyncPacket (%s);", packet_info.printable_name.c_str());
496
497 HandlePacketCallback packet_callback = packet_info.async;
498 if (packet_callback != NULL)
499 {
500 if (type != NULL)
501 *type = packet_info.type;
502 return (this->*packet_callback)(packet_data.c_str());
503 }
504 }
505
506 return err;
507}
508
509rnb_err_t
510RNBRemote::HandleReceivedPacket(PacketEnum *type)
511{
512 static DNBTimer g_packetTimer(true);
513
514 // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
515 rnb_err_t err = rnb_err;
516 std::string packet_data;
517 RNBRemote::Packet packet_info;
518 err = GetPacket (packet_data, packet_info, false);
519
520 if (err == rnb_success)
521 {
522 DNBLogThreadedIf (LOG_RNB_REMOTE, "HandleReceivedPacket (\"%s\");", packet_data.c_str());
523 HandlePacketCallback packet_callback = packet_info.normal;
524 if (packet_callback != NULL)
525 {
526 if (type != NULL)
527 *type = packet_info.type;
528 return (this->*packet_callback)(packet_data.c_str());
529 }
530 else
531 {
532 // Do not fall through to end of this function, if we have valid
533 // packet_info and it has a NULL callback, then we need to respect
534 // that it may not want any response or anything to be done.
535 return err;
536 }
537 }
538 return rnb_err;
539}
540
541void
542RNBRemote::CommDataReceived(const std::string& new_data)
543{
544 // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
545 {
546 // Put the packet data into the buffer in a thread safe fashion
547 PThreadMutex::Locker locker(m_mutex);
548
549 std::string data;
550 // See if we have any left over data from a previous call to this
551 // function?
552 if (!m_rx_partial_data.empty())
553 {
554 // We do, so lets start with that data
555 data.swap(m_rx_partial_data);
556 }
557 // Append the new incoming data
558 data += new_data;
559
560 // Parse up the packets into gdb remote packets
561 uint32_t idx = 0;
562 const size_t data_size = data.size();
563
564 while (idx < data_size)
565 {
566 // end_idx must be one past the last valid packet byte. Start
567 // it off with an invalid value that is the same as the current
568 // index.
569 size_t end_idx = idx;
570
571 switch (data[idx])
572 {
573 case '+': // Look for ack
574 case '-': // Look for cancel
575 case '\x03': // ^C to halt target
576 end_idx = idx + 1; // The command is one byte long...
577 break;
578
579 case '$':
580 // Look for a standard gdb packet?
581 end_idx = data.find('#', idx + 1);
582 if (end_idx == std::string::npos || end_idx + 2 > data_size)
583 {
584 end_idx = std::string::npos;
585 }
586 else
587 {
Greg Claytondb2bab42011-01-27 09:02:32 +0000588 // Add two for the checksum bytes and 1 to point to the
589 // byte just past the end of this packet
590 end_idx += 2 + 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000591 }
592 break;
593
594 default:
595 break;
596 }
597
598 if (end_idx == std::string::npos)
599 {
600 // Not all data may be here for the packet yet, save it for
601 // next time through this function.
602 m_rx_partial_data += data.substr(idx);
603 //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());
604 idx = end_idx;
605 }
606 else
607 if (idx < end_idx)
608 {
609 m_packets_recvd++;
610 // Hack to get rid of initial '+' ACK???
611 if (m_packets_recvd == 1 && (end_idx == idx + 1) && data[idx] == '+')
612 {
613 //DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s throwing first ACK away....[%u, npos): '+'",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, idx);
614 }
615 else
616 {
617 // We have a valid packet...
618 m_rx_packets.push_back(data.substr(idx, end_idx - idx));
619 DNBLogThreadedIf (LOG_RNB_PACKETS, "getpkt: %s", m_rx_packets.back().c_str());
620 }
621 idx = end_idx;
622 }
623 else
624 {
625 DNBLogThreadedIf (LOG_RNB_MAX, "%8d RNBRemote::%s tossing junk byte at %c",(uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, data[idx]);
626 idx = idx + 1;
627 }
628 }
629 }
630
631 if (!m_rx_packets.empty())
632 {
633 // Let the main thread know we have received a packet
634
635 //DNBLogThreadedIf (LOG_RNB_EVENTS, "%8d RNBRemote::%s called events.SetEvent(RNBContext::event_read_packet_available)", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
636 PThreadEvent& events = m_ctx.Events();
637 events.SetEvents (RNBContext::event_read_packet_available);
638 }
639}
640
641rnb_err_t
642RNBRemote::GetCommData ()
643{
644 // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8d RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
645 std::string comm_data;
646 rnb_err_t err = m_comm.Read (comm_data);
647 if (err == rnb_success)
648 {
649 if (!comm_data.empty())
650 CommDataReceived (comm_data);
651 }
652 return err;
653}
654
655void
656RNBRemote::StartReadRemoteDataThread()
657{
658 DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
659 PThreadEvent& events = m_ctx.Events();
660 if ((events.GetEventBits() & RNBContext::event_read_thread_running) == 0)
661 {
662 events.ResetEvents (RNBContext::event_read_thread_exiting);
663 int err = ::pthread_create (&m_rx_pthread, NULL, ThreadFunctionReadRemoteData, this);
664 if (err == 0)
665 {
666 // Our thread was successfully kicked off, wait for it to
667 // set the started event so we can safely continue
668 events.WaitForSetEvents (RNBContext::event_read_thread_running);
669 }
670 else
671 {
672 events.ResetEvents (RNBContext::event_read_thread_running);
673 events.SetEvents (RNBContext::event_read_thread_exiting);
674 }
675 }
676}
677
678void
679RNBRemote::StopReadRemoteDataThread()
680{
681 DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s called", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
682 PThreadEvent& events = m_ctx.Events();
683 if ((events.GetEventBits() & RNBContext::event_read_thread_running) == RNBContext::event_read_thread_running)
684 {
685 m_comm.Disconnect(true);
686 struct timespec timeout_abstime;
687 DNBTimer::OffsetTimeOfDay(&timeout_abstime, 2, 0);
688
689 // Wait for 2 seconds for the remote data thread to exit
690 if (events.WaitForSetEvents(RNBContext::event_read_thread_exiting, &timeout_abstime) == 0)
691 {
692 // Kill the remote data thread???
693 }
694 }
695}
696
697
698void*
699RNBRemote::ThreadFunctionReadRemoteData(void *arg)
700{
701 // Keep a shared pointer reference so this doesn't go away on us before the thread is killed.
702 DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread starting...", __FUNCTION__, arg);
703 RNBRemoteSP remoteSP(g_remoteSP);
704 if (remoteSP.get() != NULL)
705 {
706 RNBRemote* remote = remoteSP.get();
707 PThreadEvent& events = remote->Context().Events();
708 events.SetEvents (RNBContext::event_read_thread_running);
709 // START: main receive remote command thread loop
710 bool done = false;
711 while (!done)
712 {
713 rnb_err_t err = remote->GetCommData();
714
715 switch (err)
716 {
717 case rnb_success:
718 break;
719
720 default:
721 case rnb_err:
722 DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned error %u", err);
723 done = true;
724 break;
725
726 case rnb_not_connected:
727 DNBLogThreadedIf (LOG_RNB_REMOTE, "RNBSocket::GetCommData returned not connected...");
728 done = true;
729 break;
730 }
731 }
732 // START: main receive remote command thread loop
733 events.ResetEvents (RNBContext::event_read_thread_running);
734 events.SetEvents (RNBContext::event_read_thread_exiting);
735 }
736 DNBLogThreadedIf(LOG_RNB_REMOTE, "RNBRemote::%s (%p): thread exiting...", __FUNCTION__, arg);
737 return NULL;
738}
739
740
741
742/* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes
743 (8-bit bytes).
744 This encoding uses 0x7d ('}') as an escape character for 0x7d ('}'),
745 0x23 ('#'), and 0x24 ('$').
746 LEN is the number of bytes to be processed. If a character is escaped,
747 it is 2 characters for LEN. A LEN of -1 means encode-until-nul-byte
748 (end of string). */
749
750std::vector<uint8_t>
751decode_binary_data (const char *str, int len)
752{
753 std::vector<uint8_t> bytes;
754 if (len == 0)
755 {
756 return bytes;
757 }
758 if (len == -1)
759 len = strlen (str);
760
761 while (len--)
762 {
763 unsigned char c = *str;
764 if (c == 0x7d && len > 0)
765 {
766 len--;
767 str++;
768 c ^= 0x20;
769 }
770 bytes.push_back (c);
771 }
772 return bytes;
773}
774
775typedef struct register_map_entry
776{
777 uint32_t gdb_regnum; // gdb register number
778 uint32_t gdb_size; // gdb register size in bytes (can be greater than or less than to debugnub size...)
779 const char * gdb_name; // gdb register name
780 DNBRegisterInfo nub_info; // debugnub register info
781 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)
782 int expedite; // expedite delivery of this register in last stop reply packets
783} register_map_entry_t;
784
785
786
787// If the notion of registers differs from what is handed out by the
788// architecture, then flavors can be defined here.
789
790static const uint32_t MAX_REGISTER_BYTE_SIZE = 16;
791static const uint8_t k_zero_bytes[MAX_REGISTER_BYTE_SIZE] = {0};
792static std::vector<register_map_entry_t> g_dynamic_register_map;
793static register_map_entry_t *g_reg_entries = NULL;
794static size_t g_num_reg_entries = 0;
795
796static void
797RegisterEntryNotAvailable (register_map_entry_t *reg_entry)
798{
799 reg_entry->fail_value = k_zero_bytes;
800 reg_entry->nub_info.set = INVALID_NUB_REGNUM;
801 reg_entry->nub_info.reg = INVALID_NUB_REGNUM;
802 reg_entry->nub_info.name = NULL;
803 reg_entry->nub_info.alt = NULL;
804 reg_entry->nub_info.type = InvalidRegType;
805 reg_entry->nub_info.format = InvalidRegFormat;
806 reg_entry->nub_info.size = 0;
807 reg_entry->nub_info.offset = 0;
808 reg_entry->nub_info.reg_gcc = INVALID_NUB_REGNUM;
809 reg_entry->nub_info.reg_dwarf = INVALID_NUB_REGNUM;
810 reg_entry->nub_info.reg_generic = INVALID_NUB_REGNUM;
811 reg_entry->nub_info.reg_gdb = INVALID_NUB_REGNUM;
812}
813
Chris Lattner24943d22010-06-08 16:52:24 +0000814
815//----------------------------------------------------------------------
816// ARM regiseter sets as gdb knows them
817//----------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +0000818register_map_entry_t
819g_gdb_register_map_arm[] =
820{
821 { 0, 4, "r0", {0}, NULL, 1},
822 { 1, 4, "r1", {0}, NULL, 1},
823 { 2, 4, "r2", {0}, NULL, 1},
824 { 3, 4, "r3", {0}, NULL, 1},
825 { 4, 4, "r4", {0}, NULL, 1},
826 { 5, 4, "r5", {0}, NULL, 1},
827 { 6, 4, "r6", {0}, NULL, 1},
828 { 7, 4, "r7", {0}, NULL, 1},
829 { 8, 4, "r8", {0}, NULL, 1},
830 { 9, 4, "r9", {0}, NULL, 1},
831 { 10, 4, "r10", {0}, NULL, 1},
832 { 11, 4, "r11", {0}, NULL, 1},
833 { 12, 4, "r12", {0}, NULL, 1},
834 { 13, 4, "sp", {0}, NULL, 1},
835 { 14, 4, "lr", {0}, NULL, 1},
836 { 15, 4, "pc", {0}, NULL, 1},
Greg Clayton0a7f75f2010-09-09 06:32:46 +0000837 { 16, 12, "f0", {0}, k_zero_bytes, 0},
838 { 17, 12, "f1", {0}, k_zero_bytes, 0},
839 { 18, 12, "f2", {0}, k_zero_bytes, 0},
840 { 19, 12, "f3", {0}, k_zero_bytes, 0},
841 { 20, 12, "f4", {0}, k_zero_bytes, 0},
842 { 21, 12, "f5", {0}, k_zero_bytes, 0},
843 { 22, 12, "f6", {0}, k_zero_bytes, 0},
844 { 23, 12, "f7", {0}, k_zero_bytes, 0},
Greg Clayton24bc5d92011-03-30 18:16:51 +0000845 { 24, 4, "fps", {0}, k_zero_bytes, 0},
Chris Lattner24943d22010-06-08 16:52:24 +0000846 { 25, 4,"cpsr", {0}, NULL, 1},
847 { 26, 4, "s0", {0}, NULL, 0},
848 { 27, 4, "s1", {0}, NULL, 0},
849 { 28, 4, "s2", {0}, NULL, 0},
850 { 29, 4, "s3", {0}, NULL, 0},
851 { 30, 4, "s4", {0}, NULL, 0},
852 { 31, 4, "s5", {0}, NULL, 0},
853 { 32, 4, "s6", {0}, NULL, 0},
854 { 33, 4, "s7", {0}, NULL, 0},
855 { 34, 4, "s8", {0}, NULL, 0},
856 { 35, 4, "s9", {0}, NULL, 0},
857 { 36, 4, "s10", {0}, NULL, 0},
858 { 37, 4, "s11", {0}, NULL, 0},
859 { 38, 4, "s12", {0}, NULL, 0},
860 { 39, 4, "s13", {0}, NULL, 0},
861 { 40, 4, "s14", {0}, NULL, 0},
862 { 41, 4, "s15", {0}, NULL, 0},
863 { 42, 4, "s16", {0}, NULL, 0},
864 { 43, 4, "s17", {0}, NULL, 0},
865 { 44, 4, "s18", {0}, NULL, 0},
866 { 45, 4, "s19", {0}, NULL, 0},
867 { 46, 4, "s20", {0}, NULL, 0},
868 { 47, 4, "s21", {0}, NULL, 0},
869 { 48, 4, "s22", {0}, NULL, 0},
870 { 49, 4, "s23", {0}, NULL, 0},
871 { 50, 4, "s24", {0}, NULL, 0},
872 { 51, 4, "s25", {0}, NULL, 0},
873 { 52, 4, "s26", {0}, NULL, 0},
874 { 53, 4, "s27", {0}, NULL, 0},
875 { 54, 4, "s28", {0}, NULL, 0},
876 { 55, 4, "s29", {0}, NULL, 0},
877 { 56, 4, "s30", {0}, NULL, 0},
878 { 57, 4, "s31", {0}, NULL, 0},
879 { 58, 4, "fpscr", {0}, NULL, 0}
880};
881
Chris Lattner24943d22010-06-08 16:52:24 +0000882register_map_entry_t
883g_gdb_register_map_i386[] =
884{
885 { 0, 4, "eax" , {0}, NULL, 0 },
886 { 1, 4, "ecx" , {0}, NULL, 0 },
887 { 2, 4, "edx" , {0}, NULL, 0 },
888 { 3, 4, "ebx" , {0}, NULL, 0 },
889 { 4, 4, "esp" , {0}, NULL, 1 },
890 { 5, 4, "ebp" , {0}, NULL, 1 },
891 { 6, 4, "esi" , {0}, NULL, 0 },
892 { 7, 4, "edi" , {0}, NULL, 0 },
893 { 8, 4, "eip" , {0}, NULL, 1 },
894 { 9, 4, "eflags" , {0}, NULL, 0 },
895 { 10, 4, "cs" , {0}, NULL, 0 },
896 { 11, 4, "ss" , {0}, NULL, 0 },
897 { 12, 4, "ds" , {0}, NULL, 0 },
898 { 13, 4, "es" , {0}, NULL, 0 },
899 { 14, 4, "fs" , {0}, NULL, 0 },
900 { 15, 4, "gs" , {0}, NULL, 0 },
901 { 16, 10, "stmm0" , {0}, NULL, 0 },
902 { 17, 10, "stmm1" , {0}, NULL, 0 },
903 { 18, 10, "stmm2" , {0}, NULL, 0 },
904 { 19, 10, "stmm3" , {0}, NULL, 0 },
905 { 20, 10, "stmm4" , {0}, NULL, 0 },
906 { 21, 10, "stmm5" , {0}, NULL, 0 },
907 { 22, 10, "stmm6" , {0}, NULL, 0 },
908 { 23, 10, "stmm7" , {0}, NULL, 0 },
909 { 24, 4, "fctrl" , {0}, NULL, 0 },
910 { 25, 4, "fstat" , {0}, NULL, 0 },
911 { 26, 4, "ftag" , {0}, NULL, 0 },
912 { 27, 4, "fiseg" , {0}, NULL, 0 },
913 { 28, 4, "fioff" , {0}, NULL, 0 },
914 { 29, 4, "foseg" , {0}, NULL, 0 },
915 { 30, 4, "fooff" , {0}, NULL, 0 },
916 { 31, 4, "fop" , {0}, NULL, 0 },
917 { 32, 16, "xmm0" , {0}, NULL, 0 },
918 { 33, 16, "xmm1" , {0}, NULL, 0 },
919 { 34, 16, "xmm2" , {0}, NULL, 0 },
920 { 35, 16, "xmm3" , {0}, NULL, 0 },
921 { 36, 16, "xmm4" , {0}, NULL, 0 },
922 { 37, 16, "xmm5" , {0}, NULL, 0 },
923 { 38, 16, "xmm6" , {0}, NULL, 0 },
924 { 39, 16, "xmm7" , {0}, NULL, 0 },
925 { 40, 4, "mxcsr" , {0}, NULL, 0 },
926};
927
Chris Lattner24943d22010-06-08 16:52:24 +0000928register_map_entry_t
929g_gdb_register_map_x86_64[] =
930{
931 { 0, 8, "rax" , {0}, NULL, 0 },
932 { 1, 8, "rbx" , {0}, NULL, 0 },
933 { 2, 8, "rcx" , {0}, NULL, 0 },
934 { 3, 8, "rdx" , {0}, NULL, 0 },
935 { 4, 8, "rsi" , {0}, NULL, 0 },
936 { 5, 8, "rdi" , {0}, NULL, 0 },
937 { 6, 8, "rbp" , {0}, NULL, 1 },
938 { 7, 8, "rsp" , {0}, NULL, 1 },
939 { 8, 8, "r8" , {0}, NULL, 0 },
940 { 9, 8, "r9" , {0}, NULL, 0 },
941 { 10, 8, "r10" , {0}, NULL, 0 },
942 { 11, 8, "r11" , {0}, NULL, 0 },
943 { 12, 8, "r12" , {0}, NULL, 0 },
944 { 13, 8, "r13" , {0}, NULL, 0 },
945 { 14, 8, "r14" , {0}, NULL, 0 },
946 { 15, 8, "r15" , {0}, NULL, 0 },
947 { 16, 8, "rip" , {0}, NULL, 1 },
948 { 17, 4, "rflags", {0}, NULL, 0 },
949 { 18, 4, "cs" , {0}, NULL, 0 },
950 { 19, 4, "ss" , {0}, NULL, 0 },
951 { 20, 4, "ds" , {0}, NULL, 0 },
952 { 21, 4, "es" , {0}, NULL, 0 },
953 { 22, 4, "fs" , {0}, NULL, 0 },
954 { 23, 4, "gs" , {0}, NULL, 0 },
955 { 24, 10, "stmm0" , {0}, NULL, 0 },
956 { 25, 10, "stmm1" , {0}, NULL, 0 },
957 { 26, 10, "stmm2" , {0}, NULL, 0 },
958 { 27, 10, "stmm3" , {0}, NULL, 0 },
959 { 28, 10, "stmm4" , {0}, NULL, 0 },
960 { 29, 10, "stmm5" , {0}, NULL, 0 },
961 { 30, 10, "stmm6" , {0}, NULL, 0 },
962 { 31, 10, "stmm7" , {0}, NULL, 0 },
963 { 32, 4, "fctrl" , {0}, NULL, 0 },
964 { 33, 4, "fstat" , {0}, NULL, 0 },
965 { 34, 4, "ftag" , {0}, NULL, 0 },
966 { 35, 4, "fiseg" , {0}, NULL, 0 },
967 { 36, 4, "fioff" , {0}, NULL, 0 },
968 { 37, 4, "foseg" , {0}, NULL, 0 },
969 { 38, 4, "fooff" , {0}, NULL, 0 },
970 { 39, 4, "fop" , {0}, NULL, 0 },
971 { 40, 16, "xmm0" , {0}, NULL, 0 },
972 { 41, 16, "xmm1" , {0}, NULL, 0 },
973 { 42, 16, "xmm2" , {0}, NULL, 0 },
974 { 43, 16, "xmm3" , {0}, NULL, 0 },
975 { 44, 16, "xmm4" , {0}, NULL, 0 },
976 { 45, 16, "xmm5" , {0}, NULL, 0 },
977 { 46, 16, "xmm6" , {0}, NULL, 0 },
978 { 47, 16, "xmm7" , {0}, NULL, 0 },
979 { 48, 16, "xmm8" , {0}, NULL, 0 },
980 { 49, 16, "xmm9" , {0}, NULL, 0 },
981 { 50, 16, "xmm10" , {0}, NULL, 0 },
982 { 51, 16, "xmm11" , {0}, NULL, 0 },
983 { 52, 16, "xmm12" , {0}, NULL, 0 },
984 { 53, 16, "xmm13" , {0}, NULL, 0 },
985 { 54, 16, "xmm14" , {0}, NULL, 0 },
986 { 55, 16, "xmm15" , {0}, NULL, 0 },
987 { 56, 4, "mxcsr" , {0}, NULL, 0 }
988};
989
Greg Clayton20d338f2010-11-18 05:57:03 +0000990
Chris Lattner24943d22010-06-08 16:52:24 +0000991void
Greg Clayton20d338f2010-11-18 05:57:03 +0000992RNBRemote::Initialize()
Chris Lattner24943d22010-06-08 16:52:24 +0000993{
Greg Clayton20d338f2010-11-18 05:57:03 +0000994 DNBInitialize();
995}
996
997
998bool
999RNBRemote::InitializeRegisters ()
1000{
1001 pid_t pid = m_ctx.ProcessID();
1002 if (pid == INVALID_NUB_PROCESS)
1003 return false;
1004
1005 if (m_use_native_regs)
Chris Lattner24943d22010-06-08 16:52:24 +00001006 {
Greg Claytona2f74232011-02-24 22:24:29 +00001007 DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface", __FUNCTION__);
Greg Clayton20d338f2010-11-18 05:57:03 +00001008 // Discover the registers by querying the DNB interface and letting it
1009 // state the registers that it would like to export. This allows the
1010 // registers to be discovered using multiple qRegisterInfo calls to get
1011 // all register information after the architecture for the process is
1012 // determined.
1013 if (g_dynamic_register_map.empty())
1014 {
1015 nub_size_t num_reg_sets = 0;
1016 const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets);
1017
1018 assert (num_reg_sets > 0 && reg_sets != NULL);
1019
1020 uint32_t regnum = 0;
1021 for (nub_size_t set = 0; set < num_reg_sets; ++set)
1022 {
1023 if (reg_sets[set].registers == NULL)
1024 continue;
1025
1026 for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg)
1027 {
1028 register_map_entry_t reg_entry = {
1029 regnum++, // register number starts at zero and goes up with no gaps
1030 reg_sets[set].registers[reg].size, // register size in bytes
1031 reg_sets[set].registers[reg].name, // register name
1032 reg_sets[set].registers[reg], // DNBRegisterInfo
1033 NULL, // Value to print if case we fail to reg this register (if this is NULL, we will return an error)
1034 reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM};
1035
1036 g_dynamic_register_map.push_back (reg_entry);
1037 }
1038 }
1039 g_reg_entries = g_dynamic_register_map.data();
1040 g_num_reg_entries = g_dynamic_register_map.size();
1041 }
1042 return true;
Chris Lattner24943d22010-06-08 16:52:24 +00001043 }
1044 else
1045 {
Greg Claytona2f74232011-02-24 22:24:29 +00001046 uint32_t cpu_type = DNBProcessGetCPUType (pid);
1047 DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers(%s)", __FUNCTION__, m_arch.c_str());
Greg Clayton20d338f2010-11-18 05:57:03 +00001048#if defined (__i386__) || defined (__x86_64__)
Greg Claytona2f74232011-02-24 22:24:29 +00001049 if (cpu_type == CPU_TYPE_X86_64)
Chris Lattner24943d22010-06-08 16:52:24 +00001050 {
Greg Clayton20d338f2010-11-18 05:57:03 +00001051 const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
1052 for (uint32_t i=0; i<num_regs; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +00001053 {
Greg Clayton20d338f2010-11-18 05:57:03 +00001054 if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info))
1055 {
1056 RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]);
1057 assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE);
1058 }
Chris Lattner24943d22010-06-08 16:52:24 +00001059 }
Greg Clayton20d338f2010-11-18 05:57:03 +00001060 g_reg_entries = g_gdb_register_map_x86_64;
1061 g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t);
1062 return true;
Chris Lattner24943d22010-06-08 16:52:24 +00001063 }
Greg Claytona2f74232011-02-24 22:24:29 +00001064 else if (cpu_type == CPU_TYPE_I386)
Greg Clayton20d338f2010-11-18 05:57:03 +00001065 {
1066 const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
1067 for (uint32_t i=0; i<num_regs; ++i)
1068 {
1069 if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info))
1070 {
1071 RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]);
1072 assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
1073 }
1074 }
1075 g_reg_entries = g_gdb_register_map_i386;
1076 g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t);
1077 return true;
1078 }
1079#elif defined (__arm__)
Greg Claytona2f74232011-02-24 22:24:29 +00001080 if (cpu_type == CPU_TYPE_ARM)
Greg Clayton20d338f2010-11-18 05:57:03 +00001081 {
1082 const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
1083 for (uint32_t i=0; i<num_regs; ++i)
1084 {
1085 if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info))
1086 {
1087 RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]);
1088 assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE);
1089 }
1090 }
1091 g_reg_entries = g_gdb_register_map_arm;
1092 g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t);
1093 return true;
1094 }
Chris Lattner24943d22010-06-08 16:52:24 +00001095#endif
Chris Lattner24943d22010-06-08 16:52:24 +00001096 }
Greg Clayton20d338f2010-11-18 05:57:03 +00001097 return false;
Chris Lattner24943d22010-06-08 16:52:24 +00001098}
1099
1100/* The inferior has stopped executing; send a packet
1101 to gdb to let it know. */
1102
1103void
1104RNBRemote::NotifyThatProcessStopped (void)
1105{
Greg Clayton20d338f2010-11-18 05:57:03 +00001106 RNBRemote::HandlePacket_last_signal (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +00001107 return;
1108}
1109
1110
1111/* `A arglen,argnum,arg,...'
1112 Update the inferior context CTX with the program name and arg
1113 list.
1114 The documentation for this packet is underwhelming but my best reading
1115 of this is that it is a series of (len, position #, arg)'s, one for
1116 each argument with "arg" ``hex encoded'' (two 0-9a-f chars?).
1117 Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either
1118 is sufficient to get around the "," position separator escape issue.
1119
1120 e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is
1121
1122 6,0,676462,4,1,2d71,10,2,612e6f7574
1123
1124 Note that "argnum" and "arglen" are numbers in base 10. Again, that's
1125 not documented either way but I'm assuming it's so. */
1126
1127rnb_err_t
1128RNBRemote::HandlePacket_A (const char *p)
1129{
1130 if (p == NULL || *p == '\0')
1131 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001132 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Null packet for 'A' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00001133 }
1134 p++;
1135 if (p == '\0' || !isdigit (*p))
1136 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001137 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not specified on 'A' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00001138 }
1139
1140 /* I promise I don't modify it anywhere in this function. strtoul()'s
1141 2nd arg has to be non-const which makes it problematic to step
1142 through the string easily. */
1143 char *buf = const_cast<char *>(p);
1144
1145 RNBContext& ctx = Context();
1146
1147 while (*buf != '\0')
1148 {
1149 int arglen, argnum;
1150 std::string arg;
1151 char *c;
1152
1153 errno = 0;
1154 arglen = strtoul (buf, &c, 10);
1155 if (errno != 0 && arglen == 0)
1156 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001157 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not a number on 'A' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00001158 }
1159 if (*c != ',')
1160 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001161 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00001162 }
1163 buf = c + 1;
1164
1165 errno = 0;
1166 argnum = strtoul (buf, &c, 10);
1167 if (errno != 0 && argnum == 0)
1168 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001169 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "argnum not a number on 'A' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00001170 }
1171 if (*c != ',')
1172 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001173 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00001174 }
1175 buf = c + 1;
1176
1177 c = buf;
1178 buf = buf + arglen;
1179 while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0')
1180 {
1181 char smallbuf[3];
1182 smallbuf[0] = *c;
1183 smallbuf[1] = *(c + 1);
1184 smallbuf[2] = '\0';
1185
1186 errno = 0;
1187 int ch = strtoul (smallbuf, NULL, 16);
1188 if (errno != 0 && ch == 0)
1189 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001190 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'A' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00001191 }
1192
1193 arg.push_back(ch);
1194 c += 2;
1195 }
1196
1197 ctx.PushArgument (arg.c_str());
1198 if (*buf == ',')
1199 buf++;
1200 }
1201 SendPacket ("OK");
1202
1203 return rnb_success;
1204}
1205
1206/* `H c t'
1207 Set the thread for subsequent actions; 'c' for step/continue ops,
1208 'g' for other ops. -1 means all threads, 0 means any thread. */
1209
1210rnb_err_t
1211RNBRemote::HandlePacket_H (const char *p)
1212{
1213 p++; // skip 'H'
1214 if (*p != 'c' && *p != 'g')
1215 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001216 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing 'c' or 'g' type in H packet");
Chris Lattner24943d22010-06-08 16:52:24 +00001217 }
1218
1219 if (!m_ctx.HasValidProcessID())
1220 {
1221 // We allow gdb to connect to a server that hasn't started running
1222 // the target yet. gdb still wants to ask questions about it and
1223 // freaks out if it gets an error. So just return OK here.
1224 }
1225
1226 errno = 0;
1227 nub_thread_t tid = strtoul (p + 1, NULL, 16);
1228 if (errno != 0 && tid == 0)
1229 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001230 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in H packet");
Chris Lattner24943d22010-06-08 16:52:24 +00001231 }
1232 if (*p == 'c')
1233 SetContinueThread (tid);
1234 if (*p == 'g')
1235 SetCurrentThread (tid);
1236
1237 return SendPacket ("OK");
1238}
1239
1240
1241rnb_err_t
1242RNBRemote::HandlePacket_qLaunchSuccess (const char *p)
1243{
1244 if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0)
1245 return SendPacket("OK");
1246 std::ostringstream ret_str;
1247 std::string status_str;
1248 ret_str << "E" << m_ctx.LaunchStatusAsString(status_str);
1249
1250 return SendPacket (ret_str.str());
1251}
1252
1253rnb_err_t
1254RNBRemote::HandlePacket_qShlibInfoAddr (const char *p)
1255{
1256 if (m_ctx.HasValidProcessID())
1257 {
1258 nub_addr_t shlib_info_addr = DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID());
1259 if (shlib_info_addr != INVALID_NUB_ADDRESS)
1260 {
1261 std::ostringstream ostrm;
1262 ostrm << RAW_HEXBASE << shlib_info_addr;
1263 return SendPacket (ostrm.str ());
1264 }
1265 }
1266 return SendPacket ("E44");
1267}
1268
1269rnb_err_t
1270RNBRemote::HandlePacket_qStepPacketSupported (const char *p)
1271{
1272 // Normally the "s" packet is mandatory, yet in gdb when using ARM, they
1273 // get around the need for this packet by implementing software single
1274 // stepping from gdb. Current versions of debugserver do support the "s"
1275 // packet, yet some older versions do not. We need a way to tell if this
1276 // packet is supported so we can disable software single stepping in gdb
1277 // for remote targets (so the "s" packet will get used).
1278 return SendPacket("OK");
1279}
1280
1281rnb_err_t
1282RNBRemote::HandlePacket_qThreadStopInfo (const char *p)
1283{
1284 p += strlen ("qThreadStopInfo");
1285 nub_thread_t tid = strtoul(p, 0, 16);
1286 return SendStopReplyPacketForThread (tid);
1287}
1288
1289rnb_err_t
1290RNBRemote::HandlePacket_qThreadInfo (const char *p)
1291{
1292 // We allow gdb to connect to a server that hasn't started running
1293 // the target yet. gdb still wants to ask questions about it and
1294 // freaks out if it gets an error. So just return OK here.
1295 nub_process_t pid = m_ctx.ProcessID();
1296 if (pid == INVALID_NUB_PROCESS)
1297 return SendPacket ("OK");
1298
1299 // Only "qfThreadInfo" and "qsThreadInfo" get into this function so
1300 // we only need to check the second byte to tell which is which
1301 if (p[1] == 'f')
1302 {
1303 nub_size_t numthreads = DNBProcessGetNumThreads (pid);
1304 std::ostringstream ostrm;
1305 ostrm << "m";
1306 bool first = true;
1307 for (nub_size_t i = 0; i < numthreads; ++i)
1308 {
1309 if (first)
1310 first = false;
1311 else
1312 ostrm << ",";
1313 nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i);
1314 ostrm << std::hex << th;
1315 }
1316 return SendPacket (ostrm.str ());
1317 }
1318 else
1319 {
1320 return SendPacket ("l");
1321 }
1322}
1323
1324rnb_err_t
1325RNBRemote::HandlePacket_qThreadExtraInfo (const char *p)
1326{
1327 // We allow gdb to connect to a server that hasn't started running
1328 // the target yet. gdb still wants to ask questions about it and
1329 // freaks out if it gets an error. So just return OK here.
1330 nub_process_t pid = m_ctx.ProcessID();
1331 if (pid == INVALID_NUB_PROCESS)
1332 return SendPacket ("OK");
1333
1334 /* This is supposed to return a string like 'Runnable' or
1335 'Blocked on Mutex'.
1336 The returned string is formatted like the "A" packet - a
1337 sequence of letters encoded in as 2-hex-chars-per-letter. */
1338 p += strlen ("qThreadExtraInfo");
1339 if (*p++ != ',')
Greg Claytondb2bab42011-01-27 09:02:32 +00001340 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Illformed qThreadExtraInfo packet");
Chris Lattner24943d22010-06-08 16:52:24 +00001341 errno = 0;
1342 nub_thread_t tid = strtoul (p, NULL, 16);
1343 if (errno != 0 && tid == 0)
1344 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001345 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in qThreadExtraInfo packet");
Chris Lattner24943d22010-06-08 16:52:24 +00001346 }
1347
1348 const char * threadInfo = DNBThreadGetInfo(pid, tid);
1349 if (threadInfo != NULL && threadInfo[0])
1350 {
1351 return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL);
1352 }
1353 else
1354 {
1355 // "OK" == 4f6b
1356 // Return "OK" as a ASCII hex byte stream if things go wrong
1357 return SendPacket ("4f6b");
1358 }
1359
1360 return SendPacket ("");
1361}
1362
1363rnb_err_t
1364RNBRemote::HandlePacket_qC (const char *p)
1365{
1366 nub_process_t pid;
1367 std::ostringstream rep;
1368 // If we haven't run the process yet, we tell the debugger the
1369 // pid is 0. That way it can know to tell use to run later on.
1370 if (m_ctx.HasValidProcessID())
1371 pid = m_ctx.ProcessID();
1372 else
1373 pid = 0;
1374 rep << "QC" << std::hex << pid;
1375 return SendPacket (rep.str());
1376}
1377
1378rnb_err_t
1379RNBRemote::HandlePacket_qRegisterInfo (const char *p)
1380{
Greg Clayton20d338f2010-11-18 05:57:03 +00001381 if (g_num_reg_entries == 0)
1382 InitializeRegisters ();
1383
Chris Lattner24943d22010-06-08 16:52:24 +00001384 p += strlen ("qRegisterInfo");
1385
1386 nub_size_t num_reg_sets = 0;
1387 const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo (&num_reg_sets);
1388 uint32_t reg_num = strtoul(p, 0, 16);
1389
1390 if (reg_num < g_num_reg_entries)
1391 {
1392 const register_map_entry_t *reg_entry = &g_reg_entries[reg_num];
1393 std::ostringstream ostrm;
1394 ostrm << "name:" << reg_entry->gdb_name << ';';
1395
1396 if (reg_entry->nub_info.name && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.name))
1397 ostrm << "alt-name:" << reg_entry->nub_info.name << ';';
1398 else if (reg_entry->nub_info.alt && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.alt))
1399 ostrm << "alt-name:" << reg_entry->nub_info.alt << ';';
1400
1401 ostrm << "bitsize:" << std::dec << reg_entry->gdb_size * 8 << ';';
1402 ostrm << "offset:" << std::dec << reg_entry->nub_info.offset << ';';
1403
1404 switch (reg_entry->nub_info.type)
1405 {
1406 case Uint: ostrm << "encoding:uint;"; break;
1407 case Sint: ostrm << "encoding:sint;"; break;
1408 case IEEE754: ostrm << "encoding:ieee754;"; break;
1409 case Vector: ostrm << "encoding:vector;"; break;
1410 }
1411
1412 switch (reg_entry->nub_info.format)
1413 {
1414 case Binary: ostrm << "format:binary;"; break;
1415 case Decimal: ostrm << "format:decimal;"; break;
1416 case Hex: ostrm << "format:hex;"; break;
1417 case Float: ostrm << "format:float;"; break;
1418 case VectorOfSInt8: ostrm << "format:vector-sint8;"; break;
1419 case VectorOfUInt8: ostrm << "format:vector-uint8;"; break;
1420 case VectorOfSInt16: ostrm << "format:vector-sint16;"; break;
1421 case VectorOfUInt16: ostrm << "format:vector-uint16;"; break;
1422 case VectorOfSInt32: ostrm << "format:vector-sint32;"; break;
1423 case VectorOfUInt32: ostrm << "format:vector-uint32;"; break;
1424 case VectorOfFloat32: ostrm << "format:vector-float32;"; break;
1425 case VectorOfUInt128: ostrm << "format:vector-uint128;"; break;
1426 };
1427
1428 if (reg_set_info && reg_entry->nub_info.set < num_reg_sets)
1429 ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';';
1430
1431
1432 if (g_reg_entries != g_dynamic_register_map.data())
1433 {
1434 if (reg_entry->nub_info.reg_gdb != INVALID_NUB_REGNUM && reg_entry->nub_info.reg_gdb != reg_num)
1435 {
1436 printf("register %s is getting gdb reg_num of %u when the register info says %u\n",
1437 reg_entry->gdb_name, reg_num, reg_entry->nub_info.reg_gdb);
1438 }
1439 }
1440
1441 if (reg_entry->nub_info.reg_gcc != INVALID_NUB_REGNUM)
1442 ostrm << "gcc:" << std::dec << reg_entry->nub_info.reg_gcc << ';';
1443
1444 if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM)
1445 ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';';
1446
1447
1448 switch (reg_entry->nub_info.reg_generic)
1449 {
1450 case GENERIC_REGNUM_FP: ostrm << "generic:fp;"; break;
1451 case GENERIC_REGNUM_PC: ostrm << "generic:pc;"; break;
1452 case GENERIC_REGNUM_SP: ostrm << "generic:sp;"; break;
1453 case GENERIC_REGNUM_RA: ostrm << "generic:ra;"; break;
1454 case GENERIC_REGNUM_FLAGS: ostrm << "generic:flags;"; break;
1455 default: break;
1456 }
1457
1458 return SendPacket (ostrm.str ());
1459 }
1460 return SendPacket ("E45");
1461}
1462
1463
1464/* This expects a packet formatted like
1465
1466 QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE;
1467
1468 with the "QSetLogging:" already removed from the start. Maybe in the
1469 future this packet will include other keyvalue pairs like
1470
1471 QSetLogging:bitmask=LOG_ALL;mode=asl;
1472 */
1473
1474rnb_err_t
1475set_logging (const char *p)
1476{
1477 int bitmask = 0;
1478 while (p && *p != '\0')
1479 {
1480 if (strncmp (p, "bitmask=", sizeof ("bitmask=") - 1) == 0)
1481 {
1482 p += sizeof ("bitmask=") - 1;
1483 while (p && *p != '\0' && *p != ';')
1484 {
1485 if (*p == '|')
1486 p++;
1487 if (strncmp (p, "LOG_VERBOSE", sizeof ("LOG_VERBOSE") - 1) == 0)
1488 {
1489 p += sizeof ("LOG_VERBOSE") - 1;
1490 bitmask |= LOG_VERBOSE;
1491 }
1492 else if (strncmp (p, "LOG_PROCESS", sizeof ("LOG_PROCESS") - 1) == 0)
1493 {
1494 p += sizeof ("LOG_PROCESS") - 1;
1495 bitmask |= LOG_PROCESS;
1496 }
1497 else if (strncmp (p, "LOG_THREAD", sizeof ("LOG_THREAD") - 1) == 0)
1498 {
1499 p += sizeof ("LOG_THREAD") - 1;
1500 bitmask |= LOG_THREAD;
1501 }
1502 else if (strncmp (p, "LOG_EXCEPTIONS", sizeof ("LOG_EXCEPTIONS") - 1) == 0)
1503 {
1504 p += sizeof ("LOG_EXCEPTIONS") - 1;
1505 bitmask |= LOG_EXCEPTIONS;
1506 }
1507 else if (strncmp (p, "LOG_SHLIB", sizeof ("LOG_SHLIB") - 1) == 0)
1508 {
1509 p += sizeof ("LOG_SHLIB") - 1;
1510 bitmask |= LOG_SHLIB;
1511 }
1512 else if (strncmp (p, "LOG_MEMORY", sizeof ("LOG_MEMORY") - 1) == 0)
1513 {
1514 p += sizeof ("LOG_MEMORY") - 1;
1515 bitmask |= LOG_MEMORY;
1516 }
1517 else if (strncmp (p, "LOG_MEMORY_DATA_SHORT", sizeof ("LOG_MEMORY_DATA_SHORT") - 1) == 0)
1518 {
1519 p += sizeof ("LOG_MEMORY_DATA_SHORT") - 1;
1520 bitmask |= LOG_MEMORY_DATA_SHORT;
1521 }
1522 else if (strncmp (p, "LOG_MEMORY_DATA_LONG", sizeof ("LOG_MEMORY_DATA_LONG") - 1) == 0)
1523 {
1524 p += sizeof ("LOG_MEMORY_DATA_LONG") - 1;
1525 bitmask |= LOG_MEMORY_DATA_LONG;
1526 }
1527 else if (strncmp (p, "LOG_BREAKPOINTS", sizeof ("LOG_BREAKPOINTS") - 1) == 0)
1528 {
1529 p += sizeof ("LOG_BREAKPOINTS") - 1;
1530 bitmask |= LOG_BREAKPOINTS;
1531 }
1532 else if (strncmp (p, "LOG_ALL", sizeof ("LOG_ALL") - 1) == 0)
1533 {
1534 p += sizeof ("LOG_ALL") - 1;
1535 bitmask |= LOG_ALL;
1536 }
1537 else if (strncmp (p, "LOG_EVENTS", sizeof ("LOG_EVENTS") - 1) == 0)
1538 {
1539 p += sizeof ("LOG_EVENTS") - 1;
1540 bitmask |= LOG_EVENTS;
1541 }
1542 else if (strncmp (p, "LOG_DEFAULT", sizeof ("LOG_DEFAULT") - 1) == 0)
1543 {
1544 p += sizeof ("LOG_DEFAULT") - 1;
1545 bitmask |= LOG_DEFAULT;
1546 }
1547 else if (strncmp (p, "LOG_NONE", sizeof ("LOG_NONE") - 1) == 0)
1548 {
1549 p += sizeof ("LOG_NONE") - 1;
1550 bitmask = 0;
1551 }
1552 else if (strncmp (p, "LOG_RNB_MINIMAL", sizeof ("LOG_RNB_MINIMAL") - 1) == 0)
1553 {
1554 p += sizeof ("LOG_RNB_MINIMAL") - 1;
1555 bitmask |= LOG_RNB_MINIMAL;
1556 }
1557 else if (strncmp (p, "LOG_RNB_MEDIUM", sizeof ("LOG_RNB_MEDIUM") - 1) == 0)
1558 {
1559 p += sizeof ("LOG_RNB_MEDIUM") - 1;
1560 bitmask |= LOG_RNB_MEDIUM;
1561 }
1562 else if (strncmp (p, "LOG_RNB_MAX", sizeof ("LOG_RNB_MAX") - 1) == 0)
1563 {
1564 p += sizeof ("LOG_RNB_MAX") - 1;
1565 bitmask |= LOG_RNB_MAX;
1566 }
1567 else if (strncmp (p, "LOG_RNB_COMM", sizeof ("LOG_RNB_COMM") - 1) == 0)
1568 {
1569 p += sizeof ("LOG_RNB_COMM") - 1;
1570 bitmask |= LOG_RNB_COMM;
1571 }
1572 else if (strncmp (p, "LOG_RNB_REMOTE", sizeof ("LOG_RNB_REMOTE") - 1) == 0)
1573 {
1574 p += sizeof ("LOG_RNB_REMOTE") - 1;
1575 bitmask |= LOG_RNB_REMOTE;
1576 }
1577 else if (strncmp (p, "LOG_RNB_EVENTS", sizeof ("LOG_RNB_EVENTS") - 1) == 0)
1578 {
1579 p += sizeof ("LOG_RNB_EVENTS") - 1;
1580 bitmask |= LOG_RNB_EVENTS;
1581 }
1582 else if (strncmp (p, "LOG_RNB_PROC", sizeof ("LOG_RNB_PROC") - 1) == 0)
1583 {
1584 p += sizeof ("LOG_RNB_PROC") - 1;
1585 bitmask |= LOG_RNB_PROC;
1586 }
1587 else if (strncmp (p, "LOG_RNB_PACKETS", sizeof ("LOG_RNB_PACKETS") - 1) == 0)
1588 {
1589 p += sizeof ("LOG_RNB_PACKETS") - 1;
1590 bitmask |= LOG_RNB_PACKETS;
1591 }
1592 else if (strncmp (p, "LOG_RNB_ALL", sizeof ("LOG_RNB_ALL") - 1) == 0)
1593 {
1594 p += sizeof ("LOG_RNB_ALL") - 1;
1595 bitmask |= LOG_RNB_ALL;
1596 }
1597 else if (strncmp (p, "LOG_RNB_DEFAULT", sizeof ("LOG_RNB_DEFAULT") - 1) == 0)
1598 {
1599 p += sizeof ("LOG_RNB_DEFAULT") - 1;
1600 bitmask |= LOG_RNB_DEFAULT;
1601 }
1602 else if (strncmp (p, "LOG_RNB_NONE", sizeof ("LOG_RNB_NONE") - 1) == 0)
1603 {
1604 p += sizeof ("LOG_RNB_NONE") - 1;
1605 bitmask = 0;
1606 }
1607 else
1608 {
1609 /* Unrecognized logging bit; ignore it. */
1610 const char *c = strchr (p, '|');
1611 if (c)
1612 {
1613 p = c;
1614 }
1615 else
1616 {
1617 c = strchr (p, ';');
1618 if (c)
1619 {
1620 p = c;
1621 }
1622 else
1623 {
1624 // Improperly terminated word; just go to end of str
1625 p = strchr (p, '\0');
1626 }
1627 }
1628 }
1629 }
1630 // Did we get a properly formatted logging bitmask?
1631 if (*p == ';')
1632 {
1633 // Enable DNB logging
1634 DNBLogSetLogCallback(ASLLogCallback, NULL);
1635 DNBLogSetLogMask (bitmask);
1636 p++;
1637 }
1638 }
1639 // We're not going to support logging to a file for now. All logging
1640 // goes through ASL.
1641#if 0
1642 else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0)
1643 {
1644 p += sizeof ("mode=") - 1;
1645 if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0)
1646 {
1647 DNBLogToASL ();
1648 p += sizeof ("asl;") - 1;
1649 }
1650 else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0)
1651 {
1652 DNBLogToFile ();
1653 p += sizeof ("file;") - 1;
1654 }
1655 else
1656 {
1657 // Ignore unknown argument
1658 const char *c = strchr (p, ';');
1659 if (c)
1660 p = c + 1;
1661 else
1662 p = strchr (p, '\0');
1663 }
1664 }
1665 else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0)
1666 {
1667 p += sizeof ("filename=") - 1;
1668 const char *c = strchr (p, ';');
1669 if (c == NULL)
1670 {
1671 c = strchr (p, '\0');
1672 continue;
1673 }
1674 char *fn = (char *) alloca (c - p + 1);
1675 strncpy (fn, p, c - p);
1676 fn[c - p] = '\0';
1677
1678 // A file name of "asl" is special and is another way to indicate
1679 // that logging should be done via ASL, not by file.
1680 if (strcmp (fn, "asl") == 0)
1681 {
1682 DNBLogToASL ();
1683 }
1684 else
1685 {
1686 FILE *f = fopen (fn, "w");
1687 if (f)
1688 {
1689 DNBLogSetLogFile (f);
1690 DNBEnableLogging (f, DNBLogGetLogMask ());
1691 DNBLogToFile ();
1692 }
1693 }
1694 p = c + 1;
1695 }
1696#endif /* #if 0 to enforce ASL logging only. */
1697 else
1698 {
1699 // Ignore unknown argument
1700 const char *c = strchr (p, ';');
1701 if (c)
1702 p = c + 1;
1703 else
1704 p = strchr (p, '\0');
1705 }
1706 }
1707
1708 return rnb_success;
1709}
1710
Greg Claytonc71899e2011-01-18 19:36:39 +00001711rnb_err_t
1712RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p)
1713{
1714 m_thread_suffix_supported = true;
1715 return SendPacket ("OK");
1716}
1717
1718rnb_err_t
1719RNBRemote::HandlePacket_QStartNoAckMode (const char *p)
1720{
1721 // Send the OK packet first so the correct checksum is appended...
1722 rnb_err_t result = SendPacket ("OK");
1723 m_noack_mode = true;
1724 return result;
1725}
Chris Lattner24943d22010-06-08 16:52:24 +00001726
1727
1728rnb_err_t
Greg Claytonc71899e2011-01-18 19:36:39 +00001729RNBRemote::HandlePacket_QSetLogging (const char *p)
Chris Lattner24943d22010-06-08 16:52:24 +00001730{
Greg Claytonc71899e2011-01-18 19:36:39 +00001731 p += sizeof ("QSetLogging:") - 1;
1732 rnb_err_t result = set_logging (p);
1733 if (result == rnb_success)
Greg Clayton0a7f75f2010-09-09 06:32:46 +00001734 return SendPacket ("OK");
Greg Claytonc71899e2011-01-18 19:36:39 +00001735 else
1736 return SendPacket ("E35");
1737}
Greg Clayton0a7f75f2010-09-09 06:32:46 +00001738
Greg Claytonc71899e2011-01-18 19:36:39 +00001739rnb_err_t
1740RNBRemote::HandlePacket_QSetDisableASLR (const char *p)
1741{
1742 extern int g_disable_aslr;
1743 p += sizeof ("QSetDisableASLR:") - 1;
1744 switch (*p)
1745 {
1746 case '0': g_disable_aslr = 0; break;
1747 case '1': g_disable_aslr = 1; break;
1748 default:
1749 return SendPacket ("E56");
1750 }
1751 return SendPacket ("OK");
1752}
1753
Greg Claytona2f74232011-02-24 22:24:29 +00001754rnb_err_t
1755RNBRemote::HandlePacket_QSetSTDIO (const char *p)
1756{
1757 // Only set stdin/out/err if we don't already have a process
1758 if (!m_ctx.HasValidProcessID())
1759 {
1760 bool success = false;
1761 // Check the seventh character since the packet will be one of:
1762 // QSetSTDIN
1763 // QSetSTDOUT
1764 // QSetSTDERR
1765 StringExtractor packet(p);
1766 packet.SetFilePos (7);
1767 char ch = packet.GetChar();
1768 while (packet.GetChar() != ':')
1769 /* Do nothing. */;
1770
1771 switch (ch)
1772 {
1773 case 'I': // STDIN
1774 packet.GetHexByteString (m_ctx.GetSTDIN());
1775 success = !m_ctx.GetSTDIN().empty();
1776 break;
1777
1778 case 'O': // STDOUT
1779 packet.GetHexByteString (m_ctx.GetSTDOUT());
1780 success = !m_ctx.GetSTDOUT().empty();
1781 break;
1782
1783 case 'E': // STDERR
1784 packet.GetHexByteString (m_ctx.GetSTDERR());
1785 success = !m_ctx.GetSTDERR().empty();
1786 break;
1787
1788 default:
1789 break;
1790 }
1791 if (success)
1792 return SendPacket ("OK");
1793 return SendPacket ("E57");
1794 }
1795 return SendPacket ("E58");
1796}
1797
1798rnb_err_t
1799RNBRemote::HandlePacket_QSetWorkingDir (const char *p)
1800{
1801 // Only set the working directory if we don't already have a process
1802 if (!m_ctx.HasValidProcessID())
1803 {
1804 StringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1);
1805 if (packet.GetHexByteString (m_ctx.GetWorkingDir()))
1806 {
1807 struct stat working_dir_stat;
1808 if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1)
1809 {
1810 m_ctx.GetWorkingDir().clear();
1811 return SendPacket ("E61"); // Working directory doesn't exist...
1812 }
1813 else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR)
1814 {
1815 return SendPacket ("OK");
1816 }
1817 else
1818 {
1819 m_ctx.GetWorkingDir().clear();
1820 return SendPacket ("E62"); // Working directory isn't a directory...
1821 }
1822 }
1823 return SendPacket ("E59"); // Invalid path
1824 }
1825 return SendPacket ("E60"); // Already had a process, too late to set working dir
1826}
1827
Greg Claytonc71899e2011-01-18 19:36:39 +00001828
1829rnb_err_t
1830RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p)
1831{
Chris Lattner24943d22010-06-08 16:52:24 +00001832 /* The number of characters in a packet payload that gdb is
1833 prepared to accept. The packet-start char, packet-end char,
1834 2 checksum chars and terminating null character are not included
1835 in this size. */
Greg Claytonc71899e2011-01-18 19:36:39 +00001836 p += sizeof ("QSetMaxPayloadSize:") - 1;
1837 errno = 0;
1838 uint32_t size = strtoul (p, NULL, 16);
1839 if (errno != 0 && size == 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001840 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001841 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet");
Chris Lattner24943d22010-06-08 16:52:24 +00001842 }
Greg Claytonc71899e2011-01-18 19:36:39 +00001843 m_max_payload_size = size;
1844 return SendPacket ("OK");
1845}
Chris Lattner24943d22010-06-08 16:52:24 +00001846
Greg Claytonc71899e2011-01-18 19:36:39 +00001847rnb_err_t
1848RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p)
1849{
Chris Lattner24943d22010-06-08 16:52:24 +00001850 /* This tells us the largest packet that gdb can handle.
1851 i.e. the size of gdb's packet-reading buffer.
1852 QSetMaxPayloadSize is preferred because it is less ambiguous. */
Greg Claytonc71899e2011-01-18 19:36:39 +00001853 p += sizeof ("QSetMaxPacketSize:") - 1;
1854 errno = 0;
1855 uint32_t size = strtoul (p, NULL, 16);
1856 if (errno != 0 && size == 0)
Chris Lattner24943d22010-06-08 16:52:24 +00001857 {
Greg Claytondb2bab42011-01-27 09:02:32 +00001858 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPacketSize packet");
Chris Lattner24943d22010-06-08 16:52:24 +00001859 }
Greg Claytonc71899e2011-01-18 19:36:39 +00001860 m_max_payload_size = size - 5;
1861 return SendPacket ("OK");
1862}
Chris Lattner24943d22010-06-08 16:52:24 +00001863
Greg Claytonc71899e2011-01-18 19:36:39 +00001864
1865
1866
1867rnb_err_t
1868RNBRemote::HandlePacket_QEnvironment (const char *p)
1869{
Chris Lattner24943d22010-06-08 16:52:24 +00001870 /* This sets the environment for the target program. The packet is of the form:
1871
1872 QEnvironment:VARIABLE=VALUE
1873
1874 */
1875
Greg Claytonc71899e2011-01-18 19:36:39 +00001876 DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"",
1877 (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p);
Chris Lattner24943d22010-06-08 16:52:24 +00001878
Greg Claytonc71899e2011-01-18 19:36:39 +00001879 p += sizeof ("QEnvironment:") - 1;
1880 RNBContext& ctx = Context();
Chris Lattner24943d22010-06-08 16:52:24 +00001881
Greg Claytonc71899e2011-01-18 19:36:39 +00001882 ctx.PushEnvironment (p);
1883 return SendPacket ("OK");
Chris Lattner24943d22010-06-08 16:52:24 +00001884}
1885
1886void
1887append_hex_value (std::ostream& ostrm, const uint8_t* buf, size_t buf_size, bool swap)
1888{
1889 int i;
1890 if (swap)
1891 {
1892 for (i = buf_size-1; i >= 0; i--)
1893 ostrm << RAWHEX8(buf[i]);
1894 }
1895 else
1896 {
1897 for (i = 0; i < buf_size; i++)
1898 ostrm << RAWHEX8(buf[i]);
1899 }
1900}
1901
1902
1903void
Greg Claytona2f74232011-02-24 22:24:29 +00001904register_value_in_hex_fixed_width (std::ostream& ostrm,
1905 nub_process_t pid,
1906 nub_thread_t tid,
1907 const register_map_entry_t* reg)
Chris Lattner24943d22010-06-08 16:52:24 +00001908{
1909 if (reg != NULL)
1910 {
1911 DNBRegisterValue val;
1912 if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, &val))
1913 {
1914 append_hex_value (ostrm, val.value.v_uint8, reg->gdb_size, false);
1915 }
1916 else
1917 {
1918 // If we fail to read a regiser value, check if it has a default
1919 // fail value. If it does, return this instead in case some of
1920 // the registers are not available on the current system.
1921 if (reg->gdb_size > 0)
1922 {
1923 if (reg->fail_value != NULL)
1924 {
1925 append_hex_value (ostrm, reg->fail_value, reg->gdb_size, false);
1926 }
1927 else
1928 {
1929 std::basic_string<uint8_t> zeros(reg->gdb_size, '\0');
1930 append_hex_value (ostrm, zeros.data(), zeros.size(), false);
1931 }
1932 }
1933 }
1934 }
1935}
1936
1937
1938void
Greg Claytona2f74232011-02-24 22:24:29 +00001939gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm,
1940 nub_process_t pid,
1941 nub_thread_t tid,
1942 const register_map_entry_t* reg)
Chris Lattner24943d22010-06-08 16:52:24 +00001943{
1944 // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX
1945 // gdb register number, and VVVVVVVV is the correct number of hex bytes
1946 // as ASCII for the register value.
1947 if (reg != NULL)
1948 {
1949 ostrm << RAWHEX8(reg->gdb_regnum) << ':';
1950 register_value_in_hex_fixed_width (ostrm, pid, tid, reg);
1951 ostrm << ';';
1952 }
1953}
1954
1955rnb_err_t
1956RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
1957{
1958 const nub_process_t pid = m_ctx.ProcessID();
1959 if (pid == INVALID_NUB_PROCESS)
1960 return SendPacket("E50");
1961
1962 struct DNBThreadStopInfo tid_stop_info;
1963
1964 /* Fill the remaining space in this packet with as many registers
1965 as we can stuff in there. */
1966
1967 if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
1968 {
1969 std::ostringstream ostrm;
1970 // Output the T packet with the thread
1971 ostrm << 'T';
1972 int signum = tid_stop_info.details.signal.signo;
1973 DNBLogThreadedIf (LOG_RNB_PROC, "%8d %s got signal signo = %u, exc_type = %u", (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, tid_stop_info.details.signal.signo, tid_stop_info.details.exception.type);
1974
1975 // Translate any mach exceptions to gdb versions, unless they are
1976 // common exceptions like a breakpoint or a soft signal.
1977 switch (tid_stop_info.details.exception.type)
1978 {
1979 default: signum = 0; break;
1980 case EXC_BREAKPOINT: signum = SIGTRAP; break;
1981 case EXC_BAD_ACCESS: signum = TARGET_EXC_BAD_ACCESS; break;
1982 case EXC_BAD_INSTRUCTION: signum = TARGET_EXC_BAD_INSTRUCTION; break;
1983 case EXC_ARITHMETIC: signum = TARGET_EXC_ARITHMETIC; break;
1984 case EXC_EMULATION: signum = TARGET_EXC_EMULATION; break;
1985 case EXC_SOFTWARE:
1986 if (tid_stop_info.details.exception.data_count == 2 &&
1987 tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL)
1988 signum = tid_stop_info.details.exception.data[1];
1989 else
1990 signum = TARGET_EXC_SOFTWARE;
1991 break;
1992 }
1993
1994 ostrm << RAWHEX8(signum & 0xff);
1995
1996 ostrm << std::hex << "thread:" << tid << ';';
1997
1998 const char *thread_name = DNBThreadGetName (pid, tid);
1999 if (thread_name && thread_name[0])
Greg Clayton4862fa22011-01-08 03:17:57 +00002000 {
2001 size_t thread_name_len = strlen(thread_name);
2002
2003 if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
2004 ostrm << std::hex << "name:" << thread_name << ';';
2005 else
2006 {
2007 // the thread name contains special chars, send as hex bytes
2008 ostrm << std::hex << "hexname:";
2009 uint8_t *u_thread_name = (uint8_t *)thread_name;
2010 for (int i = 0; i < thread_name_len; i++)
2011 ostrm << RAWHEX8(u_thread_name[i]);
2012 ostrm << ';';
2013 }
2014 }
Chris Lattner24943d22010-06-08 16:52:24 +00002015
2016 thread_identifier_info_data_t thread_ident_info;
2017 if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info))
2018 {
2019 if (thread_ident_info.dispatch_qaddr != 0)
Greg Clayton0a7f75f2010-09-09 06:32:46 +00002020 ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';';
Chris Lattner24943d22010-06-08 16:52:24 +00002021 }
Greg Clayton20d338f2010-11-18 05:57:03 +00002022 if (g_num_reg_entries == 0)
2023 InitializeRegisters ();
2024
Chris Lattner24943d22010-06-08 16:52:24 +00002025 DNBRegisterValue reg_value;
2026 for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2027 {
2028 if (g_reg_entries[reg].expedite)
2029 {
2030 if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, &reg_value))
2031 continue;
2032
2033 gdb_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg]);
2034 }
2035 }
2036
2037 if (tid_stop_info.details.exception.type)
2038 {
2039 ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
2040 ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
2041 for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i)
2042 ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";";
2043 }
2044 return SendPacket (ostrm.str ());
2045 }
2046 return SendPacket("E51");
2047}
2048
2049/* `?'
2050 The stop reply packet - tell gdb what the status of the inferior is.
2051 Often called the questionmark_packet. */
2052
2053rnb_err_t
2054RNBRemote::HandlePacket_last_signal (const char *unused)
2055{
2056 if (!m_ctx.HasValidProcessID())
2057 {
2058 // Inferior is not yet specified/running
2059 return SendPacket ("E02");
2060 }
2061
2062 nub_process_t pid = m_ctx.ProcessID();
2063 nub_state_t pid_state = DNBProcessGetState (pid);
2064
2065 switch (pid_state)
2066 {
2067 case eStateAttaching:
2068 case eStateLaunching:
2069 case eStateRunning:
2070 case eStateStepping:
2071 return rnb_success; // Ignore
2072
2073 case eStateSuspended:
2074 case eStateStopped:
2075 case eStateCrashed:
Greg Clayton20d338f2010-11-18 05:57:03 +00002076 {
2077 nub_thread_t tid = DNBProcessGetCurrentThread (pid);
2078 // Make sure we set the current thread so g and p packets return
2079 // the data the gdb will expect.
2080 SetCurrentThread (tid);
Chris Lattner24943d22010-06-08 16:52:24 +00002081
Greg Clayton20d338f2010-11-18 05:57:03 +00002082 SendStopReplyPacketForThread (tid);
2083 }
Chris Lattner24943d22010-06-08 16:52:24 +00002084 break;
2085
2086 case eStateInvalid:
2087 case eStateUnloaded:
2088 case eStateExited:
Chris Lattner24943d22010-06-08 16:52:24 +00002089 {
Greg Clayton20d338f2010-11-18 05:57:03 +00002090 char pid_exited_packet[16] = "";
2091 int pid_status = 0;
2092 // Process exited with exit status
2093 if (!DNBProcessGetExitStatus(pid, &pid_status))
2094 pid_status = 0;
Chris Lattner24943d22010-06-08 16:52:24 +00002095
Greg Clayton20d338f2010-11-18 05:57:03 +00002096 if (pid_status)
2097 {
2098 if (WIFEXITED (pid_status))
2099 snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status));
2100 else if (WIFSIGNALED (pid_status))
2101 snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status));
2102 else if (WIFSTOPPED (pid_status))
2103 snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status));
2104 }
Chris Lattner24943d22010-06-08 16:52:24 +00002105
Greg Clayton20d338f2010-11-18 05:57:03 +00002106 // If we have an empty exit packet, lets fill one in to be safe.
2107 if (!pid_exited_packet[0])
2108 {
2109 strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1);
2110 pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0';
2111 }
2112
2113 return SendPacket (pid_exited_packet);
2114 }
Chris Lattner24943d22010-06-08 16:52:24 +00002115 break;
2116 }
2117 return rnb_success;
2118}
2119
2120rnb_err_t
2121RNBRemote::HandlePacket_M (const char *p)
2122{
2123 if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2124 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002125 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002126 }
2127
2128 char *c;
2129 p++;
2130 errno = 0;
2131 nub_addr_t addr = strtoull (p, &c, 16);
2132 if (errno != 0 && addr == 0)
2133 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002134 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002135 }
2136 if (*c != ',')
2137 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002138 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002139 }
2140
2141 /* Advance 'p' to the length part of the packet. */
2142 p += (c - p) + 1;
2143
2144 errno = 0;
2145 uint32_t length = strtoul (p, &c, 16);
2146 if (errno != 0 && length == 0)
2147 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002148 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002149 }
2150 if (length == 0)
2151 {
2152 return SendPacket ("OK");
2153 }
2154
2155 if (*c != ':')
2156 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002157 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002158 }
2159 /* Advance 'p' to the data part of the packet. */
2160 p += (c - p) + 1;
2161
2162 int datalen = strlen (p);
2163 if (datalen & 0x1)
2164 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002165 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002166 }
2167 if (datalen == 0)
2168 {
2169 return SendPacket ("OK");
2170 }
2171
2172 uint8_t *buf = (uint8_t *) alloca (datalen / 2);
2173 uint8_t *i = buf;
2174
2175 while (*p != '\0' && *(p + 1) != '\0')
2176 {
2177 char hexbuf[3];
2178 hexbuf[0] = *p;
2179 hexbuf[1] = *(p + 1);
2180 hexbuf[2] = '\0';
2181 errno = 0;
2182 uint8_t byte = strtoul (hexbuf, NULL, 16);
2183 if (errno != 0 && byte == 0)
2184 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002185 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002186 }
2187 *i++ = byte;
2188 p += 2;
2189 }
2190
2191 nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf);
2192 if (wrote != length)
2193 return SendPacket ("E09");
2194 else
2195 return SendPacket ("OK");
2196}
2197
2198
2199rnb_err_t
2200RNBRemote::HandlePacket_m (const char *p)
2201{
2202 if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2203 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002204 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002205 }
2206
2207 char *c;
2208 p++;
2209 errno = 0;
2210 nub_addr_t addr = strtoull (p, &c, 16);
2211 if (errno != 0 && addr == 0)
2212 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002213 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002214 }
2215 if (*c != ',')
2216 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002217 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002218 }
2219
2220 /* Advance 'p' to the length part of the packet. */
2221 p += (c - p) + 1;
2222
2223 errno = 0;
2224 uint32_t length = strtoul (p, NULL, 16);
2225 if (errno != 0 && length == 0)
2226 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002227 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002228 }
2229 if (length == 0)
2230 {
2231 return SendPacket ("");
2232 }
2233
2234 uint8_t buf[length];
2235 int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, length, buf);
2236 if (bytes_read == 0)
2237 {
2238 return SendPacket ("E08");
2239 }
2240
2241 // "The reply may contain fewer bytes than requested if the server was able
2242 // to read only part of the region of memory."
2243 length = bytes_read;
2244
2245 std::ostringstream ostrm;
2246 for (int i = 0; i < length; i++)
2247 ostrm << RAWHEX8(buf[i]);
2248 return SendPacket (ostrm.str ());
2249}
2250
2251rnb_err_t
2252RNBRemote::HandlePacket_X (const char *p)
2253{
2254 if (p == NULL || p[0] == '\0' || strlen (p) < 3)
2255 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002256 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002257 }
2258
2259 char *c;
2260 p++;
2261 errno = 0;
2262 nub_addr_t addr = strtoull (p, &c, 16);
2263 if (errno != 0 && addr == 0)
2264 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002265 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002266 }
2267 if (*c != ',')
2268 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002269 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002270 }
2271
2272 /* Advance 'p' to the length part of the packet. */
2273 p += (c - p) + 1;
2274
2275 errno = 0;
2276 int length = strtoul (p, NULL, 16);
2277 if (errno != 0 && length == 0)
2278 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002279 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002280 }
2281
2282 // I think gdb sends a zero length write request to test whether this
2283 // packet is accepted.
2284 if (length == 0)
2285 {
2286 return SendPacket ("OK");
2287 }
2288
2289 std::vector<uint8_t> data = decode_binary_data (c, -1);
2290 std::vector<uint8_t>::const_iterator it;
2291 uint8_t *buf = (uint8_t *) alloca (data.size ());
2292 uint8_t *i = buf;
2293 for (it = data.begin (); it != data.end (); ++it)
2294 {
2295 *i++ = *it;
2296 }
2297
2298 nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf);
2299 if (wrote != data.size ())
2300 return SendPacket ("E08");
2301 return SendPacket ("OK");
2302}
2303
2304/* `g' -- read registers
2305 Get the contents of the registers for the current thread,
2306 send them to gdb.
2307 Should the setting of the Hg packet determine which thread's registers
2308 are returned? */
2309
2310rnb_err_t
2311RNBRemote::HandlePacket_g (const char *p)
2312{
2313 std::ostringstream ostrm;
2314 if (!m_ctx.HasValidProcessID())
2315 {
2316 return SendPacket ("E11");
2317 }
Greg Clayton20d338f2010-11-18 05:57:03 +00002318
2319 if (g_num_reg_entries == 0)
2320 InitializeRegisters ();
2321
Chris Lattner24943d22010-06-08 16:52:24 +00002322 nub_process_t pid = m_ctx.ProcessID ();
Greg Claytonc71899e2011-01-18 19:36:39 +00002323 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1);
2324 if (tid == INVALID_NUB_THREAD)
Greg Claytondb2bab42011-01-27 09:02:32 +00002325 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002326
2327 if (m_use_native_regs)
2328 {
2329 // Get the register context size first by calling with NULL buffer
2330 nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2331 if (reg_ctx_size)
2332 {
2333 // Now allocate enough space for the entire register context
2334 std::vector<uint8_t> reg_ctx;
2335 reg_ctx.resize(reg_ctx_size);
2336 // Now read the register context
2337 reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, &reg_ctx[0], reg_ctx.size());
2338 if (reg_ctx_size)
2339 {
2340 append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false);
2341 return SendPacket (ostrm.str ());
2342 }
2343 }
2344 }
2345
2346 for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2347 register_value_in_hex_fixed_width (ostrm, pid, tid, &g_reg_entries[reg]);
2348
2349 return SendPacket (ostrm.str ());
2350}
2351
2352/* `G XXX...' -- write registers
2353 How is the thread for these specified, beyond "the current thread"?
2354 Does gdb actually use the Hg packet to set this? */
2355
2356rnb_err_t
2357RNBRemote::HandlePacket_G (const char *p)
2358{
2359 if (!m_ctx.HasValidProcessID())
2360 {
2361 return SendPacket ("E11");
2362 }
Greg Clayton20d338f2010-11-18 05:57:03 +00002363
2364 if (g_num_reg_entries == 0)
2365 InitializeRegisters ();
2366
Chris Lattner24943d22010-06-08 16:52:24 +00002367 StringExtractor packet(p);
2368 packet.SetFilePos(1); // Skip the 'G'
2369
2370 nub_process_t pid = m_ctx.ProcessID();
Greg Claytonc71899e2011-01-18 19:36:39 +00002371 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
2372 if (tid == INVALID_NUB_THREAD)
Greg Claytondb2bab42011-01-27 09:02:32 +00002373 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002374
2375 if (m_use_native_regs)
2376 {
2377 // Get the register context size first by calling with NULL buffer
2378 nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0);
2379 if (reg_ctx_size)
2380 {
2381 // Now allocate enough space for the entire register context
2382 std::vector<uint8_t> reg_ctx;
2383 reg_ctx.resize(reg_ctx_size);
2384
2385 if (packet.GetHexBytes (&reg_ctx[0], reg_ctx.size(), 0xcc) == reg_ctx.size())
2386 {
2387 // Now write the register context
2388 reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size());
2389 if (reg_ctx_size == reg_ctx.size())
2390 return SendPacket ("OK");
2391 else
2392 return SendPacket ("E55");
2393 }
2394 }
2395 }
2396
2397
2398 DNBRegisterValue reg_value;
2399 for (uint32_t reg = 0; reg < g_num_reg_entries; reg++)
2400 {
2401 const register_map_entry_t *reg_entry = &g_reg_entries[reg];
2402
2403 reg_value.info = reg_entry->nub_info;
2404 if (packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc) != reg_entry->gdb_size)
2405 break;
2406
2407 if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
2408 return SendPacket ("E15");
2409 }
2410 return SendPacket ("OK");
2411}
2412
2413static bool
2414RNBRemoteShouldCancelCallback (void *not_used)
2415{
2416 RNBRemoteSP remoteSP(g_remoteSP);
2417 if (remoteSP.get() != NULL)
2418 {
2419 RNBRemote* remote = remoteSP.get();
2420 if (remote->Comm().IsConnected())
2421 return false;
2422 else
2423 return true;
2424 }
2425 return true;
2426}
2427
2428
2429// FORMAT: _MXXXXXX,PPP
2430// XXXXXX: big endian hex chars
2431// PPP: permissions can be any combo of r w x chars
2432//
2433// RESPONSE: XXXXXX
2434// XXXXXX: hex address of the newly allocated memory
2435// EXX: error code
2436//
2437// EXAMPLES:
2438// _M123000,rw
2439// _M123000,rwx
2440// _M123000,xw
2441
2442rnb_err_t
2443RNBRemote::HandlePacket_AllocateMemory (const char *p)
2444{
2445 StringExtractor packet (p);
2446 packet.SetFilePos(2); // Skip the "_M"
2447
2448 nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0);
2449 if (size != 0)
2450 {
2451 if (packet.GetChar() == ',')
2452 {
2453 uint32_t permissions = 0;
2454 char ch;
2455 bool success = true;
2456 while (success && (ch = packet.GetChar()) != '\0')
2457 {
2458 switch (ch)
2459 {
2460 case 'r': permissions |= eMemoryPermissionsReadable; break;
2461 case 'w': permissions |= eMemoryPermissionsWritable; break;
2462 case 'x': permissions |= eMemoryPermissionsExecutable; break;
2463 default: success = false; break;
2464 }
2465 }
2466
2467 if (success)
2468 {
2469 nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions);
2470 if (addr != INVALID_NUB_ADDRESS)
2471 {
2472 std::ostringstream ostrm;
2473 ostrm << RAW_HEXBASE << addr;
2474 return SendPacket (ostrm.str ());
2475 }
2476 }
2477 }
2478 }
2479 return SendPacket ("E53");
2480}
2481
2482// FORMAT: _mXXXXXX
2483// XXXXXX: address that was previosly allocated
2484//
2485// RESPONSE: XXXXXX
2486// OK: address was deallocated
2487// EXX: error code
2488//
2489// EXAMPLES:
2490// _m123000
2491
2492rnb_err_t
2493RNBRemote::HandlePacket_DeallocateMemory (const char *p)
2494{
2495 StringExtractor packet (p);
2496 packet.SetFilePos(2); // Skip the "_m"
2497 nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS);
2498
2499 if (addr != INVALID_NUB_ADDRESS)
2500 {
2501 if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr))
2502 return SendPacket ("OK");
2503 }
2504 return SendPacket ("E54");
2505}
2506
2507/*
2508 vAttach;pid
2509
2510 Attach to a new process with the specified process ID. pid is a hexadecimal integer
2511 identifying the process. If the stub is currently controlling a process, it is
2512 killed. The attached process is stopped.This packet is only available in extended
2513 mode (see extended mode).
2514
2515 Reply:
2516 "ENN" for an error
2517 "Any Stop Reply Packet" for success
2518 */
2519
2520rnb_err_t
2521RNBRemote::HandlePacket_v (const char *p)
2522{
2523 if (strcmp (p, "vCont;c") == 0)
2524 {
2525 // Simple continue
2526 return RNBRemote::HandlePacket_c("c");
2527 }
2528 else if (strcmp (p, "vCont;s") == 0)
2529 {
2530 // Simple step
2531 return RNBRemote::HandlePacket_s("s");
2532 }
2533 else if (strstr (p, "vCont") == p)
2534 {
2535 rnb_err_t rnb_err = rnb_success;
2536 typedef struct
2537 {
2538 nub_thread_t tid;
2539 char action;
2540 int signal;
2541 } vcont_action_t;
2542
2543 DNBThreadResumeActions thread_actions;
2544 char *c = (char *)(p += strlen("vCont"));
2545 char *c_end = c + strlen(c);
2546 if (*c == '?')
2547 return SendPacket ("vCont;c;C;s;S");
2548
2549 while (c < c_end && *c == ';')
2550 {
2551 ++c; // Skip the semi-colon
2552 DNBThreadResumeAction thread_action;
2553 thread_action.tid = INVALID_NUB_THREAD;
2554 thread_action.state = eStateInvalid;
2555 thread_action.signal = 0;
2556 thread_action.addr = INVALID_NUB_ADDRESS;
2557
2558 char action = *c++;
2559
2560 switch (action)
2561 {
2562 case 'C':
2563 errno = 0;
2564 thread_action.signal = strtoul (c, &c, 16);
2565 if (errno != 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00002566 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002567 // Fall through to next case...
2568
2569 case 'c':
2570 // Continue
2571 thread_action.state = eStateRunning;
2572 break;
2573
2574 case 'S':
2575 errno = 0;
2576 thread_action.signal = strtoul (c, &c, 16);
2577 if (errno != 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00002578 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002579 // Fall through to next case...
2580
2581 case 's':
2582 // Step
2583 thread_action.state = eStateStepping;
2584 break;
2585
2586 break;
2587
2588 default:
Greg Claytondb2bab42011-01-27 09:02:32 +00002589 rnb_err = HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002590 break;
2591 }
2592 if (*c == ':')
2593 {
2594 errno = 0;
2595 thread_action.tid = strtoul (++c, &c, 16);
2596 if (errno != 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00002597 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002598 }
2599
2600 thread_actions.Append (thread_action);
2601 }
2602
2603 // If a default action for all other threads wasn't mentioned
2604 // then we should stop the threads
2605 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
2606 DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize());
2607 return rnb_success;
2608 }
2609 else if (strstr (p, "vAttach") == p)
2610 {
2611 nub_process_t attach_pid = INVALID_NUB_PROCESS;
2612 char err_str[1024]={'\0'};
2613 if (strstr (p, "vAttachWait;") == p)
2614 {
2615 p += strlen("vAttachWait;");
2616 std::string attach_name;
2617 while (*p != '\0')
2618 {
2619 char smallbuf[3];
2620 smallbuf[0] = *p;
2621 smallbuf[1] = *(p + 1);
2622 smallbuf[2] = '\0';
2623
2624 errno = 0;
2625 int ch = strtoul (smallbuf, NULL, 16);
2626 if (errno != 0 && ch == 0)
2627 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002628 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
Chris Lattner24943d22010-06-08 16:52:24 +00002629 }
2630
2631 attach_name.push_back(ch);
2632 p += 2;
2633 }
2634
2635 attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback);
2636
2637 }
Greg Clayton0561f3d2010-10-26 21:04:55 +00002638 else if (strstr (p, "vAttachName;") == p)
Greg Claytonc1d37752010-10-18 01:45:30 +00002639 {
2640 p += strlen("vAttachName;");
2641 std::string attach_name;
2642 while (*p != '\0')
2643 {
2644 char smallbuf[3];
2645 smallbuf[0] = *p;
2646 smallbuf[1] = *(p + 1);
2647 smallbuf[2] = '\0';
2648
2649 errno = 0;
2650 int ch = strtoul (smallbuf, NULL, 16);
2651 if (errno != 0 && ch == 0)
2652 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002653 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt");
Greg Claytonc1d37752010-10-18 01:45:30 +00002654 }
2655
2656 attach_name.push_back(ch);
2657 p += 2;
2658 }
2659
2660 attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str));
2661
2662 }
Chris Lattner24943d22010-06-08 16:52:24 +00002663 else if (strstr (p, "vAttach;") == p)
2664 {
2665 p += strlen("vAttach;");
2666 char *end = NULL;
2667 attach_pid = strtoul (p, &end, 16); // PID will be in hex, so use base 16 to decode
2668 if (p != end && *end == '\0')
2669 {
2670 // Wait at most 30 second for attach
2671 struct timespec attach_timeout_abstime;
2672 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0);
2673 attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str));
2674 }
2675 }
2676 else
2677 return HandlePacket_UNIMPLEMENTED(p);
2678
2679
2680 if (attach_pid != INVALID_NUB_PROCESS)
2681 {
2682 if (m_ctx.ProcessID() != attach_pid)
2683 m_ctx.SetProcessID(attach_pid);
2684 // Send a stop reply packet to indicate we successfully attached!
2685 NotifyThatProcessStopped ();
2686 return rnb_success;
2687 }
2688 else
2689 {
2690 m_ctx.LaunchStatus().SetError(-1, DNBError::Generic);
2691 if (err_str[0])
2692 m_ctx.LaunchStatus().SetErrorString(err_str);
2693 else
2694 m_ctx.LaunchStatus().SetErrorString("attach failed");
2695 return SendPacket ("E01"); // E01 is our magic error value for attach failed.
2696 }
2697 }
2698
2699 // All other failures come through here
2700 return HandlePacket_UNIMPLEMENTED(p);
2701}
2702
2703/* `T XX' -- status of thread
2704 Check if the specified thread is alive.
2705 The thread number is in hex? */
2706
2707rnb_err_t
2708RNBRemote::HandlePacket_T (const char *p)
2709{
2710 p++;
2711 if (p == NULL || *p == '\0')
2712 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002713 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002714 }
2715 if (!m_ctx.HasValidProcessID())
2716 {
2717 return SendPacket ("E15");
2718 }
2719 errno = 0;
2720 nub_thread_t tid = strtoul (p, NULL, 16);
2721 if (errno != 0 && tid == 0)
2722 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002723 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002724 }
2725
2726 nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid);
2727 if (state == eStateInvalid || state == eStateExited || state == eStateCrashed)
2728 {
2729 return SendPacket ("E16");
2730 }
2731
2732 return SendPacket ("OK");
2733}
2734
2735
2736rnb_err_t
2737RNBRemote::HandlePacket_z (const char *p)
2738{
2739 if (p == NULL || *p == '\0')
Greg Claytondb2bab42011-01-27 09:02:32 +00002740 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002741
2742 if (!m_ctx.HasValidProcessID())
2743 return SendPacket ("E15");
2744
2745 char packet_cmd = *p++;
2746 char break_type = *p++;
2747
2748 if (*p++ != ',')
Greg Claytondb2bab42011-01-27 09:02:32 +00002749 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002750
2751 char *c = NULL;
2752 nub_process_t pid = m_ctx.ProcessID();
2753 errno = 0;
2754 nub_addr_t addr = strtoull (p, &c, 16);
2755 if (errno != 0 && addr == 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00002756 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002757 p = c;
2758 if (*p++ != ',')
Greg Claytondb2bab42011-01-27 09:02:32 +00002759 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002760
2761 errno = 0;
2762 uint32_t byte_size = strtoul (p, &c, 16);
2763 if (errno != 0 && byte_size == 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00002764 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002765
2766 if (packet_cmd == 'Z')
2767 {
2768 // set
2769 switch (break_type)
2770 {
2771 case '0': // set software breakpoint
2772 case '1': // set hardware breakpoint
2773 {
2774 // gdb can send multiple Z packets for the same address and
2775 // these calls must be ref counted.
2776 bool hardware = (break_type == '1');
2777
2778 // Check if we currently have a breakpoint already set at this address
2779 BreakpointMapIter pos = m_breakpoints.find(addr);
2780 if (pos != m_breakpoints.end())
2781 {
2782 // We do already have a breakpoint at this address, increment
2783 // its reference count and return OK
2784 pos->second.Retain();
2785 return SendPacket ("OK");
2786 }
2787 else
2788 {
2789 // We do NOT already have a breakpoint at this address, So lets
2790 // create one.
2791 nub_break_t break_id = DNBBreakpointSet (pid, addr, byte_size, hardware);
2792 if (break_id != INVALID_NUB_BREAK_ID)
2793 {
2794 // We successfully created a breakpoint, now lets full out
2795 // a ref count structure with the breakID and add it to our
2796 // map.
2797 Breakpoint rnbBreakpoint(break_id);
2798 m_breakpoints[addr] = rnbBreakpoint;
2799 return SendPacket ("OK");
2800 }
2801 else
2802 {
2803 // We failed to set the software breakpoint
2804 return SendPacket ("E09");
2805 }
2806 }
2807 }
2808 break;
2809
2810 case '2': // set write watchpoint
2811 case '3': // set read watchpoint
2812 case '4': // set access watchpoint
2813 {
2814 bool hardware = true;
2815 uint32_t watch_flags = 0;
2816 if (break_type == '2')
2817 watch_flags = WATCH_TYPE_WRITE;
2818 else if (break_type == '3')
2819 watch_flags = WATCH_TYPE_READ;
2820 else
2821 watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE;
2822
2823 // Check if we currently have a watchpoint already set at this address
2824 BreakpointMapIter pos = m_watchpoints.find(addr);
2825 if (pos != m_watchpoints.end())
2826 {
2827 // We do already have a watchpoint at this address, increment
2828 // its reference count and return OK
2829 pos->second.Retain();
2830 return SendPacket ("OK");
2831 }
2832 else
2833 {
2834 // We do NOT already have a breakpoint at this address, So lets
2835 // create one.
2836 nub_watch_t watch_id = DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware);
2837 if (watch_id != INVALID_NUB_BREAK_ID)
2838 {
2839 // We successfully created a watchpoint, now lets full out
2840 // a ref count structure with the watch_id and add it to our
2841 // map.
2842 Breakpoint rnbWatchpoint(watch_id);
2843 m_watchpoints[addr] = rnbWatchpoint;
2844 return SendPacket ("OK");
2845 }
2846 else
2847 {
2848 // We failed to set the watchpoint
2849 return SendPacket ("E09");
2850 }
2851 }
2852 }
2853 break;
2854
2855 default:
2856 break;
2857 }
2858 }
2859 else if (packet_cmd == 'z')
2860 {
2861 // remove
2862 switch (break_type)
2863 {
2864 case '0': // remove software breakpoint
2865 case '1': // remove hardware breakpoint
2866 {
2867 // gdb can send multiple z packets for the same address and
2868 // these calls must be ref counted.
2869 BreakpointMapIter pos = m_breakpoints.find(addr);
2870 if (pos != m_breakpoints.end())
2871 {
2872 // We currently have a breakpoint at address ADDR. Decrement
2873 // its reference count, and it that count is now zero we
2874 // can clear the breakpoint.
2875 pos->second.Release();
2876 if (pos->second.RefCount() == 0)
2877 {
2878 if (DNBBreakpointClear (pid, pos->second.BreakID()))
2879 {
2880 m_breakpoints.erase(pos);
2881 return SendPacket ("OK");
2882 }
2883 else
2884 {
2885 return SendPacket ("E08");
2886 }
2887 }
2888 else
2889 {
2890 // We still have references to this breakpoint don't
2891 // delete it, just decrementing the reference count
2892 // is enough.
2893 return SendPacket ("OK");
2894 }
2895 }
2896 else
2897 {
2898 // We don't know about any breakpoints at this address
2899 return SendPacket ("E08");
2900 }
2901 }
2902 break;
2903
2904 case '2': // remove write watchpoint
2905 case '3': // remove read watchpoint
2906 case '4': // remove access watchpoint
2907 {
2908 // gdb can send multiple z packets for the same address and
2909 // these calls must be ref counted.
2910 BreakpointMapIter pos = m_watchpoints.find(addr);
2911 if (pos != m_watchpoints.end())
2912 {
2913 // We currently have a watchpoint at address ADDR. Decrement
2914 // its reference count, and it that count is now zero we
2915 // can clear the watchpoint.
2916 pos->second.Release();
2917 if (pos->second.RefCount() == 0)
2918 {
2919 if (DNBWatchpointClear (pid, pos->second.BreakID()))
2920 {
2921 m_watchpoints.erase(pos);
2922 return SendPacket ("OK");
2923 }
2924 else
2925 {
2926 return SendPacket ("E08");
2927 }
2928 }
2929 else
2930 {
2931 // We still have references to this watchpoint don't
2932 // delete it, just decrementing the reference count
2933 // is enough.
2934 return SendPacket ("OK");
2935 }
2936 }
2937 else
2938 {
2939 // We don't know about any watchpoints at this address
2940 return SendPacket ("E08");
2941 }
2942 }
2943 break;
2944
2945 default:
2946 break;
2947 }
2948 }
2949 return HandlePacket_UNIMPLEMENTED(p);
2950}
2951
Greg Claytonc71899e2011-01-18 19:36:39 +00002952// Extract the thread number from the thread suffix that might be appended to
2953// thread specific packets. This will only be enabled if m_thread_suffix_supported
2954// is true.
2955nub_thread_t
2956RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p)
2957{
2958 if (m_thread_suffix_supported)
2959 {
2960 nub_thread_t tid = INVALID_NUB_THREAD;
2961 if (p)
2962 {
2963 const char *tid_cstr = strstr (p, "thread:");
2964 if (tid_cstr)
2965 {
2966 tid_cstr += strlen ("thread:");
2967 tid = strtoul(tid_cstr, NULL, 16);
2968 }
Greg Claytonc71899e2011-01-18 19:36:39 +00002969 }
Greg Clayton61468e82011-01-19 07:54:15 +00002970 return tid;
Greg Claytonc71899e2011-01-18 19:36:39 +00002971 }
2972 return GetCurrentThread();
2973
2974}
2975
Chris Lattner24943d22010-06-08 16:52:24 +00002976/* `p XX'
2977 print the contents of register X */
2978
2979rnb_err_t
2980RNBRemote::HandlePacket_p (const char *p)
2981{
Greg Clayton20d338f2010-11-18 05:57:03 +00002982 if (g_num_reg_entries == 0)
2983 InitializeRegisters ();
2984
Chris Lattner24943d22010-06-08 16:52:24 +00002985 if (p == NULL || *p == '\0')
2986 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002987 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
Chris Lattner24943d22010-06-08 16:52:24 +00002988 }
2989 if (!m_ctx.HasValidProcessID())
2990 {
2991 return SendPacket ("E15");
2992 }
2993 nub_process_t pid = m_ctx.ProcessID();
2994 errno = 0;
Greg Claytonc71899e2011-01-18 19:36:39 +00002995 char *tid_cstr = NULL;
2996 uint32_t reg = strtoul (p + 1, &tid_cstr, 16);
Chris Lattner24943d22010-06-08 16:52:24 +00002997 if (errno != 0 && reg == 0)
2998 {
Greg Claytondb2bab42011-01-27 09:02:32 +00002999 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003000 }
3001
Greg Claytonc71899e2011-01-18 19:36:39 +00003002 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr);
3003 if (tid == INVALID_NUB_THREAD)
Greg Claytondb2bab42011-01-27 09:02:32 +00003004 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
Greg Claytonc71899e2011-01-18 19:36:39 +00003005
Chris Lattner24943d22010-06-08 16:52:24 +00003006 const register_map_entry_t *reg_entry;
3007
3008 if (reg < g_num_reg_entries)
3009 reg_entry = &g_reg_entries[reg];
3010 else
3011 reg_entry = NULL;
3012
3013 std::ostringstream ostrm;
3014 if (reg_entry == NULL)
3015 {
3016 DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg);
3017 ostrm << "00000000";
3018 }
3019 else if (reg_entry->nub_info.reg == -1)
3020 {
3021 if (reg_entry->gdb_size > 0)
3022 {
3023 if (reg_entry->fail_value != NULL)
3024 {
3025 append_hex_value(ostrm, reg_entry->fail_value, reg_entry->gdb_size, false);
3026 }
3027 else
3028 {
3029 std::basic_string<uint8_t> zeros(reg_entry->gdb_size, '\0');
3030 append_hex_value(ostrm, zeros.data(), zeros.size(), false);
3031 }
3032 }
3033 }
3034 else
3035 {
Chris Lattner24943d22010-06-08 16:52:24 +00003036 register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry);
3037 }
3038 return SendPacket (ostrm.str());
3039}
3040
3041/* `Pnn=rrrrr'
3042 Set register number n to value r.
3043 n and r are hex strings. */
3044
3045rnb_err_t
3046RNBRemote::HandlePacket_P (const char *p)
3047{
Greg Clayton20d338f2010-11-18 05:57:03 +00003048 if (g_num_reg_entries == 0)
3049 InitializeRegisters ();
3050
Chris Lattner24943d22010-06-08 16:52:24 +00003051 if (p == NULL || *p == '\0')
3052 {
Greg Claytondb2bab42011-01-27 09:02:32 +00003053 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003054 }
3055 if (!m_ctx.HasValidProcessID())
3056 {
3057 return SendPacket ("E28");
3058 }
3059
3060 nub_process_t pid = m_ctx.ProcessID();
3061
3062 StringExtractor packet (p);
3063
3064 const char cmd_char = packet.GetChar();
3065 // Register ID is always in big endian
3066 const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX);
3067 const char equal_char = packet.GetChar();
3068
3069 if (cmd_char != 'P')
Greg Claytondb2bab42011-01-27 09:02:32 +00003070 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003071
3072 if (reg == UINT32_MAX)
3073 return SendPacket ("E29");
3074
3075 if (equal_char != '=')
3076 return SendPacket ("E30");
3077
3078 const register_map_entry_t *reg_entry;
3079
3080 if (reg >= g_num_reg_entries)
3081 return SendPacket("E47");
3082
3083 reg_entry = &g_reg_entries[reg];
3084
3085 if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1)
3086 {
3087 DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg);
3088 return SendPacket("E48");
3089 }
3090
3091 DNBRegisterValue reg_value;
3092 reg_value.info = reg_entry->nub_info;
3093 packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc);
3094
Greg Claytonc71899e2011-01-18 19:36:39 +00003095 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p);
3096 if (tid == INVALID_NUB_THREAD)
Greg Claytondb2bab42011-01-27 09:02:32 +00003097 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003098
3099 if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, &reg_value))
3100 {
3101 return SendPacket ("E32");
3102 }
3103 return SendPacket ("OK");
3104}
3105
3106/* `c [addr]'
3107 Continue, optionally from a specified address. */
3108
3109rnb_err_t
3110RNBRemote::HandlePacket_c (const char *p)
3111{
3112 const nub_process_t pid = m_ctx.ProcessID();
3113
3114 if (pid == INVALID_NUB_PROCESS)
3115 return SendPacket ("E23");
3116
3117 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3118
3119 if (*(p + 1) != '\0')
3120 {
3121 action.tid = GetContinueThread();
3122 errno = 0;
3123 action.addr = strtoull (p + 1, NULL, 16);
3124 if (errno != 0 && action.addr == 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00003125 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003126 }
3127
3128 DNBThreadResumeActions thread_actions;
3129 thread_actions.Append(action);
3130 thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0);
3131 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3132 return SendPacket ("E25");
3133 // Don't send an "OK" packet; response is the stopped/exited message.
3134 return rnb_success;
3135}
3136
3137/* `C sig [;addr]'
3138 Resume with signal sig, optionally at address addr. */
3139
3140rnb_err_t
3141RNBRemote::HandlePacket_C (const char *p)
3142{
3143 const nub_process_t pid = m_ctx.ProcessID();
3144
3145 if (pid == INVALID_NUB_PROCESS)
3146 return SendPacket ("E36");
3147
3148 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS };
3149 int process_signo = -1;
3150 if (*(p + 1) != '\0')
3151 {
3152 action.tid = GetContinueThread();
3153 char *end = NULL;
3154 errno = 0;
3155 process_signo = strtoul (p + 1, &end, 16);
3156 if (errno != 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00003157 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003158 else if (*end == ';')
3159 {
3160 errno = 0;
3161 action.addr = strtoull (end + 1, NULL, 16);
3162 if (errno != 0 && action.addr == 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00003163 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003164 }
3165 }
3166
3167 DNBThreadResumeActions thread_actions;
3168 thread_actions.Append (action);
3169 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal);
3170 if (!DNBProcessSignal(pid, process_signo))
3171 return SendPacket ("E52");
3172 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3173 return SendPacket ("E38");
3174 /* Don't send an "OK" packet; response is the stopped/exited message. */
3175 return rnb_success;
3176}
3177
3178//----------------------------------------------------------------------
3179// 'D' packet
3180// Detach from gdb.
3181//----------------------------------------------------------------------
3182rnb_err_t
3183RNBRemote::HandlePacket_D (const char *p)
3184{
Greg Clayton3b2c41c2010-10-18 04:14:23 +00003185 // We are not supposed to send a response for deatch.
3186 //SendPacket ("OK");
Chris Lattner24943d22010-06-08 16:52:24 +00003187 if (m_ctx.HasValidProcessID())
3188 DNBProcessDetach(m_ctx.ProcessID());
3189 return rnb_success;
3190}
3191
3192/* `k'
3193 Kill the inferior process. */
3194
3195rnb_err_t
3196RNBRemote::HandlePacket_k (const char *p)
3197{
Greg Claytona4881d02011-01-22 07:12:45 +00003198 // No response to should be sent to the kill packet
3199 if (m_ctx.HasValidProcessID())
3200 DNBProcessKill (m_ctx.ProcessID());
Greg Clayton72e1c782011-01-22 23:43:18 +00003201 SendPacket ("W09");
Greg Claytona4881d02011-01-22 07:12:45 +00003202 return rnb_success;
Chris Lattner24943d22010-06-08 16:52:24 +00003203}
3204
3205rnb_err_t
3206RNBRemote::HandlePacket_stop_process (const char *p)
3207{
3208 DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP);
3209 //DNBProcessSignal (m_ctx.ProcessID(), SIGINT);
3210 // Do not send any response packet! Wait for the stop reply packet to naturally happen
3211 return rnb_success;
3212}
3213
3214/* `s'
3215 Step the inferior process. */
3216
3217rnb_err_t
3218RNBRemote::HandlePacket_s (const char *p)
3219{
3220 const nub_process_t pid = m_ctx.ProcessID();
3221 if (pid == INVALID_NUB_PROCESS)
3222 return SendPacket ("E32");
3223
3224 // Hardware supported stepping not supported on arm
3225 nub_thread_t tid = GetContinueThread ();
3226 if (tid == 0 || tid == -1)
3227 tid = GetCurrentThread();
3228
3229 if (tid == INVALID_NUB_THREAD)
3230 return SendPacket ("E33");
3231
3232 DNBThreadResumeActions thread_actions;
3233 thread_actions.AppendAction(tid, eStateStepping);
3234
3235 // Make all other threads stop when we are stepping
3236 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0);
3237 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3238 return SendPacket ("E49");
3239 // Don't send an "OK" packet; response is the stopped/exited message.
3240 return rnb_success;
3241}
3242
3243/* `S sig [;addr]'
3244 Step with signal sig, optionally at address addr. */
3245
3246rnb_err_t
3247RNBRemote::HandlePacket_S (const char *p)
3248{
3249 const nub_process_t pid = m_ctx.ProcessID();
3250 if (pid == INVALID_NUB_PROCESS)
3251 return SendPacket ("E36");
3252
3253 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS };
3254
3255 if (*(p + 1) != '\0')
3256 {
3257 char *end = NULL;
3258 errno = 0;
3259 action.signal = strtoul (p + 1, &end, 16);
3260 if (errno != 0)
Greg Claytondb2bab42011-01-27 09:02:32 +00003261 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003262 else if (*end == ';')
3263 {
3264 errno = 0;
3265 action.addr = strtoull (end + 1, NULL, 16);
3266 if (errno != 0 && action.addr == 0)
3267 {
Greg Claytondb2bab42011-01-27 09:02:32 +00003268 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet");
Chris Lattner24943d22010-06-08 16:52:24 +00003269 }
3270 }
3271 }
3272
3273 action.tid = GetContinueThread ();
3274 if (action.tid == 0 || action.tid == -1)
3275 return SendPacket ("E40");
3276
3277 nub_state_t tstate = DNBThreadGetState (pid, action.tid);
3278 if (tstate == eStateInvalid || tstate == eStateExited)
3279 return SendPacket ("E37");
3280
3281
3282 DNBThreadResumeActions thread_actions;
3283 thread_actions.Append (action);
3284
3285 // Make all other threads stop when we are stepping
3286 thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
3287 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize()))
3288 return SendPacket ("E39");
3289
3290 // Don't send an "OK" packet; response is the stopped/exited message.
3291 return rnb_success;
3292}
3293
3294rnb_err_t
3295RNBRemote::HandlePacket_qHostInfo (const char *p)
3296{
3297 std::ostringstream strm;
3298
3299 uint32_t cputype, is_64_bit_capable;
3300 size_t len = sizeof(cputype);
3301 bool promoted_to_64 = false;
3302 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
3303 {
3304 len = sizeof (is_64_bit_capable);
3305 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0)
3306 {
3307 if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0))
3308 {
3309 promoted_to_64 = true;
3310 cputype |= CPU_ARCH_ABI64;
3311 }
3312 }
3313
3314 strm << "cputype:" << std::dec << cputype << ';';
3315 }
3316
3317 uint32_t cpusubtype;
3318 len = sizeof(cpusubtype);
3319 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
3320 {
3321 if (promoted_to_64 &&
3322 cputype == CPU_TYPE_X86_64 &&
3323 cpusubtype == CPU_SUBTYPE_486)
3324 cpusubtype = CPU_SUBTYPE_X86_64_ALL;
3325
3326 strm << "cpusubtype:" << std::dec << cpusubtype << ';';
3327 }
3328
3329 char ostype[64];
3330 len = sizeof(ostype);
3331 if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0)
Greg Clayton75c703d2011-02-16 04:46:07 +00003332 {
3333 len = strlen(ostype);
3334 std::transform (ostype, ostype + len, ostype, tolower);
Chris Lattner24943d22010-06-08 16:52:24 +00003335 strm << "ostype:" << std::dec << ostype << ';';
Greg Clayton75c703d2011-02-16 04:46:07 +00003336 }
Chris Lattner24943d22010-06-08 16:52:24 +00003337
3338 strm << "vendor:apple;";
3339
3340#if defined (__LITTLE_ENDIAN__)
3341 strm << "endian:little;";
3342#elif defined (__BIG_ENDIAN__)
3343 strm << "endian:big;";
3344#elif defined (__PDP_ENDIAN__)
3345 strm << "endian:pdp;";
3346#endif
3347
Greg Clayton395fc332011-02-15 21:59:32 +00003348 if (promoted_to_64)
3349 strm << "ptrsize:8;";
3350 else
3351 strm << "ptrsize:" << std::dec << sizeof(void *) << ';';
Chris Lattner24943d22010-06-08 16:52:24 +00003352 return SendPacket (strm.str());
3353}