Home | History | Annotate | Download | only in dex
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "dex_to_dex_decompiler.h"
     18 
     19 #include "base/casts.h"
     20 #include "class_linker.h"
     21 #include "common_compiler_driver_test.h"
     22 #include "compiled_method-inl.h"
     23 #include "compiler_callbacks.h"
     24 #include "dex/class_accessor-inl.h"
     25 #include "dex/dex_file.h"
     26 #include "driver/compiler_driver.h"
     27 #include "driver/compiler_options.h"
     28 #include "handle_scope-inl.h"
     29 #include "mirror/class_loader.h"
     30 #include "quick_compiler_callbacks.h"
     31 #include "runtime.h"
     32 #include "scoped_thread_state_change-inl.h"
     33 #include "thread.h"
     34 #include "verifier/verifier_deps.h"
     35 
     36 namespace art {
     37 
     38 class DexToDexDecompilerTest : public CommonCompilerDriverTest {
     39  public:
     40   void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
     41     TimingLogger timings("DexToDexDecompilerTest::CompileAll", false, false);
     42     compiler_options_->image_type_ = CompilerOptions::ImageType::kNone;
     43     compiler_options_->SetCompilerFilter(CompilerFilter::kQuicken);
     44     // Create the main VerifierDeps, here instead of in the compiler since we want to aggregate
     45     // the results for all the dex files, not just the results for the current dex file.
     46     down_cast<QuickCompilerCallbacks*>(Runtime::Current()->GetCompilerCallbacks())->SetVerifierDeps(
     47         new verifier::VerifierDeps(GetDexFiles(class_loader)));
     48     std::vector<const DexFile*> dex_files = GetDexFiles(class_loader);
     49     CommonCompilerDriverTest::CompileAll(class_loader, dex_files, &timings);
     50   }
     51 
     52   void RunTest(const char* dex_name) {
     53     Thread* self = Thread::Current();
     54     // First load the original dex file.
     55     jobject original_class_loader;
     56     {
     57       ScopedObjectAccess soa(self);
     58       original_class_loader = LoadDex(dex_name);
     59     }
     60     const DexFile* original_dex_file = GetDexFiles(original_class_loader)[0];
     61 
     62     // Load the dex file again and make it writable to quicken them.
     63     jobject class_loader;
     64     const DexFile* updated_dex_file = nullptr;
     65     {
     66       ScopedObjectAccess soa(self);
     67       class_loader = LoadDex(dex_name);
     68       updated_dex_file = GetDexFiles(class_loader)[0];
     69       Runtime::Current()->GetClassLinker()->RegisterDexFile(
     70           *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
     71     }
     72     // The dex files should be identical.
     73     int cmp = memcmp(original_dex_file->Begin(),
     74                      updated_dex_file->Begin(),
     75                      updated_dex_file->Size());
     76     ASSERT_EQ(0, cmp);
     77 
     78     updated_dex_file->EnableWrite();
     79     CompileAll(class_loader);
     80     // The dex files should be different after quickening.
     81     cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
     82     ASSERT_NE(0, cmp);
     83 
     84     // Unquicken the dex file.
     85     for (ClassAccessor accessor : updated_dex_file->GetClasses()) {
     86       // Unquicken each method.
     87       for (const ClassAccessor::Method& method : accessor.GetMethods()) {
     88         CompiledMethod* compiled_method = compiler_driver_->GetCompiledMethod(
     89             method.GetReference());
     90         ArrayRef<const uint8_t> table;
     91         if (compiled_method != nullptr) {
     92           table = compiled_method->GetVmapTable();
     93         }
     94         optimizer::ArtDecompileDEX(*updated_dex_file,
     95                                    *accessor.GetCodeItem(method),
     96                                    table,
     97                                    /* decompile_return_instruction= */ true);
     98       }
     99     }
    100 
    101     // Make sure after unquickening we go back to the same contents as the original dex file.
    102     cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
    103     ASSERT_EQ(0, cmp);
    104   }
    105 };
    106 
    107 TEST_F(DexToDexDecompilerTest, VerifierDeps) {
    108   RunTest("VerifierDeps");
    109 }
    110 
    111 TEST_F(DexToDexDecompilerTest, DexToDexDecompiler) {
    112   RunTest("DexToDexDecompiler");
    113 }
    114 
    115 }  // namespace art
    116