Esempio n. 1
0
File: PTrace.cpp Progetto: sas/ds2
ErrorCode PTrace::readBytes(ProcessThreadId const &ptid, Address const &address,
                            void *buffer, size_t length, size_t *count,
                            bool nullTerm) {
  pid_t pid;
  CHK(ptidToPid(ptid, pid));

  bool foundNull = false;
  size_t nread = 0;
  uintptr_t base = address;
  uintptr_t *words = (uintptr_t *)buffer;

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

  while (length > 0) {
    union {
      uintptr_t word;
      uint8_t bytes[sizeof(uintptr_t)];
    } data;
    size_t ncopy = std::min(length, sizeof(uintptr_t));

    errno = 0;
    if (ncopy < sizeof(uintptr_t)) {
      data.word = wrapPtrace(PTRACE_PEEKDATA, pid, base + nread, nullptr);
      if (errno == 0) {
        std::memcpy(words, data.bytes, ncopy);
      }
    } else {
      *words = wrapPtrace(PTRACE_PEEKDATA, pid, base + nread, nullptr);
    }

    if (errno != 0)
      break;

    if (nullTerm && strnlen((char *)words, ncopy) < ncopy) {
      foundNull = true;
      break;
    }

    length -= ncopy;
    nread += ncopy;
    words++;
  }

  if (count != nullptr) {
    *count = nread;
  }

  if (errno != 0)
    return Platform::TranslateError();

  if (nullTerm && !foundNull)
    return kErrorNameTooLong;

  return kSuccess;
}
Esempio n. 2
0
File: PTrace.cpp Progetto: sas/ds2
ErrorCode PTrace::writeMemory(ProcessThreadId const &ptid,
                              Address const &address, void const *buffer,
                              size_t length, size_t *count) {
  pid_t pid;
  CHK(ptidToPid(ptid, pid));

  size_t nwritten = 0;
  uintptr_t base = address;
  uintptr_t const *words = (uintptr_t const *)buffer;

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

  while (length > 0) {
    union {
      uintptr_t word;
      uint8_t bytes[sizeof(uintptr_t)];
    } data;
    size_t ncopy = std::min(length, sizeof(uintptr_t));

    errno = 0;
    if (ncopy < sizeof(uintptr_t)) {
      data.word = wrapPtrace(PTRACE_PEEKDATA, pid, base + nwritten, nullptr);
      if (errno == 0) {
        std::memcpy(data.bytes, words, ncopy);
        wrapPtrace(PTRACE_POKEDATA, pid, base + nwritten, data.word);
      }
    } else {
      wrapPtrace(PTRACE_POKEDATA, pid, base + nwritten, *words);
    }

    if (errno != 0)
      break;

    length -= ncopy;
    nwritten += ncopy;
    words++;
  }

  if (errno != 0)
    return Platform::TranslateError();

  if (count != nullptr) {
    *count = nwritten;
  }

  return kSuccess;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
ErrorCode PTrace::writeMemory(ProcessThreadId const &ptid,
                              Address const &address, void const *buffer,
                              size_t length, size_t *count) {
  pid_t pid;
  CHK(ptidToPid(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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
File: PTrace.cpp Progetto: sas/ds2
ErrorCode PTrace::getSigInfo(ProcessThreadId const &ptid, siginfo_t &si) {
  pid_t pid;
  CHK(ptidToPid(ptid, pid));

  if (wrapPtrace(PTRACE_GETSIGINFO, pid, nullptr, &si) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
Esempio n. 10
0
ErrorCode PTrace::getLwpInfo(ProcessThreadId const &ptid,
                             struct ptrace_lwpinfo *lwpinfo) {
  pid_t pid;
  CHK(ptidToPid(ptid, pid));

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

  return kSuccess;
}
Esempio n. 11
0
File: PTrace.cpp Progetto: 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;
}
Esempio n. 12
0
ErrorCode PTrace::detach(ProcessId pid) {
  if (pid <= kAnyProcessId)
    return kErrorProcessNotFound;

  DS2LOG(Debug, "detaching from pid %" PRIu64, (uint64_t)pid);

  if (wrapPtrace(PT_DETACH, pid, nullptr, nullptr) < 0)
    return Platform::TranslateError();

  return kSuccess;
}
Esempio n. 13
0
ErrorCode PTrace::getSigInfo(ProcessThreadId const &ptid, siginfo_t &si) {
  struct ptrace_lwpinfo lwpinfo;
  pid_t pid;
  CHK(ptidToPid(ptid, pid));

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

  si = lwpinfo.pl_siginfo;
  return kSuccess;
}
Esempio n. 14
0
ErrorCode PTrace::attach(ProcessId pid) {
  if (pid <= kAnyProcessId)
    return kErrorProcessNotFound;

  DS2LOG(Debug, "attaching to pid %" PRIu64, (uint64_t)pid);

  if (wrapPtrace(PT_ATTACH, pid, nullptr, nullptr) < 0) {
    ErrorCode error = Platform::TranslateError();
    DS2LOG(Error, "Unable to attach: %d", error);
    return error;
  }

  return kSuccess;
}
Esempio n. 15
0
File: PTrace.cpp Progetto: 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;
}
Esempio n. 16
0
File: PTrace.cpp Progetto: sas/ds2
ErrorCode PTrace::traceThat(ProcessId pid) {
  if (pid <= 0)
    return kErrorInvalidArgument;

  unsigned long traceFlags = PTRACE_O_TRACECLONE;

  //
  // Trace clone and exit events to track threads.
  //
  if (wrapPtrace(PTRACE_SETOPTIONS, pid, nullptr, traceFlags) < 0) {
    DS2LOG(Warning, "unable to set PTRACE_O_TRACECLONE on pid %d, error=%s",
           pid, strerror(errno));
    return Platform::TranslateError();
  }

  return kSuccess;
}
Esempio n. 17
0
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;
}
Esempio n. 18
0
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;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
ErrorCode PTrace::traceMe(bool disableASLR) {
  if (wrapPtrace(PT_TRACE_ME, 0, nullptr, nullptr) < 0)
    return Platform::TranslateError();

  return kSuccess;
}