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