/*
 * 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.
  std::string name;  // Method name. Not filled in for all cache entries.
};

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;
  }

  const std::string& GetMethodName(art::MethodCacheEntry& entry) {
    if (entry.name.empty()) {
      entry.name = dex_file_->PrettyMethod(entry.index, false);
    }
    return entry.name;
  }
};

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->GetMethodName(*entry)};
    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"
