ErrorCode ProcessBase::resume(int signal, std::set<Thread *> const &excluded) { enumerateThreads([&](Thread *thread) { if (excluded.find(thread) != excluded.end()) return; switch (thread->state()) { case Thread::kInvalid: case Thread::kTerminated: DS2BUG("trying to resume tid %" PRI_PID " in state %s", thread->tid(), Stringify::ThreadState(thread->state())); break; case Thread::kRunning: DS2LOG(Debug, "not resuming tid %" PRI_PID ", already in state %s", thread->tid(), Stringify::ThreadState(thread->state())); break; case Thread::kStopped: case Thread::kStepped: { Architecture::CPUState state; thread->readCPUState(state); DS2LOG(Debug, "resuming tid %" PRI_PID " from pc %" PRI_PTR " with signal %d", thread->tid(), PRI_PTR_CAST(state.pc()), signal); ErrorCode error = thread->resume(signal); if (error != kSuccess) { DS2LOG(Warning, "failed resuming tid %" PRI_PID ", error=%s", thread->tid(), Stringify::Error(error)); } } break; } }); return kSuccess; }
ErrorCode Process::suspend() { std::set<Thread *> threads; enumerateThreads([&](Thread *thread) { threads.insert(thread); }); for (auto thread : threads) { Architecture::CPUState state; if (thread->state() != Thread::kRunning) { thread->readCPUState(state); } DS2LOG(Debug, "tid %d state %d at pc %#" PRIx64, thread->tid(), thread->state(), thread->state() == Thread::kStopped ? (uint64_t)state.pc() : 0); if (thread->state() == Thread::kRunning) { ErrorCode error; DS2LOG(Debug, "suspending tid %d", thread->tid()); error = thread->suspend(); if (error == kSuccess) { DS2LOG(Debug, "suspended tid %d at pc %#" PRIx64, thread->tid(), (uint64_t)state.pc()); thread->readCPUState(state); } else if (error == kErrorProcessNotFound) { // // Thread is dead. // removeThread(thread->tid()); DS2LOG(Debug, "tried to suspended tid %d which is already dead", thread->tid()); } else { return error; } } else if (thread->state() == Thread::kTerminated) { // // Thread is dead. // removeThread(thread->tid()); } } return kSuccess; }
ErrorCode Process::resume(int signal, std::set<Thread *> const &excluded) { enumerateThreads([&](Thread *thread) { if (excluded.find(thread) != excluded.end()) return; if (thread->state() == Thread::kStopped || thread->state() == Thread::kStepped) { Architecture::CPUState state; thread->readCPUState(state); DS2LOG(Debug, "resuming tid %I64u from pc %#I64x", (uint64_t)thread->tid(), (uint64_t)state.pc()); ErrorCode error = thread->resume(signal); if (error != kSuccess) { DS2LOG(Warning, "failed resuming tid %I64u, error=%d", (uint64_t)thread->tid(), error); } } }); return kSuccess; }
ErrorCode Thread::prepareSoftwareSingleStep(Address const &address) { Architecture::CPUState state; ErrorCode error = readCPUState(state); if (error != kSuccess) return error; bool link = false; bool isThumb = (state.gp.cpsr & (1 << 5)); uint32_t pc = address.valid() ? address.value() : state.pc(); uint32_t nextPC = pc; uint32_t branchPC = static_cast<uint32_t>(-1); uint32_t size = 0; // // We need to read 8 bytes, because of IT block // if (isThumb) { error = PrepareThumbSoftwareSingleStep(process(), pc, state, size, link, branchPC, nextPC); } else { error = PrepareARMSoftwareSingleStep(process(), pc, state, size, link, branchPC, nextPC); } DS2LOG(Architecture, Debug, "branchPC=%#lx[link=%s] nextPC=%#lx", (unsigned long)branchPC, link ? "true" : "false", (unsigned long)nextPC); if (branchPC != static_cast<uint32_t>(-1)) { error = process()->breakpointManager()->add( branchPC, BreakpointManager::kTypeTemporaryOneShot, size); if (error != kSuccess) return error; } if (nextPC != static_cast<uint32_t>(-1)) { if ((nextPC & ~1) == pc) { if (!isThumb) { nextPC += 4; size = 4; } else { uint32_t insn; error = process()->readMemory(pc & ~1, &insn, sizeof(insn)); if (error != kSuccess) return error; auto inst_size = Architecture::ARM::GetThumbInstSize(insn); nextPC += static_cast<std::uint8_t>(inst_size); size = 2; } } error = process()->breakpointManager()->add( nextPC, BreakpointManager::kTypeTemporaryOneShot, size); if (error != kSuccess) return error; } return kSuccess; }