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