/*
 * Copyright (C) 2015 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.
 */

#define LOG_TAG "crash_collector"

#include "coredump_writer.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/statvfs.h>
#include <unistd.h>

#include <android-base/file.h>
#include <log/logger.h>
#include <nativehelper/ScopedFd.h>

// From external/google-breakpad.
#include "common/linux/elf_core_dump.h"

namespace {

const size_t kMaxCoredumpSize = 256 * 1024 * 1024;

int64_t GetFreeDiskSpace(const std::string& path) {
  struct statvfs stats;
  if (TEMP_FAILURE_RETRY(statvfs(path.c_str(), &stats)) != 0) {
    ALOGE("statvfs() failed. errno = %d", errno);
    return -1;
  }
  return static_cast<int64_t>(stats.f_bavail) * stats.f_frsize;
}

bool Seek(int fd, off_t offset) {
  return lseek(fd, offset, SEEK_SET) == offset;
}

template<typename T>
T GetValueFromNote(const google_breakpad::ElfCoreDump::Note& note,
                   size_t offset,
                   T default_value) {
  const T* p = note.GetDescription().GetData<T>(offset);
  return p ? *p : default_value;
}

}  // namespace

class CoredumpWriter::FdReader {
 public:
  explicit FdReader(int fd) : fd_(fd), bytes_read_(0) {}

  // Reads the given number of bytes.
  bool Read(void* buf, size_t num_bytes) {
    if (!android::base::ReadFully(fd_, buf, num_bytes))
      return false;
    bytes_read_ += num_bytes;
    return true;
  }

  // Reads the given number of bytes and writes it to fd_dest.
  bool CopyTo(int fd_dest, size_t num_bytes) {
    const size_t kBufSize = 32768;
    char buf[kBufSize];
    while (num_bytes > 0) {
      int rv = TEMP_FAILURE_RETRY(
          read(fd_, buf, std::min(kBufSize, num_bytes)));
      if (rv == 0)
        break;
      if (rv == -1)
        return false;
      if (fd_dest != -1 && !android::base::WriteFully(fd_dest, buf, rv))
        return false;
      num_bytes -= rv;
      bytes_read_ += rv;
    }
    return num_bytes == 0;
  }

  // Reads data and discards it to get to the specified position.
  bool Seek(size_t offset) {
    if (offset < bytes_read_)  // Cannot move backward.
      return false;
    return CopyTo(-1, offset - bytes_read_);
  }

 private:
  int fd_;
  size_t bytes_read_;

  DISALLOW_COPY_AND_ASSIGN(FdReader);
};

CoredumpWriter::CoredumpWriter(int fd_src,
                               const std::string& coredump_filename,
                               const std::string& proc_files_dir)
    : fd_src_(fd_src),
      coredump_filename_(coredump_filename),
      proc_files_dir_(proc_files_dir) {
}

CoredumpWriter::~CoredumpWriter() {
}

ssize_t CoredumpWriter::WriteCoredump() {
  ScopedFd fd_dest(TEMP_FAILURE_RETRY(open(coredump_filename_.c_str(),
                                           O_WRONLY | O_CREAT | O_EXCL,
                                           S_IRUSR | S_IWUSR)));
  if (fd_dest.get() == -1) {
    ALOGE("Failed to open: %s, errno = %d", coredump_filename_.c_str(), errno);
    return -1;
  }
  ssize_t result = WriteCoredumpToFD(fd_dest.get());
  fd_dest.reset();
  if (result == -1)
    unlink(coredump_filename_.c_str());
  return result;
}

