1f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom/*
2f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * Copyright (C) 2008 The Android Open Source Project
3f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom *
4f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
5f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * you may not use this file except in compliance with the License.
6f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * You may obtain a copy of the License at
7f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom *
8f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
9f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom *
10f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
11f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
12f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * See the License for the specific language governing permissions and
14f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom * limitations under the License.
15f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom */
16f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "dalvik_system_DexFile.h"
18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe
198943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath#include <sstream>
208943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath
2146ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe#include "android-base/stringprintf.h"
2246ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
2307ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
24833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe#include "base/stl_util.h"
25aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "class_linker.h"
2662d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h"
27c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe#include "compiler_filter.h"
284f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
29eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "jni_internal.h"
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
3105f3057d6a4d23d712092ccd36a531590bff323bIan Rogers#include "mirror/object-inl.h"
322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/string.h"
338943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath#include "oat_file.h"
3466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "oat_file_assistant.h"
35f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier#include "oat_file_manager.h"
361d9f52b7ca91c6d30b7acfac1c9ab24d93fff470Brian Carlstrom#include "os.h"
37aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom#include "runtime.h"
380795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h"
39c981848a3425662034c5429b61c035e7533b896dIan Rogers#include "ScopedLocalRef.h"
40f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom#include "ScopedUtfChars.h"
41bb0b53f58f11c628f077603b56077dfed1a18f11Calin Juravle#include "utils.h"
42dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers#include "well_known_classes.h"
43eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "zip_archive.h"
44f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
45f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromnamespace art {
46f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
4746ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampeusing android::base::StringPrintf;
4846ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe
49e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic bool ConvertJavaArrayToDexFiles(
50e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    JNIEnv* env,
51e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    jobject arrayObject,
52e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    /*out*/ std::vector<const DexFile*>& dex_files,
53e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    /*out*/ const OatFile*& oat_file) {
54324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  jarray array = reinterpret_cast<jarray>(arrayObject);
55324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
56324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  jsize array_size = env->GetArrayLength(array);
57324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  if (env->ExceptionCheck() == JNI_TRUE) {
58e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    return false;
59324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
60324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
61324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  // TODO: Optimize. On 32bit we can use an int array.
62324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  jboolean is_long_data_copied;
63324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  jlong* long_data = env->GetLongArrayElements(reinterpret_cast<jlongArray>(array),
64324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe                                               &is_long_data_copied);
65324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  if (env->ExceptionCheck() == JNI_TRUE) {
66e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    return false;
67324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
68324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
69e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  oat_file = reinterpret_cast<const OatFile*>(static_cast<uintptr_t>(long_data[kOatFileIndex]));
70e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  dex_files.reserve(array_size - 1);
71e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  for (jsize i = kDexFileIndexStart; i < array_size; ++i) {
72e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    dex_files.push_back(reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(long_data[i])));
73324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
74324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
75324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  env->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array), long_data, JNI_ABORT);
76e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  return env->ExceptionCheck() != JNI_TRUE;
77324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe}
78324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
79e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jlongArray ConvertDexFilesToJavaArray(JNIEnv* env,
80e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                             const OatFile* oat_file,
81e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                             std::vector<std::unique_ptr<const DexFile>>& vec) {
82e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  // Add one for the oat file.
8380b37b7e679a530738c9bcbd39873b6dacf177e5Mathieu Chartier  jlongArray long_array = env->NewLongArray(static_cast<jsize>(kDexFileIndexStart + vec.size()));
84324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  if (env->ExceptionCheck() == JNI_TRUE) {
85324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    return nullptr;
86324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
87324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
88324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  jboolean is_long_data_copied;
89324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  jlong* long_data = env->GetLongArrayElements(long_array, &is_long_data_copied);
90324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  if (env->ExceptionCheck() == JNI_TRUE) {
91324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    return nullptr;
92324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
93324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
94e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  long_data[kOatFileIndex] = reinterpret_cast<uintptr_t>(oat_file);
95e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  for (size_t i = 0; i < vec.size(); ++i) {
96e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    long_data[kDexFileIndexStart + i] = reinterpret_cast<uintptr_t>(vec[i].get());
97324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
98324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
99324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  env->ReleaseLongArrayElements(long_array, long_data, 0);
100324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  if (env->ExceptionCheck() == JNI_TRUE) {
101324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    return nullptr;
102324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
103324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
104324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  // Now release all the unique_ptrs.
105324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  for (auto& dex_file : vec) {
106324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    dex_file.release();
107324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
108324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
109324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  return long_array;
110324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe}
111324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
112f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// A smart pointer that provides read-only access to a Java string's UTF chars.
113f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// Unlike libcore's NullableScopedUtfChars, this will *not* throw NullPointerException if
114f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// passed a null jstring. The correct idiom is:
115f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom//
116f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom//   NullableScopedUtfChars name(env, javaName);
117c252c3eacd83a0c110dd065690a7f652be35b0e7Brian Carlstrom//   if (env->ExceptionCheck()) {
1182cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier//       return null;
119f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom//   }
120f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom//   // ... use name.c_str()
121f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom//
122f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom// TODO: rewrite to get rid of this, or change ScopedUtfChars to offer this option.
123f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromclass NullableScopedUtfChars {
124ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes public:
125ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  NullableScopedUtfChars(JNIEnv* env, jstring s) : mEnv(env), mString(s) {
1262cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    mUtfChars = (s != nullptr) ? env->GetStringUTFChars(s, nullptr) : nullptr;
127ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  }
128f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
129ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  ~NullableScopedUtfChars() {
130ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    if (mUtfChars) {
131ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes      mEnv->ReleaseStringUTFChars(mString, mUtfChars);
132f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom    }
133ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  }
134f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
135ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  const char* c_str() const {
136ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    return mUtfChars;
137ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  }
138f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
139ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  size_t size() const {
140ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    return strlen(mUtfChars);
141ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  }
142f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
143ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  // Element access.
144ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  const char& operator[](size_t n) const {
145ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    return mUtfChars[n];
146ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  }
147f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
148ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes private:
149ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  JNIEnv* mEnv;
150ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  jstring mString;
151ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  const char* mUtfChars;
152f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
153ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  // Disallow copy and assignment.
154ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  NullableScopedUtfChars(const NullableScopedUtfChars&);
155ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes  void operator=(const NullableScopedUtfChars&);
156f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom};
157f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
158ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic std::unique_ptr<MemMap> AllocateDexMemoryMap(JNIEnv* env, jint start, jint end) {
159ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (end <= start) {
160ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ScopedObjectAccess soa(env);
161ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ThrowWrappedIOException("Bad range");
162ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    return nullptr;
163ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
164ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
165ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::string error_message;
166ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  size_t length = static_cast<size_t>(end - start);
167ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::unique_ptr<MemMap> dex_mem_map(MemMap::MapAnonymous("DEX data",
168ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                           nullptr,
169ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                           length,
170ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                           PROT_READ | PROT_WRITE,
171ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                           /* low_4gb */ false,
172ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                           /* reuse */ false,
173ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                           &error_message));
174ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (dex_mem_map == nullptr) {
175ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ScopedObjectAccess soa(env);
176ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ThrowWrappedIOException("%s", error_message.c_str());
177ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
178ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  return dex_mem_map;
179ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light}
180ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
181ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic const DexFile* CreateDexFile(JNIEnv* env, std::unique_ptr<MemMap> dex_mem_map) {
182ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::string location = StringPrintf("Anonymous-DexFile@%p-%p",
183ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                      dex_mem_map->Begin(),
184ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                      dex_mem_map->End());
185ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::string error_message;
186ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::unique_ptr<const DexFile> dex_file(DexFile::Open(location,
187ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                        0,
188ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                        std::move(dex_mem_map),
189ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                        /* verify */ true,
190ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                        /* verify_location */ true,
191ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                        &error_message));
192ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (dex_file == nullptr) {
193ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ScopedObjectAccess soa(env);
194ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ThrowWrappedIOException("%s", error_message.c_str());
195ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    return nullptr;
196ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
197ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
198ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (!dex_file->DisableWrite()) {
199ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ScopedObjectAccess soa(env);
200ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ThrowWrappedIOException("Failed to make dex file read-only");
201ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    return nullptr;
202ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
203ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
204ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  return dex_file.release();
205ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light}
206ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
207ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic jobject CreateSingleDexFileCookie(JNIEnv* env, std::unique_ptr<MemMap> data) {
208ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::unique_ptr<const DexFile> dex_file(CreateDexFile(env, std::move(data)));
209ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (dex_file.get() == nullptr) {
210ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    DCHECK(env->ExceptionCheck());
211ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    return nullptr;
212ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
213ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::vector<std::unique_ptr<const DexFile>> dex_files;
214ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  dex_files.push_back(std::move(dex_file));
215ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  return ConvertDexFilesToJavaArray(env, nullptr, dex_files);
216ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light}
217ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
218ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic jobject DexFile_createCookieWithDirectBuffer(JNIEnv* env,
219ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                    jclass,
220ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                    jobject buffer,
221ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                    jint start,
222ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                                    jint end) {
223ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  uint8_t* base_address = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(buffer));
224ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (base_address == nullptr) {
225ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ScopedObjectAccess soa(env);
226ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    ThrowWrappedIOException("dexFileBuffer not direct");
227ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    return 0;
228ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
229ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
230ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::unique_ptr<MemMap> dex_mem_map(AllocateDexMemoryMap(env, start, end));
231ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (dex_mem_map == nullptr) {
232ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    DCHECK(Thread::Current()->IsExceptionPending());
233ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    return 0;
234ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
235ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
236ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  size_t length = static_cast<size_t>(end - start);
237ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  memcpy(dex_mem_map->Begin(), base_address, length);
238ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  return CreateSingleDexFileCookie(env, std::move(dex_mem_map));
239ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light}
240ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
241ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Lightstatic jobject DexFile_createCookieWithArray(JNIEnv* env,
242ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                             jclass,
243ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                             jbyteArray buffer,
244ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                             jint start,
245ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                                             jint end) {
246ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  std::unique_ptr<MemMap> dex_mem_map(AllocateDexMemoryMap(env, start, end));
247ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  if (dex_mem_map == nullptr) {
248ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    DCHECK(Thread::Current()->IsExceptionPending());
249ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light    return 0;
250ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  }
251ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
252ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  auto destination = reinterpret_cast<jbyte*>(dex_mem_map.get()->Begin());
253ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  env->GetByteArrayRegion(buffer, start, end - start, destination);
254ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  return CreateSingleDexFileCookie(env, std::move(dex_mem_map));
255ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light}
256ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light
257c23f851300109b1c8fd4b3f0b70cb5105ef1aa7fCalin Juravle// TODO(calin): clean up the unused parameters (here and in libcore).
258b190d945459253c329062dab2440671828275767Mathieu Chartierstatic jobject DexFile_openDexFileNative(JNIEnv* env,
259b190d945459253c329062dab2440671828275767Mathieu Chartier                                         jclass,
260b190d945459253c329062dab2440671828275767Mathieu Chartier                                         jstring javaSourceName,
261c23f851300109b1c8fd4b3f0b70cb5105ef1aa7fCalin Juravle                                         jstring javaOutputName ATTRIBUTE_UNUSED,
262b190d945459253c329062dab2440671828275767Mathieu Chartier                                         jint flags ATTRIBUTE_UNUSED,
263fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                         jobject class_loader,
264fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                         jobjectArray dex_elements) {
265f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  ScopedUtfChars sourceName(env, javaSourceName);
2662cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (sourceName.c_str() == nullptr) {
267f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom    return 0;
268f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  }
269c23f851300109b1c8fd4b3f0b70cb5105ef1aa7fCalin Juravle
270f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier  Runtime* const runtime = Runtime::Current();
271f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier  ClassLinker* linker = runtime->GetClassLinker();
272324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  std::vector<std::unique_ptr<const DexFile>> dex_files;
273329d18806792771dfee064203fe27875d79cd53aAndreas Gampe  std::vector<std::string> error_msgs;
274e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  const OatFile* oat_file = nullptr;
275756ee4e090bc1e1812b41fb7b4661df601a32ef9Brian Carlstrom
276f9c6fc610b27887f832e453a0da1789187293408Mathieu Chartier  dex_files = runtime->GetOatFileManager().OpenDexFilesFromOat(sourceName.c_str(),
277fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                                               class_loader,
278fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier                                                               dex_elements,
279e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                                               /*out*/ &oat_file,
280e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                                               /*out*/ &error_msgs);
281833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe
28266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  if (!dex_files.empty()) {
283e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    jlongArray array = ConvertDexFilesToJavaArray(env, oat_file, dex_files);
284324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    if (array == nullptr) {
285324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      ScopedObjectAccess soa(env);
286324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      for (auto& dex_file : dex_files) {
287cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko        if (linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
288324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe          dex_file.release();
289324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe        }
290324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      }
291324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    }
292324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    return array;
293262bf46ddc91e5b4fbd367127ff21a1877d939f2jeffhao  } else {
29460836d5a9bcf8b30984aae4279a4f6233b0bf622Vladimir Marko    ScopedObjectAccess soa(env);
295329d18806792771dfee064203fe27875d79cd53aAndreas Gampe    CHECK(!error_msgs.empty());
296329d18806792771dfee064203fe27875d79cd53aAndreas Gampe    // The most important message is at the end. So set up nesting by going forward, which will
297329d18806792771dfee064203fe27875d79cd53aAndreas Gampe    // wrap the existing exception as a cause for the following one.
298329d18806792771dfee064203fe27875d79cd53aAndreas Gampe    auto it = error_msgs.begin();
299329d18806792771dfee064203fe27875d79cd53aAndreas Gampe    auto itEnd = error_msgs.end();
300329d18806792771dfee064203fe27875d79cd53aAndreas Gampe    for ( ; it != itEnd; ++it) {
301329d18806792771dfee064203fe27875d79cd53aAndreas Gampe      ThrowWrappedIOException("%s", it->c_str());
302329d18806792771dfee064203fe27875d79cd53aAndreas Gampe    }
303329d18806792771dfee064203fe27875d79cd53aAndreas Gampe
304324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    return nullptr;
305aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
306aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}
307aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
3081d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartierstatic jboolean DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) {
309e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  std::vector<const DexFile*> dex_files;
310e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  const OatFile* oat_file;
311e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  if (!ConvertJavaArrayToDexFiles(env, cookie, dex_files, oat_file)) {
312e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    Thread::Current()->AssertPendingException();
3131d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier    return JNI_FALSE;
3141d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier  }
315e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  Runtime* const runtime = Runtime::Current();
3161d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier  bool all_deleted = true;
317e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  {
318e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    ScopedObjectAccess soa(env);
3190795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier    ObjPtr<mirror::Object> dex_files_object = soa.Decode<mirror::Object>(cookie);
320bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier    ObjPtr<mirror::LongArray> long_dex_files = dex_files_object->AsLongArray();
321e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    // Delete dex files associated with this dalvik.system.DexFile since there should not be running
322e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    // code using it. dex_files is a vector due to multidex.
323e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    ClassLinker* const class_linker = runtime->GetClassLinker();
324e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    int32_t i = kDexFileIndexStart;  // Oat file is at index 0.
325e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    for (const DexFile* dex_file : dex_files) {
326e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier      if (dex_file != nullptr) {
327e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier        // Only delete the dex file if the dex cache is not found to prevent runtime crashes if there
328e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier        // are calls to DexFile.close while the ART DexFile is still in use.
329cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko        if (!class_linker->IsDexFileRegistered(soa.Self(), *dex_file)) {
330e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier          // Clear the element in the array so that we can call close again.
331e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier          long_dex_files->Set(i, 0);
332e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier          delete dex_file;
333e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier        } else {
334e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier          all_deleted = false;
335e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier        }
336e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier      }
337e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier      ++i;
338833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe    }
339aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
3401d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier
341fdccbd418694a4216151e562faa5fd9fe6e12057Mathieu Chartier  // oat_file can be null if we are running without dex2oat.
342fdccbd418694a4216151e562faa5fd9fe6e12057Mathieu Chartier  if (all_deleted && oat_file != nullptr) {
343e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    // If all of the dex files are no longer in use we can unmap the corresponding oat file.
344e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    VLOG(class_linker) << "Unregistering " << oat_file;
345e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier    runtime->GetOatFileManager().UnRegisterAndDeleteOatFile(oat_file);
346e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  }
3471d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier  return all_deleted ? JNI_TRUE : JNI_FALSE;
348f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}
349f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
350e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jclass DexFile_defineClassNative(JNIEnv* env,
351e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                        jclass,
352e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                        jstring javaName,
353e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                        jobject javaLoader,
35400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                                        jobject cookie,
35500310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                                        jobject dexFile) {
356e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  std::vector<const DexFile*> dex_files;
357e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  const OatFile* oat_file;
358e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  if (!ConvertJavaArrayToDexFiles(env, cookie, /*out*/ dex_files, /*out*/ oat_file)) {
3597571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom    VLOG(class_linker) << "Failed to find dex_file";
360324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    DCHECK(env->ExceptionCheck());
361324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    return nullptr;
362aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
363324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
364df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  ScopedUtfChars class_name(env, javaName);
3652cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (class_name.c_str() == nullptr) {
3662e450bf45e1bacc9c356f6ab239ccfb31bd8d7e4Brian Carlstrom    VLOG(class_linker) << "Failed to find class_name";
3672cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    return nullptr;
368df143242f4beaad4cc9fbabebfc033b68c40964eBrian Carlstrom  }
369955724179c6c739524f610023287f56b24dc31deElliott Hughes  const std::string descriptor(DotToDescriptor(class_name.c_str()));
370e7c9a8c2b8481aafbc6af4ce6229bd361ba24742Mathieu Chartier  const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str()));
371e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  for (auto& dex_file : dex_files) {
3729aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr    const DexFile::ClassDef* dex_class_def =
3739aa352e92b6ca0f2250cb7f54dfbf4b1be714c19David Sehr        OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash);
374833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe    if (dex_class_def != nullptr) {
375833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe      ScopedObjectAccess soa(env);
376833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
377833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe      StackHandleScope<1> hs(soa.Self());
378833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe      Handle<mirror::ClassLoader> class_loader(
3790795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier          hs.NewHandle(soa.Decode<mirror::ClassLoader>(javaLoader)));
380cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko      ObjPtr<mirror::DexCache> dex_cache =
381cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko          class_linker->RegisterDexFile(*dex_file, class_loader.Get());
382cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko      if (dex_cache == nullptr) {
383cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko        // OOME or InternalError (dexFile already registered with a different class loader).
384cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko        soa.Self()->AssertPendingException();
385cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko        return nullptr;
386cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko      }
387bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier      ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(),
388bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                               descriptor.c_str(),
389bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                               hash,
390bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                               class_loader,
391bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                               *dex_file,
392bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier                                                               *dex_class_def);
39300310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier      // Add the used dex file. This only required for the DexFile.loadClass API since normal
39400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier      // class loaders already keep their dex files live.
395bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier      class_linker->InsertDexFileInToClassLoader(soa.Decode<mirror::Object>(dexFile),
39600310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                                                 class_loader.Get());
397833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe      if (result != nullptr) {
398667ab7c174ebdb16fc18487901c6857709adcdb8Brian Carlstrom        VLOG(class_linker) << "DexFile_defineClassNative returning " << result
399667ab7c174ebdb16fc18487901c6857709adcdb8Brian Carlstrom                           << " for " << class_name.c_str();
400833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe        return soa.AddLocalReference<jclass>(result);
401833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe      }
402833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe    }
403aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
404667ab7c174ebdb16fc18487901c6857709adcdb8Brian Carlstrom  VLOG(class_linker) << "Failed to find dex_class_def " << class_name.c_str();
405833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe  return nullptr;
406f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}
407f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
408833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe// Needed as a compare functor for sets of const char
409833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampestruct CharPointerComparator {
410833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe  bool operator()(const char *str1, const char *str2) const {
411833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe    return strcmp(str1, str2) < 0;
412833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe  }
413833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe};
414833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe
415833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe// Note: this can be an expensive call, as we sort out duplicates in MultiDex files.
416324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampestatic jobjectArray DexFile_getClassNameList(JNIEnv* env, jclass, jobject cookie) {
417e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  const OatFile* oat_file = nullptr;
418e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  std::vector<const DexFile*> dex_files;
419e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
420324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    DCHECK(env->ExceptionCheck());
421324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    return nullptr;
422324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
423324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe
424324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  // Push all class descriptors into a set. Use set instead of unordered_set as we want to
425324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  // retrieve all in the end.
426324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  std::set<const char*, CharPointerComparator> descriptors;
427e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  for (auto& dex_file : dex_files) {
428324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) {
429324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
430324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      const char* descriptor = dex_file->GetClassDescriptor(class_def);
431324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      descriptors.insert(descriptor);
432833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe    }
433324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  }
434833a48501d560c9fa7fc78ef619888138c2d374fAndreas Gampe
435324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  // Now create output array and copy the set into it.
436e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  jobjectArray result = env->NewObjectArray(descriptors.size(),
437e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                            WellKnownClasses::java_lang_String,
438324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe                                            nullptr);
439324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  if (result != nullptr) {
440324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    auto it = descriptors.begin();
441324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    auto it_end = descriptors.end();
442324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    jsize i = 0;
443324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe    for (; it != it_end; it++, ++i) {
444324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      std::string descriptor(DescriptorToDot(*it));
445324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      ScopedLocalRef<jstring> jdescriptor(env, env->NewStringUTF(descriptor.c_str()));
446324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      if (jdescriptor.get() == nullptr) {
447324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe        return nullptr;
448dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers      }
449324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe      env->SetObjectArrayElement(result, i, jdescriptor.get());
450dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers    }
45103a20ba67cfdc46f5ad8d77242a666a4cb0512f2Brian Carlstrom  }
452dd157d732b557a854b3689faf8a24170fb47c270Ian Rogers  return result;
453f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}
454f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
455e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jint GetDexOptNeeded(JNIEnv* env,
456e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                            const char* filename,
457e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                            const char* instruction_set,
45829d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe                            const char* compiler_filter_name,
45929d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe                            bool profile_changed) {
46011d9f06a96a6909905c248ed684366190140095cNarayan Kamath  if ((filename == nullptr) || !OS::FileExists(filename)) {
46195abd04d211470ea4b9b9191b96dd0f32e7ce3a4Richard Uhler    LOG(ERROR) << "DexFile_getDexOptNeeded file '" << filename << "' does not exist";
4628d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
46311d9f06a96a6909905c248ed684366190140095cNarayan Kamath    const char* message = (filename == nullptr) ? "<empty file name>" : filename;
4648d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    env->ThrowNew(fnfe.get(), message);
465b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle    return -1;
4661d9f52b7ca91c6d30b7acfac1c9ab24d93fff470Brian Carlstrom  }
4671d9f52b7ca91c6d30b7acfac1c9ab24d93fff470Brian Carlstrom
4686e183f2e973a20f2eaca135c240908e1bf98c5d0Alex Light  const InstructionSet target_instruction_set = GetInstructionSetFromString(instruction_set);
46920c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe  if (target_instruction_set == kNone) {
47020c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe    ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
47120c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe    std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set));
47220c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe    env->ThrowNew(iae.get(), message.c_str());
473b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle    return -1;
47420c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe  }
4756e183f2e973a20f2eaca135c240908e1bf98c5d0Alex Light
47629d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe  CompilerFilter::Filter filter;
47729d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe  if (!CompilerFilter::ParseCompilerFilter(compiler_filter_name, &filter)) {
47829d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe    ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
47929d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe    std::string message(StringPrintf("Compiler filter %s is invalid.", compiler_filter_name));
48029d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe    env->ThrowNew(iae.get(), message.c_str());
48129d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe    return -1;
48229d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe  }
48329d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe
48466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // TODO: Verify the dex location is well formed, and throw an IOException if
48566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // not?
48629d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe
487d1472a27e856ec68ab5a27abaaebe9c61d91d343Richard Uhler  OatFileAssistant oat_file_assistant(filename, target_instruction_set, false);
4886e183f2e973a20f2eaca135c240908e1bf98c5d0Alex Light
48966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Always treat elements of the bootclasspath as up-to-date.
49066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  if (oat_file_assistant.IsInBootClassPath()) {
49195abd04d211470ea4b9b9191b96dd0f32e7ce3a4Richard Uhler    return OatFileAssistant::kNoDexOptNeeded;
49246774767fcf7780d1455e755729198648d08742eIgor Murashkin  }
493d1472a27e856ec68ab5a27abaaebe9c61d91d343Richard Uhler  return oat_file_assistant.GetDexOptNeeded(filter, profile_changed);
494f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}
495f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
4968943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamathstatic jstring DexFile_getDexFileStatus(JNIEnv* env,
4978943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath                                        jclass,
4988943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath                                        jstring javaFilename,
4998943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath                                        jstring javaInstructionSet) {
5008943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  ScopedUtfChars filename(env, javaFilename);
5018943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  if (env->ExceptionCheck()) {
5028943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath    return nullptr;
5038943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  }
5048943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath
5058943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  ScopedUtfChars instruction_set(env, javaInstructionSet);
5068943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  if (env->ExceptionCheck()) {
5078943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath    return nullptr;
5088943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  }
5098943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath
5108943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  const InstructionSet target_instruction_set = GetInstructionSetFromString(
5118943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath      instruction_set.c_str());
5128943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  if (target_instruction_set == kNone) {
5138943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath    ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
5148943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath    std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
5158943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath    env->ThrowNew(iae.get(), message.c_str());
5168943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath    return nullptr;
5178943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  }
5188943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath
5198943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  OatFileAssistant oat_file_assistant(filename.c_str(), target_instruction_set,
5208943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath                                      false /* load_executable */);
52146cc64f11b1b1f0ac5e4aebd665b325a68d4d42fRichard Uhler  return env->NewStringUTF(oat_file_assistant.GetStatusDump().c_str());
5228943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath}
5238943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath
524e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartierstatic jint DexFile_getDexOptNeeded(JNIEnv* env,
525e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                    jclass,
526e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                    jstring javaFilename,
527e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                                    jstring javaInstructionSet,
528c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                                    jstring javaTargetCompilerFilter,
529c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                                    jboolean newProfile) {
53011d9f06a96a6909905c248ed684366190140095cNarayan Kamath  ScopedUtfChars filename(env, javaFilename);
53120c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe  if (env->ExceptionCheck()) {
532b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle    return -1;
53320c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe  }
53420c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe
53511d9f06a96a6909905c248ed684366190140095cNarayan Kamath  ScopedUtfChars instruction_set(env, javaInstructionSet);
53620c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe  if (env->ExceptionCheck()) {
537b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle    return -1;
53820c89303a9d89ba857bf969ad14a31f12c3be878Andreas Gampe  }
53911d9f06a96a6909905c248ed684366190140095cNarayan Kamath
540c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  ScopedUtfChars target_compiler_filter(env, javaTargetCompilerFilter);
541c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  if (env->ExceptionCheck()) {
542c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe    return -1;
54329d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe  }
544c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe
545e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier  return GetDexOptNeeded(env,
546e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                         filename.c_str(),
547e58991b3b2282b5761f1a6023a16c803e1c4eb45Mathieu Chartier                         instruction_set.c_str(),
548c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                         target_compiler_filter.c_str(),
549c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                         newProfile == JNI_TRUE);
55011d9f06a96a6909905c248ed684366190140095cNarayan Kamath}
55111d9f06a96a6909905c248ed684366190140095cNarayan Kamath
552b077e15d2d11b7c81aacbcd4a46c2b1e9c9ba20dCalin Juravle// public API
55311d9f06a96a6909905c248ed684366190140095cNarayan Kamathstatic jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) {
55406e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler  ScopedUtfChars filename_utf(env, javaFilename);
55506e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler  if (env->ExceptionCheck()) {
55606e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler    return JNI_FALSE;
55706e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler  }
55806e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler
55906e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler  const char* filename = filename_utf.c_str();
56006e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler  if ((filename == nullptr) || !OS::FileExists(filename)) {
56106e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler    LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename << "' does not exist";
56206e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler    ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException"));
56306e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler    const char* message = (filename == nullptr) ? "<empty file name>" : filename;
56406e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler    env->ThrowNew(fnfe.get(), message);
56506e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler    return JNI_FALSE;
56606e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler  }
56706e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler
568d1472a27e856ec68ab5a27abaaebe9c61d91d343Richard Uhler  OatFileAssistant oat_file_assistant(filename, kRuntimeISA, false);
56906e3f4fa00ea9f71c4675f90e250e59b6d9ba36fRichard Uhler  return oat_file_assistant.IsUpToDate() ? JNI_FALSE : JNI_TRUE;
57039c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13Dave Allison}
57139c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13Dave Allison
572c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampestatic jboolean DexFile_isValidCompilerFilter(JNIEnv* env,
573c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                                            jclass javeDexFileClass ATTRIBUTE_UNUSED,
574c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                                            jstring javaCompilerFilter) {
575c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  ScopedUtfChars compiler_filter(env, javaCompilerFilter);
576c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  if (env->ExceptionCheck()) {
577c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe    return -1;
578c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  }
579c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe
580c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  CompilerFilter::Filter filter;
581c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  return CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)
582c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe      ? JNI_TRUE : JNI_FALSE;
583c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe}
584c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe
585c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampestatic jboolean DexFile_isProfileGuidedCompilerFilter(JNIEnv* env,
586c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                                                      jclass javeDexFileClass ATTRIBUTE_UNUSED,
587c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                                                      jstring javaCompilerFilter) {
588c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  ScopedUtfChars compiler_filter(env, javaCompilerFilter);
589c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  if (env->ExceptionCheck()) {
590c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe    return -1;
591c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  }
592c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe
593c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  CompilerFilter::Filter filter;
594c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
595c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe    return JNI_FALSE;
596c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  }
597c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  return CompilerFilter::DependsOnProfile(filter) ? JNI_TRUE : JNI_FALSE;
598c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe}
599c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe
60086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampestatic jstring DexFile_getNonProfileGuidedCompilerFilter(JNIEnv* env,
60186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe                                                         jclass javeDexFileClass ATTRIBUTE_UNUSED,
60286a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe                                                         jstring javaCompilerFilter) {
60386a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  ScopedUtfChars compiler_filter(env, javaCompilerFilter);
60486a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  if (env->ExceptionCheck()) {
60586a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe    return nullptr;
60686a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  }
60786a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe
60886a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  CompilerFilter::Filter filter;
60986a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
61086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe    return javaCompilerFilter;
61186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  }
61286a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe
61386a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  CompilerFilter::Filter new_filter = CompilerFilter::GetNonProfileDependentFilterFrom(filter);
61486a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe
61586a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  // Filter stayed the same, return input.
61686a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  if (filter == new_filter) {
61786a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe    return javaCompilerFilter;
61886a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  }
61986a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe
62086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  // Create a new string object and return.
62186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter);
62286a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  return env->NewStringUTF(new_filter_str.c_str());
62386a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe}
62486a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe
625d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffraystatic jstring DexFile_getSafeModeCompilerFilter(JNIEnv* env,
626d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray                                                 jclass javeDexFileClass ATTRIBUTE_UNUSED,
627d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray                                                 jstring javaCompilerFilter) {
628d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  ScopedUtfChars compiler_filter(env, javaCompilerFilter);
629d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  if (env->ExceptionCheck()) {
630d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray    return nullptr;
631d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  }
632d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray
633d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  CompilerFilter::Filter filter;
634d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  if (!CompilerFilter::ParseCompilerFilter(compiler_filter.c_str(), &filter)) {
635d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray    return javaCompilerFilter;
636d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  }
637d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray
638d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  CompilerFilter::Filter new_filter = CompilerFilter::GetSafeModeFilterFrom(filter);
639d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray
640d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  // Filter stayed the same, return input.
641d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  if (filter == new_filter) {
642d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray    return javaCompilerFilter;
643d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  }
644d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray
645d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  // Create a new string object and return.
646d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  std::string new_filter_str = CompilerFilter::NameOfFilter(new_filter);
647d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  return env->NewStringUTF(new_filter_str.c_str());
648d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray}
649d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray
65090671be8ca352f96eaf4f3109334f2f516268201Jeff Haostatic jboolean DexFile_isBackedByOatFile(JNIEnv* env, jclass, jobject cookie) {
65190671be8ca352f96eaf4f3109334f2f516268201Jeff Hao  const OatFile* oat_file = nullptr;
65290671be8ca352f96eaf4f3109334f2f516268201Jeff Hao  std::vector<const DexFile*> dex_files;
65390671be8ca352f96eaf4f3109334f2f516268201Jeff Hao  if (!ConvertJavaArrayToDexFiles(env, cookie, /*out */ dex_files, /* out */ oat_file)) {
65490671be8ca352f96eaf4f3109334f2f516268201Jeff Hao    DCHECK(env->ExceptionCheck());
65590671be8ca352f96eaf4f3109334f2f516268201Jeff Hao    return false;
65690671be8ca352f96eaf4f3109334f2f516268201Jeff Hao  }
65790671be8ca352f96eaf4f3109334f2f516268201Jeff Hao  return oat_file != nullptr;
65890671be8ca352f96eaf4f3109334f2f516268201Jeff Hao}
65990671be8ca352f96eaf4f3109334f2f516268201Jeff Hao
660cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravlestatic jobjectArray DexFile_getDexFileOutputPaths(JNIEnv* env,
661b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra                                            jclass,
662b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra                                            jstring javaFilename,
663b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra                                            jstring javaInstructionSet) {
664b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  ScopedUtfChars filename(env, javaFilename);
665b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  if (env->ExceptionCheck()) {
666b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra    return nullptr;
667b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  }
668b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra
669b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  ScopedUtfChars instruction_set(env, javaInstructionSet);
670b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  if (env->ExceptionCheck()) {
671b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra    return nullptr;
672b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  }
673b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra
674b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  const InstructionSet target_instruction_set = GetInstructionSetFromString(
675b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra      instruction_set.c_str());
676b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  if (target_instruction_set == kNone) {
677b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra    ScopedLocalRef<jclass> iae(env, env->FindClass("java/lang/IllegalArgumentException"));
678b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra    std::string message(StringPrintf("Instruction set %s is invalid.", instruction_set.c_str()));
679b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra    env->ThrowNew(iae.get(), message.c_str());
680b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra    return nullptr;
681b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  }
682b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra
683b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  OatFileAssistant oat_file_assistant(filename.c_str(),
684b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra                                      target_instruction_set,
685b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra                                      false /* load_executable */);
686b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra
687b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  std::unique_ptr<OatFile> best_oat_file = oat_file_assistant.GetBestOatFile();
688b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  if (best_oat_file == nullptr) {
689b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra    return nullptr;
690b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra  }
691b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra
692cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  std::string oat_filename = best_oat_file->GetLocation();
693cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  std::string vdex_filename = GetVdexFilename(best_oat_file->GetLocation());
694cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle
695cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  ScopedLocalRef<jstring> jvdexFilename(env, env->NewStringUTF(vdex_filename.c_str()));
696cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  if (jvdexFilename.get() == nullptr) {
697cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle    return nullptr;
698cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  }
699cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  ScopedLocalRef<jstring> joatFilename(env, env->NewStringUTF(oat_filename.c_str()));
700cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  if (joatFilename.get() == nullptr) {
701cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle    return nullptr;
702cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  }
703cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle
704cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  // Now create output array and copy the set into it.
705cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  jobjectArray result = env->NewObjectArray(2,
706cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle                                            WellKnownClasses::java_lang_String,
707cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle                                            nullptr);
708cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  env->SetObjectArrayElement(result, 0, jvdexFilename.get());
709cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  env->SetObjectArrayElement(result, 1, joatFilename.get());
710cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle
711cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  return result;
712b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra}
713b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra
714f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromstatic JNINativeMethod gMethods[] = {
7151d7d7f15f9fbb1111d4b7d79c1dab2f49a5960dcMathieu Chartier  NATIVE_METHOD(DexFile, closeDexFile, "(Ljava/lang/Object;)Z"),
71600310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier  NATIVE_METHOD(DexFile,
71700310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                defineClassNative,
71800310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                "(Ljava/lang/String;"
71900310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                "Ljava/lang/ClassLoader;"
72000310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                "Ljava/lang/Object;"
72100310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                "Ldalvik/system/DexFile;"
72200310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier                ")Ljava/lang/Class;"),
723324b9bb2f48be39e20077c1d7da45cf3dc47fe06Andreas Gampe  NATIVE_METHOD(DexFile, getClassNameList, "(Ljava/lang/Object;)[Ljava/lang/String;"),
724f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"),
7252cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  NATIVE_METHOD(DexFile, getDexOptNeeded,
726c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe                "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)I"),
7272cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  NATIVE_METHOD(DexFile, openDexFileNative,
728689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier                "(Ljava/lang/String;"
729689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier                "Ljava/lang/String;"
730689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier                "I"
731689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier                "Ljava/lang/ClassLoader;"
732689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier                "[Ldalvik/system/DexPathList$Element;"
733689a700d1c8a7c9e7ce74e6a2b45dae94c79cb7cMathieu Chartier                ")Ljava/lang/Object;"),
734ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  NATIVE_METHOD(DexFile, createCookieWithDirectBuffer,
735ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light                "(Ljava/nio/ByteBuffer;II)Ljava/lang/Object;"),
736ea9465eaaa55646b0de242d2a21f9c1f0f0aa01fAlex Light  NATIVE_METHOD(DexFile, createCookieWithArray, "([BII)Ljava/lang/Object;"),
737c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  NATIVE_METHOD(DexFile, isValidCompilerFilter, "(Ljava/lang/String;)Z"),
738c38be810ce939267c004f72b3cf0b9339414f0f9Andreas Gampe  NATIVE_METHOD(DexFile, isProfileGuidedCompilerFilter, "(Ljava/lang/String;)Z"),
73986a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe  NATIVE_METHOD(DexFile,
74086a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe                getNonProfileGuidedCompilerFilter,
74186a785d23ba3956b78c33aa3b623df4b6ec8b901Andreas Gampe                "(Ljava/lang/String;)Ljava/lang/String;"),
742d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray  NATIVE_METHOD(DexFile,
743d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray                getSafeModeCompilerFilter,
744d0faf8cedf65afd6b642ebdfb894736c6e224e6aNicolas Geoffray                "(Ljava/lang/String;)Ljava/lang/String;"),
74590671be8ca352f96eaf4f3109334f2f516268201Jeff Hao  NATIVE_METHOD(DexFile, isBackedByOatFile, "(Ljava/lang/Object;)Z"),
7468943c1dc59da4dd182fb906bbe111d3b598b9fdbNarayan Kamath  NATIVE_METHOD(DexFile, getDexFileStatus,
747b55ad7c146fbb7ca5995ff54dc655241fc54a3b3Philip Cuadra                "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
748cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle  NATIVE_METHOD(DexFile, getDexFileOutputPaths,
749cabbbc22b6a02e0b0e9fb717a1f92921b757e8f3Calin Juravle                "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;")
750f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom};
751f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
752f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstromvoid register_dalvik_system_DexFile(JNIEnv* env) {
753eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  REGISTER_NATIVE_METHODS("dalvik/system/DexFile");
754f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}
755f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom
756f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom}  // namespace art
757