- add third_party src.
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / debug_stub / target.cc
1 /*
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.
5  */
6
7 #include <string.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10
11 #include <algorithm>
12
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_log.h"
16 #include "native_client/src/trusted/debug_stub/abi.h"
17 #include "native_client/src/trusted/debug_stub/packet.h"
18 #include "native_client/src/trusted/debug_stub/platform.h"
19 #include "native_client/src/trusted/debug_stub/session.h"
20 #include "native_client/src/trusted/debug_stub/target.h"
21 #include "native_client/src/trusted/debug_stub/thread.h"
22 #include "native_client/src/trusted/debug_stub/util.h"
23 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
24 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
25 #include "native_client/src/trusted/service_runtime/thread_suspension.h"
26
27 #if NACL_WINDOWS
28 #define snprintf sprintf_s
29 #endif
30
31 using std::string;
32
33 using port::IPlatform;
34 using port::IThread;
35 using port::MutexLock;
36
37 namespace gdb_rsp {
38
39
40 Target::Target(struct NaClApp *nap, const Abi* abi)
41   : nap_(nap),
42     abi_(abi),
43     session_(NULL),
44     initial_breakpoint_addr_(0),
45     ctx_(NULL),
46     cur_signal_(0),
47     sig_thread_(0),
48     reg_thread_(0),
49     step_over_breakpoint_thread_(0) {
50   if (NULL == abi_) abi_ = Abi::Get();
51 }
52
53 Target::~Target() {
54   Destroy();
55 }
56
57 bool Target::Init() {
58   string targ_xml = "l<target><architecture>";
59
60   targ_xml += abi_->GetName();
61   targ_xml += "</architecture><osabi>NaCl</osabi>";
62   targ_xml += abi_->GetTargetXml();
63   targ_xml += "</target>";
64
65   // Set a more specific result which won't change.
66   properties_["target.xml"] = targ_xml;
67   properties_["Supported"] =
68     "PacketSize=1000;qXfer:features:read+";
69
70   NaClXMutexCtor(&mutex_);
71   ctx_ = new uint8_t[abi_->GetContextSize()];
72
73   initial_breakpoint_addr_ = (uint32_t) nap_->initial_entry_pt;
74   if (!AddBreakpoint(initial_breakpoint_addr_))
75     return false;
76   return true;
77 }
78
79 void Target::Destroy() {
80   NaClMutexDtor(&mutex_);
81
82   delete[] ctx_;
83 }
84
85 bool Target::AddBreakpoint(uint32_t user_address) {
86   const Abi::BPDef *bp = abi_->GetBreakpointDef();
87
88   // If we already have a breakpoint here then don't add it
89   if (breakpoint_map_.find(user_address) != breakpoint_map_.end())
90     return false;
91
92   uintptr_t sysaddr = NaClUserToSysAddrRange(nap_, user_address, bp->size_);
93   if (sysaddr == kNaClBadAddress)
94     return false;
95   // We allow setting breakpoints in the code area but not the data area.
96   if (user_address + bp->size_ > nap_->dynamic_text_end)
97     return false;
98
99   // We add the breakpoint by overwriting the start of an instruction
100   // with a breakpoint instruction.  (At least, we assume that we have
101   // been given the address of the start of an instruction.)  In order
102   // to be able to remove the breakpoint later, we save a copy of the
103   // locations we are overwriting into breakpoint_map_.
104   uint8_t *data = new uint8_t[bp->size_];
105
106   // Copy the old code from here
107   if (!IPlatform::GetMemory(sysaddr, bp->size_, data)) {
108     delete[] data;
109     return false;
110   }
111   if (!IPlatform::SetMemory(nap_, sysaddr, bp->size_, bp->code_)) {
112     delete[] data;
113     return false;
114   }
115
116   breakpoint_map_[user_address] = data;
117   return true;
118 }
119
120 bool Target::RemoveBreakpoint(uint32_t user_address) {
121   const Abi::BPDef *bp_def = abi_->GetBreakpointDef();
122
123   BreakpointMap_t::iterator iter = breakpoint_map_.find(user_address);
124   if (iter == breakpoint_map_.end())
125     return false;
126
127   uintptr_t sysaddr = NaClUserToSys(nap_, user_address);
128   uint8_t *data = iter->second;
129   // Copy back the old code, and free the data
130   if (!IPlatform::SetMemory(nap_, sysaddr, bp_def->size_, data)) {
131     NaClLog(LOG_ERROR, "Failed to undo breakpoint.\n");
132     return false;
133   }
134   delete[] data;
135   breakpoint_map_.erase(iter);
136   return true;
137 }
138
139 void Target::CopyFaultSignalFromAppThread(IThread *thread) {
140   if (thread->GetFaultSignal() == 0 && thread->HasThreadFaulted()) {
141     int signal =
142         IThread::ExceptionToSignal(thread->GetAppThread()->fault_signal);
143     // If a thread hits a breakpoint, we want to ensure that it is
144     // reported as SIGTRAP rather than SIGSEGV.  This is necessary
145     // because we use HLT (which produces SIGSEGV) rather than the
146     // more usual INT3 (which produces SIGTRAP) on x86, in order to
147     // work around a Mac OS X bug.
148     //
149     // We need to check each thread to see whether it hit a
150     // breakpoint.  We record this on the thread object because:
151     //  * We need to check the threads before accepting any commands
152     //    from GDB which might remove breakpoints from
153     //    breakpoint_map_, which would remove our ability to tell
154     //    whether a thread hit a breakpoint.
155     //  * Although we deliver fault events to GDB one by one, we might
156     //    have multiple threads that have hit breakpoints.
157     if (signal == NACL_ABI_SIGSEGV) {
158       // Casting to uint32_t is necessary to drop the top 32 bits of
159       // %rip on x86-64.
160       uint32_t prog_ctr = (uint32_t) thread->GetContext()->prog_ctr;
161       if (breakpoint_map_.find(prog_ctr) != breakpoint_map_.end()) {
162         signal = NACL_ABI_SIGTRAP;
163       }
164     }
165     thread->SetFaultSignal(signal);
166   }
167 }
168
169 void Target::RemoveInitialBreakpoint() {
170   if (initial_breakpoint_addr_ != 0) {
171     if (!RemoveBreakpoint(initial_breakpoint_addr_)) {
172       NaClLog(LOG_FATAL,
173               "RemoveInitialBreakpoint: Failed to remove breakpoint\n");
174     }
175     initial_breakpoint_addr_ = 0;
176   }
177 }
178
179 // When the debugger reads memory, we want to report the original
180 // memory contents without the modifications we made to add
181 // breakpoints.  This function undoes the modifications from a copy of
182 // memory.
183 void Target::EraseBreakpointsFromCopyOfMemory(uint32_t user_address,
184                                               uint8_t *data, uint32_t size) {
185   uint32_t user_end = user_address + size;
186   const Abi::BPDef *bp = abi_->GetBreakpointDef();
187   for (BreakpointMap_t::iterator iter = breakpoint_map_.begin();
188        iter != breakpoint_map_.end();
189        ++iter) {
190     uint32_t breakpoint_address = iter->first;
191     uint32_t breakpoint_end = breakpoint_address + bp->size_;
192     uint8_t *original_data = iter->second;
193
194     uint32_t overlap_start = std::max(user_address, breakpoint_address);
195     uint32_t overlap_end = std::min(user_end, breakpoint_end);
196     if (overlap_start < overlap_end) {
197       uint8_t *dest = data + (overlap_start - user_address);
198       uint8_t *src = original_data + (overlap_start - breakpoint_address);
199       size_t copy_size = overlap_end - overlap_start;
200       // Sanity check: do some bounds checks.
201       CHECK(data <= dest && dest + copy_size <= data + size);
202       CHECK(original_data <= src
203             && src + copy_size <= original_data + bp->size_);
204       memcpy(dest, src, copy_size);
205     }
206   }
207 }
208
209 void Target::Run(Session *ses) {
210   bool initial_breakpoint_seen = false;
211   NaClXMutexLock(&mutex_);
212   session_ = ses;
213   NaClXMutexUnlock(&mutex_);
214   do {
215     bool ignore_input_from_gdb = step_over_breakpoint_thread_ != 0 ||
216         !initial_breakpoint_seen;
217     ses->WaitForDebugStubEvent(nap_, ignore_input_from_gdb);
218
219     // Lock to prevent anyone else from modifying threads
220     // or updating the signal information.
221     MutexLock lock(&mutex_);
222     Packet recv, reply;
223
224     if (step_over_breakpoint_thread_ != 0) {
225       // We are waiting for a specific thread to fault while all other
226       // threads are suspended.  Note that faulted_thread_count might
227       // be >1, because multiple threads can fault simultaneously
228       // before the debug stub gets a chance to suspend all threads.
229       // This is why we must check the status of a specific thread --
230       // we cannot call UnqueueAnyFaultedThread() and expect it to
231       // return step_over_breakpoint_thread_.
232       IThread *thread = threads_[step_over_breakpoint_thread_];
233       if (!thread->HasThreadFaulted()) {
234         // The thread has not faulted.  Nothing to do, so try again.
235         // Note that we do not respond to input from GDB while in this
236         // state.
237         // TODO(mseaborn): We should allow GDB to interrupt execution.
238         continue;
239       }
240       // All threads but one are already suspended.  We only need to
241       // suspend the single thread that we allowed to run.
242       thread->SuspendThread();
243       CopyFaultSignalFromAppThread(thread);
244       cur_signal_ = thread->GetFaultSignal();
245       thread->UnqueueFaultedThread();
246       sig_thread_ = step_over_breakpoint_thread_;
247       reg_thread_ = step_over_breakpoint_thread_;
248       step_over_breakpoint_thread_ = 0;
249     } else if (nap_->faulted_thread_count != 0) {
250       // At least one untrusted thread has got an exception.  First we
251       // need to ensure that all threads are suspended.  Then we can
252       // retrieve a thread from the set of faulted threads.
253       SuspendAllThreads();
254       UnqueueAnyFaultedThread(&sig_thread_, &cur_signal_);
255       reg_thread_ = sig_thread_;
256     } else {
257       // Otherwise look for messages from GDB.  To fix a potential
258       // race condition, we don't do this on the first run, because in
259       // that case we are waiting for the initial breakpoint to be
260       // reached.  We don't want GDB to observe states where the
261       // (internal) initial breakpoint is still registered or where
262       // the initial thread is suspended in NaClStartThreadInApp()
263       // before executing its first untrusted instruction.
264       if (!initial_breakpoint_seen || !ses->IsDataAvailable()) {
265         // No input from GDB.  Nothing to do, so try again.
266         continue;
267       }
268       // GDB should have tried to interrupt the target.
269       // See http://sourceware.org/gdb/current/onlinedocs/gdb/Interrupts.html
270       // TODO(eaeltsin): should we verify the interrupt sequence?
271
272       // Indicate we have no current thread.
273       // TODO(eaeltsin): or pick any thread? Add a test.
274       // See http://code.google.com/p/nativeclient/issues/detail?id=2743
275       sig_thread_ = 0;
276       SuspendAllThreads();
277     }
278
279     if (sig_thread_ != 0) {
280       // Reset single stepping.
281       threads_[sig_thread_]->SetStep(false);
282       RemoveInitialBreakpoint();
283     }
284
285     // Next update the current thread info
286     char tmp[16];
287     snprintf(tmp, sizeof(tmp), "QC%x", sig_thread_);
288     properties_["C"] = tmp;
289
290     if (!initial_breakpoint_seen) {
291       // First time on a connection, we don't send the signal
292       initial_breakpoint_seen = true;
293     } else {
294       // All other times, send the signal that triggered us
295       Packet pktOut;
296       SetStopReply(&pktOut);
297       ses->SendPacketOnly(&pktOut);
298     }
299
300     // Now we are ready to process commands
301     // Loop through packets until we process a continue
302     // packet.
303     do {
304       if (ses->GetPacket(&recv)) {
305         reply.Clear();
306         if (ProcessPacket(&recv, &reply)) {
307           // If this is a continue command, break out of this loop
308           break;
309         } else {
310           // Othwerise send the reponse
311           ses->SendPacket(&reply);
312         }
313       }
314     } while (ses->Connected());
315
316     // Reset the signal value
317     cur_signal_ = 0;
318
319     // TODO(eaeltsin): it might make sense to resume signaled thread before
320     // others, though it is not required by GDB docs.
321     if (step_over_breakpoint_thread_ == 0) {
322       ResumeAllThreads();
323     } else {
324       // Resume one thread while leaving all others suspended.
325       threads_[step_over_breakpoint_thread_]->ResumeThread();
326     }
327
328     // Continue running until the connection is lost.
329   } while (ses->Connected());
330   NaClXMutexLock(&mutex_);
331   session_ = NULL;
332   NaClXMutexUnlock(&mutex_);
333 }
334
335
336 void Target::SetStopReply(Packet *pktOut) const {
337   pktOut->AddRawChar('T');
338   pktOut->AddWord8(cur_signal_);
339
340   // gdbserver handles GDB interrupt by sending SIGINT to the debuggee, thus
341   // GDB interrupt is also a case of a signalled thread.
342   // At the moment we handle GDB interrupt differently, without using a signal,
343   // so in this case sig_thread_ is 0.
344   // This might seem weird to GDB, so at least avoid reporting tid 0.
345   // TODO(eaeltsin): http://code.google.com/p/nativeclient/issues/detail?id=2743
346   if (sig_thread_ != 0) {
347     // Add 'thread:<tid>;' pair. Note terminating ';' is required.
348     pktOut->AddString("thread:");
349     pktOut->AddNumberSep(sig_thread_, ';');
350   }
351 }
352
353
354 bool Target::GetFirstThreadId(uint32_t *id) {
355   threadItr_ = threads_.begin();
356   return GetNextThreadId(id);
357 }
358
359 bool Target::GetNextThreadId(uint32_t *id) {
360   if (threadItr_ == threads_.end()) return false;
361
362   *id = (*threadItr_).first;
363   threadItr_++;
364
365   return true;
366 }
367
368
369 uint64_t Target::AdjustUserAddr(uint64_t addr) {
370   // On x86-64, GDB sometimes uses memory addresses with the %r15
371   // sandbox base included, so we must accept these addresses.
372   // TODO(eaeltsin): Fix GDB to not use addresses with %r15 added.
373   if (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64 &&
374       NaClIsUserAddr(nap_, (uintptr_t) addr)) {
375     return NaClSysToUser(nap_, (uintptr_t) addr);
376   }
377   // Otherwise, we expect an untrusted address.
378   return addr;
379 }
380
381 bool Target::ProcessPacket(Packet* pktIn, Packet* pktOut) {
382   char cmd;
383   int32_t seq = -1;
384   ErrDef  err = NONE;
385
386   // Clear the outbound message
387   pktOut->Clear();
388
389   // Pull out the sequence.
390   pktIn->GetSequence(&seq);
391   if (seq != -1) pktOut->SetSequence(seq);
392
393   // Find the command
394   pktIn->GetRawChar(&cmd);
395
396   switch (cmd) {
397     // IN : $?
398     // OUT: $Sxx
399     case '?':
400       SetStopReply(pktOut);
401       break;
402
403     case 'c':
404       return true;
405
406     // IN : $d
407     // OUT: -NONE-
408     case 'd':
409       Detach();
410       break;
411
412     // IN : $g
413     // OUT: $xx...xx
414     case 'g': {
415       IThread *thread = GetRegThread();
416       if (NULL == thread) {
417         err = BAD_ARGS;
418         break;
419       }
420
421       // Copy OS preserved registers to GDB payload
422       for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
423         const Abi::RegDef *def = abi_->GetRegisterDef(a);
424         thread->GetRegister(a, &ctx_[def->offset_], def->bytes_);
425       }
426
427       pktOut->AddBlock(ctx_, abi_->GetContextSize());
428       break;
429     }
430
431     // IN : $Gxx..xx
432     // OUT: $OK
433     case 'G': {
434       IThread *thread = GetRegThread();
435       if (NULL == thread) {
436         err = BAD_ARGS;
437         break;
438       }
439
440       pktIn->GetBlock(ctx_, abi_->GetContextSize());
441
442       // GDB payload to OS registers
443       for (uint32_t a = 0; a < abi_->GetRegisterCount(); a++) {
444         const Abi::RegDef *def = abi_->GetRegisterDef(a);
445         thread->SetRegister(a, &ctx_[def->offset_], def->bytes_);
446       }
447
448       pktOut->AddString("OK");
449       break;
450     }
451
452     // IN : $H(c/g)(-1,0,xxxx)
453     // OUT: $OK
454     case 'H': {
455         char type;
456         uint64_t id;
457
458         if (!pktIn->GetRawChar(&type)) {
459           err = BAD_FORMAT;
460           break;
461         }
462         if (!pktIn->GetNumberSep(&id, 0)) {
463           err = BAD_FORMAT;
464           break;
465         }
466
467         if (threads_.begin() == threads_.end()) {
468             err = BAD_ARGS;
469             break;
470         }
471
472         // If we are using "any" get the first thread
473         if (id == static_cast<uint64_t>(-1)) id = threads_.begin()->first;
474
475         // Verify that we have the thread
476         if (threads_.find(static_cast<uint32_t>(id)) == threads_.end()) {
477           err = BAD_ARGS;
478           break;
479         }
480
481         pktOut->AddString("OK");
482         switch (type) {
483           case 'g':
484             reg_thread_ = static_cast<uint32_t>(id);
485             break;
486
487           case 'c':
488             // 'c' is deprecated in favor of vCont.
489           default:
490             err = BAD_ARGS;
491             break;
492         }
493         break;
494       }
495
496     // IN : $maaaa,llll
497     // OUT: $xx..xx
498     case 'm': {
499         uint64_t user_addr;
500         uint64_t wlen;
501         uint32_t len;
502         if (!pktIn->GetNumberSep(&user_addr, 0)) {
503           err = BAD_FORMAT;
504           break;
505         }
506         if (!pktIn->GetNumberSep(&wlen, 0)) {
507           err = BAD_FORMAT;
508           break;
509         }
510         user_addr = AdjustUserAddr(user_addr);
511         uint64_t sys_addr = NaClUserToSysAddrRange(nap_, (uintptr_t) user_addr,
512                                                    (size_t) wlen);
513         if (sys_addr == kNaClBadAddress) {
514           err = FAILED;
515           break;
516         }
517
518         len = static_cast<uint32_t>(wlen);
519         nacl::scoped_array<uint8_t> block(new uint8_t[len]);
520         if (!port::IPlatform::GetMemory(sys_addr, len, block.get())) {
521           err = FAILED;
522           break;
523         }
524         EraseBreakpointsFromCopyOfMemory((uint32_t) user_addr,
525                                          block.get(), len);
526
527         pktOut->AddBlock(block.get(), len);
528         break;
529       }
530
531     // IN : $Maaaa,llll:xx..xx
532     // OUT: $OK
533     case 'M':  {
534         uint64_t user_addr;
535         uint64_t wlen;
536         uint32_t len;
537
538         if (!pktIn->GetNumberSep(&user_addr, 0)) {
539           err = BAD_FORMAT;
540           break;
541         }
542         if (!pktIn->GetNumberSep(&wlen, 0)) {
543           err = BAD_FORMAT;
544           break;
545         }
546         user_addr = AdjustUserAddr(user_addr);
547         uint64_t sys_addr = NaClUserToSysAddrRange(nap_, (uintptr_t) user_addr,
548                                                    (size_t) wlen);
549         if (sys_addr == kNaClBadAddress) {
550           err = FAILED;
551           break;
552         }
553         len = static_cast<uint32_t>(wlen);
554         // We disallow the debugger from modifying code.
555         if (user_addr < nap_->dynamic_text_end) {
556           err = FAILED;
557           break;
558         }
559
560         nacl::scoped_array<uint8_t> block(new uint8_t[len]);
561         pktIn->GetBlock(block.get(), len);
562
563         if (!port::IPlatform::SetMemory(nap_, sys_addr, len, block.get())) {
564           err = FAILED;
565           break;
566         }
567
568         pktOut->AddString("OK");
569         break;
570       }
571
572     case 'q': {
573       string tmp;
574       const char *str = &pktIn->GetPayload()[1];
575       stringvec toks = StringSplit(str, ":;");
576       PropertyMap_t::const_iterator itr = properties_.find(toks[0]);
577
578       // If this is a thread query
579       if (!strcmp(str, "fThreadInfo") || !strcmp(str, "sThreadInfo")) {
580         uint32_t curr;
581         bool more = false;
582         if (str[0] == 'f') {
583           more = GetFirstThreadId(&curr);
584         } else {
585           more = GetNextThreadId(&curr);
586         }
587
588         if (!more) {
589           pktOut->AddString("l");
590         } else {
591           pktOut->AddString("m");
592           pktOut->AddNumberSep(curr, 0);
593         }
594         break;
595       }
596
597       // Check for architecture query
598       tmp = "Xfer:features:read:target.xml";
599       if (!strncmp(str, tmp.data(), tmp.length())) {
600         stringvec args = StringSplit(&str[tmp.length()+1], ",");
601         if (args.size() != 2) break;
602
603         const char *out = properties_["target.xml"].data();
604         int offs = strtol(args[0].data(), NULL, 16);
605         int max  = strtol(args[1].data(), NULL, 16) + offs;
606         int len  = static_cast<int>(strlen(out));
607
608         if (max >= len) max = len;
609
610         while (offs < max) {
611           pktOut->AddRawChar(out[offs]);
612           offs++;
613         }
614         break;
615       }
616
617       // Check the property cache
618       if (itr != properties_.end()) {
619         pktOut->AddString(itr->second.data());
620       }
621       break;
622     }
623
624     case 's': {
625       IThread *thread = GetRunThread();
626       if (thread) thread->SetStep(true);
627       return true;
628     }
629
630     case 'T': {
631       uint64_t id;
632       if (!pktIn->GetNumberSep(&id, 0)) {
633         err = BAD_FORMAT;
634         break;
635       }
636
637       if (GetThread(static_cast<uint32_t>(id)) == NULL) {
638         err = BAD_ARGS;
639         break;
640       }
641
642       pktOut->AddString("OK");
643       break;
644     }
645
646     case 'v': {
647       const char *str = pktIn->GetPayload() + 1;
648
649       if (strncmp(str, "Cont", 4) == 0) {
650         // vCont
651         const char *subcommand = str + 4;
652
653         if (strcmp(subcommand, "?") == 0) {
654           // Report supported vCont actions. These 4 are required.
655           pktOut->AddString("vCont;s;S;c;C");
656           break;
657         }
658
659         if (strcmp(subcommand, ";c") == 0) {
660           // Continue all threads.
661           return true;
662         }
663
664         if (strncmp(subcommand, ";s:", 3) == 0) {
665           // Single step one thread and optionally continue all other threads.
666           char *end;
667           uint32_t thread_id = static_cast<uint32_t>(
668               strtol(subcommand + 3, &end, 16));
669           if (end == subcommand + 3) {
670             err = BAD_ARGS;
671             break;
672           }
673
674           ThreadMap_t::iterator it = threads_.find(thread_id);
675           if (it == threads_.end()) {
676             err = BAD_ARGS;
677             break;
678           }
679
680           if (*end == 0) {
681             // Single step one thread and keep other threads stopped.
682             // GDB uses this to continue from a breakpoint, which works by:
683             // - replacing trap instruction with the original instruction;
684             // - single-stepping through the original instruction. Other threads
685             //   must remain stopped, otherwise they might execute the code at
686             //   the same address and thus miss the breakpoint;
687             // - replacing the original instruction with trap instruction;
688             // - continuing all threads;
689             if (thread_id != sig_thread_) {
690               err = BAD_ARGS;
691               break;
692             }
693             step_over_breakpoint_thread_ = sig_thread_;
694           } else if (strcmp(end, ";c") == 0) {
695             // Single step one thread and continue all other threads.
696           } else {
697             // Unsupported combination of single step and other args.
698             err = BAD_ARGS;
699             break;
700           }
701
702           it->second->SetStep(true);
703           return true;
704         }
705
706         // Continue one thread and keep other threads stopped.
707         //
708         // GDB sends this for software single step, which is used:
709         // - on Win64 to step over rsp modification and subsequent rsp
710         //   sandboxing at once. For details, see:
711         //     http://code.google.com/p/nativeclient/issues/detail?id=2903
712         // - TODO: on ARM, which has no hardware support for single step
713         // - TODO: to step over syscalls
714         //
715         // Unfortunately, we can't make this just Win-specific. We might
716         // use Linux GDB to connect to Win debug stub, so even Linux GDB
717         // should send software single step. Vice versa, software single
718         // step-enabled Win GDB might be connected to Linux debug stub,
719         // so even Linux debug stub should accept software single step.
720         if (strncmp(subcommand, ";c:", 3) == 0) {
721           char *end;
722           uint32_t thread_id = static_cast<uint32_t>(
723               strtol(subcommand + 3, &end, 16));
724           if (end != subcommand + 3 && *end == 0) {
725             if (thread_id == sig_thread_) {
726               step_over_breakpoint_thread_ = sig_thread_;
727               return true;
728             }
729           }
730
731           err = BAD_ARGS;
732           break;
733         }
734
735         // Unsupported form of vCont.
736         err = BAD_FORMAT;
737         break;
738       }
739
740       NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload());
741       return false;
742     }
743
744     case 'Z': {
745       uint64_t breakpoint_type;
746       uint64_t breakpoint_address;
747       uint64_t breakpoint_kind;
748       if (!pktIn->GetNumberSep(&breakpoint_type, 0) ||
749           breakpoint_type != 0 ||
750           !pktIn->GetNumberSep(&breakpoint_address, 0) ||
751           !pktIn->GetNumberSep(&breakpoint_kind, 0)) {
752         err = BAD_FORMAT;
753         break;
754       }
755       if (breakpoint_address != (uint32_t) breakpoint_address ||
756           !AddBreakpoint((uint32_t) breakpoint_address)) {
757         err = FAILED;
758         break;
759       }
760       pktOut->AddString("OK");
761       break;
762     }
763
764     case 'z': {
765       uint64_t breakpoint_type;
766       uint64_t breakpoint_address;
767       uint64_t breakpoint_kind;
768       if (!pktIn->GetNumberSep(&breakpoint_type, 0) ||
769           breakpoint_type != 0 ||
770           !pktIn->GetNumberSep(&breakpoint_address, 0) ||
771           !pktIn->GetNumberSep(&breakpoint_kind, 0)) {
772         err = BAD_FORMAT;
773         break;
774       }
775       if (breakpoint_address != (uint32_t) breakpoint_address ||
776           !RemoveBreakpoint((uint32_t) breakpoint_address)) {
777         err = FAILED;
778         break;
779       }
780       pktOut->AddString("OK");
781       break;
782     }
783
784     default: {
785       // If the command is not recognzied, ignore it by sending an
786       // empty reply.
787       string str;
788       pktIn->GetString(&str);
789       NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload());
790       return false;
791     }
792   }
793
794   // If there is an error, return the error code instead of a payload
795   if (err) {
796     pktOut->Clear();
797     pktOut->AddRawChar('E');
798     pktOut->AddWord8(err);
799   }
800   return false;
801 }
802
803
804 void Target::TrackThread(struct NaClAppThread *natp) {
805   // natp->thread_num values are 0-based indexes, but we treat 0 as
806   // "not a thread ID", so we add 1.
807   uint32_t id = natp->thread_num + 1;
808   MutexLock lock(&mutex_);
809   CHECK(threads_[id] == 0);
810   threads_[id] = IThread::Create(id, natp);
811 }
812
813 void Target::IgnoreThread(struct NaClAppThread *natp) {
814   uint32_t id = natp->thread_num + 1;
815   MutexLock lock(&mutex_);
816   ThreadMap_t::iterator iter = threads_.find(id);
817   CHECK(iter != threads_.end());
818   delete iter->second;
819   threads_.erase(iter);
820 }
821
822 void Target::Exit() {
823   MutexLock lock(&mutex_);
824   if (session_ != NULL) {
825     Packet exit_packet;
826     if (NACL_ABI_WIFSIGNALED(nap_->exit_status)) {
827       exit_packet.AddRawChar('X');
828       exit_packet.AddWord8(NACL_ABI_WTERMSIG(nap_->exit_status));
829     } else {
830       exit_packet.AddRawChar('W');
831       exit_packet.AddWord8(NACL_ABI_WEXITSTATUS(nap_->exit_status));
832     }
833     session_->SendPacket(&exit_packet);
834   }
835 }
836
837 void Target::Detach() {
838   NaClLog(LOG_INFO, "Requested Detach.\n");
839 }
840
841
842 IThread* Target::GetRegThread() {
843   ThreadMap_t::const_iterator itr;
844
845   switch (reg_thread_) {
846     // If we want "any" then try the signal'd thread first
847     case 0:
848     case 0xFFFFFFFF:
849       itr = threads_.begin();
850       break;
851
852     default:
853       itr = threads_.find(reg_thread_);
854       break;
855   }
856
857   if (itr == threads_.end()) return 0;
858
859   return itr->second;
860 }
861
862 IThread* Target::GetRunThread() {
863   // This is used to select a thread for "s" (step) command only.
864   // For multi-threaded targets, "s" is deprecated in favor of "vCont", which
865   // always specifies the thread explicitly when needed. However, we want
866   // to keep backward compatibility here, as using "s" when debugging
867   // a single-threaded program might be a popular use case.
868   if (threads_.size() == 1) {
869     return threads_.begin()->second;
870   }
871   return NULL;
872 }
873
874 IThread* Target::GetThread(uint32_t id) {
875   ThreadMap_t::const_iterator itr;
876   itr = threads_.find(id);
877   if (itr != threads_.end()) return itr->second;
878
879   return NULL;
880 }
881
882 void Target::SuspendAllThreads() {
883   NaClUntrustedThreadsSuspendAll(nap_, /* save_registers= */ 1);
884   for (ThreadMap_t::const_iterator iter = threads_.begin();
885        iter != threads_.end();
886        ++iter) {
887     IThread *thread = iter->second;
888     thread->CopyRegistersFromAppThread();
889     CopyFaultSignalFromAppThread(thread);
890   }
891 }
892
893 void Target::ResumeAllThreads() {
894   for (ThreadMap_t::const_iterator iter = threads_.begin();
895        iter != threads_.end();
896        ++iter) {
897     iter->second->CopyRegistersToAppThread();
898   }
899   NaClUntrustedThreadsResumeAll(nap_);
900 }
901
902 // UnqueueAnyFaultedThread() picks a thread that has been blocked as a
903 // result of faulting and unblocks it.  It returns the thread's ID via
904 // |thread_id| and the type of fault via |signal|.  As a precondition,
905 // all threads must be currently suspended.
906 void Target::UnqueueAnyFaultedThread(uint32_t *thread_id, int8_t *signal) {
907   for (ThreadMap_t::const_iterator iter = threads_.begin();
908        iter != threads_.end();
909        ++iter) {
910     IThread *thread = iter->second;
911     if (thread->GetFaultSignal() != 0) {
912       *signal = thread->GetFaultSignal();
913       *thread_id = thread->GetId();
914       thread->UnqueueFaultedThread();
915       return;
916     }
917   }
918   NaClLog(LOG_FATAL, "UnqueueAnyFaultedThread: No threads queued\n");
919 }
920
921 }  // namespace gdb_rsp