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