/*
 * 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 <android-base/unique_fd.h>
#include <log/log.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() {
  android::base::unique_fd fd_dest(
      TEMP_FAILURE_RETRY(open(coredump_filename_.c_str(),
                              O_WRONLY | O_CREAT | O_EXCL,
                              S_IRUSR | S_IWUSR)));
  if (fd_dest == -1) {
    ALOGE("Failed to open: %s, errno = %d", coredump_filename_.c_str(), errno);
    return -1;
  }
  ssize_t result = WriteCoredumpToFD(fd_dest);
  fd_dest.reset(-1);
  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;
  }

  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(
      output_path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_EXCL,
      S_IRUSR | S_IWUSR)));
  if (fd == -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, note.GetDescription().data(), note.GetDescription().length());
}

bool CoredumpWriter::WriteMaps(const std::vector<Phdr>& program_headers,
                               const FileMappings& file_mappings,
                               const std::string& output_path) {
  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(
      output_path.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC | O_EXCL,
      S_IRUSR | S_IWUSR)));
  if (fd == -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, buf, len)) {
      return false;
    }
  }
  return true;
}
