// Copyright 2017 The Crashpad Authors
//
// 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 "util/linux/memory_map.h"

#include <stdio.h>
#include <string.h>
#include <sys/sysmacros.h>

#include "base/check_op.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "build/build_config.h"
#include "util/file/delimited_file_reader.h"
#include "util/file/file_io.h"
#include "util/file/string_file.h"
#include "util/stdlib/string_number_conversion.h"

namespace crashpad {

namespace {

template <typename Type>
bool HexStringToNumber(const std::string& string, Type* number) {
  return StringToNumber("0x" + string, number);
}

// The result from parsing a line from the maps file.
enum class ParseResult {
  // A line was successfully parsed.
  kSuccess = 0,

  // The end of the file was successfully reached.
  kEndOfFile,

  // There was an error in the file, likely because it was read non-atmoically.
  // We should try to read it again.
  kRetry,

  // An error with a message logged.
  kError
};

// Reads a line from a maps file being read by maps_file_reader and extends
// mappings with a new MemoryMap::Mapping describing the line.
ParseResult ParseMapsLine(DelimitedFileReader* maps_file_reader,
                          std::vector<MemoryMap::Mapping>* mappings) {
  std::string field;
  LinuxVMAddress start_address;
  switch (maps_file_reader->GetDelim('-', &field)) {
    case DelimitedFileReader::Result::kError:
      return ParseResult::kError;
    case DelimitedFileReader::Result::kEndOfFile:
      return ParseResult::kEndOfFile;
    case DelimitedFileReader::Result::kSuccess:
      field.pop_back();
      if (!HexStringToNumber(field, &start_address)) {
        LOG(ERROR) << "format error";
        return ParseResult::kError;
      }
      if (!mappings->empty() && start_address < mappings->back().range.End()) {
        return ParseResult::kRetry;
      }
  }

  LinuxVMAddress end_address;
  if (maps_file_reader->GetDelim(' ', &field) !=
          DelimitedFileReader::Result::kSuccess ||
      (field.pop_back(), !HexStringToNumber(field, &end_address))) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }
  if (end_address < start_address) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }
  // Skip zero-length mappings.
  if (end_address == start_address) {
    std::string rest_of_line;
    if (maps_file_reader->GetLine(&rest_of_line) !=
        DelimitedFileReader::Result::kSuccess) {
      LOG(ERROR) << "format error";
      return ParseResult::kError;
    }
    return ParseResult::kSuccess;
  }

  // TODO(jperaza): set bitness properly
#if defined(ARCH_CPU_64_BITS)
  constexpr bool is_64_bit = true;
#else
  constexpr bool is_64_bit = false;
#endif

  MemoryMap::Mapping mapping;
  mapping.range.SetRange(is_64_bit, start_address, end_address - start_address);

  if (maps_file_reader->GetDelim(' ', &field) !=
          DelimitedFileReader::Result::kSuccess ||
      (field.pop_back(), field.size() != 4)) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }
#define SET_FIELD(actual_c, outval, true_chars, false_chars) \
  do {                                                       \
    if (strchr(true_chars, actual_c)) {                      \
      *outval = true;                                        \
    } else if (strchr(false_chars, actual_c)) {              \
      *outval = false;                                       \
    } else {                                                 \
      LOG(ERROR) << "format error";                          \
      return ParseResult::kError;                            \
    }                                                        \
  } while (false)
  SET_FIELD(field[0], &mapping.readable, "r", "-");
  SET_FIELD(field[1], &mapping.writable, "w", "-");
  SET_FIELD(field[2], &mapping.executable, "x", "-");
  SET_FIELD(field[3], &mapping.shareable, "sS", "p");
#undef SET_FIELD

  if (maps_file_reader->GetDelim(' ', &field) !=
          DelimitedFileReader::Result::kSuccess ||
      (field.pop_back(), !HexStringToNumber(field, &mapping.offset))) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }

  uint32_t major;
  if (maps_file_reader->GetDelim(':', &field) !=
          DelimitedFileReader::Result::kSuccess ||
      (field.pop_back(), field.size()) < 2 ||
      !HexStringToNumber(field, &major)) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }

  uint32_t minor;
  if (maps_file_reader->GetDelim(' ', &field) !=
          DelimitedFileReader::Result::kSuccess ||
      (field.pop_back(), field.size()) < 2 ||
      !HexStringToNumber(field, &minor)) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }

  mapping.device = makedev(major, minor);

  if (maps_file_reader->GetDelim(' ', &field) !=
          DelimitedFileReader::Result::kSuccess ||
      (field.pop_back(), !StringToNumber(field, &mapping.inode))) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }

  if (maps_file_reader->GetDelim('\n', &field) !=
      DelimitedFileReader::Result::kSuccess) {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }
  if (field.back() != '\n') {
    LOG(ERROR) << "format error";
    return ParseResult::kError;
  }
  field.pop_back();

  mappings->push_back(mapping);

  size_t path_start = field.find_first_not_of(' ');
  if (path_start != std::string::npos) {
    mappings->back().name = field.substr(path_start);
  }
  return ParseResult::kSuccess;
}

