RNBRemote.cpp revision afe3763f13dc122006ad6b5ed377e789e09c8715
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, 4,"cpsr", {0}, NULL, 1}, // current program status register 882 { 17, 4, "s0", {0}, NULL, 0}, 883 { 18, 4, "s1", {0}, NULL, 0}, 884 { 19, 4, "s2", {0}, NULL, 0}, 885 { 20, 4, "s3", {0}, NULL, 0}, 886 { 21, 4, "s4", {0}, NULL, 0}, 887 { 22, 4, "s5", {0}, NULL, 0}, 888 { 23, 4, "s6", {0}, NULL, 0}, 889 { 24, 4, "s7", {0}, NULL, 0}, 890 { 25, 4, "s8", {0}, NULL, 0}, 891 { 26, 4, "s9", {0}, NULL, 0}, 892 { 27, 4, "s10", {0}, NULL, 0}, 893 { 28, 4, "s11", {0}, NULL, 0}, 894 { 29, 4, "s12", {0}, NULL, 0}, 895 { 30, 4, "s13", {0}, NULL, 0}, 896 { 31, 4, "s14", {0}, NULL, 0}, 897 { 32, 4, "s15", {0}, NULL, 0}, 898 { 33, 4, "s16", {0}, NULL, 0}, 899 { 34, 4, "s17", {0}, NULL, 0}, 900 { 35, 4, "s18", {0}, NULL, 0}, 901 { 36, 4, "s19", {0}, NULL, 0}, 902 { 37, 4, "s20", {0}, NULL, 0}, 903 { 38, 4, "s21", {0}, NULL, 0}, 904 { 39, 4, "s22", {0}, NULL, 0}, 905 { 40, 4, "s23", {0}, NULL, 0}, 906 { 41, 4, "s24", {0}, NULL, 0}, 907 { 42, 4, "s25", {0}, NULL, 0}, 908 { 43, 4, "s26", {0}, NULL, 0}, 909 { 44, 4, "s27", {0}, NULL, 0}, 910 { 45, 4, "s28", {0}, NULL, 0}, 911 { 46, 4, "s29", {0}, NULL, 0}, 912 { 47, 4, "s30", {0}, NULL, 0}, 913 { 48, 4, "s31", {0}, NULL, 0}, 914 { 49, 8, "d0", {0}, NULL, 0}, 915 { 50, 8, "d1", {0}, NULL, 0}, 916 { 51, 8, "d2", {0}, NULL, 0}, 917 { 52, 8, "d3", {0}, NULL, 0}, 918 { 53, 8, "d4", {0}, NULL, 0}, 919 { 54, 8, "d5", {0}, NULL, 0}, 920 { 55, 8, "d6", {0}, NULL, 0}, 921 { 56, 8, "d7", {0}, NULL, 0}, 922 { 57, 8, "d8", {0}, NULL, 0}, 923 { 58, 8, "d9", {0}, NULL, 0}, 924 { 59, 8, "d10", {0}, NULL, 0}, 925 { 60, 8, "d11", {0}, NULL, 0}, 926 { 61, 8, "d12", {0}, NULL, 0}, 927 { 62, 8, "d13", {0}, NULL, 0}, 928 { 63, 8, "d14", {0}, NULL, 0}, 929 { 64, 8, "d15", {0}, NULL, 0}, 930 { 65, 8, "d16", {0}, NULL, 0}, 931 { 66, 8, "d17", {0}, NULL, 0}, 932 { 67, 8, "d18", {0}, NULL, 0}, 933 { 68, 8, "d19", {0}, NULL, 0}, 934 { 69, 8, "d20", {0}, NULL, 0}, 935 { 70, 8, "d21", {0}, NULL, 0}, 936 { 71, 8, "d22", {0}, NULL, 0}, 937 { 72, 8, "d23", {0}, NULL, 0}, 938 { 73, 8, "d24", {0}, NULL, 0}, 939 { 74, 8, "d25", {0}, NULL, 0}, 940 { 75, 8, "d26", {0}, NULL, 0}, 941 { 76, 8, "d27", {0}, NULL, 0}, 942 { 77, 8, "d28", {0}, NULL, 0}, 943 { 78, 8, "d29", {0}, NULL, 0}, 944 { 79, 8, "d30", {0}, NULL, 0}, 945 { 80, 8, "d31", {0}, NULL, 0}, 946 { 81, 16, "q0", {0}, NULL, 0}, 947 { 82, 16, "q1", {0}, NULL, 0}, 948 { 83, 16, "q2", {0}, NULL, 0}, 949 { 84, 16, "q3", {0}, NULL, 0}, 950 { 85, 16, "q4", {0}, NULL, 0}, 951 { 86, 16, "q5", {0}, NULL, 0}, 952 { 87, 16, "q6", {0}, NULL, 0}, 953 { 88, 16, "q7", {0}, NULL, 0}, 954 { 89, 16, "q8", {0}, NULL, 0}, 955 { 90, 16, "q9", {0}, NULL, 0}, 956 { 91, 16, "q10", {0}, NULL, 0}, 957 { 92, 16, "q11", {0}, NULL, 0}, 958 { 93, 16, "q12", {0}, NULL, 0}, 959 { 94, 16, "q13", {0}, NULL, 0}, 960 { 95, 16, "q14", {0}, NULL, 0}, 961 { 96, 16, "q15", {0}, NULL, 0}, 962 { 97, 4, "fpscr", {0}, NULL, 0} 963}; 964 965register_map_entry_t 966g_gdb_register_map_i386[] = 967{ 968 { 0, 4, "eax" , {0}, NULL, 0 }, 969 { 1, 4, "ecx" , {0}, NULL, 0 }, 970 { 2, 4, "edx" , {0}, NULL, 0 }, 971 { 3, 4, "ebx" , {0}, NULL, 0 }, 972 { 4, 4, "esp" , {0}, NULL, 1 }, 973 { 5, 4, "ebp" , {0}, NULL, 1 }, 974 { 6, 4, "esi" , {0}, NULL, 0 }, 975 { 7, 4, "edi" , {0}, NULL, 0 }, 976 { 8, 4, "eip" , {0}, NULL, 1 }, 977 { 9, 4, "eflags" , {0}, NULL, 0 }, 978 { 10, 4, "cs" , {0}, NULL, 0 }, 979 { 11, 4, "ss" , {0}, NULL, 0 }, 980 { 12, 4, "ds" , {0}, NULL, 0 }, 981 { 13, 4, "es" , {0}, NULL, 0 }, 982 { 14, 4, "fs" , {0}, NULL, 0 }, 983 { 15, 4, "gs" , {0}, NULL, 0 }, 984 { 16, 10, "stmm0" , {0}, NULL, 0 }, 985 { 17, 10, "stmm1" , {0}, NULL, 0 }, 986 { 18, 10, "stmm2" , {0}, NULL, 0 }, 987 { 19, 10, "stmm3" , {0}, NULL, 0 }, 988 { 20, 10, "stmm4" , {0}, NULL, 0 }, 989 { 21, 10, "stmm5" , {0}, NULL, 0 }, 990 { 22, 10, "stmm6" , {0}, NULL, 0 }, 991 { 23, 10, "stmm7" , {0}, NULL, 0 }, 992 { 24, 4, "fctrl" , {0}, NULL, 0 }, 993 { 25, 4, "fstat" , {0}, NULL, 0 }, 994 { 26, 4, "ftag" , {0}, NULL, 0 }, 995 { 27, 4, "fiseg" , {0}, NULL, 0 }, 996 { 28, 4, "fioff" , {0}, NULL, 0 }, 997 { 29, 4, "foseg" , {0}, NULL, 0 }, 998 { 30, 4, "fooff" , {0}, NULL, 0 }, 999 { 31, 4, "fop" , {0}, NULL, 0 }, 1000 { 32, 16, "xmm0" , {0}, NULL, 0 }, 1001 { 33, 16, "xmm1" , {0}, NULL, 0 }, 1002 { 34, 16, "xmm2" , {0}, NULL, 0 }, 1003 { 35, 16, "xmm3" , {0}, NULL, 0 }, 1004 { 36, 16, "xmm4" , {0}, NULL, 0 }, 1005 { 37, 16, "xmm5" , {0}, NULL, 0 }, 1006 { 38, 16, "xmm6" , {0}, NULL, 0 }, 1007 { 39, 16, "xmm7" , {0}, NULL, 0 }, 1008 { 40, 4, "mxcsr" , {0}, NULL, 0 }, 1009}; 1010 1011register_map_entry_t 1012g_gdb_register_map_x86_64[] = 1013{ 1014 { 0, 8, "rax" , {0}, NULL, 0 }, 1015 { 1, 8, "rbx" , {0}, NULL, 0 }, 1016 { 2, 8, "rcx" , {0}, NULL, 0 }, 1017 { 3, 8, "rdx" , {0}, NULL, 0 }, 1018 { 4, 8, "rsi" , {0}, NULL, 0 }, 1019 { 5, 8, "rdi" , {0}, NULL, 0 }, 1020 { 6, 8, "rbp" , {0}, NULL, 1 }, 1021 { 7, 8, "rsp" , {0}, NULL, 1 }, 1022 { 8, 8, "r8" , {0}, NULL, 0 }, 1023 { 9, 8, "r9" , {0}, NULL, 0 }, 1024 { 10, 8, "r10" , {0}, NULL, 0 }, 1025 { 11, 8, "r11" , {0}, NULL, 0 }, 1026 { 12, 8, "r12" , {0}, NULL, 0 }, 1027 { 13, 8, "r13" , {0}, NULL, 0 }, 1028 { 14, 8, "r14" , {0}, NULL, 0 }, 1029 { 15, 8, "r15" , {0}, NULL, 0 }, 1030 { 16, 8, "rip" , {0}, NULL, 1 }, 1031 { 17, 4, "rflags", {0}, NULL, 0 }, 1032 { 18, 4, "cs" , {0}, NULL, 0 }, 1033 { 19, 4, "ss" , {0}, NULL, 0 }, 1034 { 20, 4, "ds" , {0}, NULL, 0 }, 1035 { 21, 4, "es" , {0}, NULL, 0 }, 1036 { 22, 4, "fs" , {0}, NULL, 0 }, 1037 { 23, 4, "gs" , {0}, NULL, 0 }, 1038 { 24, 10, "stmm0" , {0}, NULL, 0 }, 1039 { 25, 10, "stmm1" , {0}, NULL, 0 }, 1040 { 26, 10, "stmm2" , {0}, NULL, 0 }, 1041 { 27, 10, "stmm3" , {0}, NULL, 0 }, 1042 { 28, 10, "stmm4" , {0}, NULL, 0 }, 1043 { 29, 10, "stmm5" , {0}, NULL, 0 }, 1044 { 30, 10, "stmm6" , {0}, NULL, 0 }, 1045 { 31, 10, "stmm7" , {0}, NULL, 0 }, 1046 { 32, 4, "fctrl" , {0}, NULL, 0 }, 1047 { 33, 4, "fstat" , {0}, NULL, 0 }, 1048 { 34, 4, "ftag" , {0}, NULL, 0 }, 1049 { 35, 4, "fiseg" , {0}, NULL, 0 }, 1050 { 36, 4, "fioff" , {0}, NULL, 0 }, 1051 { 37, 4, "foseg" , {0}, NULL, 0 }, 1052 { 38, 4, "fooff" , {0}, NULL, 0 }, 1053 { 39, 4, "fop" , {0}, NULL, 0 }, 1054 { 40, 16, "xmm0" , {0}, NULL, 0 }, 1055 { 41, 16, "xmm1" , {0}, NULL, 0 }, 1056 { 42, 16, "xmm2" , {0}, NULL, 0 }, 1057 { 43, 16, "xmm3" , {0}, NULL, 0 }, 1058 { 44, 16, "xmm4" , {0}, NULL, 0 }, 1059 { 45, 16, "xmm5" , {0}, NULL, 0 }, 1060 { 46, 16, "xmm6" , {0}, NULL, 0 }, 1061 { 47, 16, "xmm7" , {0}, NULL, 0 }, 1062 { 48, 16, "xmm8" , {0}, NULL, 0 }, 1063 { 49, 16, "xmm9" , {0}, NULL, 0 }, 1064 { 50, 16, "xmm10" , {0}, NULL, 0 }, 1065 { 51, 16, "xmm11" , {0}, NULL, 0 }, 1066 { 52, 16, "xmm12" , {0}, NULL, 0 }, 1067 { 53, 16, "xmm13" , {0}, NULL, 0 }, 1068 { 54, 16, "xmm14" , {0}, NULL, 0 }, 1069 { 55, 16, "xmm15" , {0}, NULL, 0 }, 1070 { 56, 4, "mxcsr" , {0}, NULL, 0 } 1071}; 1072 1073 1074void 1075RNBRemote::Initialize() 1076{ 1077 DNBInitialize(); 1078} 1079 1080 1081bool 1082RNBRemote::InitializeRegisters () 1083{ 1084 pid_t pid = m_ctx.ProcessID(); 1085 if (pid == INVALID_NUB_PROCESS) 1086 return false; 1087 1088 if (m_use_native_regs) 1089 { 1090 DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface", __FUNCTION__); 1091 // Discover the registers by querying the DNB interface and letting it 1092 // state the registers that it would like to export. This allows the 1093 // registers to be discovered using multiple qRegisterInfo calls to get 1094 // all register information after the architecture for the process is 1095 // determined. 1096 if (g_dynamic_register_map.empty()) 1097 { 1098 nub_size_t num_reg_sets = 0; 1099 const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets); 1100 1101 assert (num_reg_sets > 0 && reg_sets != NULL); 1102 1103 uint32_t regnum = 0; 1104 for (nub_size_t set = 0; set < num_reg_sets; ++set) 1105 { 1106 if (reg_sets[set].registers == NULL) 1107 continue; 1108 1109 for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg) 1110 { 1111 register_map_entry_t reg_entry = { 1112 regnum++, // register number starts at zero and goes up with no gaps 1113 reg_sets[set].registers[reg].size, // register size in bytes 1114 reg_sets[set].registers[reg].name, // register name 1115 reg_sets[set].registers[reg], // DNBRegisterInfo 1116 NULL, // Value to print if case we fail to reg this register (if this is NULL, we will return an error) 1117 reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM}; 1118 1119 g_dynamic_register_map.push_back (reg_entry); 1120 } 1121 } 1122 g_reg_entries = g_dynamic_register_map.data(); 1123 g_num_reg_entries = g_dynamic_register_map.size(); 1124 } 1125 return true; 1126 } 1127 else 1128 { 1129 uint32_t cpu_type = DNBProcessGetCPUType (pid); 1130 DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers(%s)", __FUNCTION__, m_arch.c_str()); 1131#if defined (__i386__) || defined (__x86_64__) 1132 if (cpu_type == CPU_TYPE_X86_64) 1133 { 1134 const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t); 1135 for (uint32_t i=0; i<num_regs; ++i) 1136 { 1137 if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info)) 1138 { 1139 RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]); 1140 assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE); 1141 } 1142 } 1143 g_reg_entries = g_gdb_register_map_x86_64; 1144 g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t); 1145 return true; 1146 } 1147 else if (cpu_type == CPU_TYPE_I386) 1148 { 1149 const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t); 1150 for (uint32_t i=0; i<num_regs; ++i) 1151 { 1152 if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info)) 1153 { 1154 RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]); 1155 assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE); 1156 } 1157 } 1158 g_reg_entries = g_gdb_register_map_i386; 1159 g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t); 1160 return true; 1161 } 1162#elif defined (__arm__) 1163 if (cpu_type == CPU_TYPE_ARM) 1164 { 1165 const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t); 1166 for (uint32_t i=0; i<num_regs; ++i) 1167 { 1168 if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info)) 1169 { 1170 RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]); 1171 assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE); 1172 } 1173 } 1174 g_reg_entries = g_gdb_register_map_arm; 1175 g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t); 1176 return true; 1177 } 1178#endif 1179 } 1180 return false; 1181} 1182 1183/* The inferior has stopped executing; send a packet 1184 to gdb to let it know. */ 1185 1186void 1187RNBRemote::NotifyThatProcessStopped (void) 1188{ 1189 RNBRemote::HandlePacket_last_signal (NULL); 1190 return; 1191} 1192 1193 1194/* 'A arglen,argnum,arg,...' 1195 Update the inferior context CTX with the program name and arg 1196 list. 1197 The documentation for this packet is underwhelming but my best reading 1198 of this is that it is a series of (len, position #, arg)'s, one for 1199 each argument with "arg" hex encoded (two 0-9a-f chars?). 1200 Why we need BOTH a "len" and a hex encoded "arg" is beyond me - either 1201 is sufficient to get around the "," position separator escape issue. 1202 1203 e.g. our best guess for a valid 'A' packet for "gdb -q a.out" is 1204 1205 6,0,676462,4,1,2d71,10,2,612e6f7574 1206 1207 Note that "argnum" and "arglen" are numbers in base 10. Again, that's 1208 not documented either way but I'm assuming it's so. */ 1209 1210rnb_err_t 1211RNBRemote::HandlePacket_A (const char *p) 1212{ 1213 if (p == NULL || *p == '\0') 1214 { 1215 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Null packet for 'A' pkt"); 1216 } 1217 p++; 1218 if (p == '\0' || !isdigit (*p)) 1219 { 1220 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not specified on 'A' pkt"); 1221 } 1222 1223 /* I promise I don't modify it anywhere in this function. strtoul()'s 1224 2nd arg has to be non-const which makes it problematic to step 1225 through the string easily. */ 1226 char *buf = const_cast<char *>(p); 1227 1228 RNBContext& ctx = Context(); 1229 1230 while (*buf != '\0') 1231 { 1232 int arglen, argnum; 1233 std::string arg; 1234 char *c; 1235 1236 errno = 0; 1237 arglen = strtoul (buf, &c, 10); 1238 if (errno != 0 && arglen == 0) 1239 { 1240 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not a number on 'A' pkt"); 1241 } 1242 if (*c != ',') 1243 { 1244 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt"); 1245 } 1246 buf = c + 1; 1247 1248 errno = 0; 1249 argnum = strtoul (buf, &c, 10); 1250 if (errno != 0 && argnum == 0) 1251 { 1252 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "argnum not a number on 'A' pkt"); 1253 } 1254 if (*c != ',') 1255 { 1256 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "arglen not followed by comma on 'A' pkt"); 1257 } 1258 buf = c + 1; 1259 1260 c = buf; 1261 buf = buf + arglen; 1262 while (c < buf && *c != '\0' && c + 1 < buf && *(c + 1) != '\0') 1263 { 1264 char smallbuf[3]; 1265 smallbuf[0] = *c; 1266 smallbuf[1] = *(c + 1); 1267 smallbuf[2] = '\0'; 1268 1269 errno = 0; 1270 int ch = strtoul (smallbuf, NULL, 16); 1271 if (errno != 0 && ch == 0) 1272 { 1273 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'A' pkt"); 1274 } 1275 1276 arg.push_back(ch); 1277 c += 2; 1278 } 1279 1280 ctx.PushArgument (arg.c_str()); 1281 if (*buf == ',') 1282 buf++; 1283 } 1284 SendPacket ("OK"); 1285 1286 return rnb_success; 1287} 1288 1289/* 'H c t' 1290 Set the thread for subsequent actions; 'c' for step/continue ops, 1291 'g' for other ops. -1 means all threads, 0 means any thread. */ 1292 1293rnb_err_t 1294RNBRemote::HandlePacket_H (const char *p) 1295{ 1296 p++; // skip 'H' 1297 if (*p != 'c' && *p != 'g') 1298 { 1299 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing 'c' or 'g' type in H packet"); 1300 } 1301 1302 if (!m_ctx.HasValidProcessID()) 1303 { 1304 // We allow gdb to connect to a server that hasn't started running 1305 // the target yet. gdb still wants to ask questions about it and 1306 // freaks out if it gets an error. So just return OK here. 1307 } 1308 1309 errno = 0; 1310 nub_thread_t tid = strtoul (p + 1, NULL, 16); 1311 if (errno != 0 && tid == 0) 1312 { 1313 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in H packet"); 1314 } 1315 if (*p == 'c') 1316 SetContinueThread (tid); 1317 if (*p == 'g') 1318 SetCurrentThread (tid); 1319 1320 return SendPacket ("OK"); 1321} 1322 1323 1324rnb_err_t 1325RNBRemote::HandlePacket_qLaunchSuccess (const char *p) 1326{ 1327 if (m_ctx.HasValidProcessID() || m_ctx.LaunchStatus().Error() == 0) 1328 return SendPacket("OK"); 1329 std::ostringstream ret_str; 1330 std::string status_str; 1331 ret_str << "E" << m_ctx.LaunchStatusAsString(status_str); 1332 1333 return SendPacket (ret_str.str()); 1334} 1335 1336rnb_err_t 1337RNBRemote::HandlePacket_qShlibInfoAddr (const char *p) 1338{ 1339 if (m_ctx.HasValidProcessID()) 1340 { 1341 nub_addr_t shlib_info_addr = DNBProcessGetSharedLibraryInfoAddress(m_ctx.ProcessID()); 1342 if (shlib_info_addr != INVALID_NUB_ADDRESS) 1343 { 1344 std::ostringstream ostrm; 1345 ostrm << RAW_HEXBASE << shlib_info_addr; 1346 return SendPacket (ostrm.str ()); 1347 } 1348 } 1349 return SendPacket ("E44"); 1350} 1351 1352rnb_err_t 1353RNBRemote::HandlePacket_qStepPacketSupported (const char *p) 1354{ 1355 // Normally the "s" packet is mandatory, yet in gdb when using ARM, they 1356 // get around the need for this packet by implementing software single 1357 // stepping from gdb. Current versions of debugserver do support the "s" 1358 // packet, yet some older versions do not. We need a way to tell if this 1359 // packet is supported so we can disable software single stepping in gdb 1360 // for remote targets (so the "s" packet will get used). 1361 return SendPacket("OK"); 1362} 1363 1364rnb_err_t 1365RNBRemote::HandlePacket_qSyncThreadStateSupported (const char *p) 1366{ 1367 // We support attachOrWait meaning attach if the process exists, otherwise wait to attach. 1368 return SendPacket("OK"); 1369} 1370 1371rnb_err_t 1372RNBRemote::HandlePacket_qVAttachOrWaitSupported (const char *p) 1373{ 1374 // We support attachOrWait meaning attach if the process exists, otherwise wait to attach. 1375 return SendPacket("OK"); 1376} 1377 1378rnb_err_t 1379RNBRemote::HandlePacket_qThreadStopInfo (const char *p) 1380{ 1381 p += strlen ("qThreadStopInfo"); 1382 nub_thread_t tid = strtoul(p, 0, 16); 1383 return SendStopReplyPacketForThread (tid); 1384} 1385 1386rnb_err_t 1387RNBRemote::HandlePacket_qThreadInfo (const char *p) 1388{ 1389 // We allow gdb to connect to a server that hasn't started running 1390 // the target yet. gdb still wants to ask questions about it and 1391 // freaks out if it gets an error. So just return OK here. 1392 nub_process_t pid = m_ctx.ProcessID(); 1393 if (pid == INVALID_NUB_PROCESS) 1394 return SendPacket ("OK"); 1395 1396 // Only "qfThreadInfo" and "qsThreadInfo" get into this function so 1397 // we only need to check the second byte to tell which is which 1398 if (p[1] == 'f') 1399 { 1400 nub_size_t numthreads = DNBProcessGetNumThreads (pid); 1401 std::ostringstream ostrm; 1402 ostrm << "m"; 1403 bool first = true; 1404 for (nub_size_t i = 0; i < numthreads; ++i) 1405 { 1406 if (first) 1407 first = false; 1408 else 1409 ostrm << ","; 1410 nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i); 1411 ostrm << std::hex << th; 1412 } 1413 return SendPacket (ostrm.str ()); 1414 } 1415 else 1416 { 1417 return SendPacket ("l"); 1418 } 1419} 1420 1421rnb_err_t 1422RNBRemote::HandlePacket_qThreadExtraInfo (const char *p) 1423{ 1424 // We allow gdb to connect to a server that hasn't started running 1425 // the target yet. gdb still wants to ask questions about it and 1426 // freaks out if it gets an error. So just return OK here. 1427 nub_process_t pid = m_ctx.ProcessID(); 1428 if (pid == INVALID_NUB_PROCESS) 1429 return SendPacket ("OK"); 1430 1431 /* This is supposed to return a string like 'Runnable' or 1432 'Blocked on Mutex'. 1433 The returned string is formatted like the "A" packet - a 1434 sequence of letters encoded in as 2-hex-chars-per-letter. */ 1435 p += strlen ("qThreadExtraInfo"); 1436 if (*p++ != ',') 1437 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Illformed qThreadExtraInfo packet"); 1438 errno = 0; 1439 nub_thread_t tid = strtoul (p, NULL, 16); 1440 if (errno != 0 && tid == 0) 1441 { 1442 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in qThreadExtraInfo packet"); 1443 } 1444 1445 const char * threadInfo = DNBThreadGetInfo(pid, tid); 1446 if (threadInfo != NULL && threadInfo[0]) 1447 { 1448 return SendHexEncodedBytePacket(NULL, threadInfo, strlen(threadInfo), NULL); 1449 } 1450 else 1451 { 1452 // "OK" == 4f6b 1453 // Return "OK" as a ASCII hex byte stream if things go wrong 1454 return SendPacket ("4f6b"); 1455 } 1456 1457 return SendPacket (""); 1458} 1459 1460 1461const char *k_space_delimiters = " \t"; 1462static void 1463skip_spaces (std::string &line) 1464{ 1465 if (!line.empty()) 1466 { 1467 size_t space_pos = line.find_first_not_of (k_space_delimiters); 1468 if (space_pos > 0) 1469 line.erase(0, space_pos); 1470 } 1471} 1472 1473static std::string 1474get_identifier (std::string &line) 1475{ 1476 std::string word; 1477 skip_spaces (line); 1478 const size_t line_size = line.size(); 1479 size_t end_pos; 1480 for (end_pos = 0; end_pos < line_size; ++end_pos) 1481 { 1482 if (end_pos == 0) 1483 { 1484 if (isalpha(line[end_pos]) || line[end_pos] == '_') 1485 continue; 1486 } 1487 else if (isalnum(line[end_pos]) || line[end_pos] == '_') 1488 continue; 1489 break; 1490 } 1491 word.assign (line, 0, end_pos); 1492 line.erase(0, end_pos); 1493 return word; 1494} 1495 1496static std::string 1497get_operator (std::string &line) 1498{ 1499 std::string op; 1500 skip_spaces (line); 1501 if (!line.empty()) 1502 { 1503 if (line[0] == '=') 1504 { 1505 op = '='; 1506 line.erase(0,1); 1507 } 1508 } 1509 return op; 1510} 1511 1512static std::string 1513get_value (std::string &line) 1514{ 1515 std::string value; 1516 skip_spaces (line); 1517 if (!line.empty()) 1518 { 1519 value.swap(line); 1520 } 1521 return value; 1522} 1523 1524 1525extern void FileLogCallback(void *baton, uint32_t flags, const char *format, va_list args); 1526extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); 1527 1528rnb_err_t 1529RNBRemote::HandlePacket_qRcmd (const char *p) 1530{ 1531 const char *c = p + strlen("qRcmd,"); 1532 std::string line; 1533 while (c[0] && c[1]) 1534 { 1535 char smallbuf[3] = { c[0], c[1], '\0' }; 1536 errno = 0; 1537 int ch = strtoul (smallbuf, NULL, 16); 1538 if (errno != 0 && ch == 0) 1539 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in payload of qRcmd packet"); 1540 line.push_back(ch); 1541 c += 2; 1542 } 1543 if (*c == '\0') 1544 { 1545 std::string command = get_identifier(line); 1546 if (command.compare("set") == 0) 1547 { 1548 std::string variable = get_identifier (line); 1549 std::string op = get_operator (line); 1550 std::string value = get_value (line); 1551 if (variable.compare("logfile") == 0) 1552 { 1553 FILE *log_file = fopen(value.c_str(), "w"); 1554 if (log_file) 1555 { 1556 DNBLogSetLogCallback(FileLogCallback, log_file); 1557 return SendPacket ("OK"); 1558 } 1559 return SendPacket ("E71"); 1560 } 1561 else if (variable.compare("logmask") == 0) 1562 { 1563 char *end; 1564 errno = 0; 1565 uint32_t logmask = strtoul (value.c_str(), &end, 0); 1566 if (errno == 0 && end && *end == '\0') 1567 { 1568 DNBLogSetLogMask (logmask); 1569 if (!DNBLogGetLogCallback()) 1570 DNBLogSetLogCallback(ASLLogCallback, NULL); 1571 return SendPacket ("OK"); 1572 } 1573 errno = 0; 1574 logmask = strtoul (value.c_str(), &end, 16); 1575 if (errno == 0 && end && *end == '\0') 1576 { 1577 DNBLogSetLogMask (logmask); 1578 return SendPacket ("OK"); 1579 } 1580 return SendPacket ("E72"); 1581 } 1582 return SendPacket ("E70"); 1583 } 1584 return SendPacket ("E69"); 1585 } 1586 return SendPacket ("E73"); 1587} 1588 1589rnb_err_t 1590RNBRemote::HandlePacket_qC (const char *p) 1591{ 1592 nub_process_t pid; 1593 std::ostringstream rep; 1594 // If we haven't run the process yet, we tell the debugger the 1595 // pid is 0. That way it can know to tell use to run later on. 1596 if (m_ctx.HasValidProcessID()) 1597 pid = m_ctx.ProcessID(); 1598 else 1599 pid = 0; 1600 rep << "QC" << std::hex << pid; 1601 return SendPacket (rep.str()); 1602} 1603 1604rnb_err_t 1605RNBRemote::HandlePacket_qGetPid (const char *p) 1606{ 1607 nub_process_t pid; 1608 std::ostringstream rep; 1609 // If we haven't run the process yet, we tell the debugger the 1610 // pid is 0. That way it can know to tell use to run later on. 1611 if (m_ctx.HasValidProcessID()) 1612 pid = m_ctx.ProcessID(); 1613 else 1614 pid = 0; 1615 rep << std::hex << pid; 1616 return SendPacket (rep.str()); 1617} 1618 1619rnb_err_t 1620RNBRemote::HandlePacket_qRegisterInfo (const char *p) 1621{ 1622 if (g_num_reg_entries == 0) 1623 InitializeRegisters (); 1624 1625 p += strlen ("qRegisterInfo"); 1626 1627 nub_size_t num_reg_sets = 0; 1628 const DNBRegisterSetInfo *reg_set_info = DNBGetRegisterSetInfo (&num_reg_sets); 1629 uint32_t reg_num = strtoul(p, 0, 16); 1630 1631 if (reg_num < g_num_reg_entries) 1632 { 1633 const register_map_entry_t *reg_entry = &g_reg_entries[reg_num]; 1634 std::ostringstream ostrm; 1635 ostrm << "name:" << reg_entry->gdb_name << ';'; 1636 1637 if (reg_entry->nub_info.name && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.name)) 1638 ostrm << "alt-name:" << reg_entry->nub_info.name << ';'; 1639 else if (reg_entry->nub_info.alt && ::strcmp (reg_entry->gdb_name, reg_entry->nub_info.alt)) 1640 ostrm << "alt-name:" << reg_entry->nub_info.alt << ';'; 1641 1642 ostrm << "bitsize:" << std::dec << reg_entry->gdb_size * 8 << ';'; 1643 ostrm << "offset:" << std::dec << reg_entry->nub_info.offset << ';'; 1644 1645 switch (reg_entry->nub_info.type) 1646 { 1647 case Uint: ostrm << "encoding:uint;"; break; 1648 case Sint: ostrm << "encoding:sint;"; break; 1649 case IEEE754: ostrm << "encoding:ieee754;"; break; 1650 case Vector: ostrm << "encoding:vector;"; break; 1651 } 1652 1653 switch (reg_entry->nub_info.format) 1654 { 1655 case Binary: ostrm << "format:binary;"; break; 1656 case Decimal: ostrm << "format:decimal;"; break; 1657 case Hex: ostrm << "format:hex;"; break; 1658 case Float: ostrm << "format:float;"; break; 1659 case VectorOfSInt8: ostrm << "format:vector-sint8;"; break; 1660 case VectorOfUInt8: ostrm << "format:vector-uint8;"; break; 1661 case VectorOfSInt16: ostrm << "format:vector-sint16;"; break; 1662 case VectorOfUInt16: ostrm << "format:vector-uint16;"; break; 1663 case VectorOfSInt32: ostrm << "format:vector-sint32;"; break; 1664 case VectorOfUInt32: ostrm << "format:vector-uint32;"; break; 1665 case VectorOfFloat32: ostrm << "format:vector-float32;"; break; 1666 case VectorOfUInt128: ostrm << "format:vector-uint128;"; break; 1667 }; 1668 1669 if (reg_set_info && reg_entry->nub_info.set < num_reg_sets) 1670 ostrm << "set:" << reg_set_info[reg_entry->nub_info.set].name << ';'; 1671 1672 1673 if (g_reg_entries != g_dynamic_register_map.data()) 1674 { 1675 if (reg_entry->nub_info.reg_gdb != INVALID_NUB_REGNUM && reg_entry->nub_info.reg_gdb != reg_num) 1676 { 1677 printf("register %s is getting gdb reg_num of %u when the register info says %u\n", 1678 reg_entry->gdb_name, reg_num, reg_entry->nub_info.reg_gdb); 1679 } 1680 } 1681 1682 if (reg_entry->nub_info.reg_gcc != INVALID_NUB_REGNUM) 1683 ostrm << "gcc:" << std::dec << reg_entry->nub_info.reg_gcc << ';'; 1684 1685 if (reg_entry->nub_info.reg_dwarf != INVALID_NUB_REGNUM) 1686 ostrm << "dwarf:" << std::dec << reg_entry->nub_info.reg_dwarf << ';'; 1687 1688 1689 switch (reg_entry->nub_info.reg_generic) 1690 { 1691 case GENERIC_REGNUM_FP: ostrm << "generic:fp;"; break; 1692 case GENERIC_REGNUM_PC: ostrm << "generic:pc;"; break; 1693 case GENERIC_REGNUM_SP: ostrm << "generic:sp;"; break; 1694 case GENERIC_REGNUM_RA: ostrm << "generic:ra;"; break; 1695 case GENERIC_REGNUM_FLAGS: ostrm << "generic:flags;"; break; 1696 case GENERIC_REGNUM_ARG1: ostrm << "generic:arg1;"; break; 1697 case GENERIC_REGNUM_ARG2: ostrm << "generic:arg2;"; break; 1698 case GENERIC_REGNUM_ARG3: ostrm << "generic:arg3;"; break; 1699 case GENERIC_REGNUM_ARG4: ostrm << "generic:arg4;"; break; 1700 case GENERIC_REGNUM_ARG5: ostrm << "generic:arg5;"; break; 1701 case GENERIC_REGNUM_ARG6: ostrm << "generic:arg6;"; break; 1702 case GENERIC_REGNUM_ARG7: ostrm << "generic:arg7;"; break; 1703 case GENERIC_REGNUM_ARG8: ostrm << "generic:arg8;"; break; 1704 default: break; 1705 } 1706 1707 if (reg_entry->nub_info.pseudo_regs && reg_entry->nub_info.pseudo_regs[0] != INVALID_NUB_REGNUM) 1708 { 1709 ostrm << "container-regs:"; 1710 for (unsigned i=0; reg_entry->nub_info.pseudo_regs[i] != INVALID_NUB_REGNUM; ++i) 1711 { 1712 if (i > 0) 1713 ostrm << ','; 1714 ostrm << RAW_HEXBASE << reg_entry->nub_info.pseudo_regs[i]; 1715 } 1716 ostrm << ';'; 1717 } 1718 1719 if (reg_entry->nub_info.update_regs && reg_entry->nub_info.update_regs[0] != INVALID_NUB_REGNUM) 1720 { 1721 ostrm << "invalidate-regs:"; 1722 for (unsigned i=0; reg_entry->nub_info.update_regs[i] != INVALID_NUB_REGNUM; ++i) 1723 { 1724 if (i > 0) 1725 ostrm << ','; 1726 ostrm << RAW_HEXBASE << reg_entry->nub_info.update_regs[i]; 1727 } 1728 ostrm << ';'; 1729 } 1730 1731 return SendPacket (ostrm.str ()); 1732 } 1733 return SendPacket ("E45"); 1734} 1735 1736 1737/* This expects a packet formatted like 1738 1739 QSetLogging:bitmask=LOG_ALL|LOG_RNB_REMOTE; 1740 1741 with the "QSetLogging:" already removed from the start. Maybe in the 1742 future this packet will include other keyvalue pairs like 1743 1744 QSetLogging:bitmask=LOG_ALL;mode=asl; 1745 */ 1746 1747rnb_err_t 1748set_logging (const char *p) 1749{ 1750 int bitmask = 0; 1751 while (p && *p != '\0') 1752 { 1753 if (strncmp (p, "bitmask=", sizeof ("bitmask=") - 1) == 0) 1754 { 1755 p += sizeof ("bitmask=") - 1; 1756 while (p && *p != '\0' && *p != ';') 1757 { 1758 if (*p == '|') 1759 p++; 1760 1761// to regenerate the LOG_ entries (not including the LOG_RNB entries) 1762// $ for logname in `grep '^#define LOG_' DNBDefs.h | egrep -v 'LOG_HI|LOG_LO' | awk '{print $2}'` 1763// do 1764// echo " else if (strncmp (p, \"$logname\", sizeof (\"$logname\") - 1) == 0)" 1765// echo " {" 1766// echo " p += sizeof (\"$logname\") - 1;" 1767// echo " bitmask |= $logname;" 1768// echo " }" 1769// done 1770 if (strncmp (p, "LOG_VERBOSE", sizeof ("LOG_VERBOSE") - 1) == 0) 1771 { 1772 p += sizeof ("LOG_VERBOSE") - 1; 1773 bitmask |= LOG_VERBOSE; 1774 } 1775 else if (strncmp (p, "LOG_PROCESS", sizeof ("LOG_PROCESS") - 1) == 0) 1776 { 1777 p += sizeof ("LOG_PROCESS") - 1; 1778 bitmask |= LOG_PROCESS; 1779 } 1780 else if (strncmp (p, "LOG_THREAD", sizeof ("LOG_THREAD") - 1) == 0) 1781 { 1782 p += sizeof ("LOG_THREAD") - 1; 1783 bitmask |= LOG_THREAD; 1784 } 1785 else if (strncmp (p, "LOG_EXCEPTIONS", sizeof ("LOG_EXCEPTIONS") - 1) == 0) 1786 { 1787 p += sizeof ("LOG_EXCEPTIONS") - 1; 1788 bitmask |= LOG_EXCEPTIONS; 1789 } 1790 else if (strncmp (p, "LOG_SHLIB", sizeof ("LOG_SHLIB") - 1) == 0) 1791 { 1792 p += sizeof ("LOG_SHLIB") - 1; 1793 bitmask |= LOG_SHLIB; 1794 } 1795 else if (strncmp (p, "LOG_MEMORY", sizeof ("LOG_MEMORY") - 1) == 0) 1796 { 1797 p += sizeof ("LOG_MEMORY") - 1; 1798 bitmask |= LOG_MEMORY; 1799 } 1800 else if (strncmp (p, "LOG_MEMORY_DATA_SHORT", sizeof ("LOG_MEMORY_DATA_SHORT") - 1) == 0) 1801 { 1802 p += sizeof ("LOG_MEMORY_DATA_SHORT") - 1; 1803 bitmask |= LOG_MEMORY_DATA_SHORT; 1804 } 1805 else if (strncmp (p, "LOG_MEMORY_DATA_LONG", sizeof ("LOG_MEMORY_DATA_LONG") - 1) == 0) 1806 { 1807 p += sizeof ("LOG_MEMORY_DATA_LONG") - 1; 1808 bitmask |= LOG_MEMORY_DATA_LONG; 1809 } 1810 else if (strncmp (p, "LOG_MEMORY_PROTECTIONS", sizeof ("LOG_MEMORY_PROTECTIONS") - 1) == 0) 1811 { 1812 p += sizeof ("LOG_MEMORY_PROTECTIONS") - 1; 1813 bitmask |= LOG_MEMORY_PROTECTIONS; 1814 } 1815 else if (strncmp (p, "LOG_BREAKPOINTS", sizeof ("LOG_BREAKPOINTS") - 1) == 0) 1816 { 1817 p += sizeof ("LOG_BREAKPOINTS") - 1; 1818 bitmask |= LOG_BREAKPOINTS; 1819 } 1820 else if (strncmp (p, "LOG_EVENTS", sizeof ("LOG_EVENTS") - 1) == 0) 1821 { 1822 p += sizeof ("LOG_EVENTS") - 1; 1823 bitmask |= LOG_EVENTS; 1824 } 1825 else if (strncmp (p, "LOG_WATCHPOINTS", sizeof ("LOG_WATCHPOINTS") - 1) == 0) 1826 { 1827 p += sizeof ("LOG_WATCHPOINTS") - 1; 1828 bitmask |= LOG_WATCHPOINTS; 1829 } 1830 else if (strncmp (p, "LOG_STEP", sizeof ("LOG_STEP") - 1) == 0) 1831 { 1832 p += sizeof ("LOG_STEP") - 1; 1833 bitmask |= LOG_STEP; 1834 } 1835 else if (strncmp (p, "LOG_TASK", sizeof ("LOG_TASK") - 1) == 0) 1836 { 1837 p += sizeof ("LOG_TASK") - 1; 1838 bitmask |= LOG_TASK; 1839 } 1840 else if (strncmp (p, "LOG_ALL", sizeof ("LOG_ALL") - 1) == 0) 1841 { 1842 p += sizeof ("LOG_ALL") - 1; 1843 bitmask |= LOG_ALL; 1844 } 1845 else if (strncmp (p, "LOG_DEFAULT", sizeof ("LOG_DEFAULT") - 1) == 0) 1846 { 1847 p += sizeof ("LOG_DEFAULT") - 1; 1848 bitmask |= LOG_DEFAULT; 1849 } 1850// end of auto-generated entries 1851 1852 else if (strncmp (p, "LOG_NONE", sizeof ("LOG_NONE") - 1) == 0) 1853 { 1854 p += sizeof ("LOG_NONE") - 1; 1855 bitmask = 0; 1856 } 1857 else if (strncmp (p, "LOG_RNB_MINIMAL", sizeof ("LOG_RNB_MINIMAL") - 1) == 0) 1858 { 1859 p += sizeof ("LOG_RNB_MINIMAL") - 1; 1860 bitmask |= LOG_RNB_MINIMAL; 1861 } 1862 else if (strncmp (p, "LOG_RNB_MEDIUM", sizeof ("LOG_RNB_MEDIUM") - 1) == 0) 1863 { 1864 p += sizeof ("LOG_RNB_MEDIUM") - 1; 1865 bitmask |= LOG_RNB_MEDIUM; 1866 } 1867 else if (strncmp (p, "LOG_RNB_MAX", sizeof ("LOG_RNB_MAX") - 1) == 0) 1868 { 1869 p += sizeof ("LOG_RNB_MAX") - 1; 1870 bitmask |= LOG_RNB_MAX; 1871 } 1872 else if (strncmp (p, "LOG_RNB_COMM", sizeof ("LOG_RNB_COMM") - 1) == 0) 1873 { 1874 p += sizeof ("LOG_RNB_COMM") - 1; 1875 bitmask |= LOG_RNB_COMM; 1876 } 1877 else if (strncmp (p, "LOG_RNB_REMOTE", sizeof ("LOG_RNB_REMOTE") - 1) == 0) 1878 { 1879 p += sizeof ("LOG_RNB_REMOTE") - 1; 1880 bitmask |= LOG_RNB_REMOTE; 1881 } 1882 else if (strncmp (p, "LOG_RNB_EVENTS", sizeof ("LOG_RNB_EVENTS") - 1) == 0) 1883 { 1884 p += sizeof ("LOG_RNB_EVENTS") - 1; 1885 bitmask |= LOG_RNB_EVENTS; 1886 } 1887 else if (strncmp (p, "LOG_RNB_PROC", sizeof ("LOG_RNB_PROC") - 1) == 0) 1888 { 1889 p += sizeof ("LOG_RNB_PROC") - 1; 1890 bitmask |= LOG_RNB_PROC; 1891 } 1892 else if (strncmp (p, "LOG_RNB_PACKETS", sizeof ("LOG_RNB_PACKETS") - 1) == 0) 1893 { 1894 p += sizeof ("LOG_RNB_PACKETS") - 1; 1895 bitmask |= LOG_RNB_PACKETS; 1896 } 1897 else if (strncmp (p, "LOG_RNB_ALL", sizeof ("LOG_RNB_ALL") - 1) == 0) 1898 { 1899 p += sizeof ("LOG_RNB_ALL") - 1; 1900 bitmask |= LOG_RNB_ALL; 1901 } 1902 else if (strncmp (p, "LOG_RNB_DEFAULT", sizeof ("LOG_RNB_DEFAULT") - 1) == 0) 1903 { 1904 p += sizeof ("LOG_RNB_DEFAULT") - 1; 1905 bitmask |= LOG_RNB_DEFAULT; 1906 } 1907 else if (strncmp (p, "LOG_RNB_NONE", sizeof ("LOG_RNB_NONE") - 1) == 0) 1908 { 1909 p += sizeof ("LOG_RNB_NONE") - 1; 1910 bitmask = 0; 1911 } 1912 else 1913 { 1914 /* Unrecognized logging bit; ignore it. */ 1915 const char *c = strchr (p, '|'); 1916 if (c) 1917 { 1918 p = c; 1919 } 1920 else 1921 { 1922 c = strchr (p, ';'); 1923 if (c) 1924 { 1925 p = c; 1926 } 1927 else 1928 { 1929 // Improperly terminated word; just go to end of str 1930 p = strchr (p, '\0'); 1931 } 1932 } 1933 } 1934 } 1935 // Did we get a properly formatted logging bitmask? 1936 if (p && *p == ';') 1937 { 1938 // Enable DNB logging 1939 DNBLogSetLogCallback(ASLLogCallback, NULL); 1940 DNBLogSetLogMask (bitmask); 1941 p++; 1942 } 1943 } 1944 // We're not going to support logging to a file for now. All logging 1945 // goes through ASL. 1946#if 0 1947 else if (strncmp (p, "mode=", sizeof ("mode=") - 1) == 0) 1948 { 1949 p += sizeof ("mode=") - 1; 1950 if (strncmp (p, "asl;", sizeof ("asl;") - 1) == 0) 1951 { 1952 DNBLogToASL (); 1953 p += sizeof ("asl;") - 1; 1954 } 1955 else if (strncmp (p, "file;", sizeof ("file;") - 1) == 0) 1956 { 1957 DNBLogToFile (); 1958 p += sizeof ("file;") - 1; 1959 } 1960 else 1961 { 1962 // Ignore unknown argument 1963 const char *c = strchr (p, ';'); 1964 if (c) 1965 p = c + 1; 1966 else 1967 p = strchr (p, '\0'); 1968 } 1969 } 1970 else if (strncmp (p, "filename=", sizeof ("filename=") - 1) == 0) 1971 { 1972 p += sizeof ("filename=") - 1; 1973 const char *c = strchr (p, ';'); 1974 if (c == NULL) 1975 { 1976 c = strchr (p, '\0'); 1977 continue; 1978 } 1979 char *fn = (char *) alloca (c - p + 1); 1980 strncpy (fn, p, c - p); 1981 fn[c - p] = '\0'; 1982 1983 // A file name of "asl" is special and is another way to indicate 1984 // that logging should be done via ASL, not by file. 1985 if (strcmp (fn, "asl") == 0) 1986 { 1987 DNBLogToASL (); 1988 } 1989 else 1990 { 1991 FILE *f = fopen (fn, "w"); 1992 if (f) 1993 { 1994 DNBLogSetLogFile (f); 1995 DNBEnableLogging (f, DNBLogGetLogMask ()); 1996 DNBLogToFile (); 1997 } 1998 } 1999 p = c + 1; 2000 } 2001#endif /* #if 0 to enforce ASL logging only. */ 2002 else 2003 { 2004 // Ignore unknown argument 2005 const char *c = strchr (p, ';'); 2006 if (c) 2007 p = c + 1; 2008 else 2009 p = strchr (p, '\0'); 2010 } 2011 } 2012 2013 return rnb_success; 2014} 2015 2016rnb_err_t 2017RNBRemote::HandlePacket_QThreadSuffixSupported (const char *p) 2018{ 2019 m_thread_suffix_supported = true; 2020 return SendPacket ("OK"); 2021} 2022 2023rnb_err_t 2024RNBRemote::HandlePacket_QStartNoAckMode (const char *p) 2025{ 2026 // Send the OK packet first so the correct checksum is appended... 2027 rnb_err_t result = SendPacket ("OK"); 2028 m_noack_mode = true; 2029 return result; 2030} 2031 2032 2033rnb_err_t 2034RNBRemote::HandlePacket_QSetLogging (const char *p) 2035{ 2036 p += sizeof ("QSetLogging:") - 1; 2037 rnb_err_t result = set_logging (p); 2038 if (result == rnb_success) 2039 return SendPacket ("OK"); 2040 else 2041 return SendPacket ("E35"); 2042} 2043 2044rnb_err_t 2045RNBRemote::HandlePacket_QSetDisableASLR (const char *p) 2046{ 2047 extern int g_disable_aslr; 2048 p += sizeof ("QSetDisableASLR:") - 1; 2049 switch (*p) 2050 { 2051 case '0': g_disable_aslr = 0; break; 2052 case '1': g_disable_aslr = 1; break; 2053 default: 2054 return SendPacket ("E56"); 2055 } 2056 return SendPacket ("OK"); 2057} 2058 2059rnb_err_t 2060RNBRemote::HandlePacket_QSetSTDIO (const char *p) 2061{ 2062 // Only set stdin/out/err if we don't already have a process 2063 if (!m_ctx.HasValidProcessID()) 2064 { 2065 bool success = false; 2066 // Check the seventh character since the packet will be one of: 2067 // QSetSTDIN 2068 // QSetSTDOUT 2069 // QSetSTDERR 2070 StringExtractor packet(p); 2071 packet.SetFilePos (7); 2072 char ch = packet.GetChar(); 2073 while (packet.GetChar() != ':') 2074 /* Do nothing. */; 2075 2076 switch (ch) 2077 { 2078 case 'I': // STDIN 2079 packet.GetHexByteString (m_ctx.GetSTDIN()); 2080 success = !m_ctx.GetSTDIN().empty(); 2081 break; 2082 2083 case 'O': // STDOUT 2084 packet.GetHexByteString (m_ctx.GetSTDOUT()); 2085 success = !m_ctx.GetSTDOUT().empty(); 2086 break; 2087 2088 case 'E': // STDERR 2089 packet.GetHexByteString (m_ctx.GetSTDERR()); 2090 success = !m_ctx.GetSTDERR().empty(); 2091 break; 2092 2093 default: 2094 break; 2095 } 2096 if (success) 2097 return SendPacket ("OK"); 2098 return SendPacket ("E57"); 2099 } 2100 return SendPacket ("E58"); 2101} 2102 2103rnb_err_t 2104RNBRemote::HandlePacket_QSetWorkingDir (const char *p) 2105{ 2106 // Only set the working directory if we don't already have a process 2107 if (!m_ctx.HasValidProcessID()) 2108 { 2109 StringExtractor packet(p += sizeof ("QSetWorkingDir:") - 1); 2110 if (packet.GetHexByteString (m_ctx.GetWorkingDir())) 2111 { 2112 struct stat working_dir_stat; 2113 if (::stat(m_ctx.GetWorkingDirPath(), &working_dir_stat) == -1) 2114 { 2115 m_ctx.GetWorkingDir().clear(); 2116 return SendPacket ("E61"); // Working directory doesn't exist... 2117 } 2118 else if ((working_dir_stat.st_mode & S_IFMT) == S_IFDIR) 2119 { 2120 return SendPacket ("OK"); 2121 } 2122 else 2123 { 2124 m_ctx.GetWorkingDir().clear(); 2125 return SendPacket ("E62"); // Working directory isn't a directory... 2126 } 2127 } 2128 return SendPacket ("E59"); // Invalid path 2129 } 2130 return SendPacket ("E60"); // Already had a process, too late to set working dir 2131} 2132 2133rnb_err_t 2134RNBRemote::HandlePacket_QSyncThreadState (const char *p) 2135{ 2136 if (!m_ctx.HasValidProcessID()) 2137 { 2138 // We allow gdb to connect to a server that hasn't started running 2139 // the target yet. gdb still wants to ask questions about it and 2140 // freaks out if it gets an error. So just return OK here. 2141 return SendPacket ("OK"); 2142 } 2143 2144 errno = 0; 2145 p += strlen("QSyncThreadState:"); 2146 nub_thread_t tid = strtoul (p, NULL, 16); 2147 if (errno != 0 && tid == 0) 2148 { 2149 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid thread number in QSyncThreadState packet"); 2150 } 2151 if (DNBProcessSyncThreadState(m_ctx.ProcessID(), tid)) 2152 return SendPacket("OK"); 2153 else 2154 return SendPacket ("E61"); 2155} 2156 2157rnb_err_t 2158RNBRemote::HandlePacket_QListThreadsInStopReply (const char *p) 2159{ 2160 // If this packet is received, it allows us to send an extra key/value 2161 // pair in the stop reply packets where we will list all of the thread IDs 2162 // separated by commas: 2163 // 2164 // "threads:10a,10b,10c;" 2165 // 2166 // This will get included in the stop reply packet as something like: 2167 // 2168 // "T11thread:10a;00:00000000;01:00010203:threads:10a,10b,10c;" 2169 // 2170 // This can save two packets on each stop: qfThreadInfo/qsThreadInfo and 2171 // speed things up a bit. 2172 // 2173 // Send the OK packet first so the correct checksum is appended... 2174 rnb_err_t result = SendPacket ("OK"); 2175 m_list_threads_in_stop_reply = true; 2176 return result; 2177} 2178 2179 2180rnb_err_t 2181RNBRemote::HandlePacket_QSetMaxPayloadSize (const char *p) 2182{ 2183 /* The number of characters in a packet payload that gdb is 2184 prepared to accept. The packet-start char, packet-end char, 2185 2 checksum chars and terminating null character are not included 2186 in this size. */ 2187 p += sizeof ("QSetMaxPayloadSize:") - 1; 2188 errno = 0; 2189 uint32_t size = strtoul (p, NULL, 16); 2190 if (errno != 0 && size == 0) 2191 { 2192 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPayloadSize packet"); 2193 } 2194 m_max_payload_size = size; 2195 return SendPacket ("OK"); 2196} 2197 2198rnb_err_t 2199RNBRemote::HandlePacket_QSetMaxPacketSize (const char *p) 2200{ 2201 /* This tells us the largest packet that gdb can handle. 2202 i.e. the size of gdb's packet-reading buffer. 2203 QSetMaxPayloadSize is preferred because it is less ambiguous. */ 2204 p += sizeof ("QSetMaxPacketSize:") - 1; 2205 errno = 0; 2206 uint32_t size = strtoul (p, NULL, 16); 2207 if (errno != 0 && size == 0) 2208 { 2209 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in QSetMaxPacketSize packet"); 2210 } 2211 m_max_payload_size = size - 5; 2212 return SendPacket ("OK"); 2213} 2214 2215 2216 2217 2218rnb_err_t 2219RNBRemote::HandlePacket_QEnvironment (const char *p) 2220{ 2221 /* This sets the environment for the target program. The packet is of the form: 2222 2223 QEnvironment:VARIABLE=VALUE 2224 2225 */ 2226 2227 DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironment: \"%s\"", 2228 (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); 2229 2230 p += sizeof ("QEnvironment:") - 1; 2231 RNBContext& ctx = Context(); 2232 2233 ctx.PushEnvironment (p); 2234 return SendPacket ("OK"); 2235} 2236 2237rnb_err_t 2238RNBRemote::HandlePacket_QEnvironmentHexEncoded (const char *p) 2239{ 2240 /* This sets the environment for the target program. The packet is of the form: 2241 2242 QEnvironmentHexEncoded:VARIABLE=VALUE 2243 2244 The VARIABLE=VALUE part is sent hex-encoded so chracters like '#' with special 2245 meaning in the remote protocol won't break it. 2246 */ 2247 2248 DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s Handling QEnvironmentHexEncoded: \"%s\"", 2249 (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__, p); 2250 2251 p += sizeof ("QEnvironmentHexEncoded:") - 1; 2252 2253 std::string arg; 2254 const char *c; 2255 c = p; 2256 while (*c != '\0') 2257 { 2258 if (*(c + 1) == '\0') 2259 { 2260 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); 2261 } 2262 char smallbuf[3]; 2263 smallbuf[0] = *c; 2264 smallbuf[1] = *(c + 1); 2265 smallbuf[2] = '\0'; 2266 errno = 0; 2267 int ch = strtoul (smallbuf, NULL, 16); 2268 if (errno != 0 && ch == 0) 2269 { 2270 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'QEnvironmentHexEncoded' pkt"); 2271 } 2272 arg.push_back(ch); 2273 c += 2; 2274 } 2275 2276 RNBContext& ctx = Context(); 2277 if (arg.length() > 0) 2278 ctx.PushEnvironment (arg.c_str()); 2279 2280 return SendPacket ("OK"); 2281} 2282 2283 2284rnb_err_t 2285RNBRemote::HandlePacket_QLaunchArch (const char *p) 2286{ 2287 p += sizeof ("QLaunchArch:") - 1; 2288 if (DNBSetArchitecture(p)) 2289 return SendPacket ("OK"); 2290 return SendPacket ("E63"); 2291} 2292 2293void 2294append_hex_value (std::ostream& ostrm, const uint8_t* buf, size_t buf_size, bool swap) 2295{ 2296 int i; 2297 if (swap) 2298 { 2299 for (i = buf_size-1; i >= 0; i--) 2300 ostrm << RAWHEX8(buf[i]); 2301 } 2302 else 2303 { 2304 for (i = 0; i < buf_size; i++) 2305 ostrm << RAWHEX8(buf[i]); 2306 } 2307} 2308 2309 2310void 2311register_value_in_hex_fixed_width (std::ostream& ostrm, 2312 nub_process_t pid, 2313 nub_thread_t tid, 2314 const register_map_entry_t* reg, 2315 const DNBRegisterValue *reg_value_ptr) 2316{ 2317 if (reg != NULL) 2318 { 2319 DNBRegisterValue reg_value; 2320 if (reg_value_ptr == NULL) 2321 { 2322 if (DNBThreadGetRegisterValueByID (pid, tid, reg->nub_info.set, reg->nub_info.reg, ®_value)) 2323 reg_value_ptr = ®_value; 2324 } 2325 2326 if (reg_value_ptr) 2327 { 2328 append_hex_value (ostrm, reg_value_ptr->value.v_uint8, reg->gdb_size, false); 2329 } 2330 else 2331 { 2332 // If we fail to read a regiser value, check if it has a default 2333 // fail value. If it does, return this instead in case some of 2334 // the registers are not available on the current system. 2335 if (reg->gdb_size > 0) 2336 { 2337 if (reg->fail_value != NULL) 2338 { 2339 append_hex_value (ostrm, reg->fail_value, reg->gdb_size, false); 2340 } 2341 else 2342 { 2343 std::basic_string<uint8_t> zeros(reg->gdb_size, '\0'); 2344 append_hex_value (ostrm, zeros.data(), zeros.size(), false); 2345 } 2346 } 2347 } 2348 } 2349} 2350 2351 2352void 2353gdb_regnum_with_fixed_width_hex_register_value (std::ostream& ostrm, 2354 nub_process_t pid, 2355 nub_thread_t tid, 2356 const register_map_entry_t* reg, 2357 const DNBRegisterValue *reg_value_ptr) 2358{ 2359 // Output the register number as 'NN:VVVVVVVV;' where NN is a 2 bytes HEX 2360 // gdb register number, and VVVVVVVV is the correct number of hex bytes 2361 // as ASCII for the register value. 2362 if (reg != NULL) 2363 { 2364 ostrm << RAWHEX8(reg->gdb_regnum) << ':'; 2365 register_value_in_hex_fixed_width (ostrm, pid, tid, reg, reg_value_ptr); 2366 ostrm << ';'; 2367 } 2368} 2369 2370rnb_err_t 2371RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid) 2372{ 2373 const nub_process_t pid = m_ctx.ProcessID(); 2374 if (pid == INVALID_NUB_PROCESS) 2375 return SendPacket("E50"); 2376 2377 struct DNBThreadStopInfo tid_stop_info; 2378 2379 /* Fill the remaining space in this packet with as many registers 2380 as we can stuff in there. */ 2381 2382 if (DNBThreadGetStopReason (pid, tid, &tid_stop_info)) 2383 { 2384 std::ostringstream ostrm; 2385 // Output the T packet with the thread 2386 ostrm << 'T'; 2387 int signum = tid_stop_info.details.signal.signo; 2388 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); 2389 2390 // Translate any mach exceptions to gdb versions, unless they are 2391 // common exceptions like a breakpoint or a soft signal. 2392 switch (tid_stop_info.details.exception.type) 2393 { 2394 default: signum = 0; break; 2395 case EXC_BREAKPOINT: signum = SIGTRAP; break; 2396 case EXC_BAD_ACCESS: signum = TARGET_EXC_BAD_ACCESS; break; 2397 case EXC_BAD_INSTRUCTION: signum = TARGET_EXC_BAD_INSTRUCTION; break; 2398 case EXC_ARITHMETIC: signum = TARGET_EXC_ARITHMETIC; break; 2399 case EXC_EMULATION: signum = TARGET_EXC_EMULATION; break; 2400 case EXC_SOFTWARE: 2401 if (tid_stop_info.details.exception.data_count == 2 && 2402 tid_stop_info.details.exception.data[0] == EXC_SOFT_SIGNAL) 2403 signum = tid_stop_info.details.exception.data[1]; 2404 else 2405 signum = TARGET_EXC_SOFTWARE; 2406 break; 2407 } 2408 2409 ostrm << RAWHEX8(signum & 0xff); 2410 2411 ostrm << std::hex << "thread:" << tid << ';'; 2412 2413 const char *thread_name = DNBThreadGetName (pid, tid); 2414 if (thread_name && thread_name[0]) 2415 { 2416 size_t thread_name_len = strlen(thread_name); 2417 2418 if (::strcspn (thread_name, "$#+-;:") == thread_name_len) 2419 ostrm << std::hex << "name:" << thread_name << ';'; 2420 else 2421 { 2422 // the thread name contains special chars, send as hex bytes 2423 ostrm << std::hex << "hexname:"; 2424 uint8_t *u_thread_name = (uint8_t *)thread_name; 2425 for (int i = 0; i < thread_name_len; i++) 2426 ostrm << RAWHEX8(u_thread_name[i]); 2427 ostrm << ';'; 2428 } 2429 } 2430 2431 thread_identifier_info_data_t thread_ident_info; 2432 if (DNBThreadGetIdentifierInfo (pid, tid, &thread_ident_info)) 2433 { 2434 if (thread_ident_info.dispatch_qaddr != 0) 2435 ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';'; 2436 } 2437 2438 // If a 'QListThreadsInStopReply' was sent to enable this feature, we 2439 // will send all thread IDs back in the "threads" key whose value is 2440 // a listc of hex thread IDs separated by commas: 2441 // "threads:10a,10b,10c;" 2442 // This will save the debugger from having to send a pair of qfThreadInfo 2443 // and qsThreadInfo packets, but it also might take a lot of room in the 2444 // stop reply packet, so it must be enabled only on systems where there 2445 // are no limits on packet lengths. 2446 2447 if (m_list_threads_in_stop_reply) 2448 { 2449 const nub_size_t numthreads = DNBProcessGetNumThreads (pid); 2450 if (numthreads > 0) 2451 { 2452 ostrm << std::hex << "threads:"; 2453 for (nub_size_t i = 0; i < numthreads; ++i) 2454 { 2455 nub_thread_t th = DNBProcessGetThreadAtIndex (pid, i); 2456 if (i > 0) 2457 ostrm << ','; 2458 ostrm << std::hex << th; 2459 } 2460 ostrm << ';'; 2461 } 2462 } 2463 2464 if (g_num_reg_entries == 0) 2465 InitializeRegisters (); 2466 2467 if (g_reg_entries != NULL) 2468 { 2469 DNBRegisterValue reg_value; 2470 for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) 2471 { 2472 if (g_reg_entries[reg].expedite) 2473 { 2474 if (!DNBThreadGetRegisterValueByID (pid, tid, g_reg_entries[reg].nub_info.set, g_reg_entries[reg].nub_info.reg, ®_value)) 2475 continue; 2476 2477 gdb_regnum_with_fixed_width_hex_register_value (ostrm, pid, tid, &g_reg_entries[reg], ®_value); 2478 } 2479 } 2480 } 2481 2482 if (tid_stop_info.details.exception.type) 2483 { 2484 ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";"; 2485 ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";"; 2486 for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i) 2487 ostrm << "medata:" << std::hex << tid_stop_info.details.exception.data[i] << ";"; 2488 } 2489 return SendPacket (ostrm.str ()); 2490 } 2491 return SendPacket("E51"); 2492} 2493 2494/* '?' 2495 The stop reply packet - tell gdb what the status of the inferior is. 2496 Often called the questionmark_packet. */ 2497 2498rnb_err_t 2499RNBRemote::HandlePacket_last_signal (const char *unused) 2500{ 2501 if (!m_ctx.HasValidProcessID()) 2502 { 2503 // Inferior is not yet specified/running 2504 return SendPacket ("E02"); 2505 } 2506 2507 nub_process_t pid = m_ctx.ProcessID(); 2508 nub_state_t pid_state = DNBProcessGetState (pid); 2509 2510 switch (pid_state) 2511 { 2512 case eStateAttaching: 2513 case eStateLaunching: 2514 case eStateRunning: 2515 case eStateStepping: 2516 case eStateDetached: 2517 return rnb_success; // Ignore 2518 2519 case eStateSuspended: 2520 case eStateStopped: 2521 case eStateCrashed: 2522 { 2523 nub_thread_t tid = DNBProcessGetCurrentThread (pid); 2524 // Make sure we set the current thread so g and p packets return 2525 // the data the gdb will expect. 2526 SetCurrentThread (tid); 2527 2528 SendStopReplyPacketForThread (tid); 2529 } 2530 break; 2531 2532 case eStateInvalid: 2533 case eStateUnloaded: 2534 case eStateExited: 2535 { 2536 char pid_exited_packet[16] = ""; 2537 int pid_status = 0; 2538 // Process exited with exit status 2539 if (!DNBProcessGetExitStatus(pid, &pid_status)) 2540 pid_status = 0; 2541 2542 if (pid_status) 2543 { 2544 if (WIFEXITED (pid_status)) 2545 snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status)); 2546 else if (WIFSIGNALED (pid_status)) 2547 snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status)); 2548 else if (WIFSTOPPED (pid_status)) 2549 snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status)); 2550 } 2551 2552 // If we have an empty exit packet, lets fill one in to be safe. 2553 if (!pid_exited_packet[0]) 2554 { 2555 strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1); 2556 pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0'; 2557 } 2558 2559 return SendPacket (pid_exited_packet); 2560 } 2561 break; 2562 } 2563 return rnb_success; 2564} 2565 2566rnb_err_t 2567RNBRemote::HandlePacket_M (const char *p) 2568{ 2569 if (p == NULL || p[0] == '\0' || strlen (p) < 3) 2570 { 2571 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short M packet"); 2572 } 2573 2574 char *c; 2575 p++; 2576 errno = 0; 2577 nub_addr_t addr = strtoull (p, &c, 16); 2578 if (errno != 0 && addr == 0) 2579 { 2580 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in M packet"); 2581 } 2582 if (*c != ',') 2583 { 2584 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in M packet"); 2585 } 2586 2587 /* Advance 'p' to the length part of the packet. */ 2588 p += (c - p) + 1; 2589 2590 errno = 0; 2591 uint32_t length = strtoul (p, &c, 16); 2592 if (errno != 0 && length == 0) 2593 { 2594 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in M packet"); 2595 } 2596 if (length == 0) 2597 { 2598 return SendPacket ("OK"); 2599 } 2600 2601 if (*c != ':') 2602 { 2603 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Missing colon in M packet"); 2604 } 2605 /* Advance 'p' to the data part of the packet. */ 2606 p += (c - p) + 1; 2607 2608 int datalen = strlen (p); 2609 if (datalen & 0x1) 2610 { 2611 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Uneven # of hex chars for data in M packet"); 2612 } 2613 if (datalen == 0) 2614 { 2615 return SendPacket ("OK"); 2616 } 2617 2618 uint8_t *buf = (uint8_t *) alloca (datalen / 2); 2619 uint8_t *i = buf; 2620 2621 while (*p != '\0' && *(p + 1) != '\0') 2622 { 2623 char hexbuf[3]; 2624 hexbuf[0] = *p; 2625 hexbuf[1] = *(p + 1); 2626 hexbuf[2] = '\0'; 2627 errno = 0; 2628 uint8_t byte = strtoul (hexbuf, NULL, 16); 2629 if (errno != 0 && byte == 0) 2630 { 2631 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid hex byte in M packet"); 2632 } 2633 *i++ = byte; 2634 p += 2; 2635 } 2636 2637 nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, length, buf); 2638 if (wrote != length) 2639 return SendPacket ("E09"); 2640 else 2641 return SendPacket ("OK"); 2642} 2643 2644 2645rnb_err_t 2646RNBRemote::HandlePacket_m (const char *p) 2647{ 2648 if (p == NULL || p[0] == '\0' || strlen (p) < 3) 2649 { 2650 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short m packet"); 2651 } 2652 2653 char *c; 2654 p++; 2655 errno = 0; 2656 nub_addr_t addr = strtoull (p, &c, 16); 2657 if (errno != 0 && addr == 0) 2658 { 2659 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in m packet"); 2660 } 2661 if (*c != ',') 2662 { 2663 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in m packet"); 2664 } 2665 2666 /* Advance 'p' to the length part of the packet. */ 2667 p += (c - p) + 1; 2668 2669 errno = 0; 2670 uint32_t length = strtoul (p, NULL, 16); 2671 if (errno != 0 && length == 0) 2672 { 2673 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet"); 2674 } 2675 if (length == 0) 2676 { 2677 return SendPacket (""); 2678 } 2679 2680 uint8_t buf[length]; 2681 int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, length, buf); 2682 if (bytes_read == 0) 2683 { 2684 return SendPacket ("E08"); 2685 } 2686 2687 // "The reply may contain fewer bytes than requested if the server was able 2688 // to read only part of the region of memory." 2689 length = bytes_read; 2690 2691 std::ostringstream ostrm; 2692 for (int i = 0; i < length; i++) 2693 ostrm << RAWHEX8(buf[i]); 2694 return SendPacket (ostrm.str ()); 2695} 2696 2697rnb_err_t 2698RNBRemote::HandlePacket_X (const char *p) 2699{ 2700 if (p == NULL || p[0] == '\0' || strlen (p) < 3) 2701 { 2702 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet"); 2703 } 2704 2705 char *c; 2706 p++; 2707 errno = 0; 2708 nub_addr_t addr = strtoull (p, &c, 16); 2709 if (errno != 0 && addr == 0) 2710 { 2711 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet"); 2712 } 2713 if (*c != ',') 2714 { 2715 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet"); 2716 } 2717 2718 /* Advance 'p' to the length part of the packet. */ 2719 p += (c - p) + 1; 2720 2721 errno = 0; 2722 int length = strtoul (p, NULL, 16); 2723 if (errno != 0 && length == 0) 2724 { 2725 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet"); 2726 } 2727 2728 // I think gdb sends a zero length write request to test whether this 2729 // packet is accepted. 2730 if (length == 0) 2731 { 2732 return SendPacket ("OK"); 2733 } 2734 2735 std::vector<uint8_t> data = decode_binary_data (c, -1); 2736 std::vector<uint8_t>::const_iterator it; 2737 uint8_t *buf = (uint8_t *) alloca (data.size ()); 2738 uint8_t *i = buf; 2739 for (it = data.begin (); it != data.end (); ++it) 2740 { 2741 *i++ = *it; 2742 } 2743 2744 nub_size_t wrote = DNBProcessMemoryWrite (m_ctx.ProcessID(), addr, data.size(), buf); 2745 if (wrote != data.size ()) 2746 return SendPacket ("E08"); 2747 return SendPacket ("OK"); 2748} 2749 2750/* 'g' -- read registers 2751 Get the contents of the registers for the current thread, 2752 send them to gdb. 2753 Should the setting of the Hg packet determine which thread's registers 2754 are returned? */ 2755 2756rnb_err_t 2757RNBRemote::HandlePacket_g (const char *p) 2758{ 2759 std::ostringstream ostrm; 2760 if (!m_ctx.HasValidProcessID()) 2761 { 2762 return SendPacket ("E11"); 2763 } 2764 2765 if (g_num_reg_entries == 0) 2766 InitializeRegisters (); 2767 2768 nub_process_t pid = m_ctx.ProcessID (); 2769 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p + 1); 2770 if (tid == INVALID_NUB_THREAD) 2771 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 2772 2773 if (m_use_native_regs) 2774 { 2775 // Get the register context size first by calling with NULL buffer 2776 nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); 2777 if (reg_ctx_size) 2778 { 2779 // Now allocate enough space for the entire register context 2780 std::vector<uint8_t> reg_ctx; 2781 reg_ctx.resize(reg_ctx_size); 2782 // Now read the register context 2783 reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, ®_ctx[0], reg_ctx.size()); 2784 if (reg_ctx_size) 2785 { 2786 append_hex_value (ostrm, reg_ctx.data(), reg_ctx.size(), false); 2787 return SendPacket (ostrm.str ()); 2788 } 2789 } 2790 } 2791 2792 for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) 2793 register_value_in_hex_fixed_width (ostrm, pid, tid, &g_reg_entries[reg], NULL); 2794 2795 return SendPacket (ostrm.str ()); 2796} 2797 2798/* 'G XXX...' -- write registers 2799 How is the thread for these specified, beyond "the current thread"? 2800 Does gdb actually use the Hg packet to set this? */ 2801 2802rnb_err_t 2803RNBRemote::HandlePacket_G (const char *p) 2804{ 2805 if (!m_ctx.HasValidProcessID()) 2806 { 2807 return SendPacket ("E11"); 2808 } 2809 2810 if (g_num_reg_entries == 0) 2811 InitializeRegisters (); 2812 2813 StringExtractor packet(p); 2814 packet.SetFilePos(1); // Skip the 'G' 2815 2816 nub_process_t pid = m_ctx.ProcessID(); 2817 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); 2818 if (tid == INVALID_NUB_THREAD) 2819 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 2820 2821 if (m_use_native_regs) 2822 { 2823 // Get the register context size first by calling with NULL buffer 2824 nub_size_t reg_ctx_size = DNBThreadGetRegisterContext(pid, tid, NULL, 0); 2825 if (reg_ctx_size) 2826 { 2827 // Now allocate enough space for the entire register context 2828 std::vector<uint8_t> reg_ctx; 2829 reg_ctx.resize(reg_ctx_size); 2830 2831 const nub_size_t bytes_extracted = packet.GetHexBytes (®_ctx[0], reg_ctx.size(), 0xcc); 2832 if (bytes_extracted == reg_ctx.size()) 2833 { 2834 // Now write the register context 2835 reg_ctx_size = DNBThreadSetRegisterContext(pid, tid, reg_ctx.data(), reg_ctx.size()); 2836 if (reg_ctx_size == reg_ctx.size()) 2837 return SendPacket ("OK"); 2838 else 2839 return SendPacket ("E55"); 2840 } 2841 else 2842 { 2843 DNBLogError("RNBRemote::HandlePacket_G(%s): extracted %llu of %llu bytes, size mismatch\n", p, (uint64_t)bytes_extracted, (uint64_t)reg_ctx_size); 2844 return SendPacket ("E64"); 2845 } 2846 } 2847 else 2848 return SendPacket ("E65"); 2849 } 2850 2851 2852 DNBRegisterValue reg_value; 2853 for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) 2854 { 2855 const register_map_entry_t *reg_entry = &g_reg_entries[reg]; 2856 2857 reg_value.info = reg_entry->nub_info; 2858 if (packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc) != reg_entry->gdb_size) 2859 break; 2860 2861 if (reg_entry->fail_value == NULL) 2862 { 2863 if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, ®_value)) 2864 return SendPacket ("E15"); 2865 } 2866 } 2867 return SendPacket ("OK"); 2868} 2869 2870static bool 2871RNBRemoteShouldCancelCallback (void *not_used) 2872{ 2873 RNBRemoteSP remoteSP(g_remoteSP); 2874 if (remoteSP.get() != NULL) 2875 { 2876 RNBRemote* remote = remoteSP.get(); 2877 if (remote->Comm().IsConnected()) 2878 return false; 2879 else 2880 return true; 2881 } 2882 return true; 2883} 2884 2885 2886// FORMAT: _MXXXXXX,PPP 2887// XXXXXX: big endian hex chars 2888// PPP: permissions can be any combo of r w x chars 2889// 2890// RESPONSE: XXXXXX 2891// XXXXXX: hex address of the newly allocated memory 2892// EXX: error code 2893// 2894// EXAMPLES: 2895// _M123000,rw 2896// _M123000,rwx 2897// _M123000,xw 2898 2899rnb_err_t 2900RNBRemote::HandlePacket_AllocateMemory (const char *p) 2901{ 2902 StringExtractor packet (p); 2903 packet.SetFilePos(2); // Skip the "_M" 2904 2905 nub_addr_t size = packet.GetHexMaxU64 (StringExtractor::BigEndian, 0); 2906 if (size != 0) 2907 { 2908 if (packet.GetChar() == ',') 2909 { 2910 uint32_t permissions = 0; 2911 char ch; 2912 bool success = true; 2913 while (success && (ch = packet.GetChar()) != '\0') 2914 { 2915 switch (ch) 2916 { 2917 case 'r': permissions |= eMemoryPermissionsReadable; break; 2918 case 'w': permissions |= eMemoryPermissionsWritable; break; 2919 case 'x': permissions |= eMemoryPermissionsExecutable; break; 2920 default: success = false; break; 2921 } 2922 } 2923 2924 if (success) 2925 { 2926 nub_addr_t addr = DNBProcessMemoryAllocate (m_ctx.ProcessID(), size, permissions); 2927 if (addr != INVALID_NUB_ADDRESS) 2928 { 2929 std::ostringstream ostrm; 2930 ostrm << RAW_HEXBASE << addr; 2931 return SendPacket (ostrm.str ()); 2932 } 2933 } 2934 } 2935 } 2936 return SendPacket ("E53"); 2937} 2938 2939// FORMAT: _mXXXXXX 2940// XXXXXX: address that was previosly allocated 2941// 2942// RESPONSE: XXXXXX 2943// OK: address was deallocated 2944// EXX: error code 2945// 2946// EXAMPLES: 2947// _m123000 2948 2949rnb_err_t 2950RNBRemote::HandlePacket_DeallocateMemory (const char *p) 2951{ 2952 StringExtractor packet (p); 2953 packet.SetFilePos(2); // Skip the "_m" 2954 nub_addr_t addr = packet.GetHexMaxU64 (StringExtractor::BigEndian, INVALID_NUB_ADDRESS); 2955 2956 if (addr != INVALID_NUB_ADDRESS) 2957 { 2958 if (DNBProcessMemoryDeallocate (m_ctx.ProcessID(), addr)) 2959 return SendPacket ("OK"); 2960 } 2961 return SendPacket ("E54"); 2962} 2963 2964static bool 2965GetProcessNameFrom_vAttach (const char *&p, std::string &attach_name) 2966{ 2967 bool return_val = true; 2968 while (*p != '\0') 2969 { 2970 char smallbuf[3]; 2971 smallbuf[0] = *p; 2972 smallbuf[1] = *(p + 1); 2973 smallbuf[2] = '\0'; 2974 2975 errno = 0; 2976 int ch = strtoul (smallbuf, NULL, 16); 2977 if (errno != 0 && ch == 0) 2978 { 2979 return_val = false; 2980 break; 2981 } 2982 2983 attach_name.push_back(ch); 2984 p += 2; 2985 } 2986 return return_val; 2987} 2988 2989/* 2990 vAttach;pid 2991 2992 Attach to a new process with the specified process ID. pid is a hexadecimal integer 2993 identifying the process. If the stub is currently controlling a process, it is 2994 killed. The attached process is stopped.This packet is only available in extended 2995 mode (see extended mode). 2996 2997 Reply: 2998 "ENN" for an error 2999 "Any Stop Reply Packet" for success 3000 */ 3001 3002rnb_err_t 3003RNBRemote::HandlePacket_v (const char *p) 3004{ 3005 if (strcmp (p, "vCont;c") == 0) 3006 { 3007 // Simple continue 3008 return RNBRemote::HandlePacket_c("c"); 3009 } 3010 else if (strcmp (p, "vCont;s") == 0) 3011 { 3012 // Simple step 3013 return RNBRemote::HandlePacket_s("s"); 3014 } 3015 else if (strstr (p, "vCont") == p) 3016 { 3017 typedef struct 3018 { 3019 nub_thread_t tid; 3020 char action; 3021 int signal; 3022 } vcont_action_t; 3023 3024 DNBThreadResumeActions thread_actions; 3025 char *c = (char *)(p += strlen("vCont")); 3026 char *c_end = c + strlen(c); 3027 if (*c == '?') 3028 return SendPacket ("vCont;c;C;s;S"); 3029 3030 while (c < c_end && *c == ';') 3031 { 3032 ++c; // Skip the semi-colon 3033 DNBThreadResumeAction thread_action; 3034 thread_action.tid = INVALID_NUB_THREAD; 3035 thread_action.state = eStateInvalid; 3036 thread_action.signal = 0; 3037 thread_action.addr = INVALID_NUB_ADDRESS; 3038 3039 char action = *c++; 3040 3041 switch (action) 3042 { 3043 case 'C': 3044 errno = 0; 3045 thread_action.signal = strtoul (c, &c, 16); 3046 if (errno != 0) 3047 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet"); 3048 // Fall through to next case... 3049 3050 case 'c': 3051 // Continue 3052 thread_action.state = eStateRunning; 3053 break; 3054 3055 case 'S': 3056 errno = 0; 3057 thread_action.signal = strtoul (c, &c, 16); 3058 if (errno != 0) 3059 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in vCont packet"); 3060 // Fall through to next case... 3061 3062 case 's': 3063 // Step 3064 thread_action.state = eStateStepping; 3065 break; 3066 3067 default: 3068 HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Unsupported action in vCont packet"); 3069 break; 3070 } 3071 if (*c == ':') 3072 { 3073 errno = 0; 3074 thread_action.tid = strtoul (++c, &c, 16); 3075 if (errno != 0) 3076 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in vCont packet"); 3077 } 3078 3079 thread_actions.Append (thread_action); 3080 } 3081 3082 // If a default action for all other threads wasn't mentioned 3083 // then we should stop the threads 3084 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); 3085 DNBProcessResume(m_ctx.ProcessID(), thread_actions.GetFirst (), thread_actions.GetSize()); 3086 return rnb_success; 3087 } 3088 else if (strstr (p, "vAttach") == p) 3089 { 3090 nub_process_t attach_pid = INVALID_NUB_PROCESS; 3091 char err_str[1024]={'\0'}; 3092 3093 if (strstr (p, "vAttachWait;") == p) 3094 { 3095 p += strlen("vAttachWait;"); 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 'vAttachWait' pkt"); 3100 } 3101 const bool ignore_existing = true; 3102 attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); 3103 3104 } 3105 else if (strstr (p, "vAttachOrWait;") == p) 3106 { 3107 p += strlen("vAttachOrWait;"); 3108 std::string attach_name; 3109 if (!GetProcessNameFrom_vAttach(p, attach_name)) 3110 { 3111 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachOrWait' pkt"); 3112 } 3113 const bool ignore_existing = false; 3114 attach_pid = DNBProcessAttachWait(attach_name.c_str (), m_ctx.LaunchFlavor(), ignore_existing, NULL, 1000, err_str, sizeof(err_str), RNBRemoteShouldCancelCallback); 3115 } 3116 else if (strstr (p, "vAttachName;") == p) 3117 { 3118 p += strlen("vAttachName;"); 3119 std::string attach_name; 3120 if (!GetProcessNameFrom_vAttach(p, attach_name)) 3121 { 3122 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "non-hex char in arg on 'vAttachName' pkt"); 3123 } 3124 3125 attach_pid = DNBProcessAttachByName (attach_name.c_str(), NULL, err_str, sizeof(err_str)); 3126 3127 } 3128 else if (strstr (p, "vAttach;") == p) 3129 { 3130 p += strlen("vAttach;"); 3131 char *end = NULL; 3132 attach_pid = strtoul (p, &end, 16); // PID will be in hex, so use base 16 to decode 3133 if (p != end && *end == '\0') 3134 { 3135 // Wait at most 30 second for attach 3136 struct timespec attach_timeout_abstime; 3137 DNBTimer::OffsetTimeOfDay(&attach_timeout_abstime, 30, 0); 3138 attach_pid = DNBProcessAttach(attach_pid, &attach_timeout_abstime, err_str, sizeof(err_str)); 3139 } 3140 } 3141 else 3142 { 3143 return HandlePacket_UNIMPLEMENTED(p); 3144 } 3145 3146 3147 if (attach_pid != INVALID_NUB_PROCESS) 3148 { 3149 if (m_ctx.ProcessID() != attach_pid) 3150 m_ctx.SetProcessID(attach_pid); 3151 // Send a stop reply packet to indicate we successfully attached! 3152 NotifyThatProcessStopped (); 3153 return rnb_success; 3154 } 3155 else 3156 { 3157 m_ctx.LaunchStatus().SetError(-1, DNBError::Generic); 3158 if (err_str[0]) 3159 m_ctx.LaunchStatus().SetErrorString(err_str); 3160 else 3161 m_ctx.LaunchStatus().SetErrorString("attach failed"); 3162 return SendPacket ("E01"); // E01 is our magic error value for attach failed. 3163 } 3164 } 3165 3166 // All other failures come through here 3167 return HandlePacket_UNIMPLEMENTED(p); 3168} 3169 3170/* 'T XX' -- status of thread 3171 Check if the specified thread is alive. 3172 The thread number is in hex? */ 3173 3174rnb_err_t 3175RNBRemote::HandlePacket_T (const char *p) 3176{ 3177 p++; 3178 if (p == NULL || *p == '\0') 3179 { 3180 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in T packet"); 3181 } 3182 if (!m_ctx.HasValidProcessID()) 3183 { 3184 return SendPacket ("E15"); 3185 } 3186 errno = 0; 3187 nub_thread_t tid = strtoul (p, NULL, 16); 3188 if (errno != 0 && tid == 0) 3189 { 3190 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse thread number in T packet"); 3191 } 3192 3193 nub_state_t state = DNBThreadGetState (m_ctx.ProcessID(), tid); 3194 if (state == eStateInvalid || state == eStateExited || state == eStateCrashed) 3195 { 3196 return SendPacket ("E16"); 3197 } 3198 3199 return SendPacket ("OK"); 3200} 3201 3202 3203rnb_err_t 3204RNBRemote::HandlePacket_z (const char *p) 3205{ 3206 if (p == NULL || *p == '\0') 3207 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in z packet"); 3208 3209 if (!m_ctx.HasValidProcessID()) 3210 return SendPacket ("E15"); 3211 3212 char packet_cmd = *p++; 3213 char break_type = *p++; 3214 3215 if (*p++ != ',') 3216 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet"); 3217 3218 char *c = NULL; 3219 nub_process_t pid = m_ctx.ProcessID(); 3220 errno = 0; 3221 nub_addr_t addr = strtoull (p, &c, 16); 3222 if (errno != 0 && addr == 0) 3223 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in z packet"); 3224 p = c; 3225 if (*p++ != ',') 3226 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma separator missing in z packet"); 3227 3228 errno = 0; 3229 uint32_t byte_size = strtoul (p, &c, 16); 3230 if (errno != 0 && byte_size == 0) 3231 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in z packet"); 3232 3233 if (packet_cmd == 'Z') 3234 { 3235 // set 3236 switch (break_type) 3237 { 3238 case '0': // set software breakpoint 3239 case '1': // set hardware breakpoint 3240 { 3241 // gdb can send multiple Z packets for the same address and 3242 // these calls must be ref counted. 3243 bool hardware = (break_type == '1'); 3244 3245 // Check if we currently have a breakpoint already set at this address 3246 BreakpointMapIter pos = m_breakpoints.find(addr); 3247 if (pos != m_breakpoints.end()) 3248 { 3249 // We do already have a breakpoint at this address, increment 3250 // its reference count and return OK 3251 pos->second.Retain(); 3252 return SendPacket ("OK"); 3253 } 3254 else 3255 { 3256 // We do NOT already have a breakpoint at this address, So lets 3257 // create one. 3258 nub_break_t break_id = DNBBreakpointSet (pid, addr, byte_size, hardware); 3259 if (NUB_BREAK_ID_IS_VALID(break_id)) 3260 { 3261 // We successfully created a breakpoint, now lets full out 3262 // a ref count structure with the breakID and add it to our 3263 // map. 3264 Breakpoint rnbBreakpoint(break_id); 3265 m_breakpoints[addr] = rnbBreakpoint; 3266 return SendPacket ("OK"); 3267 } 3268 else 3269 { 3270 // We failed to set the software breakpoint 3271 return SendPacket ("E09"); 3272 } 3273 } 3274 } 3275 break; 3276 3277 case '2': // set write watchpoint 3278 case '3': // set read watchpoint 3279 case '4': // set access watchpoint 3280 { 3281 bool hardware = true; 3282 uint32_t watch_flags = 0; 3283 if (break_type == '2') 3284 watch_flags = WATCH_TYPE_WRITE; 3285 else if (break_type == '3') 3286 watch_flags = WATCH_TYPE_READ; 3287 else 3288 watch_flags = WATCH_TYPE_READ | WATCH_TYPE_WRITE; 3289 3290 // Check if we currently have a watchpoint already set at this address 3291 BreakpointMapIter pos = m_watchpoints.find(addr); 3292 if (pos != m_watchpoints.end()) 3293 { 3294 // We do already have a watchpoint at this address, increment 3295 // its reference count and return OK 3296 pos->second.Retain(); 3297 return SendPacket ("OK"); 3298 } 3299 else 3300 { 3301 // We do NOT already have a watchpoint at this address, So lets 3302 // create one. 3303 nub_watch_t watch_id = DNBWatchpointSet (pid, addr, byte_size, watch_flags, hardware); 3304 if (NUB_WATCH_ID_IS_VALID(watch_id)) 3305 { 3306 // We successfully created a watchpoint, now lets full out 3307 // a ref count structure with the watch_id and add it to our 3308 // map. 3309 Breakpoint rnbWatchpoint(watch_id); 3310 m_watchpoints[addr] = rnbWatchpoint; 3311 return SendPacket ("OK"); 3312 } 3313 else 3314 { 3315 // We failed to set the watchpoint 3316 return SendPacket ("E09"); 3317 } 3318 } 3319 } 3320 break; 3321 3322 default: 3323 break; 3324 } 3325 } 3326 else if (packet_cmd == 'z') 3327 { 3328 // remove 3329 switch (break_type) 3330 { 3331 case '0': // remove software breakpoint 3332 case '1': // remove hardware breakpoint 3333 { 3334 // gdb can send multiple z packets for the same address and 3335 // these calls must be ref counted. 3336 BreakpointMapIter pos = m_breakpoints.find(addr); 3337 if (pos != m_breakpoints.end()) 3338 { 3339 // We currently have a breakpoint at address ADDR. Decrement 3340 // its reference count, and it that count is now zero we 3341 // can clear the breakpoint. 3342 pos->second.Release(); 3343 if (pos->second.RefCount() == 0) 3344 { 3345 if (DNBBreakpointClear (pid, pos->second.BreakID())) 3346 { 3347 m_breakpoints.erase(pos); 3348 return SendPacket ("OK"); 3349 } 3350 else 3351 { 3352 return SendPacket ("E08"); 3353 } 3354 } 3355 else 3356 { 3357 // We still have references to this breakpoint don't 3358 // delete it, just decrementing the reference count 3359 // is enough. 3360 return SendPacket ("OK"); 3361 } 3362 } 3363 else 3364 { 3365 // We don't know about any breakpoints at this address 3366 return SendPacket ("E08"); 3367 } 3368 } 3369 break; 3370 3371 case '2': // remove write watchpoint 3372 case '3': // remove read watchpoint 3373 case '4': // remove access watchpoint 3374 { 3375 // gdb can send multiple z packets for the same address and 3376 // these calls must be ref counted. 3377 BreakpointMapIter pos = m_watchpoints.find(addr); 3378 if (pos != m_watchpoints.end()) 3379 { 3380 // We currently have a watchpoint at address ADDR. Decrement 3381 // its reference count, and it that count is now zero we 3382 // can clear the watchpoint. 3383 pos->second.Release(); 3384 if (pos->second.RefCount() == 0) 3385 { 3386 if (DNBWatchpointClear (pid, pos->second.BreakID())) 3387 { 3388 m_watchpoints.erase(pos); 3389 return SendPacket ("OK"); 3390 } 3391 else 3392 { 3393 return SendPacket ("E08"); 3394 } 3395 } 3396 else 3397 { 3398 // We still have references to this watchpoint don't 3399 // delete it, just decrementing the reference count 3400 // is enough. 3401 return SendPacket ("OK"); 3402 } 3403 } 3404 else 3405 { 3406 // We don't know about any watchpoints at this address 3407 return SendPacket ("E08"); 3408 } 3409 } 3410 break; 3411 3412 default: 3413 break; 3414 } 3415 } 3416 return HandlePacket_UNIMPLEMENTED(p); 3417} 3418 3419// Extract the thread number from the thread suffix that might be appended to 3420// thread specific packets. This will only be enabled if m_thread_suffix_supported 3421// is true. 3422nub_thread_t 3423RNBRemote::ExtractThreadIDFromThreadSuffix (const char *p) 3424{ 3425 if (m_thread_suffix_supported) 3426 { 3427 nub_thread_t tid = INVALID_NUB_THREAD; 3428 if (p) 3429 { 3430 const char *tid_cstr = strstr (p, "thread:"); 3431 if (tid_cstr) 3432 { 3433 tid_cstr += strlen ("thread:"); 3434 tid = strtoul(tid_cstr, NULL, 16); 3435 } 3436 } 3437 return tid; 3438 } 3439 return GetCurrentThread(); 3440 3441} 3442 3443/* 'p XX' 3444 print the contents of register X */ 3445 3446rnb_err_t 3447RNBRemote::HandlePacket_p (const char *p) 3448{ 3449 if (g_num_reg_entries == 0) 3450 InitializeRegisters (); 3451 3452 if (p == NULL || *p == '\0') 3453 { 3454 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 3455 } 3456 if (!m_ctx.HasValidProcessID()) 3457 { 3458 return SendPacket ("E15"); 3459 } 3460 nub_process_t pid = m_ctx.ProcessID(); 3461 errno = 0; 3462 char *tid_cstr = NULL; 3463 uint32_t reg = strtoul (p + 1, &tid_cstr, 16); 3464 if (errno != 0 && reg == 0) 3465 { 3466 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse register number in p packet"); 3467 } 3468 3469 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (tid_cstr); 3470 if (tid == INVALID_NUB_THREAD) 3471 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 3472 3473 const register_map_entry_t *reg_entry; 3474 3475 if (reg < g_num_reg_entries) 3476 reg_entry = &g_reg_entries[reg]; 3477 else 3478 reg_entry = NULL; 3479 3480 std::ostringstream ostrm; 3481 if (reg_entry == NULL) 3482 { 3483 DNBLogError("RNBRemote::HandlePacket_p(%s): unknown register number %u requested\n", p, reg); 3484 ostrm << "00000000"; 3485 } 3486 else if (reg_entry->nub_info.reg == -1) 3487 { 3488 if (reg_entry->gdb_size > 0) 3489 { 3490 if (reg_entry->fail_value != NULL) 3491 { 3492 append_hex_value(ostrm, reg_entry->fail_value, reg_entry->gdb_size, false); 3493 } 3494 else 3495 { 3496 std::basic_string<uint8_t> zeros(reg_entry->gdb_size, '\0'); 3497 append_hex_value(ostrm, zeros.data(), zeros.size(), false); 3498 } 3499 } 3500 } 3501 else 3502 { 3503 register_value_in_hex_fixed_width (ostrm, pid, tid, reg_entry, NULL); 3504 } 3505 return SendPacket (ostrm.str()); 3506} 3507 3508/* 'Pnn=rrrrr' 3509 Set register number n to value r. 3510 n and r are hex strings. */ 3511 3512rnb_err_t 3513RNBRemote::HandlePacket_P (const char *p) 3514{ 3515 if (g_num_reg_entries == 0) 3516 InitializeRegisters (); 3517 3518 if (p == NULL || *p == '\0') 3519 { 3520 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Empty P packet"); 3521 } 3522 if (!m_ctx.HasValidProcessID()) 3523 { 3524 return SendPacket ("E28"); 3525 } 3526 3527 nub_process_t pid = m_ctx.ProcessID(); 3528 3529 StringExtractor packet (p); 3530 3531 const char cmd_char = packet.GetChar(); 3532 // Register ID is always in big endian 3533 const uint32_t reg = packet.GetHexMaxU32 (false, UINT32_MAX); 3534 const char equal_char = packet.GetChar(); 3535 3536 if (cmd_char != 'P') 3537 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Improperly formed P packet"); 3538 3539 if (reg == UINT32_MAX) 3540 return SendPacket ("E29"); 3541 3542 if (equal_char != '=') 3543 return SendPacket ("E30"); 3544 3545 const register_map_entry_t *reg_entry; 3546 3547 if (reg >= g_num_reg_entries) 3548 return SendPacket("E47"); 3549 3550 reg_entry = &g_reg_entries[reg]; 3551 3552 if (reg_entry->nub_info.set == -1 && reg_entry->nub_info.reg == -1) 3553 { 3554 DNBLogError("RNBRemote::HandlePacket_P(%s): unknown register number %u requested\n", p, reg); 3555 return SendPacket("E48"); 3556 } 3557 3558 DNBRegisterValue reg_value; 3559 reg_value.info = reg_entry->nub_info; 3560 packet.GetHexBytes (reg_value.value.v_sint8, reg_entry->gdb_size, 0xcc); 3561 3562 nub_thread_t tid = ExtractThreadIDFromThreadSuffix (p); 3563 if (tid == INVALID_NUB_THREAD) 3564 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "No thread specified in p packet"); 3565 3566 if (!DNBThreadSetRegisterValueByID (pid, tid, reg_entry->nub_info.set, reg_entry->nub_info.reg, ®_value)) 3567 { 3568 return SendPacket ("E32"); 3569 } 3570 return SendPacket ("OK"); 3571} 3572 3573/* 'c [addr]' 3574 Continue, optionally from a specified address. */ 3575 3576rnb_err_t 3577RNBRemote::HandlePacket_c (const char *p) 3578{ 3579 const nub_process_t pid = m_ctx.ProcessID(); 3580 3581 if (pid == INVALID_NUB_PROCESS) 3582 return SendPacket ("E23"); 3583 3584 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS }; 3585 3586 if (*(p + 1) != '\0') 3587 { 3588 action.tid = GetContinueThread(); 3589 errno = 0; 3590 action.addr = strtoull (p + 1, NULL, 16); 3591 if (errno != 0 && action.addr == 0) 3592 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in c packet"); 3593 } 3594 3595 DNBThreadResumeActions thread_actions; 3596 thread_actions.Append(action); 3597 thread_actions.SetDefaultThreadActionIfNeeded(eStateRunning, 0); 3598 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3599 return SendPacket ("E25"); 3600 // Don't send an "OK" packet; response is the stopped/exited message. 3601 return rnb_success; 3602} 3603 3604rnb_err_t 3605RNBRemote::HandlePacket_MemoryRegionInfo (const char *p) 3606{ 3607 /* This packet will find memory attributes (e.g. readable, writable, executable, stack, jitted code) 3608 for the memory region containing a given address and return that information. 3609 3610 Users of this packet must be prepared for three results: 3611 3612 Region information is returned 3613 Region information is unavailable for this address because the address is in unmapped memory 3614 Region lookup cannot be performed on this platform or process is not yet launched 3615 This packet isn't implemented 3616 3617 Examples of use: 3618 qMemoryRegionInfo:3a55140 3619 start:3a50000,size:100000,permissions:rwx 3620 3621 qMemoryRegionInfo:0 3622 error:address in unmapped region 3623 3624 qMemoryRegionInfo:3a551140 (on a different platform) 3625 error:region lookup cannot be performed 3626 3627 qMemoryRegionInfo 3628 OK // this packet is implemented by the remote nub 3629 */ 3630 3631 p += sizeof ("qMemoryRegionInfo") - 1; 3632 if (*p == '\0') 3633 return SendPacket ("OK"); 3634 if (*p++ != ':') 3635 return SendPacket ("E67"); 3636 if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X')) 3637 p += 2; 3638 3639 errno = 0; 3640 uint64_t address = strtoul (p, NULL, 16); 3641 if (errno != 0 && address == 0) 3642 { 3643 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in qMemoryRegionInfo packet"); 3644 } 3645 3646 DNBRegionInfo region_info = { 0, 0, 0 }; 3647 DNBProcessMemoryRegionInfo (m_ctx.ProcessID(), address, ®ion_info); 3648 std::ostringstream ostrm; 3649 3650 // start:3a50000,size:100000,permissions:rwx 3651 ostrm << "start:" << std::hex << region_info.addr << ';'; 3652 3653 if (region_info.size > 0) 3654 ostrm << "size:" << std::hex << region_info.size << ';'; 3655 3656 if (region_info.permissions) 3657 { 3658 ostrm << "permissions:"; 3659 3660 if (region_info.permissions & eMemoryPermissionsReadable) 3661 ostrm << 'r'; 3662 if (region_info.permissions & eMemoryPermissionsWritable) 3663 ostrm << 'w'; 3664 if (region_info.permissions & eMemoryPermissionsExecutable) 3665 ostrm << 'x'; 3666 ostrm << ';'; 3667 } 3668 return SendPacket (ostrm.str()); 3669} 3670 3671// qGetProfileData;scan_type:0xYYYYYYY 3672rnb_err_t 3673RNBRemote::HandlePacket_GetProfileData (const char *p) 3674{ 3675 nub_process_t pid = m_ctx.ProcessID(); 3676 if (pid == INVALID_NUB_PROCESS) 3677 return SendPacket ("OK"); 3678 3679 StringExtractor packet(p += sizeof ("qGetProfileData")); 3680 DNBProfileDataScanType scan_type = eProfileAll; 3681 std::string name; 3682 std::string value; 3683 while (packet.GetNameColonValue(name, value)) 3684 { 3685 if (name.compare ("scan_type") == 0) 3686 { 3687 std::istringstream iss(value); 3688 uint32_t int_value = 0; 3689 if (iss >> std::hex >> int_value) 3690 { 3691 scan_type = (DNBProfileDataScanType)int_value; 3692 } 3693 } 3694 } 3695 3696 std::string data = DNBProcessGetProfileData(pid, scan_type); 3697 if (!data.empty()) 3698 { 3699 return SendPacket (data.c_str()); 3700 } 3701 else 3702 { 3703 return SendPacket ("OK"); 3704 } 3705} 3706 3707// QSetEnableAsyncProfiling;enable:[0|1]:interval_usec:XXXXXX;scan_type:0xYYYYYYY 3708rnb_err_t 3709RNBRemote::HandlePacket_SetEnableAsyncProfiling (const char *p) 3710{ 3711 nub_process_t pid = m_ctx.ProcessID(); 3712 if (pid == INVALID_NUB_PROCESS) 3713 return SendPacket ("OK"); 3714 3715 StringExtractor packet(p += sizeof ("QSetEnableAsyncProfiling")); 3716 bool enable = false; 3717 uint64_t interval_usec = 0; 3718 DNBProfileDataScanType scan_type = eProfileAll; 3719 std::string name; 3720 std::string value; 3721 while (packet.GetNameColonValue(name, value)) 3722 { 3723 if (name.compare ("enable") == 0) 3724 { 3725 enable = strtoul(value.c_str(), NULL, 10) > 0; 3726 } 3727 else if (name.compare ("interval_usec") == 0) 3728 { 3729 interval_usec = strtoul(value.c_str(), NULL, 10); 3730 } 3731 else if (name.compare ("scan_type") == 0) 3732 { 3733 std::istringstream iss(value); 3734 uint32_t int_value = 0; 3735 if (iss >> std::hex >> int_value) 3736 { 3737 scan_type = (DNBProfileDataScanType)int_value; 3738 } 3739 } 3740 } 3741 3742 if (interval_usec == 0) 3743 { 3744 enable = 0; 3745 } 3746 3747 DNBProcessSetEnableAsyncProfiling(pid, enable, interval_usec, scan_type); 3748 return SendPacket ("OK"); 3749} 3750 3751rnb_err_t 3752RNBRemote::HandlePacket_WatchpointSupportInfo (const char *p) 3753{ 3754 /* This packet simply returns the number of supported hardware watchpoints. 3755 3756 Examples of use: 3757 qWatchpointSupportInfo: 3758 num:4 3759 3760 qWatchpointSupportInfo 3761 OK // this packet is implemented by the remote nub 3762 */ 3763 3764 p += sizeof ("qWatchpointSupportInfo") - 1; 3765 if (*p == '\0') 3766 return SendPacket ("OK"); 3767 if (*p++ != ':') 3768 return SendPacket ("E67"); 3769 3770 errno = 0; 3771 uint32_t num = DNBWatchpointGetNumSupportedHWP (m_ctx.ProcessID()); 3772 std::ostringstream ostrm; 3773 3774 // size:4 3775 ostrm << "num:" << std::dec << num << ';'; 3776 return SendPacket (ostrm.str()); 3777} 3778 3779/* 'C sig [;addr]' 3780 Resume with signal sig, optionally at address addr. */ 3781 3782rnb_err_t 3783RNBRemote::HandlePacket_C (const char *p) 3784{ 3785 const nub_process_t pid = m_ctx.ProcessID(); 3786 3787 if (pid == INVALID_NUB_PROCESS) 3788 return SendPacket ("E36"); 3789 3790 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateRunning, 0, INVALID_NUB_ADDRESS }; 3791 int process_signo = -1; 3792 if (*(p + 1) != '\0') 3793 { 3794 action.tid = GetContinueThread(); 3795 char *end = NULL; 3796 errno = 0; 3797 process_signo = strtoul (p + 1, &end, 16); 3798 if (errno != 0) 3799 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in C packet"); 3800 else if (*end == ';') 3801 { 3802 errno = 0; 3803 action.addr = strtoull (end + 1, NULL, 16); 3804 if (errno != 0 && action.addr == 0) 3805 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in C packet"); 3806 } 3807 } 3808 3809 DNBThreadResumeActions thread_actions; 3810 thread_actions.Append (action); 3811 thread_actions.SetDefaultThreadActionIfNeeded (eStateRunning, action.signal); 3812 if (!DNBProcessSignal(pid, process_signo)) 3813 return SendPacket ("E52"); 3814 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3815 return SendPacket ("E38"); 3816 /* Don't send an "OK" packet; response is the stopped/exited message. */ 3817 return rnb_success; 3818} 3819 3820//---------------------------------------------------------------------- 3821// 'D' packet 3822// Detach from gdb. 3823//---------------------------------------------------------------------- 3824rnb_err_t 3825RNBRemote::HandlePacket_D (const char *p) 3826{ 3827 SendPacket ("OK"); 3828 if (m_ctx.HasValidProcessID()) 3829 DNBProcessDetach(m_ctx.ProcessID()); 3830 return rnb_success; 3831} 3832 3833/* 'k' 3834 Kill the inferior process. */ 3835 3836rnb_err_t 3837RNBRemote::HandlePacket_k (const char *p) 3838{ 3839 DNBLog ("Got a 'k' packet, killing the inferior process."); 3840 // No response to should be sent to the kill packet 3841 if (m_ctx.HasValidProcessID()) 3842 DNBProcessKill (m_ctx.ProcessID()); 3843 SendPacket ("W09"); 3844 return rnb_success; 3845} 3846 3847rnb_err_t 3848RNBRemote::HandlePacket_stop_process (const char *p) 3849{ 3850//#define TEST_EXIT_ON_INTERRUPT // This should only be uncommented to test exiting on interrupt 3851#if defined(TEST_EXIT_ON_INTERRUPT) 3852 rnb_err_t err = HandlePacket_k (p); 3853 m_comm.Disconnect(true); 3854 return err; 3855#else 3856 DNBProcessSignal (m_ctx.ProcessID(), SIGSTOP); 3857 //DNBProcessSignal (m_ctx.ProcessID(), SIGINT); 3858 // Do not send any response packet! Wait for the stop reply packet to naturally happen 3859 return rnb_success; 3860#endif 3861} 3862 3863/* 's' 3864 Step the inferior process. */ 3865 3866rnb_err_t 3867RNBRemote::HandlePacket_s (const char *p) 3868{ 3869 const nub_process_t pid = m_ctx.ProcessID(); 3870 if (pid == INVALID_NUB_PROCESS) 3871 return SendPacket ("E32"); 3872 3873 // Hardware supported stepping not supported on arm 3874 nub_thread_t tid = GetContinueThread (); 3875 if (tid == 0 || tid == -1) 3876 tid = GetCurrentThread(); 3877 3878 if (tid == INVALID_NUB_THREAD) 3879 return SendPacket ("E33"); 3880 3881 DNBThreadResumeActions thread_actions; 3882 thread_actions.AppendAction(tid, eStateStepping); 3883 3884 // Make all other threads stop when we are stepping 3885 thread_actions.SetDefaultThreadActionIfNeeded (eStateStopped, 0); 3886 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3887 return SendPacket ("E49"); 3888 // Don't send an "OK" packet; response is the stopped/exited message. 3889 return rnb_success; 3890} 3891 3892/* 'S sig [;addr]' 3893 Step with signal sig, optionally at address addr. */ 3894 3895rnb_err_t 3896RNBRemote::HandlePacket_S (const char *p) 3897{ 3898 const nub_process_t pid = m_ctx.ProcessID(); 3899 if (pid == INVALID_NUB_PROCESS) 3900 return SendPacket ("E36"); 3901 3902 DNBThreadResumeAction action = { INVALID_NUB_THREAD, eStateStepping, 0, INVALID_NUB_ADDRESS }; 3903 3904 if (*(p + 1) != '\0') 3905 { 3906 char *end = NULL; 3907 errno = 0; 3908 action.signal = strtoul (p + 1, &end, 16); 3909 if (errno != 0) 3910 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse signal in S packet"); 3911 else if (*end == ';') 3912 { 3913 errno = 0; 3914 action.addr = strtoull (end + 1, NULL, 16); 3915 if (errno != 0 && action.addr == 0) 3916 { 3917 return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Could not parse address in S packet"); 3918 } 3919 } 3920 } 3921 3922 action.tid = GetContinueThread (); 3923 if (action.tid == 0 || action.tid == -1) 3924 return SendPacket ("E40"); 3925 3926 nub_state_t tstate = DNBThreadGetState (pid, action.tid); 3927 if (tstate == eStateInvalid || tstate == eStateExited) 3928 return SendPacket ("E37"); 3929 3930 3931 DNBThreadResumeActions thread_actions; 3932 thread_actions.Append (action); 3933 3934 // Make all other threads stop when we are stepping 3935 thread_actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); 3936 if (!DNBProcessResume (pid, thread_actions.GetFirst(), thread_actions.GetSize())) 3937 return SendPacket ("E39"); 3938 3939 // Don't send an "OK" packet; response is the stopped/exited message. 3940 return rnb_success; 3941} 3942 3943rnb_err_t 3944RNBRemote::HandlePacket_qHostInfo (const char *p) 3945{ 3946 std::ostringstream strm; 3947 3948 uint32_t cputype, is_64_bit_capable; 3949 size_t len = sizeof(cputype); 3950 bool promoted_to_64 = false; 3951 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) 3952 { 3953 len = sizeof (is_64_bit_capable); 3954 if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) 3955 { 3956 if (is_64_bit_capable && ((cputype & CPU_ARCH_ABI64) == 0)) 3957 { 3958 promoted_to_64 = true; 3959 cputype |= CPU_ARCH_ABI64; 3960 } 3961 } 3962 3963 strm << "cputype:" << std::dec << cputype << ';'; 3964 } 3965 3966 uint32_t cpusubtype; 3967 len = sizeof(cpusubtype); 3968 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0) 3969 { 3970 if (promoted_to_64 && 3971 cputype == CPU_TYPE_X86_64 && 3972 cpusubtype == CPU_SUBTYPE_486) 3973 cpusubtype = CPU_SUBTYPE_X86_64_ALL; 3974 3975 strm << "cpusubtype:" << std::dec << cpusubtype << ';'; 3976 } 3977 3978 // The OS in the triple should be "ios" or "macosx" which doesn't match our 3979 // "Darwin" which gets returned from "kern.ostype", so we need to hardcode 3980 // this for now. 3981 if (cputype == CPU_TYPE_ARM) 3982 { 3983 strm << "ostype:ios;"; 3984 // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes. 3985 strm << "watchpoint_exceptions_received:before;"; 3986 } 3987 else 3988 { 3989 strm << "ostype:macosx;"; 3990 strm << "watchpoint_exceptions_received:after;"; 3991 } 3992// char ostype[64]; 3993// len = sizeof(ostype); 3994// if (::sysctlbyname("kern.ostype", &ostype, &len, NULL, 0) == 0) 3995// { 3996// len = strlen(ostype); 3997// std::transform (ostype, ostype + len, ostype, tolower); 3998// strm << "ostype:" << std::dec << ostype << ';'; 3999// } 4000 4001 strm << "vendor:apple;"; 4002 4003#if defined (__LITTLE_ENDIAN__) 4004 strm << "endian:little;"; 4005#elif defined (__BIG_ENDIAN__) 4006 strm << "endian:big;"; 4007#elif defined (__PDP_ENDIAN__) 4008 strm << "endian:pdp;"; 4009#endif 4010 4011 if (promoted_to_64) 4012 strm << "ptrsize:8;"; 4013 else 4014 strm << "ptrsize:" << std::dec << sizeof(void *) << ';'; 4015 return SendPacket (strm.str()); 4016} 4017 4018 4019// Note that all numeric values returned by qProcessInfo are hex encoded, 4020// including the pid and the cpu type. 4021 4022rnb_err_t 4023RNBRemote::HandlePacket_qProcessInfo (const char *p) 4024{ 4025 nub_process_t pid; 4026 std::ostringstream rep; 4027 4028 // If we haven't run the process yet, return an error. 4029 if (!m_ctx.HasValidProcessID()) 4030 return SendPacket ("E68"); 4031 4032 pid = m_ctx.ProcessID(); 4033 4034 rep << "pid:" << std::hex << pid << ";"; 4035 4036 int procpid_mib[4]; 4037 procpid_mib[0] = CTL_KERN; 4038 procpid_mib[1] = KERN_PROC; 4039 procpid_mib[2] = KERN_PROC_PID; 4040 procpid_mib[3] = pid; 4041 struct kinfo_proc proc_kinfo; 4042 size_t proc_kinfo_size = sizeof(struct kinfo_proc); 4043 4044 if (::sysctl (procpid_mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) 4045 { 4046 if (proc_kinfo_size > 0) 4047 { 4048 rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";"; 4049 rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";"; 4050 rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";"; 4051 rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";"; 4052 if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) 4053 rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";"; 4054 } 4055 } 4056 4057 int cputype_mib[CTL_MAXNAME]={0,}; 4058 size_t cputype_mib_len = CTL_MAXNAME; 4059 cpu_type_t cputype = -1; 4060 if (::sysctlnametomib("sysctl.proc_cputype", cputype_mib, &cputype_mib_len) == 0) 4061 { 4062 cputype_mib[cputype_mib_len] = pid; 4063 cputype_mib_len++; 4064 size_t len = sizeof(cputype); 4065 if (::sysctl (cputype_mib, cputype_mib_len, &cputype, &len, 0, 0) == 0) 4066 { 4067 rep << "cputype:" << std::hex << cputype << ";"; 4068 } 4069 } 4070 4071 uint32_t cpusubtype; 4072 size_t cpusubtype_len = sizeof(cpusubtype); 4073 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0) 4074 { 4075 if (cputype == CPU_TYPE_X86_64 && cpusubtype == CPU_SUBTYPE_486) 4076 { 4077 cpusubtype = CPU_SUBTYPE_X86_64_ALL; 4078 } 4079 4080 rep << "cpusubtype:" << std::hex << cpusubtype << ';'; 4081 } 4082 4083 // The OS in the triple should be "ios" or "macosx" which doesn't match our 4084 // "Darwin" which gets returned from "kern.ostype", so we need to hardcode 4085 // this for now. 4086 if (cputype == CPU_TYPE_ARM) 4087 rep << "ostype:ios;"; 4088 else 4089 rep << "ostype:macosx;"; 4090 4091 rep << "vendor:apple;"; 4092 4093#if defined (__LITTLE_ENDIAN__) 4094 rep << "endian:little;"; 4095#elif defined (__BIG_ENDIAN__) 4096 rep << "endian:big;"; 4097#elif defined (__PDP_ENDIAN__) 4098 rep << "endian:pdp;"; 4099#endif 4100 4101#if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE) 4102 nub_thread_t thread = DNBProcessGetCurrentThreadMachPort (pid); 4103 kern_return_t kr; 4104 x86_thread_state_t gp_regs; 4105 mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; 4106 kr = thread_get_state (thread, x86_THREAD_STATE, 4107 (thread_state_t) &gp_regs, &gp_count); 4108 if (kr == KERN_SUCCESS) 4109 { 4110 if (gp_regs.tsh.flavor == x86_THREAD_STATE64) 4111 rep << "ptrsize:8;"; 4112 else 4113 rep << "ptrsize:4;"; 4114 } 4115#elif defined (__arm__) 4116 rep << "ptrsize:4;"; 4117#endif 4118 4119 return SendPacket (rep.str()); 4120} 4121 4122