/*
 * Copyright (C) 2018 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 <inttypes.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <cerrno>
#include <cstring>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/mapped_file.h>
#include <android-base/stringprintf.h>

#include <dex/class_accessor-inl.h>
#include <dex/code_item_accessors-inl.h>
#include <dex/dex_file-inl.h>
#include <dex/dex_file_loader.h>

#include "art_api/ext_dex_file.h"

extern "C" class ExtDexFileString {
 public:
  const std::string str_;
};

namespace art {
namespace {

const ExtDexFileString empty_string{""};

struct MethodCacheEntry {
  int32_t offset;  // Offset relative to the start of the dex file header.
  int32_t len;
  int32_t index;  // Method index.
};

class MappedFileContainer : public DexFileContainer {
 public:
  explicit MappedFileContainer(std::unique_ptr<android::base::MappedFile>&& map)
      : map_(std::move(map)) {}
  ~MappedFileContainer() override {}
  int GetPermissions() override { return 0; }
  bool IsReadOnly() override { return true; }
  bool EnableWrite() override { return false; }
  bool DisableWrite() override { return false; }

 private:
  std::unique_ptr<android::base::MappedFile> map_;
  DISALLOW_COPY_AND_ASSIGN(MappedFileContainer);
};

}  // namespace
}  // namespace art

extern "C" {

const ExtDexFileString* ExtDexFileMakeString(const char* str) {
  if (str[0] == '\0') {
    return &art::empty_string;
  }
  return new ExtDexFileString{str};
}

const char* ExtDexFileGetString(const ExtDexFileString* ext_string, /*out*/ size_t* size) {
  DCHECK(ext_string != nullptr);
  *size = ext_string->str_.size();
  return ext_string->str_.data();
}

void ExtDexFileFreeString(const ExtDexFileString* ext_string) {
  DCHECK(ext_string != nullptr);
  if (ext_string != &art::empty_string) {
    delete (ext_string);
  }
}

// Wraps DexFile to add the caching needed by the external interface. This is
// what gets passed over as ExtDexFile*.
class ExtDexFile {
  // Method cache for GetMethodInfoForOffset. This is populated as we iterate
  // sequentially through the class defs. MethodCacheEntry.name is only set for
  // methods returned by GetMethodInfoForOffset.
  std::map<int32_t, art::MethodCacheEntry> method_cache_;

  // Index of first class def for which method_cache_ isn't complete.
  uint32_t class_def_index_ = 0;

 public:
  std::unique_ptr<const art::DexFile> dex_file_;
  explicit ExtDexFile(std::unique_ptr<const art::DexFile>&& dex_file)
      : dex_file_(std::move(dex_file)) {}

  art::MethodCacheEntry* GetMethodCacheEntryForOffset(int64_t dex_offset) {
    // First look in the method cache.
    auto it = method_cache_.upper_bound(dex_offset);
    if (it != method_cache_.end() && dex_offset >= it->second.offset) {
      return &it->second;
    }

    for (; class_def_index_ < dex_file_->NumClassDefs(); class_def_index_++) {
      art::ClassAccessor accessor(*dex_file_, class_def_index_);

      for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
        art::CodeItemInstructionAccessor code = method.GetInstructions();
        if (!code.HasCodeItem()) {
          continue;
        }

        int32_t offset = reinterpret_cast<const uint8_t*>(code.Insns()) - dex_file_->Begin();
        int32_t len = code.InsnsSizeInBytes();
        int32_t index = method.GetIndex();
        auto res = method_cache_.emplace(offset + len, art::MethodCacheEntry{offset, len, index});
        if (offset <= dex_offset && dex_offset < offset + len) {
          return &res.first->second;
        }
      }
    }

    return nullptr;
  }
};

int ExtDexFileOpenFromMemory(const void* addr,
                             /*inout*/ size_t* size,
                             const char* location,
                             /*out*/ const ExtDexFileString** ext_error_msg,
                             /*out*/ ExtDexFile** ext_dex_file) {
  if (*size < sizeof(art::DexFile::Header)) {
    *size = sizeof(art::DexFile::Header);
    *ext_error_msg = nullptr;
    return false;
  }

  const art::DexFile::Header* header = reinterpret_cast<const art::DexFile::Header*>(addr);
  uint32_t file_size = header->file_size_;
  if (art::CompactDexFile::IsMagicValid(header->magic_)) {
    // Compact dex files store the data section separately so that it can be shared.
    // Therefore we need to extend the read memory range to include it.
    // TODO: This might be wasteful as we might read data in between as well.
    //       In practice, this should be fine, as such sharing only happens on disk.
    uint32_t computed_file_size;
    if (__builtin_add_overflow(header->data_off_, header->data_size_, &computed_file_size)) {
      *ext_error_msg = new ExtDexFileString{
          android::base::StringPrintf("Corrupt CompactDexFile header in '%s'", location)};
      return false;
    }
    if (computed_file_size > file_size) {
      file_size = computed_file_size;
    }
  } else if (!art::StandardDexFile::IsMagicValid(header->magic_)) {
    *ext_error_msg = new ExtDexFileString{
        android::base::StringPrintf("Unrecognized dex file header in '%s'", location)};
    return false;
  }

  if (*size < file_size) {
    *size = file_size;
    *ext_error_msg = nullptr;
    return false;
  }

  std::string loc_str(location);
  art::DexFileLoader loader;
  std::string error_msg;
  std::unique_ptr<const art::DexFile> dex_file = loader.Open(static_cast<const uint8_t*>(addr),
                                                             *size,
                                                             loc_str,
                                                             header->checksum_,
                                                             /*oat_dex_file=*/nullptr,
                                                             /*verify=*/false,
                                                             /*verify_checksum=*/false,
                                                             &error_msg);
  if (dex_file == nullptr) {
    *ext_error_msg = new ExtDexFileString{std::move(error_msg)};
    return false;
  }

  *ext_dex_file = new ExtDexFile(std::move(dex_file));
  return true;
}

