RNBRemote.cpp revision bcf07b37b3e3cd37ac74cc42c12009f130f185a3
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 (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, ®_value)) 2516 return SendPacket ("E15"); 2517 } 2518 return SendPacket ("OK"); 2519} 2520 2521static bool 2522RNBRemoteShouldCancelCallback (void *not_used) 2523{ 2524 RNBRemoteSP remoteSP(g_remoteSP); 2525 if (remoteSP.get() != NULL) 2526 { 2527 RNBRemote* remote = remoteSP.get(); 2528 if (remote->Comm().IsConnected()) 2529 return false; 2530 else 2531 return true; 2532 } 2533 return true; 2534} 2535 2536 2537// FORMAT: _MXXXXXX,PPP 2538// XXXXXX: big endian hex chars 2539// PPP: permissions can be any combo of r w x chars 2540// 2541// RESPONSE: XXXXXX 2542// XXXXXX: hex address of the newly allocated memory 2543// EXX: error code 2544// 2545// EXAMPLES: 2546// _M123000,rw 2547// _M123000,rwx 2548// _M123000,xw 2549 2550rnb_err_t 2551RNBRemote::HandlePacket_AllocateMemory (const char *p) 2552{ 2553 StringExtractor packet (p); 2554 packet.SetFilePos(2); // Skip the "_M" 2555 2556 nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0); 2557 if (size != 0) 2558 { 2559 if (packet.GetChar() == ',') 2560 { 2561 uint32_t permissions = 0; 2562 char ch; 2563 bool success = true; 2564 while (success && (ch = packet.GetChar()) != '\0') 2565 { 2566 switch (ch) 2567 { 2568 case 'r': permissions |= eMemoryPermissionsReadable; break; 2569 case 'w': permissions |= eMemoryPermissionsWritable; break; 2570 case 'x': permissions |= eMemoryPermissionsExecutable; break; 2571 default: success = false; break; 2572 } 2573 } 2574 2575 if (success) 2576 { 2577 nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions); 2578 if (addr != INVALID_NUB_ADDRESS) 2579 { 2580 std::ostringstream ostrm; 2581 ostrm << RAW_HEXBASE << addr; 2582 return SendPacket (ostrm.str ()); 2583 } 2584 } 2585 } 2586 } 2587 return SendPacket ("E53"); 2588} 2589 2590// FORMAT: _mXXXXXX 2591// XXXXXX: address that was previosly allocated 2592// 2593// RESPONSE: XXXXXX 2594// OK: address was deallocated 2595// EXX: error code 2596// 2597// EXAMPLES: 2598// _m123000 2599 2600rnb_err_t 2601RNBRemote::HandlePacket_DeallocateMemory (const char *p) 2602{ 2603 StringExtractor packet (p); 2604 packet.SetFilePos(2); // Skip the "_m" 2605 nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS); 2606 2607 if (addr != INVALID_NUB_ADDRESS) 2608 { 2609 if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr)) 2610 return SendPacket ("OK"); 2611 } 2612 return SendPacket ("E54"); 2613} 2614 2615/* 2616 vAttach;pid 2617 2618 Attach to a new process with the specified process ID. pid is a hexadecimal integer 2619 identifying the process. If the stub is currently controlling a process, it is 2620 killed. The attached process is stopped.This packet is only available in extended 2621 mode (see extended mode). 2622 2623 Reply: 2624 "ENN" for an error 2625 "Any Stop Reply Packet" for success 2626 */ 2627 2628rnb_err_t 2629RNBRemote::HandlePacket_v (const char *p) 2630{ 2631 if (strcmp (p, "vCont;c") == 0) 2632 { 2633 // Simple continue 2634 return RNBRemote::HandlePacket_c("c"); 2635 } 2636 else if (strcmp (p, "vCont;s") == 0) 2637 { 2638 // Simple step 2639 return RNBRemote::HandlePacket_s("s"); 2640 } 2641 else if (strstr (p, "vCont") == p) 2642 { 2643 rnb_err_t rnb_err = rnb_success; 2644 typedef struct 2645 { 2646 nub_thread_t tid; 2647 char action; 2648 int signal; 2649 } vcont_action_t; 2650 2651 DNBThreadResumeActions thread_actions; 2652 char *c = (char *)(p += strlen("vCont")); 2653 char *c_end = c + strlen(c); 2654 if (*c == '?') 2655 return SendPacket ("vCont;c;C;s;S"); 2656 2657 while (c < c_end && *c == ';') 2658 { 2659 ++c; // Skip the semi-colon 2660 DNBThreadResumeAction thread_action; 2661 thread_action.tid = INVALID_NUB_THREAD; 2662 thread_action.state = eStateInvalid; 2663 thread_action.signal = 0; 2664 thread_action.addr = INVALID_NUB_ADDRESS; 2665 2666 char action = *c++; 2667 2668 switch (action) 2669 { 2670 case 'C': 2671 errno = 0; 2672 thread_action.signal = strtoul (c, &c, 16); 2673 if (errno != 0) 2674 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet"); 2675 // Fall through to next case... 2676 2677 case 'c': 2678 // Continue 2679 thread_action.state = eStateRunning; 2680 break; 2681 2682 case 'S': 2683 errno = 0; 2684 thread_action.signal = strtoul (c, &c, 16); 2685 if (errno != 0) 2686 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet"); 2687 // Fall through to next case... 2688 2689 case 's': 2690 // Step 2691 thread_action.state = eStateStepping; 2692 break; 2693 2694 default: 2695 rnb_err = HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet"); 2696 break; 2697 } 2698 if (*c == ':') 2699 { 2700 errno = 0; 2701 thread_action.tid = strtoul (++c, &c, 16); 2702 if (errno != 0) 2703 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet"); 2704 } 2705 2706 thread_actions.Append (thread_action); 2707 } 2708 2709 // If a default action for all other threads wasn't mentioned 2710 // then we should stop the threads 2711 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); 2712 DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize()); 2713 return rnb_success; 2714 } 2715 else if (strstr (p, "vAttach") == p) 2716 { 2717 nub_process_t attach_pid = INVALID_NUB_PROCESS; 2718 char err_str[1024]={'\0'}; 2719 if (strstr (p, "vAttachWait;") == p) 2720 { 2721 p += strlen("vAttachWait;"); 2722 std::string attach_name; 2723 while (*p != '\0') 2724 { 2725 char smallbuf[3]; 2726 smallbuf[0] = *p; 2727 smallbuf[1] = *(p + 1); 2728 smallbuf[2] = '\0'; 2729 2730 errno = 0; 2731 int ch = strtoul (smallbuf, NULL, 16); 2732 if (errno != 0 && ch == 0) 2733 { 2734 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt"); 2735 } 2736 2737 attach_name.push_back(ch); 2738 p += 2; 2739 } 2740 2741 attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); 2742 2743 } 2744 else if (strstr (p, "vAttachName;") == p) 2745 { 2746 p += strlen("vAttachName;"); 2747 std::string attach_name; 2748 while (*p != '\0') 2749 { 2750 char smallbuf[3]; 2751 smallbuf[0] = *p; 2752 smallbuf[1] = *(p + 1); 2753 smallbuf[2] = '\0'; 2754 2755 errno = 0; 2756 int ch = strtoul (smallbuf, NULL, 16); 2757 if (errno != 0 && ch == 0) 2758 { 2759 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachWait' pkt"); 2760 } 2761 2762 attach_name.push_back(ch); 2763 p += 2; 2764 } 2765 2766 attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str)); 2767 2768 } 2769 else if (strstr (p, "vAttach;") == p) 2770 { 2771 p += strlen("vAttach;"); 2772 char *end = NULL; 2773 attach_pid = strtoul (p, &end, 16); // PID will be in hex, so use base 16 to decode 2774 if (p != end && *end == '\0') 2775 { 2776 // Wait at most 30 second for attach 2777 struct timespec attach_timeout_abstime; 2778 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0); 2779 attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str)); 2780 } 2781 } 2782 else 2783 return HandlePacket_UNIMPLEMENTED(p); 2784 2785 2786 if (attach_pid != INVALID_NUB_PROCESS) 2787 { 2788 if (m_ctx.ProcessID() != attach_pid) 2789 m_ctx.SetProcessID(attach_pid); 2790 // Send a stop reply packet to indicate we successfully attached! 2791 NotifyThatProcessStopped (); 2792 return rnb_success; 2793 } 2794 else 2795 { 2796 m_ctx.LaunchStatus().SetError(-1, DNBError::Generic); 2797 if (err_str[0]) 2798 m_ctx.LaunchStatus().SetErrorString(err_str); 2799 else 2800 m_ctx.LaunchStatus().SetErrorString("attach failed"); 2801 return SendPacket ("E01"); // E01 is our magic error value for attach failed. 2802 } 2803 } 2804 2805 // All other failures come through here 2806 return HandlePacket_UNIMPLEMENTED(p); 2807} 2808 2809/* `T XX' -- status of thread 2810 Check if the specified thread is alive. 2811 The thread number is in hex? */ 2812 2813rnb_err_t 2814RNBRemote::HandlePacket_T (const char *p) 2815{ 2816 p++; 2817 if (p == NULL || *p == '\0') 2818 { 2819 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet"); 2820 } 2821 if (!m_ctx.HasValidProcessID()) 2822 { 2823 return SendPacket ("E15"); 2824 } 2825 errno = 0; 2826 nub_thread_t tid = strtoul (p, NULL, 16); 2827 if (errno != 0 && tid == 0) 2828 { 2829 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet"); 2830 } 2831 2832 nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid); 2833 if (state == eStateInvalid || state == eStateExited || state == eStateCrashed) 2834 { 2835 return SendPacket ("E16"); 2836 } 2837 2838 return SendPacket ("OK"); 2839} 2840 2841 2842rnb_err_t 2843RNBRemote::HandlePacket_z (const char *p) 2844{ 2845 if (p == NULL || *p == '\0') 2846 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet"); 2847 2848 if (!m_ctx.HasValidProcessID()) 2849 return SendPacket ("E15"); 2850 2851 char packet_cmd = *p++; 2852 char break_type = *p++; 2853 2854 if (*p++ != ',') 2855 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet"); 2856 2857 char *c = NULL; 2858 nub_process_t pid = m_ctx.ProcessID(); 2859 errno = 0; 2860 nub_addr_t addr = strtoull (p, &c, 16); 2861 if (errno != 0 && addr == 0) 2862 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet"); 2863 p = c; 2864 if (*p++ != ',') 2865 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet"); 2866 2867 errno = 0; 2868 uint32_t byte_size = strtoul (p, &c, 16); 2869 if (errno != 0 && byte_size == 0) 2870 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet"); 2871 2872 if (packet_cmd == 'Z') 2873 { 2874 // set 2875 switch (break_type) 2876 { 2877 case '0': // set software breakpoint 2878 case '1': // set hardware breakpoint 2879 { 2880 // gdb can send multiple Z packets for the same address and 2881 // these calls must be ref counted. 2882 bool hardware = (break_type == '1'); 2883 2884 // Check if we currently have a breakpoint already set at this address 2885 BreakpointMapIter pos = m_breakpoints.find(addr); 2886 if (pos != m_breakpoints.end()) 2887 { 2888 // We do already have a breakpoint at this address, increment 2889 // its reference count and return OK 2890 pos->second.Retain(); 2891 return SendPacket ("OK"); 2892 } 2893 else 2894 { 2895 // We do NOT already have a breakpoint at this address, So lets 2896 // create one. 2897 nub_break_t break_id = DNBBreakpointSet (pid, addr, byte_size, hardware); 2898 if (NUB_BREAK_ID_IS_VALID(break_id)) 2899 { 2900 // We successfully created a breakpoint, now lets full out 2901 // a ref count structure with the breakID and add it to our 2902 // map. 2903 Breakpoint rnbBreakpoint(break_id); 2904 m_breakpoints[addr] = rnbBreakpoint; 2905 return SendPacket ("OK"); 2906 } 2907 else 2908 { 2909 // We failed to set the software breakpoint 2910 return SendPacket ("E09"); 2911 } 2912 } 2913 } 2914 break; 2915 2916 case '2': // set write watchpoint 2917 case '3': // set read watchpoint 2918 case '4': // set access watchpoint 2919 { 2920 bool hardware = true; 2921 uint32_t watch_flags = 0; 2922 if (break_type == '2') 2923 watch_flags = WATCH_TYPE_WRITE; 2924 else if (break_type == '3') 2925 watch_flags = WATCH_TYPE_READ; 2926 else 2927 watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE; 2928 2929 // Check if we currently have a watchpoint already set at this address 2930 BreakpointMapIter pos = m_watchpoints.find(addr); 2931 if (pos != m_watchpoints.end()) 2932 { 2933 // We do already have a watchpoint at this address, increment 2934 // its reference count and return OK 2935 pos->second.Retain(); 2936 return SendPacket ("OK"); 2937 } 2938 else 2939 { 2940 // We do NOT already have a watchpoint at this address, So lets 2941 // create one. 2942 nub_watch_t watch_id = DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware); 2943 if (NUB_WATCH_ID_IS_VALID(watch_id)) 2944 { 2945 // We successfully created a watchpoint, now lets full out 2946 // a ref count structure with the watch_id and add it to our 2947 // map. 2948 Breakpoint rnbWatchpoint(watch_id); 2949 m_watchpoints[addr] = rnbWatchpoint; 2950 return SendPacket ("OK"); 2951 } 2952 else 2953 { 2954 // We failed to set the watchpoint 2955 return SendPacket ("E09"); 2956 } 2957 } 2958 } 2959 break; 2960 2961 default: 2962 break; 2963 } 2964 } 2965 else if (packet_cmd == 'z') 2966 { 2967 // remove 2968 switch (break_type) 2969 { 2970 case '0': // remove software breakpoint 2971 case '1': // remove hardware breakpoint 2972 { 2973 // gdb can send multiple z packets for the same address and 2974 // these calls must be ref counted. 2975 BreakpointMapIter pos = m_breakpoints.find(addr); 2976 if (pos != m_breakpoints.end()) 2977 { 2978 // We currently have a breakpoint at address ADDR. Decrement 2979 // its reference count, and it that count is now zero we 2980 // can clear the breakpoint. 2981 pos->second.Release(); 2982 if (pos->second.RefCount() == 0) 2983 { 2984 if (DNBBreakpointClear (pid, pos->second.BreakID())) 2985 { 2986 m_breakpoints.erase(pos); 2987 return SendPacket ("OK"); 2988 } 2989 else 2990 { 2991 return SendPacket ("E08"); 2992 } 2993 } 2994 else 2995 { 2996 // We still have references to this breakpoint don't 2997 // delete it, just decrementing the reference count 2998 // is enough. 2999 return SendPacket ("OK"); 3000 } 3001 } 3002 else 3003 { 3004 // We don't know about any breakpoints at this address 3005 return SendPacket ("E08"); 3006 } 3007 } 3008 break; 3009 3010 case '2': // remove write watchpoint 3011 case '3': // remove read watchpoint 3012 case '4': // remove access watchpoint 3013 { 3014 // gdb can send multiple z packets for the same address and 3015 // these calls must be ref counted. 3016 BreakpointMapIter pos = m_watchpoints.find(addr); 3017 if (pos != m_watchpoints.end()) 3018 { 3019 // We currently have a watchpoint at address ADDR. Decrement 3020 // its reference count, and it that count is now zero we 3021 // can clear the watchpoint. 3022 pos->second.Release(); 3023 if (pos->second.RefCount() == 0) 3024 { 3025 if (DNBWatchpointClear (pid, pos->second.BreakID())) 3026 { 3027 m_watchpoints.erase(pos); 3028 return SendPacket ("OK"); 3029 } 3030 else 3031 { 3032 return SendPacket ("E08"); 3033 } 3034 } 3035 else 3036 { 3037 // We still have references to this watchpoint don't 3038 // delete it, just decrementing the reference count 3039 // is enough. 3040 return SendPacket ("OK"); 3041 } 3042 } 3043 else 3044 { 3045 // We don't know about any watchpoints at this address 3046 return SendPacket ("E08"); 3047 } 3048 } 3049 break; 3050 3051 default: 3052 break; 3053 } 3054 } 3055 return HandlePacket_UNIMPLEMENTED(p); 3056} 3057 3058// Extract the thread number from the thread suffix that might be appended to 3059// thread specific packets. This will only be enabled if m_thread_suffix_supported 3060// is true. 3061nub_thread_t 3062RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p) 3063{ 3064 if (m_thread_suffix_supported) 3065 { 3066 nub_thread_t tid = INVALID_NUB_THREAD; 3067 if (p) 3068 { 3069 const char *tid_cstr = strstr (p, "thread:"); 3070 if (tid_cstr) 3071 { 3072 tid_cstr += strlen ("thread:"); 3073 tid = strtoul(tid_cstr, NULL, 16); 3074 } 3075 } 3076 return tid; 3077 } 3078 return GetCurrentThread(); 3079 3080} 3081 3082/* `p XX' 3083 print the contents of register X */ 3084 3085rnb_err_t 3086RNBRemote::HandlePacket_p (const char *p) 3087{ 3088 if (g_num_reg_entries == 0) 3089 InitializeRegisters (); 3090 3091 if (p == NULL || *p == '\0') 3092 { 3093 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 3094 } 3095 if (!m_ctx.HasValidProcessID()) 3096 { 3097 return SendPacket ("E15"); 3098 } 3099 nub_process_t pid = m_ctx.ProcessID(); 3100 errno = 0; 3101 char *tid_cstr = NULL; 3102 uint32_t reg = strtoul (p + 1, &tid_cstr, 16); 3103 if (errno != 0 && reg == 0) 3104 { 3105 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet"); 3106 } 3107 3108 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr); 3109 if (tid == INVALID_NUB_THREAD) 3110 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 3111 3112 const register_map_entry_t *reg_entry; 3113 3114 if (reg < g_num_reg_entries) 3115 reg_entry = &g_reg_entries[reg]; 3116 else 3117 reg_entry = NULL; 3118 3119 std::ostringstream ostrm; 3120 if (reg_entry == NULL) 3121 { 3122 DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg); 3123 ostrm << "00000000"; 3124 } 3125 else if (reg_entry->nub_info.reg == -1) 3126 { 3127 if (reg_entry->gdb_size > 0) 3128 { 3129 if (reg_entry->fail_value != NULL) 3130 { 3131 append_hex_value(ostrm, reg_entry->fail_value, reg_entry->gdb_size, false); 3132 } 3133 else 3134 { 3135 std::basic_string<uint8_t> zeros(reg_entry->gdb_size, '\0'); 3136 append_hex_value(ostrm, zeros.data(), zeros.size(), false); 3137 } 3138 } 3139 } 3140 else 3141 { 3142 register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry); 3143 } 3144 return SendPacket (ostrm.str()); 3145} 3146 3147/* `Pnn=rrrrr' 3148 Set register number n to value r. 3149 n and r are hex strings. */ 3150 3151rnb_err_t 3152RNBRemote::HandlePacket_P (const char *p) 3153{ 3154 if (g_num_reg_entries == 0) 3155 InitializeRegisters (); 3156 3157 if (p == NULL || *p == '\0') 3158 { 3159 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet"); 3160 } 3161 if (!m_ctx.HasValidProcessID()) 3162 { 3163 return SendPacket ("E28"); 3164 } 3165 3166 nub_process_t pid = m_ctx.ProcessID(); 3167 3168 StringExtractor packet (p); 3169 3170 const char cmd_char = packet.GetChar(); 3171 // Register ID is always in big endian 3172 const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX); 3173 const char equal_char = packet.GetChar(); 3174 3175 if (cmd_char != 'P') 3176 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet"); 3177 3178 if (reg == UINT32_MAX) 3179 return SendPacket ("E29"); 3180 3181 if (equal_char != '=') 3182 return SendPacket ("E30"); 3183 3184 const register_map_entry_t *reg_entry; 3185 3186 if (reg >= g_num_reg_entries) 3187 return SendPacket("E47"); 3188 3189 reg_entry = &g_reg_entries[reg]; 3190 3191 if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1) 3192 { 3193 DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg); 3194 return SendPacket("E48"); 3195 } 3196 3197 DNBRegisterValue reg_value; 3198 reg_value.info = reg_entry->nub_info; 3199 packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc); 3200 3201 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); 3202 if (tid == INVALID_NUB_THREAD) 3203 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 3204 3205 if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, ®_value)) 3206 { 3207 return SendPacket ("E32"); 3208 } 3209 return SendPacket ("OK"); 3210} 3211 3212/* `c [addr]' 3213 Continue, optionally from a specified address. */ 3214 3215rnb_err_t 3216RNBRemote::HandlePacket_c (const char *p) 3217{ 3218 const nub_process_t pid = m_ctx.ProcessID(); 3219 3220 if (pid == INVALID_NUB_PROCESS) 3221 return SendPacket ("E23"); 3222 3223 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS }; 3224 3225 if (*(p + 1) != '\0') 3226 { 3227 action.tid = GetContinueThread(); 3228 errno = 0; 3229 action.addr = strtoull (p + 1, NULL, 16); 3230 if (errno != 0 && action.addr == 0) 3231 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet"); 3232 } 3233 3234 DNBThreadResumeActions thread_actions; 3235 thread_actions.Append(action); 3236 thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); 3237 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3238 return SendPacket ("E25"); 3239 // Don't send an "OK" packet; response is the stopped/exited message. 3240 return rnb_success; 3241} 3242 3243rnb_err_t 3244RNBRemote::HandlePacket_MemoryRegionInfo (const char *p) 3245{ 3246 /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code) 3247 for the memory region containing a given address and return that information. 3248 3249 Users of this packet must be prepared for three results: 3250 3251 Region information is returned 3252 Region information is unavailable for this address because the address is in unmapped memory 3253 Region lookup cannot be performed on this platform or process is not yet launched 3254 This packet isn't implemented 3255 3256 Examples of use: 3257 qMemoryRegionInfo:3a55140 3258 start:3a50000,size:100000,permissions:rwx 3259 3260 qMemoryRegionInfo:0 3261 error:address in unmapped region 3262 3263 qMemoryRegionInfo:3a551140 (on a different platform) 3264 error:region lookup cannot be performed 3265 3266 qMemoryRegionInfo 3267 OK // this packet is implemented by the remote nub 3268 */ 3269 3270 p += sizeof ("qMemoryRegionInfo") - 1; 3271 if (*p == '\0') 3272 return SendPacket ("OK"); 3273 if (*p++ != ':') 3274 return SendPacket ("E67"); 3275 if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) 3276 p += 2; 3277 3278 errno = 0; 3279 uint64_t address = strtoul (p, NULL, 16); 3280 if (errno != 0 && address == 0) 3281 { 3282 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet"); 3283 } 3284 3285 char retbuf[1024]; 3286 3287 int ret = DNBMemoryRegionInfo (m_ctx.ProcessID(), address, retbuf, sizeof (retbuf)); 3288 retbuf[sizeof (retbuf) - 1] = '\0'; 3289 if (ret == 1) 3290 return SendPacket (retbuf); 3291 if (ret == 0) 3292 return SendPacket ("error:address in unmapped region"); 3293 if (ret == -1) 3294 return SendPacket ("error:region lookup cannot be performed"); 3295 3296 return SendPacket ("E68"); 3297} 3298 3299 3300/* `C sig [;addr]' 3301 Resume with signal sig, optionally at address addr. */ 3302 3303rnb_err_t 3304RNBRemote::HandlePacket_C (const char *p) 3305{ 3306 const nub_process_t pid = m_ctx.ProcessID(); 3307 3308 if (pid == INVALID_NUB_PROCESS) 3309 return SendPacket ("E36"); 3310 3311 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS }; 3312 int process_signo = -1; 3313 if (*(p + 1) != '\0') 3314 { 3315 action.tid = GetContinueThread(); 3316 char *end = NULL; 3317 errno = 0; 3318 process_signo = strtoul (p + 1, &end, 16); 3319 if (errno != 0) 3320 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet"); 3321 else if (*end == ';') 3322 { 3323 errno = 0; 3324 action.addr = strtoull (end + 1, NULL, 16); 3325 if (errno != 0 && action.addr == 0) 3326 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet"); 3327 } 3328 } 3329 3330 DNBThreadResumeActions thread_actions; 3331 thread_actions.Append (action); 3332 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal); 3333 if (!DNBProcessSignal(pid, process_signo)) 3334 return SendPacket ("E52"); 3335 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3336 return SendPacket ("E38"); 3337 /* Don't send an "OK" packet; response is the stopped/exited message. */ 3338 return rnb_success; 3339} 3340 3341//---------------------------------------------------------------------- 3342// 'D' packet 3343// Detach from gdb. 3344//---------------------------------------------------------------------- 3345rnb_err_t 3346RNBRemote::HandlePacket_D (const char *p) 3347{ 3348 // We are not supposed to send a response for deatch. 3349 //SendPacket ("OK"); 3350 if (m_ctx.HasValidProcessID()) 3351 DNBProcessDetach(m_ctx.ProcessID()); 3352 return rnb_success; 3353} 3354 3355/* `k' 3356 Kill the inferior process. */ 3357 3358rnb_err_t 3359RNBRemote::HandlePacket_k (const char *p) 3360{ 3361 // No response to should be sent to the kill packet 3362 if (m_ctx.HasValidProcessID()) 3363 DNBProcessKill (m_ctx.ProcessID()); 3364 SendPacket ("W09"); 3365 return rnb_success; 3366} 3367 3368rnb_err_t 3369RNBRemote::HandlePacket_stop_process (const char *p) 3370{ 3371 DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP); 3372 //DNBProcessSignal (m_ctx.ProcessID(), SIGINT); 3373 // Do not send any response packet! Wait for the stop reply packet to naturally happen 3374 return rnb_success; 3375} 3376 3377/* `s' 3378 Step the inferior process. */ 3379 3380rnb_err_t 3381RNBRemote::HandlePacket_s (const char *p) 3382{ 3383 const nub_process_t pid = m_ctx.ProcessID(); 3384 if (pid == INVALID_NUB_PROCESS) 3385 return SendPacket ("E32"); 3386 3387 // Hardware supported stepping not supported on arm 3388 nub_thread_t tid = GetContinueThread (); 3389 if (tid == 0 || tid == -1) 3390 tid = GetCurrentThread(); 3391 3392 if (tid == INVALID_NUB_THREAD) 3393 return SendPacket ("E33"); 3394 3395 DNBThreadResumeActions thread_actions; 3396 thread_actions.AppendAction(tid, eStateStepping); 3397 3398 // Make all other threads stop when we are stepping 3399 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); 3400 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3401 return SendPacket ("E49"); 3402 // Don't send an "OK" packet; response is the stopped/exited message. 3403 return rnb_success; 3404} 3405 3406/* `S sig [;addr]' 3407 Step with signal sig, optionally at address addr. */ 3408 3409rnb_err_t 3410RNBRemote::HandlePacket_S (const char *p) 3411{ 3412 const nub_process_t pid = m_ctx.ProcessID(); 3413 if (pid == INVALID_NUB_PROCESS) 3414 return SendPacket ("E36"); 3415 3416 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS }; 3417 3418 if (*(p + 1) != '\0') 3419 { 3420 char *end = NULL; 3421 errno = 0; 3422 action.signal = strtoul (p + 1, &end, 16); 3423 if (errno != 0) 3424 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet"); 3425 else if (*end == ';') 3426 { 3427 errno = 0; 3428 action.addr = strtoull (end + 1, NULL, 16); 3429 if (errno != 0 && action.addr == 0) 3430 { 3431 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet"); 3432 } 3433 } 3434 } 3435 3436 action.tid = GetContinueThread (); 3437 if (action.tid == 0 || action.tid == -1) 3438 return SendPacket ("E40"); 3439 3440 nub_state_t tstate = DNBThreadGetState (pid, action.tid); 3441 if (tstate == eStateInvalid || tstate == eStateExited) 3442 return SendPacket ("E37"); 3443 3444 3445 DNBThreadResumeActions thread_actions; 3446 thread_actions.Append (action); 3447 3448 // Make all other threads stop when we are stepping 3449 thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); 3450 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3451 return SendPacket ("E39"); 3452 3453 // Don't send an "OK" packet; response is the stopped/exited message. 3454 return rnb_success; 3455} 3456 3457rnb_err_t 3458RNBRemote::HandlePacket_qHostInfo (const char *p) 3459{ 3460 std::ostringstream strm; 3461 3462 uint32_t cputype, is_64_bit_capable; 3463 size_t len = sizeof(cputype); 3464 bool promoted_to_64 = false; 3465 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) 3466 { 3467 len = sizeof (is_64_bit_capable); 3468 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) 3469 { 3470 if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0)) 3471 { 3472 promoted_to_64 = true; 3473 cputype |= CPU_ARCH_ABI64; 3474 } 3475 } 3476 3477 strm << "cputype:" << std::dec << cputype << ';'; 3478 } 3479 3480 uint32_t cpusubtype; 3481 len = sizeof(cpusubtype); 3482 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 3483 { 3484 if (promoted_to_64 && 3485 cputype == CPU_TYPE_X86_64 && 3486 cpusubtype == CPU_SUBTYPE_486) 3487 cpusubtype = CPU_SUBTYPE_X86_64_ALL; 3488 3489 strm << "cpusubtype:" << std::dec << cpusubtype << ';'; 3490 } 3491 3492 char ostype[64]; 3493 len = sizeof(ostype); 3494 if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0) 3495 { 3496 len = strlen(ostype); 3497 std::transform (ostype, ostype + len, ostype, tolower); 3498 strm << "ostype:" << std::dec << ostype << ';'; 3499 } 3500 3501 strm << "vendor:apple;"; 3502 3503#if defined (__LITTLE_ENDIAN__) 3504 strm << "endian:little;"; 3505#elif defined (__BIG_ENDIAN__) 3506 strm << "endian:big;"; 3507#elif defined (__PDP_ENDIAN__) 3508 strm << "endian:pdp;"; 3509#endif 3510 3511 if (promoted_to_64) 3512 strm << "ptrsize:8;"; 3513 else 3514 strm << "ptrsize:" << std::dec << sizeof(void *) << ';'; 3515 return SendPacket (strm.str()); 3516} 3517