コード例 #1
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::resume(ProcessThreadId const &ptid, ProcessInfo const &pinfo,
                         int signal, Address const &address) {
  pid_t pid;
  caddr_t addr;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  //
  // Continuation from address?
  //
  if (address.valid()) {
    addr = (caddr_t)address.value();
  } else {
    // (caddr_t)1 indicate that execution is to pick up where it left off.
    addr = (caddr_t)1;
  }

  if (wrapPtrace(PT_CONTINUE, pid, addr, signal) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
コード例 #2
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::resume(ProcessThreadId const &ptid, ProcessInfo const &pinfo,
                         int signal, Address const &address) {
  pid_t pid;
  caddr_t addr = (caddr_t)1;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  //
  // Continuation from address?
  //
  if (address.valid()) {
    addr = (caddr_t)address.value();
  }

  if (wrapPtrace(PT_SYSCALL, pid, addr, signal) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
コード例 #3
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::step(ProcessThreadId const &ptid, ProcessInfo const &pinfo,
                       int signal, Address const &address) {
  pid_t pid;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  //
  // Continuation from address?
  //
  if (address.valid()) {
    Architecture::CPUState state;
    ErrorCode error = readCPUState(ptid, pinfo, state);
    if (error != kSuccess)
      return error;

    state.setPC(address);

    error = writeCPUState(ptid, pinfo, state);
    if (error != kSuccess)
      return error;
  }

  // (caddr_t)1 indicate that execution is to pick up where it left off.
  if (wrapPtrace(PT_STEP, pid, (caddr_t)1, signal) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
コード例 #4
0
ファイル: PTrace.cpp プロジェクト: sas/ds2
ErrorCode PTrace::writeRegisterSet(ProcessThreadId const &ptid, int regSetCode,
                                   void const *buffer, size_t length) {
  struct iovec iov = {const_cast<void *>(buffer), length};

  if (wrapPtrace(PTRACE_SETREGSET, ptid.validTid() ? ptid.tid : ptid.pid,
                 regSetCode, &iov) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
コード例 #5
0
ファイル: PTrace.cpp プロジェクト: emaste/ds2
//
// Execute will execute the code in the target process/thread,
// the techinique for PTRACE is to read CPU state, rewrite the
// code portion pointed by PC with the code, resuming the process/thread,
// wait for the completion, read the CPU state back to grab return
// values, then restoring the previous code.
//
ErrorCode PTrace::execute(ProcessThreadId const &ptid, ProcessInfo const &pinfo,
                          void const *code, size_t length, uint64_t &result) {
  Architecture::CPUState savedState, resultState;
  std::string savedCode;

  if (!ptid.valid() || code == nullptr || length == 0)
    return kErrorInvalidArgument;

  // 1. Read and save the CPU state
  ErrorCode error = readCPUState(ptid, pinfo, savedState);
  if (error != kSuccess)
    return error;

  // 2. Copy the code at PC
  savedCode.resize(length);
  error = readMemory(ptid, savedState.pc(), &savedCode[0], length);
  if (error != kSuccess)
    return error;

  // 3. Write the code to execute at PC
  error = writeMemory(ptid, savedState.pc(), code, length);
  if (error != kSuccess)
    goto fail;

  // 3. Resume and wait
  error = resume(ptid, pinfo);
  if (error == kSuccess) {
    error = wait(ptid);
  }

  if (error == kSuccess) {
    // 4. Read back the CPU state
    error = readCPUState(ptid, pinfo, resultState);
    if (error == kSuccess) {
      // 5. Save the result
      result = resultState.retval();
    }
  }

  // 6. Write back the old code
  error = writeMemory(ptid, savedState.pc(), &savedCode[0], length);
  if (error != kSuccess)
    goto fail;

  // 7. Restore CPU state
  error = writeCPUState(ptid, pinfo, savedState);
  if (error != kSuccess)
    goto fail;

  // Success!! We injected and executed code!
  return kSuccess;

fail:
  return kill(ptid, SIGKILL); // we can't really do much at this point :(
}
コード例 #6
0
ファイル: PTraceX86_64.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::writeCPUState(ProcessThreadId const &ptid,
                                ProcessInfo const &pinfo,
                                Architecture::CPUState const &state) {
  pid_t pid;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  //
  // Initialize the CPU state, just in case.
  //
  initCPUState(pid);

  if (pinfo.pointerSize == sizeof(uint32_t) && !state.is32)
    return kErrorInvalidArgument;
  else if (pinfo.pointerSize != sizeof(uint32_t) && state.is32)
    return kErrorInvalidArgument;

  //
  // Write GPRs
  //
  user_regs_struct gprs;
  if (state.is32) {
    state32_to_user(gprs, state.state32);
  } else {
    state64_to_user(gprs, state.state64);
  }

  if (wrapPtrace(PTRACE_SETREGS, pid, nullptr, &gprs) < 0)
    return Platform::TranslateError();

  //
  // Write X87 and SSE state
  //
  user_fpregs_struct fprs;
  if (state.is32) {
    state32_to_user(fprs, state.state32);
  } else {
    state64_to_user(fprs, state.state64);
  }

  wrapPtrace(PTRACE_SETFPREGS, pid, nullptr, &fprs);

  return kSuccess;
}
コード例 #7
0
ファイル: PTrace.cpp プロジェクト: sas/ds2
ErrorCode PTrace::readRegisterSet(ProcessThreadId const &ptid, int regSetCode,
                                  void *buffer, size_t length) {
  struct iovec iov = {buffer, length};

  if (wrapPtrace(PTRACE_GETREGSET, ptid.validTid() ? ptid.tid : ptid.pid,
                 regSetCode, &iov) < 0)
    return Platform::TranslateError();

  // On return, the kernel modifies iov.len to return the number of bytes read.
  // This should be exactly equal to the number of bytes requested.
  DS2ASSERT(iov.iov_len == length);

  return kSuccess;
}
コード例 #8
0
ファイル: PTraceX86_64.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::readCPUState(ProcessThreadId const &ptid,
                               ProcessInfo const &pinfo,
                               Architecture::CPUState &state) {
  pid_t pid;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  //
  // Initialize the CPU state, just in case.
  //
  initCPUState(pid);

  //
  // Read GPRs
  //
  user_regs_struct gprs;
  if (wrapPtrace(PTRACE_GETREGS, pid, nullptr, &gprs) < 0)
    return Platform::TranslateError();

  if (pinfo.pointerSize == sizeof(uint32_t)) {
    state.is32 = true;
    user_to_state32(state.state32, gprs);
  } else {
    state.is32 = false;
    user_to_state64(state.state64, gprs);
  }

  //
  // Read X87 and SSE state
  //
  user_fpregs_struct fprs;
  if (wrapPtrace(PTRACE_GETFPREGS, pid, nullptr, &fprs) == 0) {
    if (pinfo.pointerSize == sizeof(uint32_t)) {
      user_to_state32(state.state32, fprs);
    } else {
      user_to_state64(state.state64, fprs);
    }
  }

  return kSuccess;
}
コード例 #9
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::kill(ProcessThreadId const &ptid, int signal) {
  if (!ptid.valid())
    return kErrorInvalidArgument;

  int rc;
  if (!(ptid.tid <= kAnyThreadId)) {
    DS2BUG("not implemented");
  } else {
    rc = ::kill(ptid.pid, signal);
  }

  if (rc < 0)
    return Platform::TranslateError();

  return kSuccess;
}
コード例 #10
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::suspend(ProcessThreadId const &ptid) {
  pid_t pid;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  if (kill(pid, SIGSTOP) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
コード例 #11
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::getLwpInfo(ProcessThreadId const &ptid,
                             struct ptrace_lwpinfo *lwpinfo) {
  pid_t pid;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  if (wrapPtrace(PT_LWPINFO, pid, lwpinfo, sizeof(struct ptrace_lwpinfo)) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
コード例 #12
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::getSigInfo(ProcessThreadId const &ptid, siginfo_t &si) {
  struct ptrace_lwpinfo lwpinfo;
  pid_t pid;

  if (!ptid.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  if (wrapPtrace(PT_LWPINFO, pid, &lwpinfo, sizeof lwpinfo) < 0)
    return Platform::TranslateError();

  si = lwpinfo.pl_siginfo;
  return kSuccess;
}
コード例 #13
0
ファイル: PTrace.cpp プロジェクト: YtnbFirewings/ds2
ErrorCode PTrace::writeMemory(ProcessThreadId const &ptid,
                              Address const &address, void const *buffer,
                              size_t length, size_t *count) {
  pid_t pid;

  if (!ptid.valid() || !address.valid())
    return kErrorInvalidArgument;

  if (!(ptid.tid <= kAnyThreadId)) {
    pid = ptid.tid;
  } else {
    pid = ptid.pid;
  }

  uintptr_t base = address;
  struct ptrace_io_desc desc;

  if (length == 0 || buffer == nullptr) {
    if (count != nullptr)
      *count = 0;

    return kSuccess;
  }

  desc.piod_op = PIOD_WRITE_D;
  desc.piod_offs = (void *)base;
  desc.piod_addr = (void *)buffer;
  desc.piod_len = length;

  if (wrapPtrace(PT_IO, pid, &desc, nullptr) < 0)
    return Platform::TranslateError();

  if (count != nullptr)
    *count = desc.piod_len;
  return kSuccess;
}