/* Copyright (C) 2016 The Android Open Source Project
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This file implements interfaces from the file jvmti.h. This implementation
 * is licensed under the same terms as the file jvmti.h.  The
 * copyright and license information for the file jvmti.h follows.
 *
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

#include "transform.h"

#include "class_linker.h"
#include "dex_file.h"
#include "gc_root-inl.h"
#include "globals.h"
#include "jni_env_ext-inl.h"
#include "jvmti.h"
#include "linear_alloc.h"
#include "mem_map.h"
#include "mirror/array.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader-inl.h"
#include "mirror/string-inl.h"
#include "oat_file.h"
#include "scoped_thread_state_change-inl.h"
#include "thread_list.h"
#include "transform.h"
#include "utf.h"
#include "utils/dex_cache_arrays_layout-inl.h"

namespace openjdkjvmti {

static bool ReadChecksum(jint data_len, const unsigned char* dex, /*out*/uint32_t* res) {
  if (data_len < static_cast<jint>(sizeof(art::DexFile::Header))) {
    return false;
  }
  *res = reinterpret_cast<const art::DexFile::Header*>(dex)->checksum_;
  return true;
}

static std::unique_ptr<art::MemMap> MoveDataToMemMap(const std::string& original_location,
                                                      jint data_len,
                                                      unsigned char* dex_data) {
  std::string error_msg;
  std::unique_ptr<art::MemMap> map(art::MemMap::MapAnonymous(
      art::StringPrintf("%s-transformed", original_location.c_str()).c_str(),
      nullptr,
      data_len,
      PROT_READ|PROT_WRITE,
      /*low_4gb*/false,
      /*reuse*/false,
      &error_msg));
  if (map == nullptr) {
    return map;
  }
  memcpy(map->Begin(), dex_data, data_len);
  map->Protect(PROT_READ);
  return map;
}

static void InvalidateExistingMethods(art::Thread* self,
                                      art::Handle<art::mirror::Class> klass,
                                      art::Handle<art::mirror::DexCache> cache,
                                      const art::DexFile* dex_file)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  // Create new DexCache with new DexFile.
  // reset dex_class_def_idx_
  // for each method reset entry_point_from_quick_compiled_code_ to bridge
  // for each method reset dex_code_item_offset_
  // for each method reset dex_method_index_
  // for each method set dex_cache_resolved_methods_ to new DexCache
  // for each method set dex_cache_resolved_types_ to new DexCache
  auto* runtime = art::Runtime::Current();
  art::ClassLinker* linker = runtime->GetClassLinker();
  art::PointerSize image_pointer_size = linker->GetImagePointerSize();
  std::string descriptor_storage;
  const char* descriptor = klass->GetDescriptor(&descriptor_storage);
  // Get the new class def
  const art::DexFile::ClassDef* class_def = art::OatFile::OatDexFile::FindClassDef(
      *dex_file, descriptor, art::ComputeModifiedUtf8Hash(descriptor));
  CHECK(class_def != nullptr);
  const art::DexFile::TypeId& declaring_class_id = dex_file->GetTypeId(class_def->class_idx_);
  art::StackHandleScope<6> hs(self);
  const art::DexFile& old_dex_file = klass->GetDexFile();
  for (art::ArtMethod& method : klass->GetMethods(image_pointer_size)) {
    // Find the code_item for the method then find the dex_method_index and dex_code_item_offset to
    // set.
    const art::DexFile::StringId* new_name_id = dex_file->FindStringId(method.GetName());
    uint16_t method_return_idx =
        dex_file->GetIndexForTypeId(*dex_file->FindTypeId(method.GetReturnTypeDescriptor()));
    const auto* old_type_list = method.GetParameterTypeList();
    std::vector<uint16_t> new_type_list;
    for (uint32_t i = 0; old_type_list != nullptr && i < old_type_list->Size(); i++) {
      new_type_list.push_back(
          dex_file->GetIndexForTypeId(
              *dex_file->FindTypeId(
                  old_dex_file.GetTypeDescriptor(
                      old_dex_file.GetTypeId(
                          old_type_list->GetTypeItem(i).type_idx_)))));
    }
    const art::DexFile::ProtoId* proto_id = dex_file->FindProtoId(method_return_idx,
                                                                  new_type_list);
    CHECK(proto_id != nullptr || old_type_list == nullptr);
    const art::DexFile::MethodId* method_id = dex_file->FindMethodId(declaring_class_id,
                                                                      *new_name_id,
                                                                      *proto_id);
    CHECK(method_id != nullptr);
    uint32_t dex_method_idx = dex_file->GetIndexForMethodId(*method_id);
    method.SetDexMethodIndex(dex_method_idx);
    linker->SetEntryPointsToInterpreter(&method);
    method.SetCodeItemOffset(dex_file->FindCodeItemOffset(*class_def, dex_method_idx));
    method.SetDexCacheResolvedMethods(cache->GetResolvedMethods(), image_pointer_size);
    method.SetDexCacheResolvedTypes(cache->GetResolvedTypes(), image_pointer_size);
  }

  // Update the class fields.
  // Need to update class last since the ArtMethod gets its DexFile from the class (which is needed
  // to call GetReturnTypeDescriptor and GetParameterTypeList above).
  klass->SetDexCache(cache.Get());
  klass->SetDexCacheStrings(cache->GetStrings());
  klass->SetDexClassDefIndex(dex_file->GetIndexForClassDef(*class_def));
  klass->SetDexTypeIndex(dex_file->GetIndexForTypeId(*dex_file->FindTypeId(descriptor)));
}