class SparseReverseIterator : public MemoryMap::Iterator {
 public:
  SparseReverseIterator(const std::vector<const MemoryMap::Mapping*>& mappings)
      : mappings_(mappings), riter_(mappings_.rbegin()) {}

  SparseReverseIterator() : mappings_(), riter_(mappings_.rend()) {}

  SparseReverseIterator(const SparseReverseIterator&) = delete;
  SparseReverseIterator& operator=(const SparseReverseIterator&) = delete;

  // Iterator:
  const MemoryMap::Mapping* Next() override {
    return riter_ == mappings_.rend() ? nullptr : *(riter_++);
  }

  unsigned int Count() override { return mappings_.rend() - riter_; }

 private:
  std::vector<const MemoryMap::Mapping*> mappings_;
  std::vector<const MemoryMap::Mapping*>::reverse_iterator riter_;
};

class FullReverseIterator : public MemoryMap::Iterator {
 public:
  FullReverseIterator(
      std::vector<MemoryMap::Mapping>::const_reverse_iterator rbegin,
      std::vector<MemoryMap::Mapping>::const_reverse_iterator rend)
      : riter_(rbegin), rend_(rend) {}

  FullReverseIterator(const FullReverseIterator&) = delete;
  FullReverseIterator& operator=(const FullReverseIterator&) = delete;

  // Iterator:
  const MemoryMap::Mapping* Next() override {
    return riter_ == rend_ ? nullptr : &*riter_++;
  }

  unsigned int Count() override { return rend_ - riter_; }

 private:
  std::vector<MemoryMap::Mapping>::const_reverse_iterator riter_;
  std::vector<MemoryMap::Mapping>::const_reverse_iterator rend_;
};

// Faster than a CheckedRange, for temporary values.
struct FastRange {
  VMAddress base;
  VMSize size;
};

}  // namespace

MemoryMap::Mapping::Mapping()
    : name(),
      range(false, 0, 0),
      offset(0),
      device(0),
      inode(0),
      readable(false),
      writable(false),
      executable(false),
      shareable(false) {}

MemoryMap::MemoryMap() : mappings_(), connection_(nullptr), initialized_() {}

MemoryMap::~MemoryMap() {}

bool MemoryMap::Mapping::Equals(const Mapping& other) const {
  DCHECK_EQ(range.Is64Bit(), other.range.Is64Bit());
  return range.Base() == other.range.Base() &&
         range.Size() == other.range.Size() && name == other.name &&
         offset == other.offset && device == other.device &&
         inode == other.inode && readable == other.readable &&
         writable == other.writable && executable == other.executable &&
         shareable == other.shareable;
}

bool MemoryMap::Initialize(PtraceConnection* connection) {
  INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
  connection_ = connection;

  // If the maps file is not read atomically, entries can be read multiple times
  // or missed entirely. The kernel reads entries from this file into a page
  // sized buffer, so maps files larger than a page require multiple reads.
  // Attempt to reduce the time between reads by reading the entire file into a
  // StringFile before attempting to parse it. If ParseMapsLine detects
  // duplicate, overlapping, or out-of-order entries, it will trigger restarting
  // the read up to |attempts| times.
  int attempts = 3;
  do {
    std::string contents;
    char path[32];
    snprintf(path, sizeof(path), "/proc/%d/maps", connection_->GetProcessID());
    if (!connection_->ReadFileContents(base::FilePath(path), &contents)) {
      return false;
    }

    StringFile maps_file;
    maps_file.SetString(contents);
    DelimitedFileReader maps_file_reader(&maps_file);

    ParseResult result;
    while ((result = ParseMapsLine(&maps_file_reader, &mappings_)) ==
           ParseResult::kSuccess) {
    }
    if (result == ParseResult::kEndOfFile) {
      INITIALIZATION_STATE_SET_VALID(initialized_);
      return true;
    }
    if (result == ParseResult::kError) {
      return false;
    }

    DCHECK(result == ParseResult::kRetry);
  } while (--attempts > 0);

  LOG(ERROR) << "retry count exceeded";
  return false;
}

const MemoryMap::Mapping* MemoryMap::FindMapping(LinuxVMAddress address) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);
  address = connection_->Memory()->PointerToAddress(address);

  for (const auto& mapping : mappings_) {
    if (mapping.range.Base() <= address && mapping.range.End() > address) {
      return &mapping;
    }
  }
  return nullptr;
}

const MemoryMap::Mapping* MemoryMap::FindMappingWithName(
    const std::string& name) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  for (const auto& mapping : mappings_) {
    if (mapping.name == name) {
      return &mapping;
    }
  }
  return nullptr;
}

