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

#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#include <algorithm>
#include <memory>

#include <android-base/unique_fd.h>

#include <unwindstack/Memory.h>

#include "Check.h"

namespace unwindstack {

bool Memory::ReadString(uint64_t addr, std::string* string, uint64_t max_read) {
  string->clear();
  uint64_t bytes_read = 0;
  while (bytes_read < max_read) {
    uint8_t value;
    if (!Read(addr, &value, sizeof(value))) {
      return false;
    }
    if (value == '\0') {
      return true;
    }
    string->push_back(value);
    addr++;
    bytes_read++;
  }
  return false;
}

std::shared_ptr<Memory> Memory::CreateProcessMemory(pid_t pid) {
  if (pid == getpid()) {
    return std::shared_ptr<Memory>(new MemoryLocal());
  }
  return std::shared_ptr<Memory>(new MemoryRemote(pid));
}

bool MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
  uint64_t last_read_byte;
  if (__builtin_add_overflow(size, addr, &last_read_byte)) {
    return false;
  }
  if (last_read_byte > raw_.size()) {
    return false;
  }
  memcpy(dst, &raw_[addr], size);
  return true;
}

uint8_t* MemoryBuffer::GetPtr(size_t offset) {
  if (offset < raw_.size()) {
    return &raw_[offset];
  }
  return nullptr;
}

MemoryFileAtOffset::~MemoryFileAtOffset() {
  Clear();
}

void MemoryFileAtOffset::Clear() {
  if (data_) {
    munmap(&data_[-offset_], size_ + offset_);
    data_ = nullptr;
  }
}

bool MemoryFileAtOffset::Init(const std::string& file, uint64_t offset, uint64_t size) {
  // Clear out any previous data if it exists.
  Clear();

  android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(file.c_str(), O_RDONLY | O_CLOEXEC)));
  if (fd == -1) {
    return false;
  }
  struct stat buf;
  if (fstat(fd, &buf) == -1) {
    return false;
  }
  if (offset >= static_cast<uint64_t>(buf.st_size)) {
    return false;
  }

  offset_ = offset & (getpagesize() - 1);
  uint64_t aligned_offset = offset & ~(getpagesize() - 1);
  if (aligned_offset > static_cast<uint64_t>(buf.st_size) ||
      offset > static_cast<uint64_t>(buf.st_size)) {
    return false;
  }

  size_ = buf.st_size - aligned_offset;
  uint64_t max_size;
  if (!__builtin_add_overflow(size, offset_, &max_size) && max_size < size_) {
    // Truncate the mapped size.
    size_ = max_size;
  }
  void* map = mmap(nullptr, size_, PROT_READ, MAP_PRIVATE, fd, aligned_offset);
  if (map == MAP_FAILED) {
    return false;
  }

  data_ = &reinterpret_cast<uint8_t*>(map)[offset_];
  size_ -= offset_;

  return true;
}

bool MemoryFileAtOffset::Read(uint64_t addr, void* dst, size_t size) {
  uint64_t max_size;
  if (__builtin_add_overflow(addr, size, &max_size) || max_size > size_) {
    return false;
  }
  memcpy(dst, &data_[addr], size);
  return true;
}

bool MemoryRemote::PtraceRead(uint64_t addr, long* value) {
#if !defined(__LP64__)
  // Cannot read an address greater than 32 bits.
  if (addr > UINT32_MAX) {
    return false;
  }
#endif
  // ptrace() returns -1 and sets errno when the operation fails.
  // To disambiguate -1 from a valid result, we clear errno beforehand.
  errno = 0;
  *value = ptrace(PTRACE_PEEKTEXT, pid_, reinterpret_cast<void*>(addr), nullptr);
  if (*value == -1 && errno) {
    return false;
  }
  return true;
}

bool MemoryRemote::Read(uint64_t addr, void* dst, size_t bytes) {
  // Make sure that there is no overflow.
  uint64_t max_size;
  if (__builtin_add_overflow(addr, bytes, &max_size)) {
    return false;
  }

  size_t bytes_read = 0;
  long data;
  size_t align_bytes = addr & (sizeof(long) - 1);
  if (align_bytes != 0) {
    if (!PtraceRead(addr & ~(sizeof(long) - 1), &data)) {
      return false;
    }
    size_t copy_bytes = std::min(sizeof(long) - align_bytes, bytes);
    memcpy(dst, reinterpret_cast<uint8_t*>(&data) + align_bytes, copy_bytes);
    addr += copy_bytes;
    dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + copy_bytes);
    bytes -= copy_bytes;
    bytes_read += copy_bytes;
  }

  for (size_t i = 0; i < bytes / sizeof(long); i++) {
    if (!PtraceRead(addr, &data)) {
      return false;
    }
    memcpy(dst, &data, sizeof(long));
    dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + sizeof(long));
    addr += sizeof(long);
    bytes_read += sizeof(long);
  }

  size_t left_over = bytes & (sizeof(long) - 1);
  if (left_over) {
    if (!PtraceRead(addr, &data)) {
      return false;
    }
    memcpy(dst, &data, left_over);
    bytes_read += left_over;
  }
  return true;
}

bool MemoryLocal::Read(uint64_t addr, void* dst, size_t size) {
  // Make sure that there is no overflow.
  uint64_t max_size;
  if (__builtin_add_overflow(addr, size, &max_size)) {
    return false;
  }

  // The process_vm_readv call will not always work on remote
  // processes, so only use it for reads from the current pid.
  // Use this method to avoid crashes if an address is invalid since
  // unwind data could try to access any part of the address space.
  struct iovec local_io;
  local_io.iov_base = dst;
  local_io.iov_len = size;

  struct iovec remote_io;
  remote_io.iov_base = reinterpret_cast<void*>(static_cast<uintptr_t>(addr));
  remote_io.iov_len = size;

  ssize_t bytes_read = process_vm_readv(getpid(), &local_io, 1, &remote_io, 1, 0);
  if (bytes_read == -1) {
    return false;
  }
  return static_cast<size_t>(bytes_read) == size;
}

bool MemoryOffline::Init(const std::string& file, uint64_t offset) {
  if (!MemoryFileAtOffset::Init(file, offset)) {
    return false;
  }
  // The first uint64_t value is the start of memory.
  if (!MemoryFileAtOffset::Read(0, &start_, sizeof(start_))) {
    return false;
  }
  // Subtract the first 64 bit value from the total size.
  size_ -= sizeof(start_);
  return true;
}

bool MemoryOffline::Read(uint64_t addr, void* dst, size_t size) {
  uint64_t max_size;
  if (__builtin_add_overflow(addr, size, &max_size)) {
    return false;
  }

  uint64_t real_size;
  if (__builtin_add_overflow(start_, offset_, &real_size) ||
      __builtin_add_overflow(real_size, size_, &real_size)) {
    return false;
  }

  if (addr < start_ || max_size > real_size) {
    return false;
  }
  memcpy(dst, &data_[addr + offset_ - start_ + sizeof(start_)], size);
  return true;
}

MemoryRange::MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t end)
    : memory_(memory), begin_(begin), length_(end - begin) {
  CHECK(end > begin);
}

bool MemoryRange::Read(uint64_t addr, void* dst, size_t size) {
  uint64_t max_read;
  if (__builtin_add_overflow(addr, size, &max_read) || max_read > length_) {
    return false;
  }
  // The check above guarantees that addr + begin_ will not overflow.
  return memory_->Read(addr + begin_, dst, size);
}

}  // namespace unwindstack