ssize_t CoredumpWriter::WriteCoredumpToFD(int fd_dest) {
  // Input coredump is generated by kernel's fs/binfmt_elf.c and formatted like:
  //
  //   ELF Header
  //   Program Header 1
  //   Program Header 2
  //   ...
  //   Program Header n
  //   Segment 1 (This segment's type should be PT_NOTE)
  //   Segment 2
  //   ...
  //   Segment n

  // First, read ELF Header, all program headers, and the first segment whose
  // type is PT_NOTE.
  FdReader reader(fd_src_);
  Ehdr elf_header;
  std::vector<Phdr> program_headers;
  std::vector<char> note_buf;
  if (!ReadUntilNote(&reader, &elf_header, &program_headers, &note_buf)) {
    return -1;
  }
  // Get a set of address ranges occupied by mapped files from NOTE.
  FileMappings file_mappings;
  if (!GetFileMappings(note_buf, &file_mappings)) {
    return -1;
  }
  // Filter out segments backed by mapped files as they are useless when
  // generating minidump.
  std::vector<Phdr> program_headers_filtered;
  FilterSegments(program_headers, file_mappings, &program_headers_filtered);

  // Calculate the coredump size limit.
  const int64_t free_disk_space = GetFreeDiskSpace(coredump_filename_);
  if (free_disk_space < 0) {
    return -1;
  }
  coredump_size_limit_ = std::min(static_cast<size_t>(free_disk_space / 20),
                                  kMaxCoredumpSize);

  // Calculate the output file size.
  expected_coredump_size_ = program_headers_filtered.back().p_offset +
      program_headers_filtered.back().p_filesz;
  if (expected_coredump_size_ > coredump_size_limit_) {
    ALOGE("Coredump too large: %zu", expected_coredump_size_);
    return -1;
  }

  // Write proc files.
  if (!WriteAuxv(note_buf, proc_files_dir_ + "/auxv") ||
      !WriteMaps(program_headers, file_mappings, proc_files_dir_ + "/maps")) {
    return -1;
  }

  // Write ELF header.
  if (!android::base::WriteFully(fd_dest, &elf_header, sizeof(elf_header))) {
    ALOGE("Failed to write ELF header.");
    return -1;
  }
  // Write program headers.
  for (size_t i = 0; i < program_headers_filtered.size(); ++i) {
    const Phdr& program_header = program_headers_filtered[i];
    const size_t offset = sizeof(elf_header) + i * elf_header.e_phentsize;
    if (!Seek(fd_dest, offset) ||
        !android::base::WriteFully(fd_dest, &program_header,
                                   sizeof(program_header))) {
      ALOGE("Failed to write program header: i = %zu", i);
      return -1;
    }
  }
  // Write NOTE segment.
  if (!Seek(fd_dest, program_headers_filtered[0].p_offset) ||
      !android::base::WriteFully(fd_dest, note_buf.data(), note_buf.size())) {
    ALOGE("Failed to write NOTE.");
    return -1;
  }
  // Read all remaining segments and write some of them.
  for (size_t i = 1; i < program_headers_filtered.size(); ++i) {
    const Phdr& program_header = program_headers_filtered[i];
    if (program_header.p_filesz > 0) {
      const Phdr& program_header_original = program_headers[i];
      if (!reader.Seek(program_header_original.p_offset)) {
        ALOGE("Failed to seek segment: i = %zu", i);
        return -1;
      }
      if (!Seek(fd_dest, program_header.p_offset) ||
          !reader.CopyTo(fd_dest, program_header.p_filesz)) {
        ALOGE("Failed to write segment: i = %zu", i);
        return -1;
      }
    }
  }
  return expected_coredump_size_;
}

bool CoredumpWriter::ReadUntilNote(FdReader* reader,
                                   Ehdr* elf_header,
                                   std::vector<Phdr>* program_headers,
                                   std::vector<char>* note_buf) {
  // Read ELF header.
  if (!reader->Read(elf_header, sizeof(*elf_header)) ||
      memcmp(elf_header->e_ident, ELFMAG, SELFMAG) != 0 ||
      elf_header->e_ident[EI_CLASS] != google_breakpad::ElfCoreDump::kClass ||
      elf_header->e_version != EV_CURRENT ||
      elf_header->e_type != ET_CORE ||
      elf_header->e_ehsize != sizeof(Ehdr) ||
      elf_header->e_phentsize != sizeof(Phdr)) {
    ALOGE("Failed to read ELF header.");
    return false;
  }

  // Read program headers;
  program_headers->resize(elf_header->e_phnum);
  if (!reader->Seek(elf_header->e_phoff) ||
      !reader->Read(program_headers->data(),
                    sizeof(Phdr) * program_headers->size())) {
    ALOGE("Failed to read program headers.");
    return false;
  }

  // The first segment should be NOTE.
  if (program_headers->size() < 1 ||
      (*program_headers)[0].p_type != PT_NOTE) {
    ALOGE("Failed to locate NOTE.");
    return false;
  }
  const Phdr& note_program_header = (*program_headers)[0];

  // Read NOTE segment.
  note_buf->resize(note_program_header.p_filesz);
  if (!reader->Seek(note_program_header.p_offset) ||
      !reader->Read(note_buf->data(), note_buf->size())) {
    ALOGE("Failed to read NOTE.");
    return false;
  }
  return true;
}

