Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}