std::vector<CheckedRange<VMAddress>> MemoryMap::GetReadableRanges(
    const CheckedRange<VMAddress, VMSize>& range) const {
  using Range = CheckedRange<VMAddress, VMSize>;

  VMAddress range_base = range.base();
  VMAddress range_end = range.end();
  std::vector<FastRange> overlapping;

  // Find all readable ranges overlapping the target range, maintaining order.
  for (const auto& mapping : mappings_) {
    if (!mapping.readable)
      continue;
    if (mapping.range.End() < range_base)
      continue;
    if (mapping.range.Base() >= range_end)
      continue;
    // Special case: the "[vvar]" region is marked readable, but we can't
    // access it.
    if (mapping.inode == 0 && mapping.name == "[vvar]")
      continue;
    overlapping.push_back({mapping.range.Base(), mapping.range.Size()});
  }
  if (overlapping.empty())
    return std::vector<Range>();

  // For the first and last, trim to the boundary of the incoming range.
  FastRange& front = overlapping.front();
  VMAddress original_front_base = front.base;
  front.base = std::max(front.base, range_base);
  front.size = (original_front_base + front.size) - front.base;
  FastRange& back = overlapping.back();
  VMAddress back_end = back.base + back.size;
  back.size = std::min(range_end, back_end) - back.base;

  // Coalesce, and convert to return type.
  std::vector<Range> result;
  result.push_back({overlapping[0].base, overlapping[0].size});
  DCHECK(result.back().IsValid());
  for (size_t i = 1; i < overlapping.size(); ++i) {
    if (result.back().end() == overlapping[i].base) {
      result.back().SetRange(result.back().base(),
                             result.back().size() + overlapping[i].size);
    } else {
      result.push_back({overlapping[i].base, overlapping[i].size});
    }
    DCHECK(result.back().IsValid());
  }

  return result;
}

std::unique_ptr<MemoryMap::Iterator> MemoryMap::FindFilePossibleMmapStarts(
    const Mapping& mapping) const {
  INITIALIZATION_STATE_DCHECK_VALID(initialized_);

  std::vector<const Mapping*> possible_starts;

  // If the mapping is anonymous, as is for the VDSO, there is no mapped file to
  // find the start of, so just return the input mapping.
  if (mapping.device == 0 && mapping.inode == 0) {
    for (const auto& candidate : mappings_) {
      if (mapping.Equals(candidate)) {
        possible_starts.push_back(&candidate);
        return std::make_unique<SparseReverseIterator>(possible_starts);
      }
    }

    LOG(ERROR) << "mapping not found";
    return std::make_unique<SparseReverseIterator>();
  }

#if BUILDFLAG(IS_ANDROID)
  // The Android Chromium linker uses ashmem to share RELRO segments between
  // processes. The original RELRO segment has been unmapped and replaced with a
  // mapping named "/dev/ashmem/RELRO:<libname>" where <libname> is the base
  // library name (e.g. libchrome.so) sans any preceding path that may be
  // present in other mappings for the library.
  // https://crashpad.chromium.org/bug/253
  static constexpr char kRelro[] = "/dev/ashmem/RELRO:";
  if (mapping.name.compare(0, strlen(kRelro), kRelro, 0, strlen(kRelro)) == 0) {
    // The kernel appends "(deleted)" to ashmem mappings because there isn't
    // any corresponding file on the filesystem.
    static constexpr char kDeleted[] = " (deleted)";
    size_t libname_end = mapping.name.rfind(kDeleted);
    DCHECK_NE(libname_end, std::string::npos);
    if (libname_end == std::string::npos) {
      libname_end = mapping.name.size();
    }

    std::string libname =
        mapping.name.substr(strlen(kRelro), libname_end - strlen(kRelro));
    for (const auto& candidate : mappings_) {
      if (candidate.name.rfind(libname) != std::string::npos) {
        possible_starts.push_back(&candidate);
      }
      if (mapping.Equals(candidate)) {
        return std::make_unique<SparseReverseIterator>(possible_starts);
      }
    }
  }
#endif  // BUILDFLAG(IS_ANDROID)

  for (const auto& candidate : mappings_) {
    if (candidate.device == mapping.device &&
        candidate.inode == mapping.inode
#if !BUILDFLAG(IS_ANDROID)
        // Libraries on Android may be mapped from zipfiles (APKs), in which
        // case the offset is not 0.
        && candidate.offset == 0
#endif  // !BUILDFLAG(IS_ANDROID)
    ) {
      possible_starts.push_back(&candidate);
    }
    if (mapping.Equals(candidate)) {
      return std::make_unique<SparseReverseIterator>(possible_starts);
    }
  }

  LOG(ERROR) << "mapping not found";
  return std::make_unique<SparseReverseIterator>();
}

std::unique_ptr<MemoryMap::Iterator> MemoryMap::ReverseIteratorFrom(
    const Mapping& target) const {
  for (auto riter = mappings_.crbegin(); riter != mappings_.rend(); ++riter) {
    if (riter->Equals(target)) {
      return std::make_unique<FullReverseIterator>(riter, mappings_.rend());
    }
  }
  return std::make_unique<FullReverseIterator>(mappings_.rend(),
                                               mappings_.rend());
}

}  // namespace crashpad