bool CoredumpWriter::GetFileMappings(const std::vector<char>& note_buf,
                                     FileMappings* file_mappings) {
  // Locate FILE note.
  google_breakpad::ElfCoreDump::Note note(
      google_breakpad::MemoryRange(note_buf.data(), note_buf.size()));
  while (note.IsValid() && note.GetType() != NT_FILE) {
    note = note.GetNextNote();
  }
  if (!note.IsValid()) {
    ALOGE("Failed to locate NT_FILE.");
    return false;
  }

  // NT_FILE note format: (see kernel's fs/binfmt_elf.c for details)
  //   Number of mapped files
  //   Page size
  //   Start address of file 1
  //   End address of file 1
  //   Offset of file 1
  //   Start address of file 2
  //   ...
  //   Offset of file n
  //   File name 1 (null-terminated)
  //   File name 2
  //   ...
  //   File name n
  const long kInvalidValue = -1;
  const long file_count = GetValueFromNote<long>(note, 0, kInvalidValue);
  const long page_size = GetValueFromNote<long>(note, sizeof(long),
                                                kInvalidValue);
  if (file_count == kInvalidValue || page_size == kInvalidValue) {
    ALOGE("Invalid FILE note.");
    return false;
  }
  // Read contents of FILE note.
  size_t filename_pos = sizeof(long) * (2 + 3 * file_count);
  for (long i = 0; i < file_count; ++i) {
    const long start = GetValueFromNote<long>(
        note, sizeof(long) * (2 + 3 * i), kInvalidValue);
    const long end = GetValueFromNote<long>(
        note, sizeof(long) * (2 + 3 * i + 1), kInvalidValue);
    const long offset = GetValueFromNote<long>(
        note, sizeof(long) * (2 + 3 * i + 2), kInvalidValue);
    if (start == kInvalidValue || end == kInvalidValue ||
        offset == kInvalidValue) {
      ALOGE("Invalid FILE Note.");
      return false;
    }
    // Add a new mapping.
    FileInfo& info = (*file_mappings)[std::make_pair(start, end)];
    info.offset = offset * page_size;
    // Read file name.
    while (true) {
      const char c = GetValueFromNote<char>(note, filename_pos++, 0);
      if (!c)
        break;
      info.path.push_back(c);
    }
  }
  return true;
}

void CoredumpWriter::FilterSegments(
    const std::vector<Phdr>& program_headers,
    const FileMappings& file_mappings,
    std::vector<Phdr>* program_headers_filtered) {
  program_headers_filtered->resize(program_headers.size());

  // The first segment is NOTE. Use the original data unchanged.
  (*program_headers_filtered)[0] = program_headers[0];

  for (size_t i = 1; i < program_headers.size(); ++i) {
    Phdr& out = (*program_headers_filtered)[i];
    out = program_headers[i];

    // If the type is PT_LOAD and the range is found in the set, it means the
    // segment is backed by a file.  So it can be excluded as it doesn't cotnain
    // stack data useful to generate minidump.
    const FileRange range(out.p_vaddr, out.p_vaddr + out.p_memsz);
    if (out.p_type == PT_LOAD && file_mappings.count(range)) {
      out.p_filesz = 0;
    }
    // Calculate offset.
    const Phdr& prev_program_header = (*program_headers_filtered)[i - 1];
    out.p_offset = prev_program_header.p_offset + prev_program_header.p_filesz;
    // Offset alignment.
    if (out.p_align != 0 && out.p_offset % out.p_align != 0) {
      out.p_offset += out.p_align - out.p_offset % out.p_align;
    }
  }
}

bool CoredumpWriter::WriteAuxv(const std::vector<char>& note_buf,
                               const std::string& output_path) {
  // Locate AUXV note.
  google_breakpad::ElfCoreDump::Note note(
      google_breakpad::MemoryRange(note_buf.data(), note_buf.size()));
  while (note.IsValid() && note.GetType() != NT_AUXV) {
    note = note.GetNextNote();
  }
  if (!note.IsValid()) {
    ALOGE("Failed to locate NT_AUXV.");
    return false;
  }

  ScopedFd fd(TEMP_FAILURE_RETRY(open(
      output_path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_EXCL,
      S_IRUSR | S_IWUSR)));
  if (fd.get() == -1) {
    ALOGE("Failed to open %s", output_path.c_str());
    return false;
  }
  // The contents of NT_AUXV is in the same format as that of /proc/[pid]/auxv.
  return android::base::WriteFully(
      fd.get(), note.GetDescription().data(), note.GetDescription().length());
}

bool CoredumpWriter::WriteMaps(const std::vector<Phdr>& program_headers,
                               const FileMappings& file_mappings,
                               const std::string& output_path) {
  ScopedFd fd(TEMP_FAILURE_RETRY(open(
      output_path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_EXCL,
      S_IRUSR | S_IWUSR)));
  if (fd.get() == -1) {
    ALOGE("Failed to open %s", output_path.c_str());
    return false;
  }
  for (const auto& program_header : program_headers) {
    if (program_header.p_type != PT_LOAD)
      continue;
    const FileRange range(program_header.p_vaddr,
                          program_header.p_vaddr + program_header.p_memsz);
    // If a mapping is found for the range, the range is mapped to a file.
    const auto it = file_mappings.find(range);
    const long offset = it != file_mappings.end() ? it->second.offset : 0;
    const std::string path = it != file_mappings.end() ? it->second.path : "";

    const int kBufSize = 1024;
    char buf[kBufSize];
    const int len = snprintf(
        buf, kBufSize, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %d %s\n",
        range.first, range.second,
        program_header.p_flags & PF_R ? 'r' : '-',
        program_header.p_flags & PF_W ? 'w' : '-',
        program_header.p_flags & PF_X ? 'x' : '-',
        'p',  // Fake value: We can't know if the mapping is shared or private.
        offset,
        0,  // Fake device (major) value.
        0,  // Fake device (minor) value.
        0,  // Fake inode value.
        path.c_str());
    if (len < 0 || len > kBufSize ||
        !android::base::WriteFully(fd.get(), buf, len)) {
      return false;
    }
  }
  return true;
}
