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.
CheckDexFileHook(jvmtiEnv * jvmti_env ATTRIBUTE_UNUSED,JNIEnv * jni_env ATTRIBUTE_UNUSED,jclass class_being_redefined,jobject loader ATTRIBUTE_UNUSED,const char * name,jobject protection_domain ATTRIBUTE_UNUSED,jint class_data_len,const unsigned char * class_data,jint * new_class_data_len ATTRIBUTE_UNUSED,unsigned char ** new_class_data ATTRIBUTE_UNUSED)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.
OnLoad(JavaVM * vm,char * options ATTRIBUTE_UNUSED,void * reserved ATTRIBUTE_UNUSED)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