int ExtDexFileOpenFromFd(int fd,
                         off_t offset,
                         const char* location,
                         /*out*/ const ExtDexFileString** ext_error_msg,
                         /*out*/ ExtDexFile** ext_dex_file) {
  size_t length;
  {
    struct stat sbuf;
    std::memset(&sbuf, 0, sizeof(sbuf));
    if (fstat(fd, &sbuf) == -1) {
      *ext_error_msg = new ExtDexFileString{
          android::base::StringPrintf("fstat '%s' failed: %s", location, std::strerror(errno))};
      return false;
    }
    if (S_ISDIR(sbuf.st_mode)) {
      *ext_error_msg = new ExtDexFileString{
          android::base::StringPrintf("Attempt to mmap directory '%s'", location)};
      return false;
    }
    length = sbuf.st_size;
  }

  if (length < offset + sizeof(art::DexFile::Header)) {
    *ext_error_msg = new ExtDexFileString{android::base::StringPrintf(
        "Offset %" PRId64 " too large for '%s' of size %zu", int64_t{offset}, location, length)};
    return false;
  }

  // Cannot use MemMap in libartbase here, because it pulls in dlopen which we
  // can't have when being compiled statically.
  std::unique_ptr<android::base::MappedFile> map =
      android::base::MappedFile::FromFd(fd, offset, length, PROT_READ);
  if (map == nullptr) {
    *ext_error_msg = new ExtDexFileString{
        android::base::StringPrintf("mmap '%s' failed: %s", location, std::strerror(errno))};
    return false;
  }

  const art::DexFile::Header* header = reinterpret_cast<const art::DexFile::Header*>(map->data());
  uint32_t file_size;
  if (__builtin_add_overflow(offset, header->file_size_, &file_size)) {
    *ext_error_msg =
        new ExtDexFileString{android::base::StringPrintf("Corrupt header in '%s'", location)};
    return false;
  }
  if (length < file_size) {
    *ext_error_msg = new ExtDexFileString{
        android::base::StringPrintf("Dex file '%s' too short: expected %" PRIu32 ", got %" PRIu64,
                                    location,
                                    file_size,
                                    uint64_t{length})};
    return false;
  }

  void* addr = map->data();
  size_t size = map->size();
  auto container = std::make_unique<art::MappedFileContainer>(std::move(map));

  std::string loc_str(location);
  std::string error_msg;
  art::DexFileLoader loader;
  std::unique_ptr<const art::DexFile> dex_file = loader.Open(reinterpret_cast<const uint8_t*>(addr),
                                                             size,
                                                             loc_str,
                                                             header->checksum_,
                                                             /*oat_dex_file=*/nullptr,
                                                             /*verify=*/false,
                                                             /*verify_checksum=*/false,
                                                             &error_msg,
                                                             std::move(container));
  if (dex_file == nullptr) {
    *ext_error_msg = new ExtDexFileString{std::move(error_msg)};
    return false;
  }
  *ext_dex_file = new ExtDexFile(std::move(dex_file));
  return true;
}

int ExtDexFileGetMethodInfoForOffset(ExtDexFile* ext_dex_file,
                                     int64_t dex_offset,
                                     /*out*/ ExtDexFileMethodInfo* method_info) {
  if (!ext_dex_file->dex_file_->IsInDataSection(ext_dex_file->dex_file_->Begin() + dex_offset)) {
    return false;  // The DEX offset is not within the bytecode of this dex file.
  }

  if (ext_dex_file->dex_file_->IsCompactDexFile()) {
    // The data section of compact dex files might be shared.
    // Check the subrange unique to this compact dex.
    const art::CompactDexFile::Header& cdex_header =
        ext_dex_file->dex_file_->AsCompactDexFile()->GetHeader();
    uint32_t begin = cdex_header.data_off_ + cdex_header.OwnedDataBegin();
    uint32_t end = cdex_header.data_off_ + cdex_header.OwnedDataEnd();
    if (dex_offset < begin || dex_offset >= end) {
      return false;  // The DEX offset is not within the bytecode of this dex file.
    }
  }

  art::MethodCacheEntry* entry = ext_dex_file->GetMethodCacheEntryForOffset(dex_offset);
  if (entry != nullptr) {
    method_info->offset = entry->offset;
    method_info->len = entry->len;
    method_info->name =
        new ExtDexFileString{ext_dex_file->dex_file_->PrettyMethod(entry->index, false)};
    return true;
  }

  return false;
}

void ExtDexFileGetAllMethodInfos(ExtDexFile* ext_dex_file,
                                 int with_signature,
                                 ExtDexFileMethodInfoCallback* method_info_cb,
                                 void* user_data) {
  for (art::ClassAccessor accessor : ext_dex_file->dex_file_->GetClasses()) {
    for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
      art::CodeItemInstructionAccessor code = method.GetInstructions();
      if (!code.HasCodeItem()) {
        continue;
      }

      ExtDexFileMethodInfo method_info;
      method_info.offset = static_cast<int32_t>(reinterpret_cast<const uint8_t*>(code.Insns()) -
                                                ext_dex_file->dex_file_->Begin());
      method_info.len = code.InsnsSizeInBytes();
      method_info.name = new ExtDexFileString{
          ext_dex_file->dex_file_->PrettyMethod(method.GetIndex(), with_signature)};
      method_info_cb(&method_info, user_data);
    }
  }
}

void ExtDexFileFree(ExtDexFile* ext_dex_file) { delete (ext_dex_file); }

}  // extern "C"
