2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
13 #include "native_client/src/include/nacl_scoped_ptr.h"
14 #include "native_client/src/shared/platform/nacl_check.h"
15 #include "native_client/src/shared/platform/nacl_exit.h"
16 #include "native_client/src/shared/platform/nacl_log.h"
17 #include "native_client/src/trusted/debug_stub/abi.h"
18 #include "native_client/src/trusted/debug_stub/packet.h"
19 #include "native_client/src/trusted/debug_stub/platform.h"
20 #include "native_client/src/trusted/debug_stub/session.h"
21 #include "native_client/src/trusted/debug_stub/target.h"
22 #include "native_client/src/trusted/debug_stub/thread.h"
23 #include "native_client/src/trusted/debug_stub/util.h"
24 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
25 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
26 #include "native_client/src/trusted/service_runtime/thread_suspension.h"
29 #define snprintf sprintf_s
34 using port::IPlatform;
36 using port::MutexLock;
41 // Arbitrary descriptor to return when the main nexe is opened.
42 // This can be shared as the file connections are stateless.
43 static const char kMainNexeFilename[] = "nexe";
44 static const char kIrtNexeFilename[] = "irt";
45 static const uint64_t kMainNexeFd = 123;
46 static const uint64_t kIrtNexeFd = 234;
48 // The GDB debug protocol specifies particular values for return values,
49 // errno values, and mode flags. Explicitly defining the subset used herein.
50 static const uint64_t kGdbErrorResult = static_cast<uint64_t>(-1);
51 static const uint64_t kGdbO_RDONLY = 0;
52 static const uint64_t kGdbEPERM = 1;
53 static const uint64_t kGdbENOENT = 2;
54 static const uint64_t kGdbEBADF = 9;
56 // Assume a buffer size that matches GDB's actual current request size.
57 static const size_t kGdbPreadChunkSize = 4096;
60 Target::Target(struct NaClApp *nap, const Abi* abi)
64 initial_breakpoint_addr_(0),
69 step_over_breakpoint_thread_(0),
70 all_threads_suspended_(false),
73 if (NULL == abi_) abi_ = Abi::Get();
81 string targ_xml = "l<target><architecture>";
83 targ_xml += abi_->GetName();
84 targ_xml += "</architecture><osabi>NaCl</osabi>";
85 targ_xml += abi_->GetTargetXml();
86 targ_xml += "</target>";
88 // Set a more specific result which won't change.
89 properties_["target.xml"] = targ_xml;
90 properties_["Supported"] =
91 "PacketSize=1000;qXfer:features:read+";
93 NaClXMutexCtor(&mutex_);
94 ctx_ = new uint8_t[abi_->GetContextSize()];
96 initial_breakpoint_addr_ = (uint32_t) nap_->initial_entry_pt;
97 if (!AddBreakpoint(initial_breakpoint_addr_))
102 void Target::Destroy() {
103 NaClMutexDtor(&mutex_);
108 bool Target::AddBreakpoint(uint32_t user_address) {
109 const Abi::BPDef *bp = abi_->GetBreakpointDef();
111 // If we already have a breakpoint here then don't add it
112 if (breakpoint_map_.find(user_address) != breakpoint_map_.end())
115 uintptr_t sysaddr = NaClUserToSysAddrRange(nap_, user_address, bp->size_);
116 if (sysaddr == kNaClBadAddress)
118 // We allow setting breakpoints in the code area but not the data area.
119 if (user_address + bp->size_ > nap_->dynamic_text_end)
122 // We add the breakpoint by overwriting the start of an instruction
123 // with a breakpoint instruction. (At least, we assume that we have
124 // been given the address of the start of an instruction.) In order
125 // to be able to remove the breakpoint later, we save a copy of the
126 // locations we are overwriting into breakpoint_map_.
127 uint8_t *data = new uint8_t[bp->size_];
129 // Copy the old code from here
130 if (!IPlatform::GetMemory(sysaddr, bp->size_, data)) {
134 if (!IPlatform::SetMemory(nap_, sysaddr, bp->size_, bp->code_)) {
139 breakpoint_map_[user_address] = data;
143 bool Target::RemoveBreakpoint(uint32_t user_address) {
144 const Abi::BPDef *bp_def = abi_->GetBreakpointDef();
146 BreakpointMap_t::iterator iter = breakpoint_map_.find(user_address);
147 if (iter == breakpoint_map_.end())
150 uintptr_t sysaddr = NaClUserToSys(nap_, user_address);
151 uint8_t *data = iter->second;
152 // Copy back the old code, and free the data
153 if (!IPlatform::SetMemory(nap_, sysaddr, bp_def->size_, data)) {
154 NaClLog(LOG_ERROR, "Failed to undo breakpoint.\n");
158 breakpoint_map_.erase(iter);
162 void Target::CopyFaultSignalFromAppThread(IThread *thread) {
163 if (thread->GetFaultSignal() == 0 && thread->HasThreadFaulted()) {
165 IThread::ExceptionToSignal(thread->GetAppThread()->fault_signal);
166 // If a thread hits a breakpoint, we want to ensure that it is
167 // reported as SIGTRAP rather than SIGSEGV. This is necessary
168 // because we use HLT (which produces SIGSEGV) rather than the
169 // more usual INT3 (which produces SIGTRAP) on x86, in order to
170 // work around a Mac OS X bug. Similarly, on ARM we use an
171 // illegal instruction (which produces SIGILL) rather than the
172 // more usual BKPT (which produces SIGTRAP).
174 // We need to check each thread to see whether it hit a
175 // breakpoint. We record this on the thread object because:
176 // * We need to check the threads before accepting any commands
177 // from GDB which might remove breakpoints from
178 // breakpoint_map_, which would remove our ability to tell
179 // whether a thread hit a breakpoint.
180 // * Although we deliver fault events to GDB one by one, we might
181 // have multiple threads that have hit breakpoints.
182 if ((NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 &&
183 signal == NACL_ABI_SIGSEGV) ||
184 (NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm &&
185 signal == NACL_ABI_SIGILL)) {
186 // Casting to uint32_t is necessary to drop the top 32 bits of
188 uint32_t prog_ctr = (uint32_t) thread->GetContext()->prog_ctr;
189 if (breakpoint_map_.find(prog_ctr) != breakpoint_map_.end()) {
190 signal = NACL_ABI_SIGTRAP;
193 thread->SetFaultSignal(signal);
197 void Target::RemoveInitialBreakpoint() {
198 if (initial_breakpoint_addr_ != 0) {
199 if (!RemoveBreakpoint(initial_breakpoint_addr_)) {
201 "RemoveInitialBreakpoint: Failed to remove breakpoint\n");
203 initial_breakpoint_addr_ = 0;
207 // When the debugger reads memory, we want to report the original
208 // memory contents without the modifications we made to add
209 // breakpoints. This function undoes the modifications from a copy of
211 void Target::EraseBreakpointsFromCopyOfMemory(uint32_t user_address,
212 uint8_t *data, uint32_t size) {
213 uint32_t user_end = user_address + size;
214 const Abi::BPDef *bp = abi_->GetBreakpointDef();
215 for (BreakpointMap_t::iterator iter = breakpoint_map_.begin();
216 iter != breakpoint_map_.end();
218 uint32_t breakpoint_address = iter->first;
219 uint32_t breakpoint_end = breakpoint_address + bp->size_;
220 uint8_t *original_data = iter->second;
222 uint32_t overlap_start = std::max(user_address, breakpoint_address);
223 uint32_t overlap_end = std::min(user_end, breakpoint_end);
224 if (overlap_start < overlap_end) {
225 uint8_t *dest = data + (overlap_start - user_address);
226 uint8_t *src = original_data + (overlap_start - breakpoint_address);
227 size_t copy_size = overlap_end - overlap_start;
228 // Sanity check: do some bounds checks.
229 CHECK(data <= dest && dest + copy_size <= data + size);
230 CHECK(original_data <= src
231 && src + copy_size <= original_data + bp->size_);
232 memcpy(dest, src, copy_size);
237 void Target::Run(Session *ses) {
238 NaClXMutexLock(&mutex_);
240 NaClXMutexUnlock(&mutex_);
245 // Lock to prevent anyone else from modifying threads
246 // or updating the signal information.
247 MutexLock lock(&mutex_);
251 } while (session_->Connected());
253 NaClXMutexLock(&mutex_);
255 NaClXMutexUnlock(&mutex_);
258 bool Target::IsInitialBreakpointActive() {
259 return initial_breakpoint_addr_ != 0;
262 void Target::WaitForDebugEvent() {
263 if (all_threads_suspended_) {
264 // If all threads are suspended (which may be left over from a previous
265 // connection), we are already ready to handle commands from GDB.
269 // * an untrusted thread to fault (or single-step)
270 // * an interrupt from GDB
271 bool ignore_input_from_gdb = step_over_breakpoint_thread_ != 0 ||
272 IsInitialBreakpointActive();
273 session_->WaitForDebugStubEvent(nap_, ignore_input_from_gdb);
276 void Target::ProcessDebugEvent() {
277 if (all_threads_suspended_) {
278 // We are already in a suspended state.
280 } else if (step_over_breakpoint_thread_ != 0) {
281 // We are waiting for a specific thread to fault while all other
282 // threads are suspended. Note that faulted_thread_count might
283 // be >1, because multiple threads can fault simultaneously
284 // before the debug stub gets a chance to suspend all threads.
285 // This is why we must check the status of a specific thread --
286 // we cannot call UnqueueAnyFaultedThread() and expect it to
287 // return step_over_breakpoint_thread_.
288 IThread *thread = threads_[step_over_breakpoint_thread_];
289 if (!thread->HasThreadFaulted()) {
290 // The thread has not faulted. Nothing to do, so try again.
291 // Note that we do not respond to input from GDB while in this
293 // TODO(mseaborn): We should allow GDB to interrupt execution.
296 // All threads but one are already suspended. We only need to
297 // suspend the single thread that we allowed to run.
298 thread->SuspendThread();
299 CopyFaultSignalFromAppThread(thread);
300 cur_signal_ = thread->GetFaultSignal();
301 thread->UnqueueFaultedThread();
302 sig_thread_ = step_over_breakpoint_thread_;
303 reg_thread_ = step_over_breakpoint_thread_;
304 step_over_breakpoint_thread_ = 0;
305 } else if (nap_->faulted_thread_count != 0) {
306 // At least one untrusted thread has got an exception. First we
307 // need to ensure that all threads are suspended. Then we can
308 // retrieve a thread from the set of faulted threads.
310 UnqueueAnyFaultedThread(&sig_thread_, &cur_signal_);
311 reg_thread_ = sig_thread_;
313 // Otherwise look for messages from GDB. To fix a potential
314 // race condition, we don't do this on the first run, because in
315 // that case we are waiting for the initial breakpoint to be
316 // reached. We don't want GDB to observe states where the
317 // (internal) initial breakpoint is still registered or where
318 // the initial thread is suspended in NaClStartThreadInApp()
319 // before executing its first untrusted instruction.
320 if (IsInitialBreakpointActive() || !session_->IsDataAvailable()) {
321 // No input from GDB. Nothing to do, so try again.
324 // GDB should have tried to interrupt the target.
325 // See http://sourceware.org/gdb/current/onlinedocs/gdb/Interrupts.html
326 // TODO(eaeltsin): should we verify the interrupt sequence?
328 // Indicate we have no current thread.
329 // TODO(eaeltsin): or pick any thread? Add a test.
330 // See http://code.google.com/p/nativeclient/issues/detail?id=2743
335 bool initial_breakpoint_was_active = IsInitialBreakpointActive();
337 if (sig_thread_ != 0) {
338 // Reset single stepping.
339 threads_[sig_thread_]->SetStep(false);
340 RemoveInitialBreakpoint();
343 // Next update the current thread info
345 snprintf(tmp, sizeof(tmp), "QC%x", sig_thread_);
346 properties_["C"] = tmp;
348 if (!initial_breakpoint_was_active) {
349 // First time on a connection, we don't send the signal.
350 // All other times, send the signal that triggered us.
352 SetStopReply(&pktOut);
353 session_->SendPacketOnly(&pktOut);
356 all_threads_suspended_ = true;
359 void Target::ProcessCommands() {
360 if (!all_threads_suspended_) {
361 // Don't process commands if we haven't stopped all threads.
365 // Now we are ready to process commands.
366 // Loop through packets until we process a continue packet or a detach.
369 if (!session_->GetPacket(&recv))
372 if (ProcessPacket(&recv, &reply)) {
373 // If this is a continue type command, break out of this loop.
376 // Otherwise send the response.
377 session_->SendPacket(&reply);
381 session_->Disconnect();
389 } while (session_->Connected());
391 if (session_->Connected()) {
392 // Continue if we're still connected.
397 void Target::Resume() {
398 // Reset the signal value
401 // TODO(eaeltsin): it might make sense to resume signaled thread before
402 // others, though it is not required by GDB docs.
403 if (step_over_breakpoint_thread_ == 0) {
406 // Resume one thread while leaving all others suspended.
407 threads_[step_over_breakpoint_thread_]->ResumeThread();
410 all_threads_suspended_ = false;
413 void Target::SetStopReply(Packet *pktOut) const {
414 pktOut->AddRawChar('T');
415 pktOut->AddWord8(cur_signal_);
417 // gdbserver handles GDB interrupt by sending SIGINT to the debuggee, thus
418 // GDB interrupt is also a case of a signalled thread.
419 // At the moment we handle GDB interrupt differently, without using a signal,
420 // so in this case sig_thread_ is 0.
421 // This might seem weird to GDB, so at least avoid reporting tid 0.
422 // TODO(eaeltsin): http://code.google.com/p/nativeclient/issues/detail?id=2743
423 if (sig_thread_ != 0) {
424 // Add 'thread:<tid>;' pair. Note terminating ';' is required.
425 pktOut->AddString("thread:");
426 pktOut->AddNumberSep(sig_thread_, ';');
431 bool Target::GetFirstThreadId(uint32_t *id) {
432 threadItr_ = threads_.begin();
433 return GetNextThreadId(id);
436 bool Target::GetNextThreadId(uint32_t *id) {
437 if (threadItr_ == threads_.end()) return false;
439 *id = (*threadItr_).first;
446 uint64_t Target::AdjustUserAddr(uint64_t addr) {
447 // On x86-64, GDB sometimes uses memory addresses with the %r15
448 // sandbox base included, so we must accept these addresses.
449 // TODO(eaeltsin): Fix GDB to not use addresses with %r15 added.
450 if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64 &&
451 NaClIsUserAddr(nap_, (uintptr_t) addr)) {
452 return NaClSysToUser(nap_, (uintptr_t) addr);
454 // Otherwise, we expect an untrusted address.
458 void Target::EmitFileError(Packet *pktOut, int code) {
459 pktOut->AddString("F");
460 pktOut->AddNumberSep(kGdbErrorResult, ',');
461 pktOut->AddNumberSep(code, 0);
464 void Target::ProcessFilePacket(Packet *pktIn, Packet *pktOut, ErrDef *err) {
466 if (!pktIn->GetStringSep(&cmd, ':')) {
470 CHECK(cmd == "File");
472 if (!pktIn->GetStringSep(&subcmd, ':')) {
476 if (subcmd == "open") {
477 std::string filename;
481 if (!pktIn->GetHexString(&filename) ||
482 !pktIn->GetRawChar(&sep) ||
484 !pktIn->GetNumberSep(&flags, NULL) ||
485 !pktIn->GetNumberSep(&mode, NULL)) {
489 if (filename == kMainNexeFilename) {
490 if (flags == kGdbO_RDONLY) {
491 pktOut->AddString("F");
492 pktOut->AddNumberSep(kMainNexeFd, 0);
494 EmitFileError(pktOut, kGdbEPERM);
496 } else if (filename == kIrtNexeFilename) {
497 if (flags == kGdbO_RDONLY) {
498 pktOut->AddString("F");
499 pktOut->AddNumberSep(kIrtNexeFd, 0);
501 EmitFileError(pktOut, kGdbEPERM);
504 EmitFileError(pktOut, kGdbENOENT);
507 } else if (subcmd == "close") {
509 if (!pktIn->GetNumberSep(&fd, NULL)) {
513 if (fd == kMainNexeFd) {
514 pktOut->AddString("F");
515 pktOut->AddNumberSep(0, 0);
516 } else if (fd == kIrtNexeFd) {
517 pktOut->AddString("F");
518 pktOut->AddNumberSep(0, 0);
520 EmitFileError(pktOut, kGdbEBADF);
523 } else if (subcmd == "pread") {
528 if (!pktIn->GetNumberSep(&fd, NULL) ||
529 !pktIn->GetNumberSep(&count, NULL) ||
530 !pktIn->GetNumberSep(&offset, NULL)) {
535 if (fd == kMainNexeFd) {
536 desc = nap_->main_nexe_desc;
537 } else if (fd == kIrtNexeFd) {
538 desc = nap_->irt_nexe_desc;
540 EmitFileError(pktOut, kGdbEBADF);
544 if (count > kGdbPreadChunkSize) {
545 count = kGdbPreadChunkSize;
547 nacl::scoped_array<char> buffer(new char[kGdbPreadChunkSize]);
548 ssize_t result = (*NACL_VTBL(NaClDesc, desc)->PRead)(
550 static_cast<size_t>(count),
551 static_cast<nacl_off64_t>(offset));
552 pktOut->AddString("F");
554 pktOut->AddNumberSep(kGdbErrorResult, ',');
555 pktOut->AddNumberSep(static_cast<uint64_t>(-result), 0);
557 pktOut->AddNumberSep(static_cast<uint64_t>(result), ';');
558 pktOut->AddEscapedData(buffer.get(), static_cast<size_t>(result));
562 NaClLog(LOG_ERROR, "Unknown vFile command: %s\n", pktIn->GetPayload());
566 bool Target::ProcessPacket(Packet* pktIn, Packet* pktOut) {
571 // Clear the outbound message
574 // Pull out the sequence.
575 pktIn->GetSequence(&seq);
576 if (seq != -1) pktOut->SetSequence(seq);
579 pktIn->GetRawChar(&cmd);
585 SetStopReply(pktOut);
595 pktOut->AddString("OK");
602 pktOut->AddString("OK");
608 IThread *thread = GetRegThread();
609 if (NULL == thread) {
614 // Copy OS preserved registers to GDB payload
615 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
616 const Abi::RegDef *def = abi_->GetRegisterDef(a);
617 thread->GetRegister(a, &ctx_[def->offset_], def->bytes_);
620 pktOut->AddBlock(ctx_, abi_->GetContextSize());
627 IThread *thread = GetRegThread();
628 if (NULL == thread) {
633 pktIn->GetBlock(ctx_, abi_->GetContextSize());
635 // GDB payload to OS registers
636 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
637 const Abi::RegDef *def = abi_->GetRegisterDef(a);
638 thread->SetRegister(a, &ctx_[def->offset_], def->bytes_);
641 pktOut->AddString("OK");
645 // IN : $H(c/g)(-1,0,xxxx)
651 if (!pktIn->GetRawChar(&type)) {
655 if (!pktIn->GetNumberSep(&id, 0)) {
660 if (threads_.begin() == threads_.end()) {
665 // If we are using "any" get the first thread
666 if (id == static_cast<uint64_t>(-1)) id = threads_.begin()->first;
668 // Verify that we have the thread
669 if (threads_.find(static_cast<uint32_t>(id)) == threads_.end()) {
674 pktOut->AddString("OK");
677 reg_thread_ = static_cast<uint32_t>(id);
681 // 'c' is deprecated in favor of vCont.
695 if (!pktIn->GetNumberSep(&user_addr, 0)) {
699 if (!pktIn->GetNumberSep(&wlen, 0)) {
703 user_addr = AdjustUserAddr(user_addr);
704 uint64_t sys_addr = NaClUserToSysAddrRange(nap_, (uintptr_t) user_addr,
706 if (sys_addr == kNaClBadAddress) {
711 len = static_cast<uint32_t>(wlen);
712 nacl::scoped_array<uint8_t> block(new uint8_t[len]);
713 if (!port::IPlatform::GetMemory(sys_addr, len, block.get())) {
717 EraseBreakpointsFromCopyOfMemory((uint32_t) user_addr,
720 pktOut->AddBlock(block.get(), len);
724 // IN : $Maaaa,llll:xx..xx
731 if (!pktIn->GetNumberSep(&user_addr, 0)) {
735 if (!pktIn->GetNumberSep(&wlen, 0)) {
739 user_addr = AdjustUserAddr(user_addr);
740 uint64_t sys_addr = NaClUserToSysAddrRange(nap_, (uintptr_t) user_addr,
742 if (sys_addr == kNaClBadAddress) {
746 len = static_cast<uint32_t>(wlen);
747 // We disallow the debugger from modifying code.
748 if (user_addr < nap_->dynamic_text_end) {
753 nacl::scoped_array<uint8_t> block(new uint8_t[len]);
754 pktIn->GetBlock(block.get(), len);
756 if (!port::IPlatform::SetMemory(nap_, sys_addr, len, block.get())) {
761 pktOut->AddString("OK");
767 const char *str = &pktIn->GetPayload()[1];
768 stringvec toks = StringSplit(str, ":;");
769 PropertyMap_t::const_iterator itr = properties_.find(toks[0]);
771 // If this is a thread query
772 if (!strcmp(str, "fThreadInfo") || !strcmp(str, "sThreadInfo")) {
776 more = GetFirstThreadId(&curr);
778 more = GetNextThreadId(&curr);
782 pktOut->AddString("l");
784 pktOut->AddString("m");
785 pktOut->AddNumberSep(curr, 0);
790 // Check for architecture query
791 tmp = "Xfer:features:read:target.xml";
792 if (!strncmp(str, tmp.data(), tmp.length())) {
793 stringvec args = StringSplit(&str[tmp.length()+1], ",");
794 if (args.size() != 2) break;
796 const char *out = properties_["target.xml"].data();
797 int offs = strtol(args[0].data(), NULL, 16);
798 int max = strtol(args[1].data(), NULL, 16) + offs;
799 int len = static_cast<int>(strlen(out));
801 if (max >= len) max = len;
804 pktOut->AddRawChar(out[offs]);
810 // Check the property cache
811 if (itr != properties_.end()) {
812 pktOut->AddString(itr->second.data());
818 IThread *thread = GetRunThread();
819 if (thread) thread->SetStep(true);
825 if (!pktIn->GetNumberSep(&id, 0)) {
830 if (GetThread(static_cast<uint32_t>(id)) == NULL) {
835 pktOut->AddString("OK");
840 const char *str = pktIn->GetPayload() + 1;
842 if (strncmp(str, "Cont", 4) == 0) {
844 const char *subcommand = str + 4;
846 if (strcmp(subcommand, "?") == 0) {
847 // Report supported vCont actions. These 4 are required.
848 pktOut->AddString("vCont;s;S;c;C");
852 if (strcmp(subcommand, ";c") == 0) {
853 // Continue all threads.
857 if (strncmp(subcommand, ";s:", 3) == 0) {
858 // Single step one thread and optionally continue all other threads.
860 uint32_t thread_id = static_cast<uint32_t>(
861 strtol(subcommand + 3, &end, 16));
862 if (end == subcommand + 3) {
867 ThreadMap_t::iterator it = threads_.find(thread_id);
868 if (it == threads_.end()) {
874 // Single step one thread and keep other threads stopped.
875 // GDB uses this to continue from a breakpoint, which works by:
876 // - replacing trap instruction with the original instruction;
877 // - single-stepping through the original instruction. Other threads
878 // must remain stopped, otherwise they might execute the code at
879 // the same address and thus miss the breakpoint;
880 // - replacing the original instruction with trap instruction;
881 // - continuing all threads;
882 if (thread_id != sig_thread_) {
886 step_over_breakpoint_thread_ = sig_thread_;
887 } else if (strcmp(end, ";c") == 0) {
888 // Single step one thread and continue all other threads.
890 // Unsupported combination of single step and other args.
895 it->second->SetStep(true);
899 // Continue one thread and keep other threads stopped.
901 // GDB sends this for software single step, which is used:
902 // - on Win64 to step over rsp modification and subsequent rsp
903 // sandboxing at once. For details, see:
904 // http://code.google.com/p/nativeclient/issues/detail?id=2903
905 // - TODO: on ARM, which has no hardware support for single step
906 // - TODO: to step over syscalls
908 // Unfortunately, we can't make this just Win-specific. We might
909 // use Linux GDB to connect to Win debug stub, so even Linux GDB
910 // should send software single step. Vice versa, software single
911 // step-enabled Win GDB might be connected to Linux debug stub,
912 // so even Linux debug stub should accept software single step.
913 if (strncmp(subcommand, ";c:", 3) == 0) {
915 uint32_t thread_id = static_cast<uint32_t>(
916 strtol(subcommand + 3, &end, 16));
917 if (end != subcommand + 3 && *end == 0) {
918 if (thread_id == sig_thread_) {
919 step_over_breakpoint_thread_ = sig_thread_;
928 // Unsupported form of vCont.
931 } else if (strncmp(str, "File:", 5) == 0) {
932 ProcessFilePacket(pktIn, pktOut, &err);
936 NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload());
941 uint64_t breakpoint_type;
942 uint64_t breakpoint_address;
943 uint64_t breakpoint_kind;
944 if (!pktIn->GetNumberSep(&breakpoint_type, 0) ||
945 breakpoint_type != 0 ||
946 !pktIn->GetNumberSep(&breakpoint_address, 0) ||
947 !pktIn->GetNumberSep(&breakpoint_kind, 0)) {
951 if (breakpoint_address != (uint32_t) breakpoint_address ||
952 !AddBreakpoint((uint32_t) breakpoint_address)) {
956 pktOut->AddString("OK");
961 uint64_t breakpoint_type;
962 uint64_t breakpoint_address;
963 uint64_t breakpoint_kind;
964 if (!pktIn->GetNumberSep(&breakpoint_type, 0) ||
965 breakpoint_type != 0 ||
966 !pktIn->GetNumberSep(&breakpoint_address, 0) ||
967 !pktIn->GetNumberSep(&breakpoint_kind, 0)) {
971 if (breakpoint_address != (uint32_t) breakpoint_address ||
972 !RemoveBreakpoint((uint32_t) breakpoint_address)) {
976 pktOut->AddString("OK");
981 // If the command is not recognzied, ignore it by sending an
984 pktIn->GetString(&str);
985 NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload());
990 // If there is an error, return the error code instead of a payload
993 pktOut->AddRawChar('E');
994 pktOut->AddWord8(err);
1000 void Target::TrackThread(struct NaClAppThread *natp) {
1001 // natp->thread_num values are 0-based indexes, but we treat 0 as
1002 // "not a thread ID", so we add 1.
1003 uint32_t id = natp->thread_num + 1;
1004 MutexLock lock(&mutex_);
1005 CHECK(threads_[id] == 0);
1006 threads_[id] = IThread::Create(id, natp);
1009 void Target::IgnoreThread(struct NaClAppThread *natp) {
1010 uint32_t id = natp->thread_num + 1;
1011 MutexLock lock(&mutex_);
1012 ThreadMap_t::iterator iter = threads_.find(id);
1013 CHECK(iter != threads_.end());
1014 delete iter->second;
1015 threads_.erase(iter);
1018 void Target::Exit() {
1019 MutexLock lock(&mutex_);
1020 if (session_ != NULL) {
1022 if (NACL_ABI_WIFSIGNALED(nap_->exit_status)) {
1023 exit_packet.AddRawChar('X');
1024 exit_packet.AddWord8(NACL_ABI_WTERMSIG(nap_->exit_status));
1026 exit_packet.AddRawChar('W');
1027 exit_packet.AddWord8(NACL_ABI_WEXITSTATUS(nap_->exit_status));
1029 session_->SendPacket(&exit_packet);
1033 void Target::Detach() {
1034 NaClLog(LOG_INFO, "Requested Detach.\n");
1038 void Target::Kill() {
1039 NaClLog(LOG_INFO, "Requested Kill.\n");
1040 should_exit_ = true;
1043 IThread* Target::GetRegThread() {
1044 ThreadMap_t::const_iterator itr;
1046 switch (reg_thread_) {
1047 // If we want "any" then try the signal'd thread first
1050 itr = threads_.begin();
1054 itr = threads_.find(reg_thread_);
1058 if (itr == threads_.end()) return 0;
1063 IThread* Target::GetRunThread() {
1064 // This is used to select a thread for "s" (step) command only.
1065 // For multi-threaded targets, "s" is deprecated in favor of "vCont", which
1066 // always specifies the thread explicitly when needed. However, we want
1067 // to keep backward compatibility here, as using "s" when debugging
1068 // a single-threaded program might be a popular use case.
1069 if (threads_.size() == 1) {
1070 return threads_.begin()->second;
1075 IThread* Target::GetThread(uint32_t id) {
1076 ThreadMap_t::const_iterator itr;
1077 itr = threads_.find(id);
1078 if (itr != threads_.end()) return itr->second;
1083 void Target::SuspendAllThreads() {
1084 NaClUntrustedThreadsSuspendAll(nap_, /* save_registers= */ 1);
1085 for (ThreadMap_t::const_iterator iter = threads_.begin();
1086 iter != threads_.end();
1088 IThread *thread = iter->second;
1089 thread->CopyRegistersFromAppThread();
1090 CopyFaultSignalFromAppThread(thread);
1094 void Target::ResumeAllThreads() {
1095 for (ThreadMap_t::const_iterator iter = threads_.begin();
1096 iter != threads_.end();
1098 iter->second->CopyRegistersToAppThread();
1100 NaClUntrustedThreadsResumeAll(nap_);
1103 // UnqueueAnyFaultedThread() picks a thread that has been blocked as a
1104 // result of faulting and unblocks it. It returns the thread's ID via
1105 // |thread_id| and the type of fault via |signal|. As a precondition,
1106 // all threads must be currently suspended.
1107 void Target::UnqueueAnyFaultedThread(uint32_t *thread_id, int8_t *signal) {
1108 for (ThreadMap_t::const_iterator iter = threads_.begin();
1109 iter != threads_.end();
1111 IThread *thread = iter->second;
1112 if (thread->GetFaultSignal() != 0) {
1113 *signal = thread->GetFaultSignal();
1114 *thread_id = thread->GetId();
1115 thread->UnqueueFaultedThread();
1119 NaClLog(LOG_FATAL, "UnqueueAnyFaultedThread: No threads queued\n");
1122 } // namespace gdb_rsp