/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ThreadCapture.h"

#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>

#include <map>
#include <memory>
#include <set>
#include <vector>

#include <android-base/unique_fd.h>

#include "Allocator.h"
#include "log.h"

// bionic interfaces used:
// atoi
// strlcat
// writev

// bionic interfaces reimplemented to avoid allocation:
// getdents64

// Convert a pid > 0 to a string.  sprintf might allocate, so we can't use it.
// Returns a pointer somewhere in buf to a null terminated string, or NULL
// on error.
static char *pid_to_str(char *buf, size_t len, pid_t pid) {
  if (pid <= 0) {
    return nullptr;
  }

  char *ptr = buf + len - 1;
  *ptr = 0;
  while (pid > 0) {
    ptr--;
    if (ptr < buf) {
      return nullptr;
    }
    *ptr = '0' + (pid % 10);
    pid /= 10;
  }

  return ptr;
}

class ThreadCaptureImpl {
 public:
  ThreadCaptureImpl(pid_t pid, Allocator<ThreadCaptureImpl>& allocator);
  ~ThreadCaptureImpl() {}
  bool ListThreads(TidList& tids);
  bool CaptureThreads();
  bool ReleaseThreads();
  bool ReleaseThread(pid_t tid);
  bool CapturedThreadInfo(ThreadInfoList& threads);
  void InjectTestFunc(std::function<void(pid_t)>&& f) { inject_test_func_ = f; }
 private:
  int CaptureThread(pid_t tid);
  bool ReleaseThread(pid_t tid, unsigned int signal);
  int PtraceAttach(pid_t tid);
  void PtraceDetach(pid_t tid, unsigned int signal);
  bool PtraceThreadInfo(pid_t tid, ThreadInfo& thread_info);

  allocator::map<pid_t, unsigned int> captured_threads_;
  Allocator<ThreadCaptureImpl> allocator_;
  pid_t pid_;
  std::function<void(pid_t)> inject_test_func_;
};

ThreadCaptureImpl::ThreadCaptureImpl(pid_t pid, Allocator<ThreadCaptureImpl>& allocator) :
    captured_threads_(allocator), allocator_(allocator), pid_(pid) {
}

bool ThreadCaptureImpl::ListThreads(TidList& tids) {
  tids.clear();

  char pid_buf[11];
  char path[256] = "/proc/";
  char* pid_str = pid_to_str(pid_buf, sizeof(pid_buf), pid_);
  if (!pid_str) {
    return false;
  }
  strlcat(path, pid_str, sizeof(path));
  strlcat(path, "/task", sizeof(path));

  android::base::unique_fd fd(open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
  if (fd == -1) {
    MEM_ALOGE("failed to open %s: %s", path, strerror(errno));
    return false;
  }

  struct linux_dirent64 {
    uint64_t  d_ino;
    int64_t   d_off;
    uint16_t  d_reclen;
    char      d_type;
    char      d_name[];
  } __attribute((packed));
  char dirent_buf[4096];
  ssize_t nread;
  do {
    nread = syscall(SYS_getdents64, fd.get(), dirent_buf, sizeof(dirent_buf));
    if (nread < 0) {
      MEM_ALOGE("failed to get directory entries from %s: %s", path, strerror(errno));
      return false;
    } else if (nread > 0) {
      ssize_t off = 0;
      while (off < nread) {
        linux_dirent64* dirent = reinterpret_cast<linux_dirent64*>(dirent_buf + off);
        off += dirent->d_reclen;
        pid_t tid = atoi(dirent->d_name);
        if (tid <= 0) {
          continue;
        }
        tids.push_back(tid);
      }
    }

  } while (nread != 0);

  return true;
}

bool ThreadCaptureImpl::CaptureThreads() {
  TidList tids{allocator_};

  bool found_new_thread;
  do {
    if (!ListThreads(tids)) {
      ReleaseThreads();
      return false;
    }

    found_new_thread = false;

    for (auto it = tids.begin(); it != tids.end(); it++) {
      auto captured = captured_threads_.find(*it);
      if (captured == captured_threads_.end()) {
        if (CaptureThread(*it) < 0) {
          ReleaseThreads();
          return false;
        }
        found_new_thread = true;
      }
    }
  } while (found_new_thread);

  return true;
}

// Detatches from a thread, delivering signal if nonzero, logs on error
void ThreadCaptureImpl::PtraceDetach(pid_t tid, unsigned int signal) {
  void* sig_ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(signal));
  if (ptrace(PTRACE_DETACH, tid, NULL, sig_ptr) < 0 && errno != ESRCH) {
    MEM_ALOGE("failed to detach from thread %d of process %d: %s", tid, pid_, strerror(errno));
  }
}

// Attaches to and pauses thread.
// Returns 1 on attach, 0 on tid not found, -1 and logs on error
int ThreadCaptureImpl::PtraceAttach(pid_t tid) {
  int ret = ptrace(PTRACE_SEIZE, tid, NULL, NULL);
  if (ret < 0) {
    MEM_ALOGE("failed to attach to thread %d of process %d: %s", tid, pid_, strerror(errno));
    return -1;
  }

  if (inject_test_func_) {
    inject_test_func_(tid);
  }

  if (ptrace(PTRACE_INTERRUPT, tid, 0, 0) < 0) {
    if (errno == ESRCH) {
      return 0;
    } else {
      MEM_ALOGE("failed to interrupt thread %d of process %d: %s", tid, pid_, strerror(errno));
      PtraceDetach(tid, 0);
      return -1;
    }
  }
  return 1;
}

