// Copyright 2017 The Crashpad Authors. All rights reserved.
//
// 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/bit_cast.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()) {}

  // 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_;

  DISALLOW_COPY_AND_ASSIGN(SparseReverseIterator);
};

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) {}

  // 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_;

  DISALLOW_COPY_AND_ASSIGN(FullReverseIterator);
};

}  // 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_(), 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_);

  // 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_);

  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::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 defined(OS_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  // OS_ANDROID

  for (const auto& candidate : mappings_) {
    if (candidate.device == mapping.device &&
        candidate.inode == mapping.inode
#if !defined(OS_ANDROID)
        // Libraries on Android may be mapped from zipfiles (APKs), in which
        // case the offset is not 0.
        && candidate.offset == 0
#endif  // !defined(OS_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