// Adds the dex file.
static art::mirror::LongArray* InsertDexFileIntoArray(art::Thread* self,
                                                      const art::DexFile* dex,
                                                      art::Handle<art::mirror::LongArray>& orig)
    REQUIRES_SHARED(art::Locks::mutator_lock_) {
  art::StackHandleScope<1> hs(self);
  CHECK_GE(orig->GetLength(), 1);
  art::Handle<art::mirror::LongArray> ret(
      hs.NewHandle(art::mirror::LongArray::Alloc(self, orig->GetLength() + 1)));
  CHECK(ret.Get() != nullptr);
  // Copy the oat-dex.
  // TODO Should I clear the oatdex element?
  ret->SetWithoutChecks<false>(0, orig->GetWithoutChecks(0));
  ret->SetWithoutChecks<false>(1, static_cast<int64_t>(reinterpret_cast<intptr_t>(dex)));
  ret->Memcpy(2, orig.Get(), 1, orig->GetLength() - 1);
  return ret.Get();
}

// TODO Handle all types of class loaders.
static bool FindDalvikSystemDexFileAndLoaderForClass(
    art::Handle<art::mirror::Class> klass,
    /*out*/art::mirror::Object** dex_file,
    /*out*/art::mirror::ClassLoader** loader)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
  const char* dex_path_list_element_array_name = "[Ldalvik/system/DexPathList$Element;";
  const char* dex_path_list_element_name = "Ldalvik/system/DexPathList$Element;";
  const char* dex_file_name = "Ldalvik/system/DexFile;";
  const char* dex_path_list_name = "Ldalvik/system/DexPathList;";
  const char* dex_class_loader_name = "Ldalvik/system/BaseDexClassLoader;";

  art::Thread* self = art::Thread::Current();
  CHECK(!self->IsExceptionPending());
  art::StackHandleScope<11> hs(self);
  art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();

  art::Handle<art::mirror::ClassLoader> null_loader(hs.NewHandle<art::mirror::ClassLoader>(
      nullptr));
  art::Handle<art::mirror::Class> base_dex_loader_class(hs.NewHandle(class_linker->FindClass(
      self, dex_class_loader_name, null_loader)));

  art::ArtField* path_list_field = base_dex_loader_class->FindDeclaredInstanceField(
      "pathList", dex_path_list_name);
  CHECK(path_list_field != nullptr);

  art::ArtField* dex_path_list_element_field =
      class_linker->FindClass(self, dex_path_list_name, null_loader)
        ->FindDeclaredInstanceField("dexElements", dex_path_list_element_array_name);
  CHECK(dex_path_list_element_field != nullptr);

  art::ArtField* element_dex_file_field =
      class_linker->FindClass(self, dex_path_list_element_name, null_loader)
        ->FindDeclaredInstanceField("dexFile", dex_file_name);
  CHECK(element_dex_file_field != nullptr);

  art::Handle<art::mirror::ClassLoader> h_class_loader(hs.NewHandle(klass->GetClassLoader()));
  art::Handle<art::mirror::Class> loader_class(hs.NewHandle(h_class_loader->GetClass()));
  // Check if loader is a BaseDexClassLoader
  if (!loader_class->IsSubClass(base_dex_loader_class.Get())) {
    LOG(ERROR) << "The classloader is not a BaseDexClassLoader which is currently the only "
               << "supported class loader type!";
    return false;
  }
  art::Handle<art::mirror::Object> path_list(
      hs.NewHandle(path_list_field->GetObject(h_class_loader.Get())));
  CHECK(path_list.Get() != nullptr);
  CHECK(!self->IsExceptionPending());
  art::Handle<art::mirror::ObjectArray<art::mirror::Object>> dex_elements_list(hs.NewHandle(
      dex_path_list_element_field->GetObject(path_list.Get())->
      AsObjectArray<art::mirror::Object>()));
  CHECK(!self->IsExceptionPending());
  CHECK(dex_elements_list.Get() != nullptr);
  size_t num_elements = dex_elements_list->GetLength();
  art::MutableHandle<art::mirror::Object> current_element(
      hs.NewHandle<art::mirror::Object>(nullptr));
  art::MutableHandle<art::mirror::Object> first_dex_file(
      hs.NewHandle<art::mirror::Object>(nullptr));
  for (size_t i = 0; i < num_elements; i++) {
    current_element.Assign(dex_elements_list->Get(i));
    CHECK(current_element.Get() != nullptr);
    CHECK(!self->IsExceptionPending());
    CHECK(dex_elements_list.Get() != nullptr);
    CHECK_EQ(current_element->GetClass(), class_linker->FindClass(self,
                                                                  dex_path_list_element_name,
                                                                  null_loader));
    // TODO It would be cleaner to put the art::DexFile into the dalvik.system.DexFile the class
    // comes from but it is more annoying because we would need to find this class. It is not
    // necessary for proper function since we just need to be in front of the classes old dex file
    // in the path.
    first_dex_file.Assign(element_dex_file_field->GetObject(current_element.Get()));
    if (first_dex_file.Get() != nullptr) {
      *dex_file = first_dex_file.Get();
      *loader = h_class_loader.Get();
      return true;
    }
  }
  return false;
}

