RNBRemote.cpp revision cec43ab7f30085ac7f65a26a58b956a69e363a3b
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 61extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); 62 63RNBRemote::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 87RNBRemote::~RNBRemote() 88{ 89 DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); 90 StopReadRemoteDataThread(); 91} 92 93void 94RNBRemote::CreatePacketTable () 95{ 96 // Step required to add new packets: 97 // 1 - Add new enumeration to RNBRemote::PacketEnum 98 // 2 - Create a the RNBRemote::HandlePacket_ function if a new function is needed 99 // 3 - Register the Packet definition with any needed callbacks in this 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_qRcmd, NULL, "qRcmd", "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 203void 204RNBRemote::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 231void 232RNBRemote::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 250rnb_err_t 251RNBRemote::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 270rnb_err_t 271RNBRemote::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 278rnb_err_t 279RNBRemote::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. 287rnb_err_t 288RNBRemote::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 298rnb_err_t 299RNBRemote::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 349rnb_err_t 350RNBRemote::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 445rnb_err_t 446RNBRemote::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 452rnb_err_t 453RNBRemote::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 459rnb_err_t 460RNBRemote::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 524rnb_err_t 525RNBRemote::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 553rnb_err_t 554RNBRemote::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 585void 586RNBRemote::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 685rnb_err_t 686RNBRemote::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 699void 700RNBRemote::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 722void 723RNBRemote::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 742void* 743RNBRemote::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 794std::vector<uint8_t> 795decode_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 819typedef 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 834static const uint32_t MAX_REGISTER_BYTE_SIZE = 16; 835static const uint8_t k_zero_bytes[MAX_REGISTER_BYTE_SIZE] = {0}; 836static std::vector<register_map_entry_t> g_dynamic_register_map; 837static register_map_entry_t *g_reg_entries = NULL; 838static size_t g_num_reg_entries = 0; 839 840static void 841RegisterEntryNotAvailable (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//---------------------------------------------------------------------- 862register_map_entry_t 863g_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 942register_map_entry_t 943g_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 988register_map_entry_t 989g_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 1051void 1052RNBRemote::Initialize() 1053{ 1054 DNBInitialize(); 1055} 1056 1057 1058bool 1059RNBRemote::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 1163void 1164RNBRemote::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 1187rnb_err_t 1188RNBRemote::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 1270rnb_err_t 1271RNBRemote::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 1301rnb_err_t 1302RNBRemote::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 1313rnb_err_t 1314RNBRemote::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 1329rnb_err_t 1330RNBRemote::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 1341rnb_err_t 1342RNBRemote::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 1348rnb_err_t 1349RNBRemote::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 1355rnb_err_t 1356RNBRemote::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 1363rnb_err_t 1364RNBRemote::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 1398rnb_err_t 1399RNBRemote::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 1438const char *k_space_delimiters = " \t"; 1439static void 1440skip_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 1450static std::string 1451get_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 1473static std::string 1474get_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 1489static std::string 1490get_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 1502extern void FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args); 1503extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); 1504 1505rnb_err_t 1506RNBRemote::HandlePacket_qRcmd (const char *p) 1507{ 1508 const char *c = p + strlen("qRcmd,"); 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 qRcmd 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 1566rnb_err_t 1567RNBRemote::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 1581rnb_err_t 1582RNBRemote::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 1596rnb_err_t 1597RNBRemote::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 1724rnb_err_t 1725set_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 1993rnb_err_t 1994RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p) 1995{ 1996 m_thread_suffix_supported = true; 1997 return SendPacket ("OK"); 1998} 1999 2000rnb_err_t 2001RNBRemote::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 2010rnb_err_t 2011RNBRemote::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 2021rnb_err_t 2022RNBRemote::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 2036rnb_err_t 2037RNBRemote::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 2080rnb_err_t 2081RNBRemote::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 2110rnb_err_t 2111RNBRemote::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 2134rnb_err_t 2135RNBRemote::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 2157rnb_err_t 2158RNBRemote::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 2175rnb_err_t 2176RNBRemote::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 2195rnb_err_t 2196RNBRemote::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 2214rnb_err_t 2215RNBRemote::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 2261rnb_err_t 2262RNBRemote::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 2270void 2271append_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 2287void 2288register_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 2329void 2330gdb_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 2347rnb_err_t 2348RNBRemote::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 2475rnb_err_t 2476RNBRemote::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 2543rnb_err_t 2544RNBRemote::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 2622rnb_err_t 2623RNBRemote::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 2674rnb_err_t 2675RNBRemote::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 2733rnb_err_t 2734RNBRemote::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 2779rnb_err_t 2780RNBRemote::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 2847static bool 2848RNBRemoteShouldCancelCallback (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 2876rnb_err_t 2877RNBRemote::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 2926rnb_err_t 2927RNBRemote::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 2941static bool 2942GetProcessNameFrom_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 2979rnb_err_t 2980RNBRemote::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 3151rnb_err_t 3152RNBRemote::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 3180rnb_err_t 3181RNBRemote::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. 3399nub_thread_t 3400RNBRemote::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 3423rnb_err_t 3424RNBRemote::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 3489rnb_err_t 3490RNBRemote::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 3553rnb_err_t 3554RNBRemote::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 3581rnb_err_t 3582RNBRemote::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// qGetProfileData;scan_type:0xYYYYYYY 3649rnb_err_t 3650RNBRemote::HandlePacket_GetProfileData (const char *p) 3651{ 3652 nub_process_t pid = m_ctx.ProcessID(); 3653 if (pid == INVALID_NUB_PROCESS) 3654 return SendPacket ("OK"); 3655 3656 StringExtractor packet(p += sizeof ("qGetProfileData")); 3657 DNBProfileDataScanType scan_type = eProfileAll; 3658 std::string name; 3659 std::string value; 3660 while (packet.GetNameColonValue(name, value)) 3661 { 3662 if (name.compare ("scan_type") == 0) 3663 { 3664 std::istringstream iss(value); 3665 uint32_t int_value = 0; 3666 if (iss >> std::hex >> int_value) 3667 { 3668 scan_type = (DNBProfileDataScanType)int_value; 3669 } 3670 } 3671 } 3672 3673 std::string data = DNBProcessGetProfileData(pid, scan_type); 3674 if (!data.empty()) 3675 { 3676 return SendPacket (data.c_str()); 3677 } 3678 else 3679 { 3680 return SendPacket ("OK"); 3681 } 3682} 3683 3684// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY 3685rnb_err_t 3686RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p) 3687{ 3688 nub_process_t pid = m_ctx.ProcessID(); 3689 if (pid == INVALID_NUB_PROCESS) 3690 return SendPacket ("OK"); 3691 3692 StringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling")); 3693 bool enable = false; 3694 uint64_t interval_usec = 0; 3695 DNBProfileDataScanType scan_type = eProfileAll; 3696 std::string name; 3697 std::string value; 3698 while (packet.GetNameColonValue(name, value)) 3699 { 3700 if (name.compare ("enable") == 0) 3701 { 3702 enable = strtoul(value.c_str(), NULL, 10) > 0; 3703 } 3704 else if (name.compare ("interval_usec") == 0) 3705 { 3706 interval_usec = strtoul(value.c_str(), NULL, 10); 3707 } 3708 else if (name.compare ("scan_type") == 0) 3709 { 3710 std::istringstream iss(value); 3711 uint32_t int_value = 0; 3712 if (iss >> std::hex >> int_value) 3713 { 3714 scan_type = (DNBProfileDataScanType)int_value; 3715 } 3716 } 3717 } 3718 3719 if (interval_usec == 0) 3720 { 3721 enable = 0; 3722 } 3723 3724 DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type); 3725 return SendPacket ("OK"); 3726} 3727 3728rnb_err_t 3729RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p) 3730{ 3731 /* This packet simply returns the number of supported hardware watchpoints. 3732 3733 Examples of use: 3734 qWatchpointSupportInfo: 3735 num:4 3736 3737 qWatchpointSupportInfo 3738 OK // this packet is implemented by the remote nub 3739 */ 3740 3741 p += sizeof ("qWatchpointSupportInfo") - 1; 3742 if (*p == '\0') 3743 return SendPacket ("OK"); 3744 if (*p++ != ':') 3745 return SendPacket ("E67"); 3746 3747 errno = 0; 3748 uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID()); 3749 std::ostringstream ostrm; 3750 3751 // size:4 3752 ostrm << "num:" << std::dec << num << ';'; 3753 return SendPacket (ostrm.str()); 3754} 3755 3756/* 'C sig [;addr]' 3757 Resume with signal sig, optionally at address addr. */ 3758 3759rnb_err_t 3760RNBRemote::HandlePacket_C (const char *p) 3761{ 3762 const nub_process_t pid = m_ctx.ProcessID(); 3763 3764 if (pid == INVALID_NUB_PROCESS) 3765 return SendPacket ("E36"); 3766 3767 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS }; 3768 int process_signo = -1; 3769 if (*(p + 1) != '\0') 3770 { 3771 action.tid = GetContinueThread(); 3772 char *end = NULL; 3773 errno = 0; 3774 process_signo = strtoul (p + 1, &end, 16); 3775 if (errno != 0) 3776 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet"); 3777 else if (*end == ';') 3778 { 3779 errno = 0; 3780 action.addr = strtoull (end + 1, NULL, 16); 3781 if (errno != 0 && action.addr == 0) 3782 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet"); 3783 } 3784 } 3785 3786 DNBThreadResumeActions thread_actions; 3787 thread_actions.Append (action); 3788 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal); 3789 if (!DNBProcessSignal(pid, process_signo)) 3790 return SendPacket ("E52"); 3791 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3792 return SendPacket ("E38"); 3793 /* Don't send an "OK" packet; response is the stopped/exited message. */ 3794 return rnb_success; 3795} 3796 3797//---------------------------------------------------------------------- 3798// 'D' packet 3799// Detach from gdb. 3800//---------------------------------------------------------------------- 3801rnb_err_t 3802RNBRemote::HandlePacket_D (const char *p) 3803{ 3804 SendPacket ("OK"); 3805 if (m_ctx.HasValidProcessID()) 3806 DNBProcessDetach(m_ctx.ProcessID()); 3807 return rnb_success; 3808} 3809 3810/* 'k' 3811 Kill the inferior process. */ 3812 3813rnb_err_t 3814RNBRemote::HandlePacket_k (const char *p) 3815{ 3816 // No response to should be sent to the kill packet 3817 if (m_ctx.HasValidProcessID()) 3818 DNBProcessKill (m_ctx.ProcessID()); 3819 SendPacket ("W09"); 3820 return rnb_success; 3821} 3822 3823rnb_err_t 3824RNBRemote::HandlePacket_stop_process (const char *p) 3825{ 3826//#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test exiting on interrupt 3827#if defined(TEST_EXIT_ON_INTERRUPT) 3828 rnb_err_t err = HandlePacket_k (p); 3829 m_comm.Disconnect(true); 3830 return err; 3831#else 3832 DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP); 3833 //DNBProcessSignal (m_ctx.ProcessID(), SIGINT); 3834 // Do not send any response packet! Wait for the stop reply packet to naturally happen 3835 return rnb_success; 3836#endif 3837} 3838 3839/* 's' 3840 Step the inferior process. */ 3841 3842rnb_err_t 3843RNBRemote::HandlePacket_s (const char *p) 3844{ 3845 const nub_process_t pid = m_ctx.ProcessID(); 3846 if (pid == INVALID_NUB_PROCESS) 3847 return SendPacket ("E32"); 3848 3849 // Hardware supported stepping not supported on arm 3850 nub_thread_t tid = GetContinueThread (); 3851 if (tid == 0 || tid == -1) 3852 tid = GetCurrentThread(); 3853 3854 if (tid == INVALID_NUB_THREAD) 3855 return SendPacket ("E33"); 3856 3857 DNBThreadResumeActions thread_actions; 3858 thread_actions.AppendAction(tid, eStateStepping); 3859 3860 // Make all other threads stop when we are stepping 3861 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); 3862 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3863 return SendPacket ("E49"); 3864 // Don't send an "OK" packet; response is the stopped/exited message. 3865 return rnb_success; 3866} 3867 3868/* 'S sig [;addr]' 3869 Step with signal sig, optionally at address addr. */ 3870 3871rnb_err_t 3872RNBRemote::HandlePacket_S (const char *p) 3873{ 3874 const nub_process_t pid = m_ctx.ProcessID(); 3875 if (pid == INVALID_NUB_PROCESS) 3876 return SendPacket ("E36"); 3877 3878 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS }; 3879 3880 if (*(p + 1) != '\0') 3881 { 3882 char *end = NULL; 3883 errno = 0; 3884 action.signal = strtoul (p + 1, &end, 16); 3885 if (errno != 0) 3886 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet"); 3887 else if (*end == ';') 3888 { 3889 errno = 0; 3890 action.addr = strtoull (end + 1, NULL, 16); 3891 if (errno != 0 && action.addr == 0) 3892 { 3893 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet"); 3894 } 3895 } 3896 } 3897 3898 action.tid = GetContinueThread (); 3899 if (action.tid == 0 || action.tid == -1) 3900 return SendPacket ("E40"); 3901 3902 nub_state_t tstate = DNBThreadGetState (pid, action.tid); 3903 if (tstate == eStateInvalid || tstate == eStateExited) 3904 return SendPacket ("E37"); 3905 3906 3907 DNBThreadResumeActions thread_actions; 3908 thread_actions.Append (action); 3909 3910 // Make all other threads stop when we are stepping 3911 thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); 3912 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3913 return SendPacket ("E39"); 3914 3915 // Don't send an "OK" packet; response is the stopped/exited message. 3916 return rnb_success; 3917} 3918 3919rnb_err_t 3920RNBRemote::HandlePacket_qHostInfo (const char *p) 3921{ 3922 std::ostringstream strm; 3923 3924 uint32_t cputype, is_64_bit_capable; 3925 size_t len = sizeof(cputype); 3926 bool promoted_to_64 = false; 3927 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) 3928 { 3929 len = sizeof (is_64_bit_capable); 3930 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) 3931 { 3932 if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0)) 3933 { 3934 promoted_to_64 = true; 3935 cputype |= CPU_ARCH_ABI64; 3936 } 3937 } 3938 3939 strm << "cputype:" << std::dec << cputype << ';'; 3940 } 3941 3942 uint32_t cpusubtype; 3943 len = sizeof(cpusubtype); 3944 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 3945 { 3946 if (promoted_to_64 && 3947 cputype == CPU_TYPE_X86_64 && 3948 cpusubtype == CPU_SUBTYPE_486) 3949 cpusubtype = CPU_SUBTYPE_X86_64_ALL; 3950 3951 strm << "cpusubtype:" << std::dec << cpusubtype << ';'; 3952 } 3953 3954 // The OS in the triple should be "ios" or "macosx" which doesn't match our 3955 // "Darwin" which gets returned from "kern.ostype", so we need to hardcode 3956 // this for now. 3957 if (cputype == CPU_TYPE_ARM) 3958 { 3959 strm << "ostype:ios;"; 3960 // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes. 3961 strm << "watchpoint_exceptions_received:before;"; 3962 } 3963 else 3964 { 3965 strm << "ostype:macosx;"; 3966 strm << "watchpoint_exceptions_received:after;"; 3967 } 3968// char ostype[64]; 3969// len = sizeof(ostype); 3970// if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0) 3971// { 3972// len = strlen(ostype); 3973// std::transform (ostype, ostype + len, ostype, tolower); 3974// strm << "ostype:" << std::dec << ostype << ';'; 3975// } 3976 3977 strm << "vendor:apple;"; 3978 3979#if defined (__LITTLE_ENDIAN__) 3980 strm << "endian:little;"; 3981#elif defined (__BIG_ENDIAN__) 3982 strm << "endian:big;"; 3983#elif defined (__PDP_ENDIAN__) 3984 strm << "endian:pdp;"; 3985#endif 3986 3987 if (promoted_to_64) 3988 strm << "ptrsize:8;"; 3989 else 3990 strm << "ptrsize:" << std::dec << sizeof(void *) << ';'; 3991 return SendPacket (strm.str()); 3992} 3993 3994 3995// Note that all numeric values returned by qProcessInfo are hex encoded, 3996// including the pid and the cpu type. 3997 3998rnb_err_t 3999RNBRemote::HandlePacket_qProcessInfo (const char *p) 4000{ 4001 nub_process_t pid; 4002 std::ostringstream rep; 4003 4004 // If we haven't run the process yet, return an error. 4005 if (!m_ctx.HasValidProcessID()) 4006 return SendPacket ("E68"); 4007 4008 pid = m_ctx.ProcessID(); 4009 4010 rep << "pid:" << std::hex << pid << ";"; 4011 4012 int procpid_mib[4]; 4013 procpid_mib[0] = CTL_KERN; 4014 procpid_mib[1] = KERN_PROC; 4015 procpid_mib[2] = KERN_PROC_PID; 4016 procpid_mib[3] = pid; 4017 struct kinfo_proc proc_kinfo; 4018 size_t proc_kinfo_size = sizeof(struct kinfo_proc); 4019 4020 if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) 4021 { 4022 if (proc_kinfo_size > 0) 4023 { 4024 rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";"; 4025 rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";"; 4026 rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";"; 4027 rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";"; 4028 if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) 4029 rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";"; 4030 } 4031 } 4032 4033 int cputype_mib[CTL_MAXNAME]={0,}; 4034 size_t cputype_mib_len = CTL_MAXNAME; 4035 cpu_type_t cputype = -1; 4036 if (::sysctlnametomib("sysctl.proc_cputype", cputype_mib, &cputype_mib_len) == 0) 4037 { 4038 cputype_mib[cputype_mib_len] = pid; 4039 cputype_mib_len++; 4040 size_t len = sizeof(cputype); 4041 if (::sysctl (cputype_mib, cputype_mib_len, &cputype, &len, 0, 0) == 0) 4042 { 4043 rep << "cputype:" << std::hex << cputype << ";"; 4044 } 4045 } 4046 4047 uint32_t cpusubtype; 4048 size_t cpusubtype_len = sizeof(cpusubtype); 4049 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0) 4050 { 4051 if (cputype == CPU_TYPE_X86_64 && cpusubtype == CPU_SUBTYPE_486) 4052 { 4053 cpusubtype = CPU_SUBTYPE_X86_64_ALL; 4054 } 4055 4056 rep << "cpusubtype:" << std::hex << cpusubtype << ';'; 4057 } 4058 4059 // The OS in the triple should be "ios" or "macosx" which doesn't match our 4060 // "Darwin" which gets returned from "kern.ostype", so we need to hardcode 4061 // this for now. 4062 if (cputype == CPU_TYPE_ARM) 4063 rep << "ostype:ios;"; 4064 else 4065 rep << "ostype:macosx;"; 4066 4067 rep << "vendor:apple;"; 4068 4069#if defined (__LITTLE_ENDIAN__) 4070 rep << "endian:little;"; 4071#elif defined (__BIG_ENDIAN__) 4072 rep << "endian:big;"; 4073#elif defined (__PDP_ENDIAN__) 4074 rep << "endian:pdp;"; 4075#endif 4076 4077#if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE) 4078 nub_thread_t thread = DNBProcessGetCurrentThread (pid); 4079 kern_return_t kr; 4080 x86_thread_state_t gp_regs; 4081 mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; 4082 kr = thread_get_state (thread, x86_THREAD_STATE, 4083 (thread_state_t) &gp_regs, &gp_count); 4084 if (kr == KERN_SUCCESS) 4085 { 4086 if (gp_regs.tsh.flavor == x86_THREAD_STATE64) 4087 rep << "ptrsize:8;"; 4088 else 4089 rep << "ptrsize:4;"; 4090 } 4091#elif defined (__arm__) 4092 rep << "ptrsize:4;"; 4093#endif 4094 4095 return SendPacket (rep.str()); 4096} 4097 4098