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 Target::Target(struct NaClApp *nap, const Abi* abi)
45 initial_breakpoint_addr_(0),
50 step_over_breakpoint_thread_(0),
51 all_threads_suspended_(false),
54 if (NULL == abi_) abi_ = Abi::Get();
62 string targ_xml = "l<target><architecture>";
64 targ_xml += abi_->GetName();
65 targ_xml += "</architecture><osabi>NaCl</osabi>";
66 targ_xml += abi_->GetTargetXml();
67 targ_xml += "</target>";
69 // Set a more specific result which won't change.
70 properties_["target.xml"] = targ_xml;
71 properties_["Supported"] =
72 "PacketSize=1000;qXfer:features:read+";
74 NaClXMutexCtor(&mutex_);
75 ctx_ = new uint8_t[abi_->GetContextSize()];
77 initial_breakpoint_addr_ = (uint32_t) nap_->initial_entry_pt;
78 if (!AddBreakpoint(initial_breakpoint_addr_))
83 void Target::Destroy() {
84 NaClMutexDtor(&mutex_);
89 bool Target::AddBreakpoint(uint32_t user_address) {
90 const Abi::BPDef *bp = abi_->GetBreakpointDef();
92 // If we already have a breakpoint here then don't add it
93 if (breakpoint_map_.find(user_address) != breakpoint_map_.end())
96 uintptr_t sysaddr = NaClUserToSysAddrRange(nap_, user_address, bp->size_);
97 if (sysaddr == kNaClBadAddress)
99 // We allow setting breakpoints in the code area but not the data area.
100 if (user_address + bp->size_ > nap_->dynamic_text_end)
103 // We add the breakpoint by overwriting the start of an instruction
104 // with a breakpoint instruction. (At least, we assume that we have
105 // been given the address of the start of an instruction.) In order
106 // to be able to remove the breakpoint later, we save a copy of the
107 // locations we are overwriting into breakpoint_map_.
108 uint8_t *data = new uint8_t[bp->size_];
110 // Copy the old code from here
111 if (!IPlatform::GetMemory(sysaddr, bp->size_, data)) {
115 if (!IPlatform::SetMemory(nap_, sysaddr, bp->size_, bp->code_)) {
120 breakpoint_map_[user_address] = data;
124 bool Target::RemoveBreakpoint(uint32_t user_address) {
125 const Abi::BPDef *bp_def = abi_->GetBreakpointDef();
127 BreakpointMap_t::iterator iter = breakpoint_map_.find(user_address);
128 if (iter == breakpoint_map_.end())
131 uintptr_t sysaddr = NaClUserToSys(nap_, user_address);
132 uint8_t *data = iter->second;
133 // Copy back the old code, and free the data
134 if (!IPlatform::SetMemory(nap_, sysaddr, bp_def->size_, data)) {
135 NaClLog(LOG_ERROR, "Failed to undo breakpoint.\n");
139 breakpoint_map_.erase(iter);
143 void Target::CopyFaultSignalFromAppThread(IThread *thread) {
144 if (thread->GetFaultSignal() == 0 && thread->HasThreadFaulted()) {
146 IThread::ExceptionToSignal(thread->GetAppThread()->fault_signal);
147 // If a thread hits a breakpoint, we want to ensure that it is
148 // reported as SIGTRAP rather than SIGSEGV. This is necessary
149 // because we use HLT (which produces SIGSEGV) rather than the
150 // more usual INT3 (which produces SIGTRAP) on x86, in order to
151 // work around a Mac OS X bug. Similarly, on ARM we use an
152 // illegal instruction (which produces SIGILL) rather than the
153 // more usual BKPT (which produces SIGTRAP).
155 // We need to check each thread to see whether it hit a
156 // breakpoint. We record this on the thread object because:
157 // * We need to check the threads before accepting any commands
158 // from GDB which might remove breakpoints from
159 // breakpoint_map_, which would remove our ability to tell
160 // whether a thread hit a breakpoint.
161 // * Although we deliver fault events to GDB one by one, we might
162 // have multiple threads that have hit breakpoints.
163 if ((NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 &&
164 signal == NACL_ABI_SIGSEGV) ||
165 (NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm &&
166 signal == NACL_ABI_SIGILL)) {
167 // Casting to uint32_t is necessary to drop the top 32 bits of
169 uint32_t prog_ctr = (uint32_t) thread->GetContext()->prog_ctr;
170 if (breakpoint_map_.find(prog_ctr) != breakpoint_map_.end()) {
171 signal = NACL_ABI_SIGTRAP;
174 thread->SetFaultSignal(signal);
178 void Target::RemoveInitialBreakpoint() {
179 if (initial_breakpoint_addr_ != 0) {
180 if (!RemoveBreakpoint(initial_breakpoint_addr_)) {
182 "RemoveInitialBreakpoint: Failed to remove breakpoint\n");
184 initial_breakpoint_addr_ = 0;
188 // When the debugger reads memory, we want to report the original
189 // memory contents without the modifications we made to add
190 // breakpoints. This function undoes the modifications from a copy of
192 void Target::EraseBreakpointsFromCopyOfMemory(uint32_t user_address,
193 uint8_t *data, uint32_t size) {
194 uint32_t user_end = user_address + size;
195 const Abi::BPDef *bp = abi_->GetBreakpointDef();
196 for (BreakpointMap_t::iterator iter = breakpoint_map_.begin();
197 iter != breakpoint_map_.end();
199 uint32_t breakpoint_address = iter->first;
200 uint32_t breakpoint_end = breakpoint_address + bp->size_;
201 uint8_t *original_data = iter->second;
203 uint32_t overlap_start = std::max(user_address, breakpoint_address);
204 uint32_t overlap_end = std::min(user_end, breakpoint_end);
205 if (overlap_start < overlap_end) {
206 uint8_t *dest = data + (overlap_start - user_address);
207 uint8_t *src = original_data + (overlap_start - breakpoint_address);
208 size_t copy_size = overlap_end - overlap_start;
209 // Sanity check: do some bounds checks.
210 CHECK(data <= dest && dest + copy_size <= data + size);
211 CHECK(original_data <= src
212 && src + copy_size <= original_data + bp->size_);
213 memcpy(dest, src, copy_size);
218 void Target::Run(Session *ses) {
219 NaClXMutexLock(&mutex_);
221 NaClXMutexUnlock(&mutex_);
226 // Lock to prevent anyone else from modifying threads
227 // or updating the signal information.
228 MutexLock lock(&mutex_);
232 } while (session_->Connected());
234 NaClXMutexLock(&mutex_);
236 NaClXMutexUnlock(&mutex_);
239 bool Target::IsInitialBreakpointActive() {
240 return initial_breakpoint_addr_ != 0;
243 void Target::WaitForDebugEvent() {
244 if (all_threads_suspended_) {
245 // If all threads are suspended (which may be left over from a previous
246 // connection), we are already ready to handle commands from GDB.
250 // * an untrusted thread to fault (or single-step)
251 // * an interrupt from GDB
252 bool ignore_input_from_gdb = step_over_breakpoint_thread_ != 0 ||
253 IsInitialBreakpointActive();
254 session_->WaitForDebugStubEvent(nap_, ignore_input_from_gdb);
257 void Target::ProcessDebugEvent() {
258 if (all_threads_suspended_) {
259 // We are already in a suspended state.
261 } else if (step_over_breakpoint_thread_ != 0) {
262 // We are waiting for a specific thread to fault while all other
263 // threads are suspended. Note that faulted_thread_count might
264 // be >1, because multiple threads can fault simultaneously
265 // before the debug stub gets a chance to suspend all threads.
266 // This is why we must check the status of a specific thread --
267 // we cannot call UnqueueAnyFaultedThread() and expect it to
268 // return step_over_breakpoint_thread_.
269 IThread *thread = threads_[step_over_breakpoint_thread_];
270 if (!thread->HasThreadFaulted()) {
271 // The thread has not faulted. Nothing to do, so try again.
272 // Note that we do not respond to input from GDB while in this
274 // TODO(mseaborn): We should allow GDB to interrupt execution.
277 // All threads but one are already suspended. We only need to
278 // suspend the single thread that we allowed to run.
279 thread->SuspendThread();
280 CopyFaultSignalFromAppThread(thread);
281 cur_signal_ = thread->GetFaultSignal();
282 thread->UnqueueFaultedThread();
283 sig_thread_ = step_over_breakpoint_thread_;
284 reg_thread_ = step_over_breakpoint_thread_;
285 step_over_breakpoint_thread_ = 0;
286 } else if (nap_->faulted_thread_count != 0) {
287 // At least one untrusted thread has got an exception. First we
288 // need to ensure that all threads are suspended. Then we can
289 // retrieve a thread from the set of faulted threads.
291 UnqueueAnyFaultedThread(&sig_thread_, &cur_signal_);
292 reg_thread_ = sig_thread_;
294 // Otherwise look for messages from GDB. To fix a potential
295 // race condition, we don't do this on the first run, because in
296 // that case we are waiting for the initial breakpoint to be
297 // reached. We don't want GDB to observe states where the
298 // (internal) initial breakpoint is still registered or where
299 // the initial thread is suspended in NaClStartThreadInApp()
300 // before executing its first untrusted instruction.
301 if (IsInitialBreakpointActive() || !session_->IsDataAvailable()) {
302 // No input from GDB. Nothing to do, so try again.
305 // GDB should have tried to interrupt the target.
306 // See http://sourceware.org/gdb/current/onlinedocs/gdb/Interrupts.html
307 // TODO(eaeltsin): should we verify the interrupt sequence?
309 // Indicate we have no current thread.
310 // TODO(eaeltsin): or pick any thread? Add a test.
311 // See http://code.google.com/p/nativeclient/issues/detail?id=2743
316 bool initial_breakpoint_was_active = IsInitialBreakpointActive();
318 if (sig_thread_ != 0) {
319 // Reset single stepping.
320 threads_[sig_thread_]->SetStep(false);
321 RemoveInitialBreakpoint();
324 // Next update the current thread info
326 snprintf(tmp, sizeof(tmp), "QC%x", sig_thread_);
327 properties_["C"] = tmp;
329 if (!initial_breakpoint_was_active) {
330 // First time on a connection, we don't send the signal.
331 // All other times, send the signal that triggered us.
333 SetStopReply(&pktOut);
334 session_->SendPacketOnly(&pktOut);
337 all_threads_suspended_ = true;
340 void Target::ProcessCommands() {
341 if (!all_threads_suspended_) {
342 // Don't process commands if we haven't stopped all threads.
346 // Now we are ready to process commands.
347 // Loop through packets until we process a continue packet or a detach.
350 if (!session_->GetPacket(&recv))
353 if (ProcessPacket(&recv, &reply)) {
354 // If this is a continue type command, break out of this loop.
357 // Otherwise send the response.
358 session_->SendPacket(&reply);
362 session_->Disconnect();
370 } while (session_->Connected());
372 if (session_->Connected()) {
373 // Continue if we're still connected.
378 void Target::Resume() {
379 // Reset the signal value
382 // TODO(eaeltsin): it might make sense to resume signaled thread before
383 // others, though it is not required by GDB docs.
384 if (step_over_breakpoint_thread_ == 0) {
387 // Resume one thread while leaving all others suspended.
388 threads_[step_over_breakpoint_thread_]->ResumeThread();
391 all_threads_suspended_ = false;
394 void Target::SetStopReply(Packet *pktOut) const {
395 pktOut->AddRawChar('T');
396 pktOut->AddWord8(cur_signal_);
398 // gdbserver handles GDB interrupt by sending SIGINT to the debuggee, thus
399 // GDB interrupt is also a case of a signalled thread.
400 // At the moment we handle GDB interrupt differently, without using a signal,
401 // so in this case sig_thread_ is 0.
402 // This might seem weird to GDB, so at least avoid reporting tid 0.
403 // TODO(eaeltsin): http://code.google.com/p/nativeclient/issues/detail?id=2743
404 if (sig_thread_ != 0) {
405 // Add 'thread:<tid>;' pair. Note terminating ';' is required.
406 pktOut->AddString("thread:");
407 pktOut->AddNumberSep(sig_thread_, ';');
412 bool Target::GetFirstThreadId(uint32_t *id) {
413 threadItr_ = threads_.begin();
414 return GetNextThreadId(id);
417 bool Target::GetNextThreadId(uint32_t *id) {
418 if (threadItr_ == threads_.end()) return false;
420 *id = (*threadItr_).first;
427 uint64_t Target::AdjustUserAddr(uint64_t addr) {
428 // On x86-64, GDB sometimes uses memory addresses with the %r15
429 // sandbox base included, so we must accept these addresses.
430 // TODO(eaeltsin): Fix GDB to not use addresses with %r15 added.
431 if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64 &&
432 NaClIsUserAddr(nap_, (uintptr_t) addr)) {
433 return NaClSysToUser(nap_, (uintptr_t) addr);
435 // Otherwise, we expect an untrusted address.
439 bool Target::ProcessPacket(Packet* pktIn, Packet* pktOut) {
444 // Clear the outbound message
447 // Pull out the sequence.
448 pktIn->GetSequence(&seq);
449 if (seq != -1) pktOut->SetSequence(seq);
452 pktIn->GetRawChar(&cmd);
458 SetStopReply(pktOut);
468 pktOut->AddString("OK");
475 pktOut->AddString("OK");
481 IThread *thread = GetRegThread();
482 if (NULL == thread) {
487 // Copy OS preserved registers to GDB payload
488 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
489 const Abi::RegDef *def = abi_->GetRegisterDef(a);
490 thread->GetRegister(a, &ctx_[def->offset_], def->bytes_);
493 pktOut->AddBlock(ctx_, abi_->GetContextSize());
500 IThread *thread = GetRegThread();
501 if (NULL == thread) {
506 pktIn->GetBlock(ctx_, abi_->GetContextSize());
508 // GDB payload to OS registers
509 for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
510 const Abi::RegDef *def = abi_->GetRegisterDef(a);
511 thread->SetRegister(a, &ctx_[def->offset_], def->bytes_);
514 pktOut->AddString("OK");
518 // IN : $H(c/g)(-1,0,xxxx)
524 if (!pktIn->GetRawChar(&type)) {
528 if (!pktIn->GetNumberSep(&id, 0)) {
533 if (threads_.begin() == threads_.end()) {
538 // If we are using "any" get the first thread
539 if (id == static_cast<uint64_t>(-1)) id = threads_.begin()->first;
541 // Verify that we have the thread
542 if (threads_.find(static_cast<uint32_t>(id)) == threads_.end()) {
547 pktOut->AddString("OK");
550 reg_thread_ = static_cast<uint32_t>(id);
554 // 'c' is deprecated in favor of vCont.
568 if (!pktIn->GetNumberSep(&user_addr, 0)) {
572 if (!pktIn->GetNumberSep(&wlen, 0)) {
576 user_addr = AdjustUserAddr(user_addr);
577 uint64_t sys_addr = NaClUserToSysAddrRange(nap_, (uintptr_t) user_addr,
579 if (sys_addr == kNaClBadAddress) {
584 len = static_cast<uint32_t>(wlen);
585 nacl::scoped_array<uint8_t> block(new uint8_t[len]);
586 if (!port::IPlatform::GetMemory(sys_addr, len, block.get())) {
590 EraseBreakpointsFromCopyOfMemory((uint32_t) user_addr,
593 pktOut->AddBlock(block.get(), len);
597 // IN : $Maaaa,llll:xx..xx
604 if (!pktIn->GetNumberSep(&user_addr, 0)) {
608 if (!pktIn->GetNumberSep(&wlen, 0)) {
612 user_addr = AdjustUserAddr(user_addr);
613 uint64_t sys_addr = NaClUserToSysAddrRange(nap_, (uintptr_t) user_addr,
615 if (sys_addr == kNaClBadAddress) {
619 len = static_cast<uint32_t>(wlen);
620 // We disallow the debugger from modifying code.
621 if (user_addr < nap_->dynamic_text_end) {
626 nacl::scoped_array<uint8_t> block(new uint8_t[len]);
627 pktIn->GetBlock(block.get(), len);
629 if (!port::IPlatform::SetMemory(nap_, sys_addr, len, block.get())) {
634 pktOut->AddString("OK");
640 const char *str = &pktIn->GetPayload()[1];
641 stringvec toks = StringSplit(str, ":;");
642 PropertyMap_t::const_iterator itr = properties_.find(toks[0]);
644 // If this is a thread query
645 if (!strcmp(str, "fThreadInfo") || !strcmp(str, "sThreadInfo")) {
649 more = GetFirstThreadId(&curr);
651 more = GetNextThreadId(&curr);
655 pktOut->AddString("l");
657 pktOut->AddString("m");
658 pktOut->AddNumberSep(curr, 0);
663 // Check for architecture query
664 tmp = "Xfer:features:read:target.xml";
665 if (!strncmp(str, tmp.data(), tmp.length())) {
666 stringvec args = StringSplit(&str[tmp.length()+1], ",");
667 if (args.size() != 2) break;
669 const char *out = properties_["target.xml"].data();
670 int offs = strtol(args[0].data(), NULL, 16);
671 int max = strtol(args[1].data(), NULL, 16) + offs;
672 int len = static_cast<int>(strlen(out));
674 if (max >= len) max = len;
677 pktOut->AddRawChar(out[offs]);
683 // Check the property cache
684 if (itr != properties_.end()) {
685 pktOut->AddString(itr->second.data());
691 IThread *thread = GetRunThread();
692 if (thread) thread->SetStep(true);
698 if (!pktIn->GetNumberSep(&id, 0)) {
703 if (GetThread(static_cast<uint32_t>(id)) == NULL) {
708 pktOut->AddString("OK");
713 const char *str = pktIn->GetPayload() + 1;
715 if (strncmp(str, "Cont", 4) == 0) {
717 const char *subcommand = str + 4;
719 if (strcmp(subcommand, "?") == 0) {
720 // Report supported vCont actions. These 4 are required.
721 pktOut->AddString("vCont;s;S;c;C");
725 if (strcmp(subcommand, ";c") == 0) {
726 // Continue all threads.
730 if (strncmp(subcommand, ";s:", 3) == 0) {
731 // Single step one thread and optionally continue all other threads.
733 uint32_t thread_id = static_cast<uint32_t>(
734 strtol(subcommand + 3, &end, 16));
735 if (end == subcommand + 3) {
740 ThreadMap_t::iterator it = threads_.find(thread_id);
741 if (it == threads_.end()) {
747 // Single step one thread and keep other threads stopped.
748 // GDB uses this to continue from a breakpoint, which works by:
749 // - replacing trap instruction with the original instruction;
750 // - single-stepping through the original instruction. Other threads
751 // must remain stopped, otherwise they might execute the code at
752 // the same address and thus miss the breakpoint;
753 // - replacing the original instruction with trap instruction;
754 // - continuing all threads;
755 if (thread_id != sig_thread_) {
759 step_over_breakpoint_thread_ = sig_thread_;
760 } else if (strcmp(end, ";c") == 0) {
761 // Single step one thread and continue all other threads.
763 // Unsupported combination of single step and other args.
768 it->second->SetStep(true);
772 // Continue one thread and keep other threads stopped.
774 // GDB sends this for software single step, which is used:
775 // - on Win64 to step over rsp modification and subsequent rsp
776 // sandboxing at once. For details, see:
777 // http://code.google.com/p/nativeclient/issues/detail?id=2903
778 // - TODO: on ARM, which has no hardware support for single step
779 // - TODO: to step over syscalls
781 // Unfortunately, we can't make this just Win-specific. We might
782 // use Linux GDB to connect to Win debug stub, so even Linux GDB
783 // should send software single step. Vice versa, software single
784 // step-enabled Win GDB might be connected to Linux debug stub,
785 // so even Linux debug stub should accept software single step.
786 if (strncmp(subcommand, ";c:", 3) == 0) {
788 uint32_t thread_id = static_cast<uint32_t>(
789 strtol(subcommand + 3, &end, 16));
790 if (end != subcommand + 3 && *end == 0) {
791 if (thread_id == sig_thread_) {
792 step_over_breakpoint_thread_ = sig_thread_;
801 // Unsupported form of vCont.
806 NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload());
811 uint64_t breakpoint_type;
812 uint64_t breakpoint_address;
813 uint64_t breakpoint_kind;
814 if (!pktIn->GetNumberSep(&breakpoint_type, 0) ||
815 breakpoint_type != 0 ||
816 !pktIn->GetNumberSep(&breakpoint_address, 0) ||
817 !pktIn->GetNumberSep(&breakpoint_kind, 0)) {
821 if (breakpoint_address != (uint32_t) breakpoint_address ||
822 !AddBreakpoint((uint32_t) breakpoint_address)) {
826 pktOut->AddString("OK");
831 uint64_t breakpoint_type;
832 uint64_t breakpoint_address;
833 uint64_t breakpoint_kind;
834 if (!pktIn->GetNumberSep(&breakpoint_type, 0) ||
835 breakpoint_type != 0 ||
836 !pktIn->GetNumberSep(&breakpoint_address, 0) ||
837 !pktIn->GetNumberSep(&breakpoint_kind, 0)) {
841 if (breakpoint_address != (uint32_t) breakpoint_address ||
842 !RemoveBreakpoint((uint32_t) breakpoint_address)) {
846 pktOut->AddString("OK");
851 // If the command is not recognzied, ignore it by sending an
854 pktIn->GetString(&str);
855 NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload());
860 // If there is an error, return the error code instead of a payload
863 pktOut->AddRawChar('E');
864 pktOut->AddWord8(err);
870 void Target::TrackThread(struct NaClAppThread *natp) {
871 // natp->thread_num values are 0-based indexes, but we treat 0 as
872 // "not a thread ID", so we add 1.
873 uint32_t id = natp->thread_num + 1;
874 MutexLock lock(&mutex_);
875 CHECK(threads_[id] == 0);
876 threads_[id] = IThread::Create(id, natp);
879 void Target::IgnoreThread(struct NaClAppThread *natp) {
880 uint32_t id = natp->thread_num + 1;
881 MutexLock lock(&mutex_);
882 ThreadMap_t::iterator iter = threads_.find(id);
883 CHECK(iter != threads_.end());
885 threads_.erase(iter);
888 void Target::Exit() {
889 MutexLock lock(&mutex_);
890 if (session_ != NULL) {
892 if (NACL_ABI_WIFSIGNALED(nap_->exit_status)) {
893 exit_packet.AddRawChar('X');
894 exit_packet.AddWord8(NACL_ABI_WTERMSIG(nap_->exit_status));
896 exit_packet.AddRawChar('W');
897 exit_packet.AddWord8(NACL_ABI_WEXITSTATUS(nap_->exit_status));
899 session_->SendPacket(&exit_packet);
903 void Target::Detach() {
904 NaClLog(LOG_INFO, "Requested Detach.\n");
908 void Target::Kill() {
909 NaClLog(LOG_INFO, "Requested Kill.\n");
913 IThread* Target::GetRegThread() {
914 ThreadMap_t::const_iterator itr;
916 switch (reg_thread_) {
917 // If we want "any" then try the signal'd thread first
920 itr = threads_.begin();
924 itr = threads_.find(reg_thread_);
928 if (itr == threads_.end()) return 0;
933 IThread* Target::GetRunThread() {
934 // This is used to select a thread for "s" (step) command only.
935 // For multi-threaded targets, "s" is deprecated in favor of "vCont", which
936 // always specifies the thread explicitly when needed. However, we want
937 // to keep backward compatibility here, as using "s" when debugging
938 // a single-threaded program might be a popular use case.
939 if (threads_.size() == 1) {
940 return threads_.begin()->second;
945 IThread* Target::GetThread(uint32_t id) {
946 ThreadMap_t::const_iterator itr;
947 itr = threads_.find(id);
948 if (itr != threads_.end()) return itr->second;
953 void Target::SuspendAllThreads() {
954 NaClUntrustedThreadsSuspendAll(nap_, /* save_registers= */ 1);
955 for (ThreadMap_t::const_iterator iter = threads_.begin();
956 iter != threads_.end();
958 IThread *thread = iter->second;
959 thread->CopyRegistersFromAppThread();
960 CopyFaultSignalFromAppThread(thread);
964 void Target::ResumeAllThreads() {
965 for (ThreadMap_t::const_iterator iter = threads_.begin();
966 iter != threads_.end();
968 iter->second->CopyRegistersToAppThread();
970 NaClUntrustedThreadsResumeAll(nap_);
973 // UnqueueAnyFaultedThread() picks a thread that has been blocked as a
974 // result of faulting and unblocks it. It returns the thread's ID via
975 // |thread_id| and the type of fault via |signal|. As a precondition,
976 // all threads must be currently suspended.
977 void Target::UnqueueAnyFaultedThread(uint32_t *thread_id, int8_t *signal) {
978 for (ThreadMap_t::const_iterator iter = threads_.begin();
979 iter != threads_.end();
981 IThread *thread = iter->second;
982 if (thread->GetFaultSignal() != 0) {
983 *signal = thread->GetFaultSignal();
984 *thread_id = thread->GetId();
985 thread->UnqueueFaultedThread();
989 NaClLog(LOG_FATAL, "UnqueueAnyFaultedThread: No threads queued\n");
992 } // namespace gdb_rsp