// Gets the data surrounding the given class.
jvmtiError GetTransformationData(ArtJvmTiEnv* env,
                                 jclass klass,
                                 /*out*/std::string* location,
                                 /*out*/JNIEnv** jni_env_ptr,
                                 /*out*/jobject* loader,
                                 /*out*/std::string* name,
                                 /*out*/jobject* protection_domain,
                                 /*out*/jint* data_len,
                                 /*out*/unsigned char** dex_data) {
  jint ret = env->art_vm->GetEnv(reinterpret_cast<void**>(jni_env_ptr), JNI_VERSION_1_1);
  if (ret != JNI_OK) {
    // TODO Different error might be better?
    return ERR(INTERNAL);
  }
  JNIEnv* jni_env = *jni_env_ptr;
  art::ScopedObjectAccess soa(jni_env);
  art::StackHandleScope<3> hs(art::Thread::Current());
  art::Handle<art::mirror::Class> hs_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
  *loader = soa.AddLocalReference<jobject>(hs_klass->GetClassLoader());
  *name = art::mirror::Class::ComputeName(hs_klass)->ToModifiedUtf8();
  // TODO is this always null?
  *protection_domain = nullptr;
  const art::DexFile& dex = hs_klass->GetDexFile();
  *location = dex.GetLocation();
  *data_len = static_cast<jint>(dex.Size());
  // TODO We should maybe change env->Allocate to allow us to mprotect this memory and stop writes.
  jvmtiError alloc_error = env->Allocate(*data_len, dex_data);
  if (alloc_error != OK) {
    return alloc_error;
  }
  // Copy the data into a temporary buffer.
  memcpy(reinterpret_cast<void*>(*dex_data),
          reinterpret_cast<const void*>(dex.Begin()),
          *data_len);
  return OK;
}

