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