/* Copyright (C) 2017 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 "base/leb128.h"
#include "fixed_up_dex_file.h"
#include "dex/class_accessor-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/dex_file_verifier.h"

// Runtime includes.
#include "dex_container.h"
#include "dex/compact_dex_level.h"
#include "dex_to_dex_decompiler.h"
#include "dexlayout.h"
#include "oat_file.h"
#include "vdex_file.h"

namespace openjdkjvmti {

static void RecomputeDexChecksum(art::DexFile* dex_file) {
  reinterpret_cast<art::DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_ =
      dex_file->CalculateChecksum();
}

static void UnhideApis(const art::DexFile& target_dex_file) {
  for (art::ClassAccessor accessor : target_dex_file.GetClasses()) {
    for (const art::ClassAccessor::Field& field : accessor.GetFields()) {
      field.UnHideAccessFlags();
    }
    for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
      method.UnHideAccessFlags();
    }
  }
}

static const art::VdexFile* GetVdex(const art::DexFile& original_dex_file) {
  const art::OatDexFile* oat_dex = original_dex_file.GetOatDexFile();
  if (oat_dex == nullptr) {
    return nullptr;
  }
  const art::OatFile* oat_file = oat_dex->GetOatFile();
  if (oat_file == nullptr) {
    return nullptr;
  }
  return oat_file->GetVdexFile();
}

static void DoDexUnquicken(const art::DexFile& new_dex_file,
                           const art::DexFile& original_dex_file) {
  const art::VdexFile* vdex = GetVdex(original_dex_file);
  if (vdex != nullptr) {
    vdex->UnquickenDexFile(new_dex_file, original_dex_file, /* decompile_return_instruction */true);
  }
  UnhideApis(new_dex_file);
}

static void DCheckVerifyDexFile(const art::DexFile& dex) {
  if (art::kIsDebugBuild) {
    std::string error;
    if (!art::DexFileVerifier::Verify(&dex,
                                      dex.Begin(),
                                      dex.Size(),
                                      "FixedUpDexFile_Verification.dex",
                                      /*verify_checksum*/ true,
                                      &error)) {
      LOG(FATAL) << "Failed to verify de-quickened dex file: " << error;
    }
  }
}

std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& original,
                                                       const char* descriptor) {
  // Copy the data into mutable memory.
  std::vector<unsigned char> data;
  std::unique_ptr<const art::DexFile> new_dex_file;
  std::string error;

  // Do not use ArtDexFileLoader here. This code runs in a signal handler and
  // its stack is too small to invoke the required LocationIsOnSystemFramework
  // (b/76429651). Instead, we use DexFileLoader and copy the IsPlatformDexFile
  // property from `original` to `new_dex_file`.
  const art::DexFileLoader dex_file_loader;

  if (original.IsCompactDexFile()) {
    // Since we are supposed to return a standard dex, convert back using dexlayout. It's OK to do
    // this before unquickening.
    art::Options options;
    options.compact_dex_level_ = art::CompactDexLevel::kCompactDexLevelNone;
    // Never verify the output since hidden API flags may cause the dex file verifier to fail.
    // See b/74063493
    options.verify_output_ = false;
    // Add a filter to only include the class that has the matching descriptor.
    static constexpr bool kFilterByDescriptor = true;
    if (kFilterByDescriptor) {
      options.class_filter_.insert(descriptor);
    }
    art::DexLayout dex_layout(options,
                              /*info*/ nullptr,
                              /*out_file*/ nullptr,
                              /*header*/ nullptr);
    std::unique_ptr<art::DexContainer> dex_container;
    bool result = dex_layout.ProcessDexFile(
        original.GetLocation().c_str(),
        &original,
        0,
        &dex_container,
        &error);
    CHECK(result) << "Failed to generate dex file " << error;
    art::DexContainer::Section* main_section = dex_container->GetMainSection();
    CHECK_EQ(dex_container->GetDataSection()->Size(), 0u);
    data.insert(data.end(), main_section->Begin(), main_section->End());
  } else {
    data.resize(original.Size());
    memcpy(data.data(), original.Begin(), original.Size());
  }

  // Open the dex file in the buffer.
  new_dex_file = dex_file_loader.Open(
      data.data(),
      data.size(),
      /*location*/"Unquickening_dexfile.dex",
      /*location_checksum*/0,
      /*oat_dex_file*/nullptr,
      /*verify*/false,
      /*verify_checksum*/false,
      &error);

  if (new_dex_file  == nullptr) {
    LOG(ERROR) << "Unable to open dex file from memory for unquickening! error: " << error;
    return nullptr;
  }

  if (original.IsPlatformDexFile()) {
    const_cast<art::DexFile*>(new_dex_file.get())->SetIsPlatformDexFile();
  }

  DoDexUnquicken(*new_dex_file, original);

  RecomputeDexChecksum(const_cast<art::DexFile*>(new_dex_file.get()));
  DCheckVerifyDexFile(*new_dex_file);
  std::unique_ptr<FixedUpDexFile> ret(new FixedUpDexFile(std::move(new_dex_file), std::move(data)));
  return ret;
}

}  // namespace openjdkjvmti
