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 "common_compiler_test.h"
     21 #include "compiled_method-inl.h"
     22 #include "compiler_callbacks.h"
     23 #include "dex/dex_file.h"
     24 #include "driver/compiler_driver.h"
     25 #include "driver/compiler_options.h"
     26 #include "handle_scope-inl.h"
     27 #include "mirror/class_loader.h"
     28 #include "runtime.h"
     29 #include "scoped_thread_state_change-inl.h"
     30 #include "thread.h"
     31 #include "verifier/method_verifier-inl.h"
     32 #include "verifier/verifier_deps.h"
     33 
     34 namespace art {
     35 
     36 class DexToDexDecompilerTest : public CommonCompilerTest {
     37  public:
     38   void CompileAll(jobject class_loader) REQUIRES(!Locks::mutator_lock_) {
     39     TimingLogger timings("CompilerDriverTest::CompileAll", false, false);
     40     TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
     41     compiler_options_->boot_image_ = false;
     42     compiler_options_->SetCompilerFilter(CompilerFilter::kQuicken);
     43     // Create the main VerifierDeps, here instead of in the compiler since we want to aggregate
     44     // the results for all the dex files, not just the results for the current dex file.
     45     Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps(
     46         new verifier::VerifierDeps(GetDexFiles(class_loader)));
     47     compiler_driver_->SetDexFilesForOatFile(GetDexFiles(class_loader));
     48     compiler_driver_->CompileAll(class_loader, GetDexFiles(class_loader), &timings);
     49   }
     50 
     51   void RunTest(const char* dex_name) {
     52     Thread* self = Thread::Current();
     53     // First load the original dex file.
     54     jobject original_class_loader;
     55     {
     56       ScopedObjectAccess soa(self);
     57       original_class_loader = LoadDex(dex_name);
     58     }
     59     const DexFile* original_dex_file = GetDexFiles(original_class_loader)[0];
     60 
     61     // Load the dex file again and make it writable to quicken them.
     62     jobject class_loader;
     63     const DexFile* updated_dex_file = nullptr;
     64     {
     65       ScopedObjectAccess soa(self);
     66       class_loader = LoadDex(dex_name);
     67       updated_dex_file = GetDexFiles(class_loader)[0];
     68       Runtime::Current()->GetClassLinker()->RegisterDexFile(
     69           *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
     70     }
     71     // The dex files should be identical.
     72     int cmp = memcmp(original_dex_file->Begin(),
     73                      updated_dex_file->Begin(),
     74                      updated_dex_file->Size());
     75     ASSERT_EQ(0, cmp);
     76 
     77     updated_dex_file->EnableWrite();
     78     CompileAll(class_loader);
     79     // The dex files should be different after quickening.
     80     cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
     81     ASSERT_NE(0, cmp);
     82 
     83     // Unquicken the dex file.
     84     for (uint32_t i = 0; i < updated_dex_file->NumClassDefs(); ++i) {
     85       const DexFile::ClassDef& class_def = updated_dex_file->GetClassDef(i);
     86       const uint8_t* class_data = updated_dex_file->GetClassData(class_def);
     87       if (class_data == nullptr) {
     88         continue;
     89       }
     90       ClassDataItemIterator it(*updated_dex_file, class_data);
     91       it.SkipAllFields();
     92 
     93       // Unquicken each method.
     94       while (it.HasNextMethod()) {
     95         uint32_t method_idx = it.GetMemberIndex();
     96         CompiledMethod* compiled_method =
     97             compiler_driver_->GetCompiledMethod(MethodReference(updated_dex_file, method_idx));
     98         ArrayRef<const uint8_t> table;
     99         if (compiled_method != nullptr) {
    100           table = compiled_method->GetVmapTable();
    101         }
    102         optimizer::ArtDecompileDEX(*updated_dex_file,
    103                                    *it.GetMethodCodeItem(),
    104                                    table,
    105                                    /* decompile_return_instruction */ true);
    106         it.Next();
    107       }
    108       DCHECK(!it.HasNext());
    109     }
    110 
    111     // Make sure after unquickening we go back to the same contents as the original dex file.
    112     cmp = memcmp(original_dex_file->Begin(), updated_dex_file->Begin(), updated_dex_file->Size());
    113     ASSERT_EQ(0, cmp);
    114   }
    115 };
    116 
    117 TEST_F(DexToDexDecompilerTest, VerifierDeps) {
    118   RunTest("VerifierDeps");
    119 }
    120 
    121 TEST_F(DexToDexDecompilerTest, DexToDexDecompiler) {
    122   RunTest("DexToDexDecompiler");
    123 }
    124 
    125 }  // namespace art
    126