| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 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 | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include <string.h> | 7 #include <string.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 #include <stdio.h> | 9 #include <stdio.h> |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 namespace gdb_rsp { | 34 namespace gdb_rsp { |
| 35 | 35 |
| 36 | 36 |
| 37 Target::Target(const Abi* abi) | 37 Target::Target(const Abi* abi) |
| 38 : abi_(abi), | 38 : abi_(abi), |
| 39 mutex_(NULL), | 39 mutex_(NULL), |
| 40 sig_start_(NULL), | 40 sig_start_(NULL), |
| 41 sig_done_(NULL), | 41 sig_done_(NULL), |
| 42 session_(NULL), | 42 session_(NULL), |
| 43 ctx_(NULL), | 43 ctx_(NULL), |
| 44 stepping_over_breakpoint_(false), |
| 44 cur_signal_(-1), | 45 cur_signal_(-1), |
| 45 sig_thread_(0), | 46 sig_thread_(0), |
| 46 run_thread_(-1), | 47 run_thread_(-1), |
| 47 reg_thread_(-1), | 48 reg_thread_(-1), |
| 48 mem_base_(0) { | 49 mem_base_(0) { |
| 49 if (NULL == abi_) abi_ = Abi::Get(); | 50 if (NULL == abi_) abi_ = Abi::Get(); |
| 50 } | 51 } |
| 51 | 52 |
| 52 Target::~Target() { | 53 Target::~Target() { |
| 53 Destroy(); | 54 Destroy(); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 176 |
| 176 return true; | 177 return true; |
| 177 } | 178 } |
| 178 | 179 |
| 179 | 180 |
| 180 | 181 |
| 181 void Target::Signal(uint32_t id, int8_t sig, bool wait) { | 182 void Target::Signal(uint32_t id, int8_t sig, bool wait) { |
| 182 // Wait for this signal's turn in the signal Q. | 183 // Wait for this signal's turn in the signal Q. |
| 183 sig_start_->Wait(); | 184 sig_start_->Wait(); |
| 184 { | 185 { |
| 185 // Now lock the target, sleeping all active threads | 186 // Now lock the target |
| 186 MutexLock lock(mutex_); | 187 MutexLock lock(mutex_); |
| 187 | 188 |
| 188 // Suspend all threads except this one | |
| 189 uint32_t curId; | |
| 190 bool more = GetFirstThreadId(&curId); | |
| 191 while (more) { | |
| 192 if (curId != id) { | |
| 193 IThread *thread = threads_[curId]; | |
| 194 thread->Suspend(); | |
| 195 } | |
| 196 more = GetNextThreadId(&curId); | |
| 197 } | |
| 198 | |
| 199 // Signal the stub (Run thread) that we are ready to process | 189 // Signal the stub (Run thread) that we are ready to process |
| 200 // a trap, by updating the signal information and releasing | 190 // a trap, by updating the signal information and releasing |
| 201 // the lock. | 191 // the lock. |
| 202 cur_signal_ = sig; | 192 cur_signal_ = sig; |
| 203 sig_thread_ = id; | 193 sig_thread_ = id; |
| 204 reg_thread_ = id; | 194 reg_thread_ = id; |
| 205 run_thread_ = id; | 195 run_thread_ = id; |
| 206 } | 196 } |
| 207 | 197 |
| 208 // Wait for permission to continue | 198 // Wait for permission to continue |
| (...skipping 18 matching lines...) Expand all Loading... |
| 227 | 217 |
| 228 // If no signal is waiting for this iteration... | 218 // If no signal is waiting for this iteration... |
| 229 if (-1 == cur_signal_) { | 219 if (-1 == cur_signal_) { |
| 230 // but the debugger is talking to us then force a break | 220 // but the debugger is talking to us then force a break |
| 231 if (ses->DataAvailable()) { | 221 if (ses->DataAvailable()) { |
| 232 // set signal to 0 to signify paused | 222 // set signal to 0 to signify paused |
| 233 cur_signal_ = 0; | 223 cur_signal_ = 0; |
| 234 sig_thread_ = 0; | 224 sig_thread_ = 0; |
| 235 | 225 |
| 236 // put all the threads to sleep. | 226 // put all the threads to sleep. |
| 237 uint32_t curId; | 227 IThread::SuspendAll(0); |
| 238 bool more = GetFirstThreadId(&curId); | |
| 239 while (more) { | |
| 240 if (curId != id) { | |
| 241 IThread *thread = threads_[curId]; | |
| 242 thread->Suspend(); | |
| 243 } | |
| 244 more = GetNextThreadId(&curId); | |
| 245 } | |
| 246 } else { | 228 } else { |
| 247 // otherwise, nothing to do so try again. | 229 // otherwise, nothing to do so try again. |
| 248 continue; | 230 continue; |
| 249 } | 231 } |
| 250 } else { | 232 } else { |
| 251 // otherwise there really is an exception so get the id of the thread | 233 // otherwise there really is an exception so get the id of the thread |
| 252 id = GetRegThreadId(); | 234 id = sig_thread_; |
| 235 |
| 236 // Suspend all threads, unless we just did a step over breakpoint without |
| 237 // resuming threads. |
| 238 if (!stepping_over_breakpoint_) { |
| 239 IThread::SuspendAll(id); |
| 240 } |
| 241 stepping_over_breakpoint_ = false; |
| 253 | 242 |
| 254 // Reset single stepping. | 243 // Reset single stepping. |
| 255 IThread *thread = threads_[id]; | 244 IThread *thread = threads_[id]; |
| 256 thread->SetStep(false); | 245 thread->SetStep(false); |
| 257 | 246 |
| 258 RemoveTemporaryBreakpoints(thread); | 247 RemoveTemporaryBreakpoints(thread); |
| 259 } | 248 } |
| 260 | 249 |
| 261 // Next update the current thread info | 250 // Next update the current thread info |
| 262 char tmp[16]; | 251 char tmp[16]; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 282 if (ProcessPacket(&recv, &reply)) { | 271 if (ProcessPacket(&recv, &reply)) { |
| 283 // If this is a continue command, break out of this loop | 272 // If this is a continue command, break out of this loop |
| 284 break; | 273 break; |
| 285 } else { | 274 } else { |
| 286 // Othwerise send the reponse | 275 // Othwerise send the reponse |
| 287 ses->SendPacket(&reply); | 276 ses->SendPacket(&reply); |
| 288 } | 277 } |
| 289 } | 278 } |
| 290 } while (ses->Connected()); | 279 } while (ses->Connected()); |
| 291 | 280 |
| 292 | 281 // Resume all threads, unless we need to single step signaled thread over |
| 293 // Now that we are done, we want to continue in the "correct order". | 282 // breakpoint. |
| 294 // This means letting the active thread go first, in case we are single | 283 if (!stepping_over_breakpoint_) { |
| 295 // stepping and want to catch it again. This is a desired behavior but | 284 IThread::ResumeAll(id); |
| 296 // it is not guaranteed since another thread may already be in an | |
| 297 // exception state and next in line to notify the target. | |
| 298 | |
| 299 // If the run thread is not the exception thread, wake it up now. | |
| 300 uint32_t run_thread = GetRunThreadId(); | |
| 301 if (run_thread != id | |
| 302 && run_thread != static_cast<uint32_t>(-1)) { | |
| 303 IThread* thread = threads_[run_thread]; | |
| 304 thread->Resume(); | |
| 305 } | |
| 306 | |
| 307 // Now wake up everyone else | |
| 308 uint32_t curId; | |
| 309 bool more = GetFirstThreadId(&curId); | |
| 310 while (more) { | |
| 311 if ((curId != id) && (curId != GetRunThreadId())) { | |
| 312 IThread *thread = threads_[curId]; | |
| 313 thread->Resume(); | |
| 314 } | |
| 315 more = GetNextThreadId(&curId); | |
| 316 } | 285 } |
| 317 | 286 |
| 318 // Reset the signal value | 287 // Reset the signal value |
| 319 cur_signal_ = -1; | 288 cur_signal_ = -1; |
| 320 | 289 |
| 321 // If there is no signaled thread, then we were interrupted by GDB, and | 290 // If there is no signaled thread, then we were interrupted by GDB, and |
| 322 // there is no signal handler waiting. | 291 // there is no signal handler waiting. |
| 323 // If there was a signaled thread, let the signal handler resume. | 292 // If there was a signaled thread, let the signal handler resume. |
| 324 if (id != 0) { | 293 if (id != 0) { |
| 325 sig_done_->Signal(); | 294 sig_done_->Signal(); |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 } | 625 } |
| 657 | 626 |
| 658 ThreadMap_t::iterator it = threads_.find(thread_id); | 627 ThreadMap_t::iterator it = threads_.find(thread_id); |
| 659 if (it == threads_.end()) { | 628 if (it == threads_.end()) { |
| 660 err = BAD_ARGS; | 629 err = BAD_ARGS; |
| 661 break; | 630 break; |
| 662 } | 631 } |
| 663 | 632 |
| 664 it->second->SetStep(true); | 633 it->second->SetStep(true); |
| 665 run_thread_ = thread_id; | 634 run_thread_ = thread_id; |
| 635 // TODO: check thread_id is signaled thread id! |
| 636 // This is the only case we allow one thread to single step while |
| 637 // others remain stopped. |
| 638 stepping_over_breakpoint_ = true; |
| 666 return true; | 639 return true; |
| 667 } | 640 } |
| 668 | 641 |
| 669 // Unsupported form of vCont. | 642 // Unsupported form of vCont. |
| 670 err = BAD_FORMAT; | 643 err = BAD_FORMAT; |
| 671 break; | 644 break; |
| 672 } | 645 } |
| 673 | 646 |
| 674 NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload()); | 647 NaClLog(LOG_ERROR, "Unknown command: %s\n", pktIn->GetPayload()); |
| 675 return false; | 648 return false; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 | 731 |
| 759 return NULL; | 732 return NULL; |
| 760 } | 733 } |
| 761 | 734 |
| 762 | 735 |
| 763 } // namespace gdb_rsp | 736 } // namespace gdb_rsp |
| 764 | 737 |
| 765 | 738 |
| 766 | 739 |
| 767 | 740 |
| OLD | NEW |