bool ThreadCaptureImpl::PtraceThreadInfo(pid_t tid, ThreadInfo& thread_info) {
  thread_info.tid = tid;

  const unsigned int max_num_regs = 128; // larger than number of registers on any device
  uintptr_t regs[max_num_regs];
  struct iovec iovec;
  iovec.iov_base = &regs;
  iovec.iov_len = sizeof(regs);

  if (ptrace(PTRACE_GETREGSET, tid, reinterpret_cast<void*>(NT_PRSTATUS), &iovec)) {
    MEM_ALOGE("ptrace getregset for thread %d of process %d failed: %s", tid, pid_, strerror(errno));
    return false;
  }

  unsigned int num_regs = iovec.iov_len / sizeof(uintptr_t);
  thread_info.regs.assign(&regs[0], &regs[num_regs]);

  const int sp =
#if defined(__x86_64__)
      offsetof(struct pt_regs, rsp) / sizeof(uintptr_t)
#elif defined(__i386__)
      offsetof(struct pt_regs, esp) / sizeof(uintptr_t)
#elif defined(__arm__)
      offsetof(struct pt_regs, ARM_sp) / sizeof(uintptr_t)
#elif defined(__aarch64__)
      offsetof(struct user_pt_regs, sp) / sizeof(uintptr_t)
#elif defined(__mips__) || defined(__mips64__)
      offsetof(struct pt_regs, regs[29]) / sizeof(uintptr_t)
#else
#error Unrecognized architecture
#endif
      ;

  // TODO(ccross): use /proc/tid/status or /proc/pid/maps to get start_stack

  thread_info.stack = std::pair<uintptr_t, uintptr_t>(regs[sp], 0);

   return true;
}

int ThreadCaptureImpl::CaptureThread(pid_t tid) {
  int ret = PtraceAttach(tid);
  if (ret <= 0) {
    return ret;
  }

  int status = 0;
  if (TEMP_FAILURE_RETRY(waitpid(tid, &status, __WALL)) < 0) {
    MEM_ALOGE("failed to wait for pause of thread %d of process %d: %s", tid, pid_, strerror(errno));
    PtraceDetach(tid, 0);
    return -1;
  }

  if (!WIFSTOPPED(status)) {
    MEM_ALOGE("thread %d of process %d was not paused after waitpid, killed?", tid, pid_);
    return 0;
  }

  unsigned int resume_signal = 0;

  unsigned int signal =  WSTOPSIG(status);
  if ((status >> 16) == PTRACE_EVENT_STOP) {
    switch (signal) {
      case SIGSTOP:
      case SIGTSTP:
      case SIGTTIN:
      case SIGTTOU:
        // group-stop signals
        break;
      case SIGTRAP:
        // normal ptrace interrupt stop
        break;
      default:
        MEM_ALOGE("unexpected signal %d with PTRACE_EVENT_STOP for thread %d of process %d", signal,
                  tid, pid_);
        return -1;
    }
  } else {
    // signal-delivery-stop
    resume_signal = signal;
  }

  captured_threads_[tid] = resume_signal;
  return 1;
}

bool ThreadCaptureImpl::ReleaseThread(pid_t tid) {
  auto it = captured_threads_.find(tid);
  if (it == captured_threads_.end()) {
    return false;
  }
  return ReleaseThread(it->first, it->second);
}

bool ThreadCaptureImpl::ReleaseThread(pid_t tid, unsigned int signal) {
  PtraceDetach(tid, signal);
  return true;
}

bool ThreadCaptureImpl::ReleaseThreads() {
  bool ret = true;
  for (auto it = captured_threads_.begin(); it != captured_threads_.end(); ) {
    if (ReleaseThread(it->first, it->second)) {
      it = captured_threads_.erase(it);
    } else {
      it++;
      ret = false;
    }
  }
  return ret;
}

bool ThreadCaptureImpl::CapturedThreadInfo(ThreadInfoList& threads) {
  threads.clear();

  for (auto it = captured_threads_.begin(); it != captured_threads_.end(); it++) {
    ThreadInfo t{0, allocator::vector<uintptr_t>(allocator_), std::pair<uintptr_t, uintptr_t>(0, 0)};
    if (!PtraceThreadInfo(it->first, t)) {
      return false;
    }
    threads.push_back(t);
  }
  return true;
}

ThreadCapture::ThreadCapture(pid_t pid, Allocator<ThreadCapture> allocator) {
  Allocator<ThreadCaptureImpl> impl_allocator = allocator;
  impl_ = impl_allocator.make_unique(pid, impl_allocator);
}

ThreadCapture::~ThreadCapture() {}

bool ThreadCapture::ListThreads(TidList& tids) {
  return impl_->ListThreads(tids);
}

bool ThreadCapture::CaptureThreads() {
  return impl_->CaptureThreads();
}

bool ThreadCapture::ReleaseThreads() {
  return impl_->ReleaseThreads();
}

bool ThreadCapture::ReleaseThread(pid_t tid) {
  return impl_->ReleaseThread(tid);
}

bool ThreadCapture::CapturedThreadInfo(ThreadInfoList& threads) {
  return impl_->CapturedThreadInfo(threads);
}

void ThreadCapture::InjectTestFunc(std::function<void(pid_t)>&& f) {
  impl_->InjectTestFunc(std::forward<std::function<void(pid_t)>>(f));
}