// Install the new dex file.
// TODO do error checks for bad state (method in a stack, changes to number of methods/fields/etc).
jvmtiError MoveTransformedFileIntoRuntime(jclass jklass,
                                          std::string original_location,
                                          jint data_len,
                                          unsigned char* dex_data) {
  const char* dex_file_name = "Ldalvik/system/DexFile;";
  art::Thread* self = art::Thread::Current();
  art::Runtime* runtime = art::Runtime::Current();
  art::ThreadList* threads = runtime->GetThreadList();
  art::ClassLinker* class_linker = runtime->GetClassLinker();
  uint32_t checksum = 0;
  if (!ReadChecksum(data_len, dex_data, &checksum)) {
    return ERR(INVALID_CLASS_FORMAT);
  }

  std::unique_ptr<art::MemMap> map(MoveDataToMemMap(original_location, data_len, dex_data));
  if (map.get() == nullptr) {
    return ERR(INTERNAL);
  }
  std::string error_msg;
  // Load the new dex_data in memory (mmap it, etc)
  std::unique_ptr<const art::DexFile> new_dex_file = art::DexFile::Open(map->GetName(),
                                                                        checksum,
                                                                        std::move(map),
                                                                        /*verify*/ true,
                                                                        /*verify_checksum*/ true,
                                                                        &error_msg);
  CHECK(new_dex_file.get() != nullptr) << "Unable to load dex file! " << error_msg;

  // Get mutator lock. We need the lifetimes of these variables (hs, the classes, etc.) to be longer
  // then current lock (since there isn't upgrading of the lock) so we don't use soa.
  art::ThreadState old_state = self->TransitionFromSuspendedToRunnable();
  // This scope is needed to make sure that the HandleScope dies with mutator_lock_ since we need to
  // upgrade the mutator_lock during the execution.
  {
    art::StackHandleScope<11> hs(self);
    art::Handle<art::mirror::ClassLoader> null_loader(
        hs.NewHandle<art::mirror::ClassLoader>(nullptr));
    CHECK(null_loader.Get() == nullptr);
    art::ArtField* dex_file_cookie_field = class_linker->
        FindClass(self, dex_file_name, null_loader)->
        FindDeclaredInstanceField("mCookie", "Ljava/lang/Object;");
    art::ArtField* dex_file_internal_cookie_field =
        class_linker->FindClass(self, dex_file_name, null_loader)
          ->FindDeclaredInstanceField("mInternalCookie", "Ljava/lang/Object;");
    CHECK(dex_file_cookie_field != nullptr);
    art::Handle<art::mirror::Class> klass(
        hs.NewHandle(art::down_cast<art::mirror::Class*>(self->DecodeJObject(jklass))));
    art::mirror::Object* dex_file_ptr = nullptr;
    art::mirror::ClassLoader* class_loader_ptr = nullptr;
    // Find dalvik.system.DexFile that represents the dex file we are changing.
    if (!FindDalvikSystemDexFileAndLoaderForClass(klass, &dex_file_ptr, &class_loader_ptr)) {
      self->TransitionFromRunnableToSuspended(old_state);
      LOG(ERROR) << "Could not find DexFile.";
      return ERR(INTERNAL);
    }
    art::Handle<art::mirror::Object> dex_file_obj(hs.NewHandle(dex_file_ptr));
    art::Handle<art::mirror::ClassLoader> class_loader(hs.NewHandle(class_loader_ptr));
    art::Handle<art::mirror::LongArray> art_dex_array(
        hs.NewHandle<art::mirror::LongArray>(
            dex_file_cookie_field->GetObject(dex_file_obj.Get())->AsLongArray()));
    art::Handle<art::mirror::LongArray> new_art_dex_array(
        hs.NewHandle<art::mirror::LongArray>(
            InsertDexFileIntoArray(self, new_dex_file.get(), art_dex_array)));
    art::Handle<art::mirror::DexCache> cache(
        hs.NewHandle(class_linker->RegisterDexFile(*new_dex_file.get(), class_loader.Get())));
    self->TransitionFromRunnableToSuspended(old_state);

    threads->SuspendAll("moving dex file into runtime", /*long_suspend*/true);
    // Change the mCookie field. Old value will be GC'd as normal.
    dex_file_cookie_field->SetObject<false>(dex_file_obj.Get(), new_art_dex_array.Get());
    dex_file_internal_cookie_field->SetObject<false>(dex_file_obj.Get(), new_art_dex_array.Get());
    // Invalidate existing methods.
    InvalidateExistingMethods(self, klass, cache, new_dex_file.release());
  }
  threads->ResumeAll();
  return OK;
}

}  // namespace openjdkjvmti
