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