Home | History | Annotate | Download | only in 983-source-transform-verify
      1 /*
      2  * Copyright (C) 2017 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 <inttypes.h>
     18 #include <stdio.h>
     19 #include <string.h>
     20 
     21 #include <iostream>
     22 #include <vector>
     23 
     24 #include "android-base/stringprintf.h"
     25 
     26 #include "base/logging.h"
     27 #include "base/macros.h"
     28 #include "bytecode_utils.h"
     29 #include "dex_file.h"
     30 #include "dex_instruction.h"
     31 #include "jit/jit.h"
     32 #include "jni.h"
     33 #include "native_stack_dump.h"
     34 #include "jvmti.h"
     35 #include "runtime.h"
     36 #include "scoped_thread_state_change-inl.h"
     37 #include "thread-current-inl.h"
     38 #include "thread_list.h"
     39 
     40 // Test infrastructure
     41 #include "jvmti_helper.h"
     42 #include "test_env.h"
     43 
     44 namespace art {
     45 namespace Test983SourceTransformVerify {
     46 
     47 constexpr bool kSkipInitialLoad = true;
     48 
     49 // The hook we are using.
     50 void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
     51                               JNIEnv* jni_env ATTRIBUTE_UNUSED,
     52                               jclass class_being_redefined,
     53                               jobject loader ATTRIBUTE_UNUSED,
     54                               const char* name,
     55                               jobject protection_domain ATTRIBUTE_UNUSED,
     56                               jint class_data_len,
     57                               const unsigned char* class_data,
     58                               jint* new_class_data_len ATTRIBUTE_UNUSED,
     59                               unsigned char** new_class_data ATTRIBUTE_UNUSED) {
     60   if (kSkipInitialLoad && class_being_redefined == nullptr) {
     61     // Something got loaded concurrently. Just ignore it for now.
     62     return;
     63   }
     64   std::cout << "Dex file hook for " << name << std::endl;
     65   if (IsJVM()) {
     66     return;
     67   }
     68   std::string error;
     69   std::unique_ptr<const DexFile> dex(DexFile::Open(class_data,
     70                                                    class_data_len,
     71                                                    "fake_location.dex",
     72                                                    /*location_checksum*/ 0,
     73                                                    /*oat_dex_file*/ nullptr,
     74                                                    /*verify*/ true,
     75                                                    /*verify_checksum*/ true,
     76                                                    &error));
     77   if (dex.get() == nullptr) {
     78     std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl;
     79     return;
     80   }
     81   for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
     82     const DexFile::ClassDef& def = dex->GetClassDef(i);
     83     const uint8_t* data_item = dex->GetClassData(def);
     84     if (data_item == nullptr) {
     85       continue;
     86     }
     87     for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
     88       if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
     89         continue;
     90       }
     91       for (CodeItemIterator code_it(*it.GetMethodCodeItem()); !code_it.Done(); code_it.Advance()) {
     92         const Instruction& inst = code_it.CurrentInstruction();
     93         int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
     94         if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
     95             (inst.GetVerifyExtraFlags() & forbiden_flags) != 0) {
     96           std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
     97                     << " [Dex PC: 0x" << std::hex << code_it.CurrentDexPc() << std::dec << "] : "
     98                     << inst.DumpString(dex.get()) << std::endl;
     99           continue;
    100         }
    101       }
    102     }
    103   }
    104 }
    105 
    106 // Get all capabilities except those related to retransformation.
    107 jint OnLoad(JavaVM* vm,
    108             char* options ATTRIBUTE_UNUSED,
    109             void* reserved ATTRIBUTE_UNUSED) {
    110   if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
    111     printf("Unable to get jvmti env!\n");
    112     return 1;
    113   }
    114   SetAllCapabilities(jvmti_env);
    115   jvmtiEventCallbacks cb;
    116   memset(&cb, 0, sizeof(cb));
    117   cb.ClassFileLoadHook = CheckDexFileHook;
    118   if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
    119     printf("Unable to set class file load hook cb!\n");
    120     return 1;
    121   }
    122   return 0;
    123 }
    124 
    125 }  // namespace Test983SourceTransformVerify
    126 }  // namespace art
    127