/*
 * Copyright (C) 2017 The Android Open Source Project
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <dirent.h>
#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
#include <stddef.h>
#include <sys/ucontext.h>
#include <syscall.h>
#include <unistd.h>

#include <atomic>
#include <memory>
#include <mutex>

#include <android-base/file.h>
#include <android-base/unique_fd.h>
#include <async_safe/log.h>
#include <unwindstack/DexFiles.h>
#include <unwindstack/JitDebug.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
#include <unwindstack/Unwinder.h>

#include "debuggerd/handler.h"
#include "handler/fallback.h"
#include "tombstoned/tombstoned.h"
#include "util.h"

#include "libdebuggerd/backtrace.h"
#include "libdebuggerd/tombstone.h"

using android::base::unique_fd;

extern "C" bool __linker_enable_fallback_allocator();
extern "C" void __linker_disable_fallback_allocator();

// This is incredibly sketchy to do inside of a signal handler, especially when libbacktrace
// uses the C++ standard library throughout, but this code runs in the linker, so we'll be using
// the linker's malloc instead of the libc one. Switch it out for a replacement, just in case.
//
// This isn't the default method of dumping because it can fail in cases such as address space
// exhaustion.
static void debuggerd_fallback_trace(int output_fd, ucontext_t* ucontext) {
  if (!__linker_enable_fallback_allocator()) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use");
    return;
  }

  {
    std::unique_ptr<unwindstack::Regs> regs;

    ThreadInfo thread;
    thread.pid = getpid();
    thread.tid = gettid();
    thread.thread_name = get_thread_name(gettid());
    unwindstack::ArchEnum arch = unwindstack::Regs::CurrentArch();
    thread.registers.reset(unwindstack::Regs::CreateFromUcontext(arch, ucontext));

    // TODO: Create this once and store it in a global?
    unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid());
    if (unwinder.Init(arch)) {
      dump_backtrace_thread(output_fd, &unwinder, thread);
    } else {
      async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Unable to init unwinder.");
    }
  }
  __linker_disable_fallback_allocator();
}

static void debuggerd_fallback_tombstone(int output_fd, ucontext_t* ucontext, siginfo_t* siginfo,
                                         void* abort_message) {
  if (!__linker_enable_fallback_allocator()) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "fallback allocator already in use");
    return;
  }

  engrave_tombstone_ucontext(output_fd, reinterpret_cast<uintptr_t>(abort_message), siginfo,
                             ucontext);
  __linker_disable_fallback_allocator();
}

static void iterate_siblings(bool (*callback)(pid_t, int), int output_fd) {
  pid_t current_tid = gettid();
  char buf[BUFSIZ];
  snprintf(buf, sizeof(buf), "/proc/%d/task", current_tid);
  DIR* dir = opendir(buf);

  if (!dir) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to open %s: %s", buf, strerror(errno));
    return;
  }

  struct dirent* ent;
  while ((ent = readdir(dir))) {
    char* end;
    long tid = strtol(ent->d_name, &end, 10);
    if (end == ent->d_name || *end != '\0') {
      continue;
    }

    if (tid != current_tid) {
      callback(tid, output_fd);
    }
  }
  closedir(dir);
}

static bool forward_output(int src_fd, int dst_fd, pid_t expected_tid) {
  // Make sure the thread actually got the signal.
  struct pollfd pfd = {
    .fd = src_fd, .events = POLLIN,
  };

  // Wait for up to a second for output to start flowing.
  if (poll(&pfd, 1, 1000) != 1) {
    return false;
  }

  pid_t tid;
  if (TEMP_FAILURE_RETRY(read(src_fd, &tid, sizeof(tid))) != sizeof(tid)) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to read tid");
    return false;
  }

  if (tid != expected_tid) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "received tid %d, expected %d", tid,
                          expected_tid);
    return false;
  }

  while (true) {
    char buf[512];
    ssize_t rc = TEMP_FAILURE_RETRY(read(src_fd, buf, sizeof(buf)));
    if (rc == 0) {
      return true;
    } else if (rc < 0) {
      return false;
    }

    if (!android::base::WriteFully(dst_fd, buf, rc)) {
      // We failed to write to tombstoned, but there's not much we can do.
      // Keep reading from src_fd to keep things going.
      continue;
    }
  }
}

struct __attribute__((__packed__)) packed_thread_output {
  int32_t tid;
  int32_t fd;
};

static uint64_t pack_thread_fd(pid_t tid, int fd) {
  packed_thread_output packed = {.tid = tid, .fd = fd};
  uint64_t result;
  static_assert(sizeof(packed) == sizeof(result));
  memcpy(&result, &packed, sizeof(packed));
  return result;
}

static std::pair<pid_t, int> unpack_thread_fd(uint64_t value) {
  packed_thread_output result;
  memcpy(&result, &value, sizeof(value));
  return std::make_pair(result.tid, result.fd);
}

static void trace_handler(siginfo_t* info, ucontext_t* ucontext) {
  static std::atomic<uint64_t> trace_output(pack_thread_fd(-1, -1));

  if (info->si_value.sival_ptr == kDebuggerdFallbackSivalPtrRequestDump) {
    // Asked to dump by the original signal recipient.
    uint64_t val = trace_output.load();
    auto [tid, fd] = unpack_thread_fd(val);
    if (tid != gettid()) {
      // We received some other thread's info request?
      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
                            "thread %d received output fd for thread %d?", gettid(), tid);
      return;
    }

    if (!trace_output.compare_exchange_strong(val, pack_thread_fd(-1, -1))) {
      // Presumably, the timeout in forward_output expired, and the main thread moved on.
      // If this happened, the main thread closed our fd for us, so just return.
      async_safe_format_log(ANDROID_LOG_ERROR, "libc", "cmpxchg for thread %d failed", gettid());
      return;
    }

    // Write our tid to the output fd to let the main thread know that we're working.
    if (TEMP_FAILURE_RETRY(write(fd, &tid, sizeof(tid))) == sizeof(tid)) {
      debuggerd_fallback_trace(fd, ucontext);
    } else {
      async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to write to output fd");
    }

    close(fd);
    return;
  }

  // Only allow one thread to perform a trace at a time.
  static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
  int ret = pthread_mutex_trylock(&trace_mutex);
  if (ret != 0) {
    async_safe_format_log(ANDROID_LOG_INFO, "libc", "pthread_mutex_try_lock failed: %s",
                          strerror(ret));
    return;
  }

  // Fetch output fd from tombstoned.
  unique_fd tombstone_socket, output_fd;
  if (!tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdNativeBacktrace)) {
    goto exit;
  }

  dump_backtrace_header(output_fd.get());

  // Dump our own stack.
  debuggerd_fallback_trace(output_fd.get(), ucontext);

  // Send a signal to all of our siblings, asking them to dump their stack.
  iterate_siblings(
      [](pid_t tid, int output_fd) {
        // Use a pipe, to be able to detect situations where the thread gracefully exits before
        // receiving our signal.
        unique_fd pipe_read, pipe_write;
        if (!Pipe(&pipe_read, &pipe_write)) {
          async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to create pipe: %s",
                                strerror(errno));
          return false;
        }

        uint64_t expected = pack_thread_fd(-1, -1);
        int sent_fd = pipe_write.release();
        if (!trace_output.compare_exchange_strong(expected, pack_thread_fd(tid, sent_fd))) {
          auto [tid, fd] = unpack_thread_fd(expected);
          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
                                "thread %d is already outputting to fd %d?", tid, fd);
          close(sent_fd);
          return false;
        }

        siginfo_t siginfo = {};
        siginfo.si_code = SI_QUEUE;
        siginfo.si_value.sival_ptr = kDebuggerdFallbackSivalPtrRequestDump;
        siginfo.si_pid = getpid();
        siginfo.si_uid = getuid();

        if (syscall(__NR_rt_tgsigqueueinfo, getpid(), tid, DEBUGGER_SIGNAL, &siginfo) != 0) {
          async_safe_format_log(ANDROID_LOG_ERROR, "libc", "failed to send trace signal to %d: %s",
                                tid, strerror(errno));
          return false;
        }

        bool success = forward_output(pipe_read.get(), output_fd, tid);
        if (!success) {
          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
                                "timeout expired while waiting for thread %d to dump", tid);
        }

        // Regardless of whether the poll succeeds, check to see if the thread took fd ownership.
        uint64_t post_wait = trace_output.exchange(pack_thread_fd(-1, -1));
        if (post_wait != pack_thread_fd(-1, -1)) {
          auto [tid, fd] = unpack_thread_fd(post_wait);
          if (fd != -1) {
            async_safe_format_log(ANDROID_LOG_ERROR, "libc", "closing fd %d for thread %d", fd, tid);
            close(fd);
          }
        }

        return true;
      },
      output_fd.get());

  dump_backtrace_footer(output_fd.get());
  tombstoned_notify_completion(tombstone_socket.get());

exit:
  pthread_mutex_unlock(&trace_mutex);
}

static void crash_handler(siginfo_t* info, ucontext_t* ucontext, void* abort_message) {
  // Only allow one thread to handle a crash at a time (this can happen multiple times without
  // exit, since tombstones can be requested without a real crash happening.)
  static std::recursive_mutex crash_mutex;
  static int lock_count;

  crash_mutex.lock();
  if (lock_count++ > 0) {
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "recursed signal handler call, aborting");
    signal(SIGABRT, SIG_DFL);
    raise(SIGABRT);
    sigset_t sigset;
    sigemptyset(&sigset);
    sigaddset(&sigset, SIGABRT);
    sigprocmask(SIG_UNBLOCK, &sigset, nullptr);

    // Just in case...
    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "abort didn't exit, exiting");
    _exit(1);
  }

  unique_fd tombstone_socket, output_fd;
  bool tombstoned_connected =
      tombstoned_connect(getpid(), &tombstone_socket, &output_fd, kDebuggerdTombstone);
  debuggerd_fallback_tombstone(output_fd.get(), ucontext, info, abort_message);
  if (tombstoned_connected) {
    tombstoned_notify_completion(tombstone_socket.get());
  }

  --lock_count;
  crash_mutex.unlock();
}

extern "C" void debuggerd_fallback_handler(siginfo_t* info, ucontext_t* ucontext,
                                           void* abort_message) {
  if (info->si_signo == DEBUGGER_SIGNAL && info->si_value.sival_ptr != nullptr) {
    return trace_handler(info, ucontext);
  } else {
    return crash_handler(info, ucontext, abort_message);
  }
}
