1 /*
2  * Copyright 2016 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 <pthread.h>
18 
19 #include <cstdio>
20 #include <iostream>
21 #include <vector>
22 
23 #include "jni.h"
24 
25 #include "gc/heap.h"
26 #include "gc/space/image_space.h"
27 #include "gc/space/space-inl.h"
28 #include "mirror/class.h"
29 #include "nativehelper/scoped_utf_chars.h"
30 #include "oat/image.h"
31 #include "oat/oat_file.h"
32 #include "runtime.h"
33 #include "scoped_thread_state_change-inl.h"
34 
35 namespace art {
36 
37 namespace {
38 
39 // Returns whether the extensionless basename of `location` is equal to name.
40 // E.g. check_name("/foo/bar/baz.odex", "baz") == true,
41 //      check_name("/foo/bar/baz.odex", "bar") == false
check_name(const std::string & location,const std::string & name)42 static bool check_name(const std::string& location, const std::string& name) {
43   std::string loc_name = location;
44   size_t idx = loc_name.rfind('/');
45   if (idx != std::string::npos) {
46     loc_name = loc_name.substr(idx + 1);
47   }
48   idx = loc_name.rfind('.');
49   if (idx != std::string::npos) {
50     loc_name = loc_name.substr(0, idx);
51   }
52   return loc_name == name;
53 }
54 
Java_Main_checkAppImageLoaded(JNIEnv * env,jclass,jstring jimage_name)55 extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkAppImageLoaded(JNIEnv* env,
56                                                                     jclass,
57                                                                     jstring jimage_name) {
58   ScopedUtfChars image_name(env, jimage_name);
59   ScopedObjectAccess soa(Thread::Current());
60   for (auto* space : Runtime::Current()->GetHeap()->GetContinuousSpaces()) {
61     if (space->IsImageSpace()) {
62       auto* image_space = space->AsImageSpace();
63       const auto& image_header = image_space->GetImageHeader();
64       // Check that this is an app image associated with the dex file named
65       // `jname` by verifying the extensionless basename of the odex file
66       // location is equal to `jname`.
67       if (image_header.IsAppImage() &&
68           check_name(image_space->GetOatFile()->GetLocation(), image_name.c_str())) {
69         return JNI_TRUE;
70       }
71     }
72   }
73   return JNI_FALSE;
74 }
75 
Java_Main_checkAppImageContains(JNIEnv *,jclass,jclass c)76 extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkAppImageContains(JNIEnv*, jclass, jclass c) {
77   ScopedObjectAccess soa(Thread::Current());
78   ObjPtr<mirror::Class> klass_ptr = soa.Decode<mirror::Class>(c);
79   for (auto* space : Runtime::Current()->GetHeap()->GetContinuousSpaces()) {
80     if (space->IsImageSpace()) {
81       auto* image_space = space->AsImageSpace();
82       const auto& image_header = image_space->GetImageHeader();
83       if (image_header.IsAppImage()) {
84         if (image_space->HasAddress(klass_ptr.Ptr())) {
85           return JNI_TRUE;
86         }
87       }
88     }
89   }
90   return JNI_FALSE;
91 }
92 
Java_Main_checkInitialized(JNIEnv *,jclass,jclass c)93 extern "C" JNIEXPORT jboolean JNICALL Java_Main_checkInitialized(JNIEnv*, jclass, jclass c) {
94   ScopedObjectAccess soa(Thread::Current());
95   ObjPtr<mirror::Class> klass_ptr = soa.Decode<mirror::Class>(c);
96   return klass_ptr->IsInitialized();
97 }
98 
99 }  // namespace
100 
101 }  // namespace art
102