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 "class_linker.h"
     20 #include "compiler/common_compiler_test.h"
     21 #include "compiler/compiled_method.h"
     22 #include "compiler/driver/compiler_options.h"
     23 #include "compiler/driver/compiler_driver.h"
     24 #include "compiler_callbacks.h"
     25 #include "dex_file.h"
     26 #include "handle_scope-inl.h"
     27 #include "verifier/method_verifier-inl.h"
     28 #include "mirror/class_loader.h"
     29 #include "runtime.h"
     30 #include "scoped_thread_state_change-inl.h"
     31 #include "thread.h"
     32 #include "verifier/method_verifier-inl.h"
     33 #include "verifier/verifier_deps.h"
     34 
     35 namespace art {
     36 
     37 class DexToDexDecompilerTest : public CommonCompilerTest {
     38  public:
     39   void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
     40     TimingLogger timings("CompilerDriverTest::CompileAll", false, false);
     41     TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
     42     compiler_options_->boot_image_ = false;
     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     Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps(
     47         new verifier::VerifierDeps(GetDexFiles(class_loader)));
     48     compiler_driver_->SetDexFilesForOatFile(GetDexFiles(class_loader));
     49     compiler_driver_->CompileAll(class_loader, GetDexFiles(class_loader), &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).Ptr());
     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 (uint32_t i = 0; i < updated_dex_file->NumClassDefs(); ++i) {
     86       const DexFile::ClassDef& class_def = updated_dex_file->GetClassDef(i);
     87       const uint8_t* class_data = updated_dex_file->GetClassData(class_def);
     88       if (class_data == nullptr) {
     89         continue;
     90       }
     91       ClassDataItemIterator it(*updated_dex_file, class_data);
     92       it.SkipAllFields();
     93 
     94       // Unquicken each method.
     95       while (it.HasNextDirectMethod()) {
     96         uint32_t method_idx = it.GetMemberIndex();
     97         CompiledMethod* compiled_method =
     98             compiler_driver_->GetCompiledMethod(MethodReference(updated_dex_file, method_idx));
     99         ArrayRef<const uint8_t> table;
    100         if (compiled_method != nullptr) {
    101           table = compiled_method->GetVmapTable();
    102         }
    103         optimizer::ArtDecompileDEX(
    104             *it.GetMethodCodeItem(), table, /* decompile_return_instruction */ true);
    105         it.Next();
    106       }
    107       while (it.HasNextVirtualMethod()) {
    108         uint32_t method_idx = it.GetMemberIndex();
    109         CompiledMethod* compiled_method =
    110             compiler_driver_->GetCompiledMethod(MethodReference(updated_dex_file, method_idx));
    111         ArrayRef<const uint8_t> table;
    112         if (compiled_method != nullptr) {
    113           table = compiled_method->GetVmapTable();
    114         }
    115         optimizer::ArtDecompileDEX(
    116             *it.GetMethodCodeItem(), table, /* decompile_return_instruction */ true);
    117         it.Next();
    118       }
    119       DCHECK(!it.HasNext());
    120     }
    121 
    122     // Make sure after unquickening we go back to the same contents as the original dex file.
    123     cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
    124     ASSERT_EQ(0, cmp);
    125   }
    126 };
    127 
    128 TEST_F(DexToDexDecompilerTest, VerifierDeps) {
    129   RunTest("VerifierDeps");
    130 }
    131 
    132 TEST_F(DexToDexDecompilerTest, DexToDexDecompiler) {
    133   RunTest("DexToDexDecompiler");
    134 }
    135 
    136 }  // namespace art
    137