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 "class_loader_utils.h"
18 #include "jni.h"
19 #include "nativehelper/scoped_utf_chars.h"
20 #include "oat_file_assistant.h"
21 #include "oat_file_manager.h"
22 #include "scoped_thread_state_change-inl.h"
23 #include "thread.h"
24
25 namespace art {
26 namespace Test692VdexInmemLoader {
27
Java_Main_waitForVerifier(JNIEnv *,jclass)28 extern "C" JNIEXPORT void JNICALL Java_Main_waitForVerifier(JNIEnv*, jclass) {
29 Runtime::Current()->GetOatFileManager().WaitForBackgroundVerificationTasks();
30 }
31
Java_Main_setProcessDataDir(JNIEnv * env,jclass,jstring jpath)32 extern "C" JNIEXPORT void JNICALL Java_Main_setProcessDataDir(JNIEnv* env, jclass, jstring jpath) {
33 const char* path = env->GetStringUTFChars(jpath, nullptr);
34 Runtime::Current()->SetProcessDataDirectory(path);
35 env->ReleaseStringUTFChars(jpath, path);
36 }
37
Java_Main_areClassesVerified(JNIEnv *,jclass,jobject loader)38 extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesVerified(JNIEnv*,
39 jclass,
40 jobject loader) {
41 ScopedObjectAccess soa(Thread::Current());
42 StackHandleScope<2> hs(soa.Self());
43 Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
44
45 std::vector<const DexFile*> dex_files;
46 VisitClassLoaderDexFiles(
47 soa,
48 h_loader,
49 [&](const DexFile* dex_file) {
50 dex_files.push_back(dex_file);
51 return true;
52 });
53
54 MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
55 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
56
57 bool is_first = true;
58 bool all_verified = false;
59 for (const DexFile* dex_file : dex_files) {
60 for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
61 const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
62 h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
63 CHECK(h_class != nullptr) << "Could not find class " << desc;
64 bool is_verified = h_class->IsVerified();
65 if (is_first) {
66 all_verified = is_verified;
67 is_first = false;
68 } else if (all_verified != is_verified) {
69 // Classes should either all or none be verified.
70 LOG(ERROR) << "areClassesVerified is inconsistent";
71 }
72 }
73 }
74 return all_verified ? JNI_TRUE : JNI_FALSE;
75 }
76
Java_Main_hasVdexFile(JNIEnv *,jclass,jobject loader)77 extern "C" JNIEXPORT bool JNICALL Java_Main_hasVdexFile(JNIEnv*,
78 jclass,
79 jobject loader) {
80 ScopedObjectAccess soa(Thread::Current());
81 StackHandleScope<1> hs(soa.Self());
82 Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));
83
84 std::vector<const DexFile::Header*> dex_headers;
85 VisitClassLoaderDexFiles(
86 soa,
87 h_loader,
88 [&](const DexFile* dex_file) {
89 dex_headers.push_back(&dex_file->GetHeader());
90 return true;
91 });
92
93 uint32_t location_checksum;
94 std::string dex_location;
95 std::string vdex_filename;
96 std::string error_msg;
97 return OatFileAssistant::AnonymousDexVdexLocation(dex_headers,
98 kRuntimeISA,
99 &location_checksum,
100 &dex_location,
101 &vdex_filename) &&
102 OS::FileExists(vdex_filename.c_str());
103 }
104
Java_Main_isBackedByOatFile(JNIEnv *,jclass,jobject loader)105 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isBackedByOatFile(JNIEnv*,
106 jclass,
107 jobject loader) {
108 ScopedObjectAccess soa(Thread::Current());
109 StackHandleScope<1> hs(soa.Self());
110 Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));
111
112 bool is_first = true;
113 bool all_backed_by_oat = false;
114
115 VisitClassLoaderDexFiles(
116 soa,
117 h_loader,
118 [&](const DexFile* dex_file) {
119 bool is_backed_by_oat = (dex_file->GetOatDexFile() != nullptr);
120 if (is_first) {
121 all_backed_by_oat = is_backed_by_oat;
122 is_first = false;
123 } else if (all_backed_by_oat != is_backed_by_oat) {
124 // DexFiles should either all or none be backed by oat.
125 LOG(ERROR) << "isBackedByOatFile is inconsistent";
126 }
127 return true;
128 });
129 return all_backed_by_oat ? JNI_TRUE : JNI_FALSE;
130 }
131
Java_Main_areClassesPreverified(JNIEnv *,jclass,jobject loader)132 extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesPreverified(JNIEnv*,
133 jclass,
134 jobject loader) {
135 ScopedObjectAccess soa(Thread::Current());
136 StackHandleScope<2> hs(soa.Self());
137 Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
138
139 std::vector<const DexFile*> dex_files;
140 VisitClassLoaderDexFiles(
141 soa,
142 h_loader,
143 [&](const DexFile* dex_file) {
144 dex_files.push_back(dex_file);
145 return true;
146 });
147
148 MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
149 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
150
151 bool is_first = true;
152 bool all_preverified = false;
153 for (const DexFile* dex_file : dex_files) {
154 for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
155 const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
156 h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
157 CHECK(h_class != nullptr) << "Could not find class " << desc;
158
159 ClassStatus oat_file_class_status(ClassStatus::kNotReady);
160 bool is_preverified = class_linker->VerifyClassUsingOatFile(
161 *dex_file, h_class.Get(), oat_file_class_status);
162
163 if (is_first) {
164 all_preverified = is_preverified;
165 is_first = false;
166 } else if (all_preverified != is_preverified) {
167 // Classes should either all or none be preverified.
168 LOG(ERROR) << "areClassesPreverified is inconsistent";
169 }
170 }
171 }
172
173 return all_preverified ? JNI_TRUE : JNI_FALSE;
174 }
175
Java_Main_getVdexCacheSize(JNIEnv *,jclass)176 extern "C" JNIEXPORT jint JNICALL Java_Main_getVdexCacheSize(JNIEnv*, jclass) {
177 return static_cast<jint>(OatFileManager::kAnonymousVdexCacheSize);
178 }
179
Java_Main_isAnonymousVdexBasename(JNIEnv * env,jclass,jstring basename)180 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAnonymousVdexBasename(JNIEnv* env,
181 jclass,
182 jstring basename) {
183 if (basename == nullptr) {
184 return JNI_FALSE;
185 }
186 ScopedUtfChars basename_utf(env, basename);
187 return OatFileAssistant::IsAnonymousVdexBasename(basename_utf.c_str()) ? JNI_TRUE : JNI_FALSE;
188 }
189
190 } // namespace Test692VdexInmemLoader
191 } // namespace art
192