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