1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2008 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "check_jni.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <sys/mman.h>
20*795d594fSAndroid Build Coastguard Worker #include <zlib.h>
21*795d594fSAndroid Build Coastguard Worker
22*795d594fSAndroid Build Coastguard Worker #include <iomanip>
23*795d594fSAndroid Build Coastguard Worker
24*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
25*795d594fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/to_str.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/time_utils.h"
32*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
34*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
35*795d594fSAndroid Build Coastguard Worker #include "dex/descriptors_names.h"
36*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "gc/space/space.h"
38*795d594fSAndroid Build Coastguard Worker #include "indirect_reference_table-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "java_vm_ext.h"
40*795d594fSAndroid Build Coastguard Worker #include "jni_internal.h"
41*795d594fSAndroid Build Coastguard Worker #include "local_reference_table-inl.h"
42*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "mirror/field.h"
44*795d594fSAndroid Build Coastguard Worker #include "mirror/method.h"
45*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
47*795d594fSAndroid Build Coastguard Worker #include "mirror/string-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "mirror/throwable.h"
49*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
50*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
51*795d594fSAndroid Build Coastguard Worker #include "thread.h"
52*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker // This helper cannot be in the anonymous namespace because it needs to be
57*795d594fSAndroid Build Coastguard Worker // declared as a friend by JniVmExt and JniEnvExt.
GetIndirectReferenceTable(ScopedObjectAccess & soa,IndirectRefKind kind)58*795d594fSAndroid Build Coastguard Worker inline IndirectReferenceTable* GetIndirectReferenceTable(ScopedObjectAccess& soa,
59*795d594fSAndroid Build Coastguard Worker IndirectRefKind kind) {
60*795d594fSAndroid Build Coastguard Worker DCHECK_NE(kind, kJniTransition);
61*795d594fSAndroid Build Coastguard Worker DCHECK_NE(kind, kLocal);
62*795d594fSAndroid Build Coastguard Worker JavaVMExt* vm = soa.Env()->GetVm();
63*795d594fSAndroid Build Coastguard Worker IndirectReferenceTable* irt = (kind == kGlobal) ? &vm->globals_ : &vm->weak_globals_;
64*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(irt->GetKind(), kind);
65*795d594fSAndroid Build Coastguard Worker return irt;
66*795d594fSAndroid Build Coastguard Worker }
67*795d594fSAndroid Build Coastguard Worker
68*795d594fSAndroid Build Coastguard Worker // This helper cannot be in the anonymous namespace because it needs to be
69*795d594fSAndroid Build Coastguard Worker // declared as a friend by JniEnvExt.
GetLocalReferenceTable(ScopedObjectAccess & soa)70*795d594fSAndroid Build Coastguard Worker inline jni::LocalReferenceTable* GetLocalReferenceTable(ScopedObjectAccess& soa) {
71*795d594fSAndroid Build Coastguard Worker return &soa.Env()->locals_;
72*795d594fSAndroid Build Coastguard Worker }
73*795d594fSAndroid Build Coastguard Worker
74*795d594fSAndroid Build Coastguard Worker namespace {
75*795d594fSAndroid Build Coastguard Worker
76*795d594fSAndroid Build Coastguard Worker using android::base::StringAppendF;
77*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
78*795d594fSAndroid Build Coastguard Worker
79*795d594fSAndroid Build Coastguard Worker /*
80*795d594fSAndroid Build Coastguard Worker * ===========================================================================
81*795d594fSAndroid Build Coastguard Worker * JNI function helpers
82*795d594fSAndroid Build Coastguard Worker * ===========================================================================
83*795d594fSAndroid Build Coastguard Worker */
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker // Warn if a JNI critical is held for longer than 16ms.
86*795d594fSAndroid Build Coastguard Worker static constexpr uint64_t kCriticalWarnTimeUs = MsToUs(16);
87*795d594fSAndroid Build Coastguard Worker static_assert(kCriticalWarnTimeUs > 0, "No JNI critical warn time set");
88*795d594fSAndroid Build Coastguard Worker
89*795d594fSAndroid Build Coastguard Worker // True if primitives within specific ranges cause a fatal error,
90*795d594fSAndroid Build Coastguard Worker // otherwise just warn.
91*795d594fSAndroid Build Coastguard Worker static constexpr bool kBrokenPrimitivesAreFatal = kIsDebugBuild;
92*795d594fSAndroid Build Coastguard Worker
93*795d594fSAndroid Build Coastguard Worker // Flags passed into ScopedCheck.
94*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_Default = 0x0000;
95*795d594fSAndroid Build Coastguard Worker
96*795d594fSAndroid Build Coastguard Worker // Calling while in critical is not allowed.
97*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritBad = 0x0000;
98*795d594fSAndroid Build Coastguard Worker // Calling while in critical is allowed.
99*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritOkay = 0x0001;
100*795d594fSAndroid Build Coastguard Worker // This is a critical "get".
101*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritGet = 0x0002;
102*795d594fSAndroid Build Coastguard Worker // This is a critical "release".
103*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritRelease = 0x0003;
104*795d594fSAndroid Build Coastguard Worker // Bit mask to get "crit" value.
105*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_CritMask = 0x0003;
106*795d594fSAndroid Build Coastguard Worker
107*795d594fSAndroid Build Coastguard Worker // Raised exceptions are allowed.
108*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_ExcepOkay = 0x0004;
109*795d594fSAndroid Build Coastguard Worker
110*795d594fSAndroid Build Coastguard Worker // Are we in a non-critical release function?
111*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_Release = 0x0010;
112*795d594fSAndroid Build Coastguard Worker // Are our UTF parameters nullable?
113*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_NullableUtf = 0x0020;
114*795d594fSAndroid Build Coastguard Worker
115*795d594fSAndroid Build Coastguard Worker // Part of the invocation interface (JavaVM*).
116*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_Invocation = 0x0100;
117*795d594fSAndroid Build Coastguard Worker
118*795d594fSAndroid Build Coastguard Worker // Add this to a JNI function's flags if you want to trace every call.
119*795d594fSAndroid Build Coastguard Worker static constexpr uint16_t kFlag_ForceTrace = 0x8000;
120*795d594fSAndroid Build Coastguard Worker
121*795d594fSAndroid Build Coastguard Worker class VarArgs;
122*795d594fSAndroid Build Coastguard Worker /*
123*795d594fSAndroid Build Coastguard Worker * Java primitive types:
124*795d594fSAndroid Build Coastguard Worker * B - jbyte
125*795d594fSAndroid Build Coastguard Worker * C - jchar
126*795d594fSAndroid Build Coastguard Worker * D - jdouble
127*795d594fSAndroid Build Coastguard Worker * F - jfloat
128*795d594fSAndroid Build Coastguard Worker * I - jint
129*795d594fSAndroid Build Coastguard Worker * J - jlong
130*795d594fSAndroid Build Coastguard Worker * S - jshort
131*795d594fSAndroid Build Coastguard Worker * Z - jboolean (shown as true and false)
132*795d594fSAndroid Build Coastguard Worker * V - void
133*795d594fSAndroid Build Coastguard Worker *
134*795d594fSAndroid Build Coastguard Worker * Java reference types:
135*795d594fSAndroid Build Coastguard Worker * L - jobject
136*795d594fSAndroid Build Coastguard Worker * a - jarray
137*795d594fSAndroid Build Coastguard Worker * c - jclass
138*795d594fSAndroid Build Coastguard Worker * s - jstring
139*795d594fSAndroid Build Coastguard Worker * t - jthrowable
140*795d594fSAndroid Build Coastguard Worker *
141*795d594fSAndroid Build Coastguard Worker * JNI types:
142*795d594fSAndroid Build Coastguard Worker * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
143*795d594fSAndroid Build Coastguard Worker * f - jfieldID
144*795d594fSAndroid Build Coastguard Worker * i - JNI error value (JNI_OK, JNI_ERR, JNI_EDETACHED, JNI_EVERSION)
145*795d594fSAndroid Build Coastguard Worker * m - jmethodID
146*795d594fSAndroid Build Coastguard Worker * p - void*
147*795d594fSAndroid Build Coastguard Worker * r - jint (for release mode arguments)
148*795d594fSAndroid Build Coastguard Worker * u - const char* (Modified UTF-8)
149*795d594fSAndroid Build Coastguard Worker * z - jsize (for lengths; use i if negative values are okay)
150*795d594fSAndroid Build Coastguard Worker * v - JavaVM*
151*795d594fSAndroid Build Coastguard Worker * w - jobjectRefType
152*795d594fSAndroid Build Coastguard Worker * E - JNIEnv*
153*795d594fSAndroid Build Coastguard Worker * . - no argument; just print "..." (used for varargs JNI calls)
154*795d594fSAndroid Build Coastguard Worker *
155*795d594fSAndroid Build Coastguard Worker */
156*795d594fSAndroid Build Coastguard Worker union JniValueType {
157*795d594fSAndroid Build Coastguard Worker jarray a;
158*795d594fSAndroid Build Coastguard Worker jboolean b;
159*795d594fSAndroid Build Coastguard Worker jclass c;
160*795d594fSAndroid Build Coastguard Worker jfieldID f;
161*795d594fSAndroid Build Coastguard Worker jint i;
162*795d594fSAndroid Build Coastguard Worker jmethodID m;
163*795d594fSAndroid Build Coastguard Worker const void* p; // Pointer.
164*795d594fSAndroid Build Coastguard Worker jint r; // Release mode.
165*795d594fSAndroid Build Coastguard Worker jstring s;
166*795d594fSAndroid Build Coastguard Worker jthrowable t;
167*795d594fSAndroid Build Coastguard Worker const char* u; // Modified UTF-8.
168*795d594fSAndroid Build Coastguard Worker JavaVM* v;
169*795d594fSAndroid Build Coastguard Worker jobjectRefType w;
170*795d594fSAndroid Build Coastguard Worker jsize z;
171*795d594fSAndroid Build Coastguard Worker jbyte B;
172*795d594fSAndroid Build Coastguard Worker jchar C;
173*795d594fSAndroid Build Coastguard Worker jdouble D;
174*795d594fSAndroid Build Coastguard Worker JNIEnv* E;
175*795d594fSAndroid Build Coastguard Worker jfloat F;
176*795d594fSAndroid Build Coastguard Worker jint I;
177*795d594fSAndroid Build Coastguard Worker jlong J;
178*795d594fSAndroid Build Coastguard Worker jobject L;
179*795d594fSAndroid Build Coastguard Worker jshort S;
180*795d594fSAndroid Build Coastguard Worker const void* V; // void
181*795d594fSAndroid Build Coastguard Worker jboolean Z;
182*795d594fSAndroid Build Coastguard Worker const VarArgs* va;
183*795d594fSAndroid Build Coastguard Worker };
184*795d594fSAndroid Build Coastguard Worker
185*795d594fSAndroid Build Coastguard Worker /*
186*795d594fSAndroid Build Coastguard Worker * A structure containing all the information needed to validate varargs arguments.
187*795d594fSAndroid Build Coastguard Worker *
188*795d594fSAndroid Build Coastguard Worker * Note that actually getting the arguments from this structure mutates it so should only be done on
189*795d594fSAndroid Build Coastguard Worker * owned copies.
190*795d594fSAndroid Build Coastguard Worker */
191*795d594fSAndroid Build Coastguard Worker class VarArgs {
192*795d594fSAndroid Build Coastguard Worker public:
VarArgs(jmethodID m,va_list var)193*795d594fSAndroid Build Coastguard Worker VarArgs(jmethodID m, va_list var) : m_(m), type_(kTypeVaList), cnt_(0) {
194*795d594fSAndroid Build Coastguard Worker va_copy(vargs_, var);
195*795d594fSAndroid Build Coastguard Worker }
196*795d594fSAndroid Build Coastguard Worker
VarArgs(jmethodID m,const jvalue * vals)197*795d594fSAndroid Build Coastguard Worker VarArgs(jmethodID m, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(0), ptr_(vals) {}
198*795d594fSAndroid Build Coastguard Worker
~VarArgs()199*795d594fSAndroid Build Coastguard Worker ~VarArgs() {
200*795d594fSAndroid Build Coastguard Worker if (type_ == kTypeVaList) {
201*795d594fSAndroid Build Coastguard Worker va_end(vargs_);
202*795d594fSAndroid Build Coastguard Worker }
203*795d594fSAndroid Build Coastguard Worker }
204*795d594fSAndroid Build Coastguard Worker
VarArgs(VarArgs && other)205*795d594fSAndroid Build Coastguard Worker VarArgs(VarArgs&& other) noexcept {
206*795d594fSAndroid Build Coastguard Worker m_ = other.m_;
207*795d594fSAndroid Build Coastguard Worker cnt_ = other.cnt_;
208*795d594fSAndroid Build Coastguard Worker type_ = other.type_;
209*795d594fSAndroid Build Coastguard Worker if (other.type_ == kTypeVaList) {
210*795d594fSAndroid Build Coastguard Worker va_copy(vargs_, other.vargs_);
211*795d594fSAndroid Build Coastguard Worker } else {
212*795d594fSAndroid Build Coastguard Worker ptr_ = other.ptr_;
213*795d594fSAndroid Build Coastguard Worker }
214*795d594fSAndroid Build Coastguard Worker }
215*795d594fSAndroid Build Coastguard Worker
216*795d594fSAndroid Build Coastguard Worker // This method is const because we need to ensure that one only uses the GetValue method on an
217*795d594fSAndroid Build Coastguard Worker // owned copy of the VarArgs. This is because getting the next argument from a va_list is a
218*795d594fSAndroid Build Coastguard Worker // mutating operation. Therefore we pass around these VarArgs with the 'const' qualifier and when
219*795d594fSAndroid Build Coastguard Worker // we want to use one we need to Clone() it.
Clone() const220*795d594fSAndroid Build Coastguard Worker VarArgs Clone() const {
221*795d594fSAndroid Build Coastguard Worker if (type_ == kTypeVaList) {
222*795d594fSAndroid Build Coastguard Worker // const_cast needed to make sure the compiler is okay with va_copy, which (being a macro) is
223*795d594fSAndroid Build Coastguard Worker // messed up if the source argument is not the exact type 'va_list'.
224*795d594fSAndroid Build Coastguard Worker return VarArgs(m_, cnt_, const_cast<VarArgs*>(this)->vargs_);
225*795d594fSAndroid Build Coastguard Worker } else {
226*795d594fSAndroid Build Coastguard Worker return VarArgs(m_, cnt_, ptr_);
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker }
229*795d594fSAndroid Build Coastguard Worker
GetMethodID() const230*795d594fSAndroid Build Coastguard Worker jmethodID GetMethodID() const {
231*795d594fSAndroid Build Coastguard Worker return m_;
232*795d594fSAndroid Build Coastguard Worker }
233*795d594fSAndroid Build Coastguard Worker
GetValue(char fmt)234*795d594fSAndroid Build Coastguard Worker JniValueType GetValue(char fmt) {
235*795d594fSAndroid Build Coastguard Worker JniValueType o;
236*795d594fSAndroid Build Coastguard Worker if (type_ == kTypeVaList) {
237*795d594fSAndroid Build Coastguard Worker switch (fmt) {
238*795d594fSAndroid Build Coastguard Worker // Assign a full int for va_list values as this is what is done in reflection.cc.
239*795d594fSAndroid Build Coastguard Worker // TODO(b/73656264): avoid undefined behavior.
240*795d594fSAndroid Build Coastguard Worker case 'Z': FALLTHROUGH_INTENDED;
241*795d594fSAndroid Build Coastguard Worker case 'B': FALLTHROUGH_INTENDED;
242*795d594fSAndroid Build Coastguard Worker case 'C': FALLTHROUGH_INTENDED;
243*795d594fSAndroid Build Coastguard Worker case 'S': FALLTHROUGH_INTENDED;
244*795d594fSAndroid Build Coastguard Worker case 'I': o.I = va_arg(vargs_, jint); break;
245*795d594fSAndroid Build Coastguard Worker case 'J': o.J = va_arg(vargs_, jlong); break;
246*795d594fSAndroid Build Coastguard Worker case 'F': o.F = static_cast<jfloat>(va_arg(vargs_, jdouble)); break;
247*795d594fSAndroid Build Coastguard Worker case 'D': o.D = va_arg(vargs_, jdouble); break;
248*795d594fSAndroid Build Coastguard Worker case 'L': o.L = va_arg(vargs_, jobject); break;
249*795d594fSAndroid Build Coastguard Worker default:
250*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Illegal type format char " << fmt;
251*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
252*795d594fSAndroid Build Coastguard Worker }
253*795d594fSAndroid Build Coastguard Worker } else {
254*795d594fSAndroid Build Coastguard Worker CHECK(type_ == kTypePtr);
255*795d594fSAndroid Build Coastguard Worker jvalue v = ptr_[cnt_];
256*795d594fSAndroid Build Coastguard Worker cnt_++;
257*795d594fSAndroid Build Coastguard Worker switch (fmt) {
258*795d594fSAndroid Build Coastguard Worker // Copy just the amount of the jvalue necessary, as done in
259*795d594fSAndroid Build Coastguard Worker // reflection.cc, but extend to an int to be consistent with
260*795d594fSAndroid Build Coastguard Worker // var args in CheckNonHeapValue.
261*795d594fSAndroid Build Coastguard Worker // TODO(b/73656264): avoid undefined behavior.
262*795d594fSAndroid Build Coastguard Worker case 'Z': o.I = v.z; break;
263*795d594fSAndroid Build Coastguard Worker case 'B': o.I = v.b; break;
264*795d594fSAndroid Build Coastguard Worker case 'C': o.I = v.c; break;
265*795d594fSAndroid Build Coastguard Worker case 'S': o.I = v.s; break;
266*795d594fSAndroid Build Coastguard Worker case 'I': o.I = v.i; break;
267*795d594fSAndroid Build Coastguard Worker case 'J': o.J = v.j; break;
268*795d594fSAndroid Build Coastguard Worker case 'F': o.F = v.f; break;
269*795d594fSAndroid Build Coastguard Worker case 'D': o.D = v.d; break;
270*795d594fSAndroid Build Coastguard Worker case 'L': o.L = v.l; break;
271*795d594fSAndroid Build Coastguard Worker default:
272*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Illegal type format char " << fmt;
273*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker }
276*795d594fSAndroid Build Coastguard Worker return o;
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker
279*795d594fSAndroid Build Coastguard Worker private:
VarArgs(jmethodID m,uint32_t cnt,va_list var)280*795d594fSAndroid Build Coastguard Worker VarArgs(jmethodID m, uint32_t cnt, va_list var) : m_(m), type_(kTypeVaList), cnt_(cnt) {
281*795d594fSAndroid Build Coastguard Worker va_copy(vargs_, var);
282*795d594fSAndroid Build Coastguard Worker }
283*795d594fSAndroid Build Coastguard Worker
VarArgs(jmethodID m,uint32_t cnt,const jvalue * vals)284*795d594fSAndroid Build Coastguard Worker VarArgs(jmethodID m, uint32_t cnt, const jvalue* vals) : m_(m), type_(kTypePtr), cnt_(cnt), ptr_(vals) {}
285*795d594fSAndroid Build Coastguard Worker
286*795d594fSAndroid Build Coastguard Worker enum VarArgsType {
287*795d594fSAndroid Build Coastguard Worker kTypeVaList,
288*795d594fSAndroid Build Coastguard Worker kTypePtr,
289*795d594fSAndroid Build Coastguard Worker };
290*795d594fSAndroid Build Coastguard Worker
291*795d594fSAndroid Build Coastguard Worker jmethodID m_;
292*795d594fSAndroid Build Coastguard Worker VarArgsType type_;
293*795d594fSAndroid Build Coastguard Worker uint32_t cnt_;
294*795d594fSAndroid Build Coastguard Worker union {
295*795d594fSAndroid Build Coastguard Worker va_list vargs_;
296*795d594fSAndroid Build Coastguard Worker const jvalue* ptr_;
297*795d594fSAndroid Build Coastguard Worker };
298*795d594fSAndroid Build Coastguard Worker };
299*795d594fSAndroid Build Coastguard Worker
300*795d594fSAndroid Build Coastguard Worker // Check whether the current thread is attached. This is usually required
301*795d594fSAndroid Build Coastguard Worker // to be the first check, as ScopedCheck needs a ScopedObjectAccess for
302*795d594fSAndroid Build Coastguard Worker // checking heap values (and that will fail with unattached threads).
CheckAttachedThread(const char * function_name)303*795d594fSAndroid Build Coastguard Worker bool CheckAttachedThread(const char* function_name) {
304*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
305*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(self == nullptr)) {
306*795d594fSAndroid Build Coastguard Worker // Need to attach this thread for a proper abort to work. We prefer this
307*795d594fSAndroid Build Coastguard Worker // to get reasonable stacks and environment, rather than relying on
308*795d594fSAndroid Build Coastguard Worker // tombstoned.
309*795d594fSAndroid Build Coastguard Worker JNIEnv* env;
310*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetJavaVM()->AttachCurrentThread(&env, /* thr_args= */ nullptr);
311*795d594fSAndroid Build Coastguard Worker
312*795d594fSAndroid Build Coastguard Worker std::string tmp = android::base::StringPrintf(
313*795d594fSAndroid Build Coastguard Worker "a thread (tid %" PRId64 " is making JNI calls without being attached",
314*795d594fSAndroid Build Coastguard Worker static_cast<int64_t>(GetTid()));
315*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetJavaVM()->JniAbort(function_name, tmp.c_str());
316*795d594fSAndroid Build Coastguard Worker
317*795d594fSAndroid Build Coastguard Worker CHECK_NE(Runtime::Current()->GetJavaVM()->DetachCurrentThread(), JNI_ERR);
318*795d594fSAndroid Build Coastguard Worker return false;
319*795d594fSAndroid Build Coastguard Worker }
320*795d594fSAndroid Build Coastguard Worker return true;
321*795d594fSAndroid Build Coastguard Worker }
322*795d594fSAndroid Build Coastguard Worker
323*795d594fSAndroid Build Coastguard Worker // Macro helpers for the above.
324*795d594fSAndroid Build Coastguard Worker #define CHECK_ATTACHED_THREAD(function_name, fail_val) \
325*795d594fSAndroid Build Coastguard Worker do { \
326*795d594fSAndroid Build Coastguard Worker if (!CheckAttachedThread((function_name))) { \
327*795d594fSAndroid Build Coastguard Worker return fail_val; \
328*795d594fSAndroid Build Coastguard Worker } \
329*795d594fSAndroid Build Coastguard Worker } while (false)
330*795d594fSAndroid Build Coastguard Worker #define CHECK_ATTACHED_THREAD_VOID(function_name) \
331*795d594fSAndroid Build Coastguard Worker do { \
332*795d594fSAndroid Build Coastguard Worker if (!CheckAttachedThread((function_name))) { \
333*795d594fSAndroid Build Coastguard Worker return; \
334*795d594fSAndroid Build Coastguard Worker } \
335*795d594fSAndroid Build Coastguard Worker } while (false)
336*795d594fSAndroid Build Coastguard Worker
337*795d594fSAndroid Build Coastguard Worker class ScopedCheck {
338*795d594fSAndroid Build Coastguard Worker public:
ScopedCheck(uint16_t flags,const char * functionName,bool has_method=true)339*795d594fSAndroid Build Coastguard Worker ScopedCheck(uint16_t flags, const char* functionName, bool has_method = true)
340*795d594fSAndroid Build Coastguard Worker : function_name_(functionName), indent_(0), flags_(flags), has_method_(has_method) {
341*795d594fSAndroid Build Coastguard Worker }
342*795d594fSAndroid Build Coastguard Worker
~ScopedCheck()343*795d594fSAndroid Build Coastguard Worker ~ScopedCheck() {}
344*795d594fSAndroid Build Coastguard Worker
345*795d594fSAndroid Build Coastguard Worker // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
346*795d594fSAndroid Build Coastguard Worker // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
347*795d594fSAndroid Build Coastguard Worker // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
348*795d594fSAndroid Build Coastguard Worker // circumstances, but this is incorrect.
CheckClassName(const char * class_name)349*795d594fSAndroid Build Coastguard Worker bool CheckClassName(const char* class_name) {
350*795d594fSAndroid Build Coastguard Worker if ((class_name == nullptr) || !IsValidJniClassName(class_name)) {
351*795d594fSAndroid Build Coastguard Worker AbortF("illegal class name '%s'\n"
352*795d594fSAndroid Build Coastguard Worker " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')",
353*795d594fSAndroid Build Coastguard Worker class_name);
354*795d594fSAndroid Build Coastguard Worker return false;
355*795d594fSAndroid Build Coastguard Worker }
356*795d594fSAndroid Build Coastguard Worker return true;
357*795d594fSAndroid Build Coastguard Worker }
358*795d594fSAndroid Build Coastguard Worker
359*795d594fSAndroid Build Coastguard Worker /*
360*795d594fSAndroid Build Coastguard Worker * Verify that this instance field ID is valid for this object.
361*795d594fSAndroid Build Coastguard Worker *
362*795d594fSAndroid Build Coastguard Worker * Assumes "jobj" has already been validated.
363*795d594fSAndroid Build Coastguard Worker */
CheckInstanceFieldID(ScopedObjectAccess & soa,jobject java_object,jfieldID fid)364*795d594fSAndroid Build Coastguard Worker bool CheckInstanceFieldID(ScopedObjectAccess& soa, jobject java_object, jfieldID fid)
365*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
366*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
367*795d594fSAndroid Build Coastguard Worker if (o == nullptr) {
368*795d594fSAndroid Build Coastguard Worker AbortF("field operation on NULL object: %p", java_object);
369*795d594fSAndroid Build Coastguard Worker return false;
370*795d594fSAndroid Build Coastguard Worker }
371*795d594fSAndroid Build Coastguard Worker if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(o.Ptr())) {
372*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
373*795d594fSAndroid Build Coastguard Worker AbortF("field operation on invalid %s: %p",
374*795d594fSAndroid Build Coastguard Worker GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
375*795d594fSAndroid Build Coastguard Worker java_object);
376*795d594fSAndroid Build Coastguard Worker return false;
377*795d594fSAndroid Build Coastguard Worker }
378*795d594fSAndroid Build Coastguard Worker
379*795d594fSAndroid Build Coastguard Worker ArtField* f = CheckFieldID(fid);
380*795d594fSAndroid Build Coastguard Worker if (f == nullptr) {
381*795d594fSAndroid Build Coastguard Worker return false;
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = o->GetClass();
384*795d594fSAndroid Build Coastguard Worker if (c->FindInstanceField(f->GetName(), f->GetTypeDescriptor()) == nullptr) {
385*795d594fSAndroid Build Coastguard Worker AbortF("jfieldID %s not valid for an object of class %s",
386*795d594fSAndroid Build Coastguard Worker f->PrettyField().c_str(), o->PrettyTypeOf().c_str());
387*795d594fSAndroid Build Coastguard Worker return false;
388*795d594fSAndroid Build Coastguard Worker }
389*795d594fSAndroid Build Coastguard Worker return true;
390*795d594fSAndroid Build Coastguard Worker }
391*795d594fSAndroid Build Coastguard Worker
392*795d594fSAndroid Build Coastguard Worker /*
393*795d594fSAndroid Build Coastguard Worker * Verify that the pointer value is non-null.
394*795d594fSAndroid Build Coastguard Worker */
CheckNonNull(const void * ptr)395*795d594fSAndroid Build Coastguard Worker bool CheckNonNull(const void* ptr) {
396*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(ptr == nullptr)) {
397*795d594fSAndroid Build Coastguard Worker AbortF("non-nullable argument was NULL");
398*795d594fSAndroid Build Coastguard Worker return false;
399*795d594fSAndroid Build Coastguard Worker }
400*795d594fSAndroid Build Coastguard Worker return true;
401*795d594fSAndroid Build Coastguard Worker }
402*795d594fSAndroid Build Coastguard Worker
403*795d594fSAndroid Build Coastguard Worker /*
404*795d594fSAndroid Build Coastguard Worker * Verify that the method's return type matches the type of call.
405*795d594fSAndroid Build Coastguard Worker * 'expectedType' will be "L" for all objects, including arrays.
406*795d594fSAndroid Build Coastguard Worker */
CheckMethodAndSig(ScopedObjectAccess & soa,jobject jobj,jclass jc,jmethodID mid,Primitive::Type type,InvokeType invoke)407*795d594fSAndroid Build Coastguard Worker bool CheckMethodAndSig(ScopedObjectAccess& soa, jobject jobj, jclass jc,
408*795d594fSAndroid Build Coastguard Worker jmethodID mid, Primitive::Type type, InvokeType invoke)
409*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
410*795d594fSAndroid Build Coastguard Worker ArtMethod* m = CheckMethodID(mid);
411*795d594fSAndroid Build Coastguard Worker if (m == nullptr) {
412*795d594fSAndroid Build Coastguard Worker return false;
413*795d594fSAndroid Build Coastguard Worker }
414*795d594fSAndroid Build Coastguard Worker if (type != Primitive::GetType(m->GetShorty()[0])) {
415*795d594fSAndroid Build Coastguard Worker AbortF("the return type of %s does not match %s", function_name_, m->PrettyMethod().c_str());
416*795d594fSAndroid Build Coastguard Worker return false;
417*795d594fSAndroid Build Coastguard Worker }
418*795d594fSAndroid Build Coastguard Worker bool is_static = (invoke == kStatic);
419*795d594fSAndroid Build Coastguard Worker if (is_static != m->IsStatic()) {
420*795d594fSAndroid Build Coastguard Worker if (is_static) {
421*795d594fSAndroid Build Coastguard Worker AbortF("calling non-static method %s with %s",
422*795d594fSAndroid Build Coastguard Worker m->PrettyMethod().c_str(), function_name_);
423*795d594fSAndroid Build Coastguard Worker } else {
424*795d594fSAndroid Build Coastguard Worker AbortF("calling static method %s with %s",
425*795d594fSAndroid Build Coastguard Worker m->PrettyMethod().c_str(), function_name_);
426*795d594fSAndroid Build Coastguard Worker }
427*795d594fSAndroid Build Coastguard Worker return false;
428*795d594fSAndroid Build Coastguard Worker }
429*795d594fSAndroid Build Coastguard Worker if (invoke != kVirtual) {
430*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
431*795d594fSAndroid Build Coastguard Worker if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
432*795d594fSAndroid Build Coastguard Worker AbortF("can't call %s %s with class %s", invoke == kStatic ? "static" : "nonvirtual",
433*795d594fSAndroid Build Coastguard Worker m->PrettyMethod().c_str(), mirror::Class::PrettyClass(c).c_str());
434*795d594fSAndroid Build Coastguard Worker return false;
435*795d594fSAndroid Build Coastguard Worker }
436*795d594fSAndroid Build Coastguard Worker }
437*795d594fSAndroid Build Coastguard Worker if (invoke != kStatic) {
438*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(jobj);
439*795d594fSAndroid Build Coastguard Worker if (o == nullptr) {
440*795d594fSAndroid Build Coastguard Worker AbortF("can't call %s on null object", m->PrettyMethod().c_str());
441*795d594fSAndroid Build Coastguard Worker return false;
442*795d594fSAndroid Build Coastguard Worker } else if (!o->InstanceOf(m->GetDeclaringClass())) {
443*795d594fSAndroid Build Coastguard Worker AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
444*795d594fSAndroid Build Coastguard Worker o->PrettyTypeOf().c_str());
445*795d594fSAndroid Build Coastguard Worker return false;
446*795d594fSAndroid Build Coastguard Worker }
447*795d594fSAndroid Build Coastguard Worker }
448*795d594fSAndroid Build Coastguard Worker return true;
449*795d594fSAndroid Build Coastguard Worker }
450*795d594fSAndroid Build Coastguard Worker
451*795d594fSAndroid Build Coastguard Worker /*
452*795d594fSAndroid Build Coastguard Worker * Verify that this static field ID is valid for this class.
453*795d594fSAndroid Build Coastguard Worker *
454*795d594fSAndroid Build Coastguard Worker * Assumes "java_class" has already been validated.
455*795d594fSAndroid Build Coastguard Worker */
CheckStaticFieldID(ScopedObjectAccess & soa,jclass java_class,jfieldID fid)456*795d594fSAndroid Build Coastguard Worker bool CheckStaticFieldID(ScopedObjectAccess& soa, jclass java_class, jfieldID fid)
457*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
458*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
459*795d594fSAndroid Build Coastguard Worker ArtField* f = CheckFieldID(fid);
460*795d594fSAndroid Build Coastguard Worker if (f == nullptr) {
461*795d594fSAndroid Build Coastguard Worker return false;
462*795d594fSAndroid Build Coastguard Worker }
463*795d594fSAndroid Build Coastguard Worker if (!f->GetDeclaringClass()->IsAssignableFrom(c)) {
464*795d594fSAndroid Build Coastguard Worker AbortF("static jfieldID %p not valid for class %s", fid,
465*795d594fSAndroid Build Coastguard Worker mirror::Class::PrettyClass(c).c_str());
466*795d594fSAndroid Build Coastguard Worker return false;
467*795d594fSAndroid Build Coastguard Worker }
468*795d594fSAndroid Build Coastguard Worker return true;
469*795d594fSAndroid Build Coastguard Worker }
470*795d594fSAndroid Build Coastguard Worker
471*795d594fSAndroid Build Coastguard Worker /*
472*795d594fSAndroid Build Coastguard Worker * Verify that "mid" is appropriate for "java_class".
473*795d594fSAndroid Build Coastguard Worker *
474*795d594fSAndroid Build Coastguard Worker * A mismatch isn't dangerous, because the jmethodID defines the class. In
475*795d594fSAndroid Build Coastguard Worker * fact, java_class is unused in the implementation. It's best if we don't
476*795d594fSAndroid Build Coastguard Worker * allow bad code in the system though.
477*795d594fSAndroid Build Coastguard Worker *
478*795d594fSAndroid Build Coastguard Worker * Instances of "java_class" must be instances of the method's declaring class.
479*795d594fSAndroid Build Coastguard Worker */
CheckStaticMethod(ScopedObjectAccess & soa,jclass java_class,jmethodID mid)480*795d594fSAndroid Build Coastguard Worker bool CheckStaticMethod(ScopedObjectAccess& soa, jclass java_class, jmethodID mid)
481*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
482*795d594fSAndroid Build Coastguard Worker ArtMethod* m = CheckMethodID(mid);
483*795d594fSAndroid Build Coastguard Worker if (m == nullptr) {
484*795d594fSAndroid Build Coastguard Worker return false;
485*795d594fSAndroid Build Coastguard Worker }
486*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(java_class);
487*795d594fSAndroid Build Coastguard Worker if (!m->GetDeclaringClass()->IsAssignableFrom(c)) {
488*795d594fSAndroid Build Coastguard Worker AbortF("can't call static %s on class %s", m->PrettyMethod().c_str(),
489*795d594fSAndroid Build Coastguard Worker mirror::Class::PrettyClass(c).c_str());
490*795d594fSAndroid Build Coastguard Worker return false;
491*795d594fSAndroid Build Coastguard Worker }
492*795d594fSAndroid Build Coastguard Worker return true;
493*795d594fSAndroid Build Coastguard Worker }
494*795d594fSAndroid Build Coastguard Worker
495*795d594fSAndroid Build Coastguard Worker /*
496*795d594fSAndroid Build Coastguard Worker * Verify that "mid" is appropriate for "jobj".
497*795d594fSAndroid Build Coastguard Worker *
498*795d594fSAndroid Build Coastguard Worker * Make sure the object is an instance of the method's declaring class.
499*795d594fSAndroid Build Coastguard Worker * (Note the mid might point to a declaration in an interface; this
500*795d594fSAndroid Build Coastguard Worker * will be handled automatically by the instanceof check.)
501*795d594fSAndroid Build Coastguard Worker */
CheckVirtualMethod(ScopedObjectAccess & soa,jobject java_object,jmethodID mid)502*795d594fSAndroid Build Coastguard Worker bool CheckVirtualMethod(ScopedObjectAccess& soa, jobject java_object, jmethodID mid)
503*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
504*795d594fSAndroid Build Coastguard Worker ArtMethod* m = CheckMethodID(mid);
505*795d594fSAndroid Build Coastguard Worker if (m == nullptr) {
506*795d594fSAndroid Build Coastguard Worker return false;
507*795d594fSAndroid Build Coastguard Worker }
508*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object);
509*795d594fSAndroid Build Coastguard Worker if (o == nullptr) {
510*795d594fSAndroid Build Coastguard Worker AbortF("can't call %s on null object", m->PrettyMethod().c_str());
511*795d594fSAndroid Build Coastguard Worker return false;
512*795d594fSAndroid Build Coastguard Worker } else if (!o->InstanceOf(m->GetDeclaringClass())) {
513*795d594fSAndroid Build Coastguard Worker AbortF("can't call %s on instance of %s", m->PrettyMethod().c_str(),
514*795d594fSAndroid Build Coastguard Worker o->PrettyTypeOf().c_str());
515*795d594fSAndroid Build Coastguard Worker return false;
516*795d594fSAndroid Build Coastguard Worker }
517*795d594fSAndroid Build Coastguard Worker return true;
518*795d594fSAndroid Build Coastguard Worker }
519*795d594fSAndroid Build Coastguard Worker
520*795d594fSAndroid Build Coastguard Worker /**
521*795d594fSAndroid Build Coastguard Worker * The format string is a sequence of the following characters,
522*795d594fSAndroid Build Coastguard Worker * and must be followed by arguments of the corresponding types
523*795d594fSAndroid Build Coastguard Worker * in the same order.
524*795d594fSAndroid Build Coastguard Worker *
525*795d594fSAndroid Build Coastguard Worker * Java primitive types:
526*795d594fSAndroid Build Coastguard Worker * B - jbyte
527*795d594fSAndroid Build Coastguard Worker * C - jchar
528*795d594fSAndroid Build Coastguard Worker * D - jdouble
529*795d594fSAndroid Build Coastguard Worker * F - jfloat
530*795d594fSAndroid Build Coastguard Worker * I - jint
531*795d594fSAndroid Build Coastguard Worker * J - jlong
532*795d594fSAndroid Build Coastguard Worker * S - jshort
533*795d594fSAndroid Build Coastguard Worker * Z - jboolean (shown as true and false)
534*795d594fSAndroid Build Coastguard Worker * V - void
535*795d594fSAndroid Build Coastguard Worker *
536*795d594fSAndroid Build Coastguard Worker * Java reference types:
537*795d594fSAndroid Build Coastguard Worker * L - jobject
538*795d594fSAndroid Build Coastguard Worker * a - jarray
539*795d594fSAndroid Build Coastguard Worker * c - jclass
540*795d594fSAndroid Build Coastguard Worker * s - jstring
541*795d594fSAndroid Build Coastguard Worker *
542*795d594fSAndroid Build Coastguard Worker * JNI types:
543*795d594fSAndroid Build Coastguard Worker * b - jboolean (shown as JNI_TRUE and JNI_FALSE)
544*795d594fSAndroid Build Coastguard Worker * f - jfieldID
545*795d594fSAndroid Build Coastguard Worker * m - jmethodID
546*795d594fSAndroid Build Coastguard Worker * p - void*
547*795d594fSAndroid Build Coastguard Worker * r - jint (for release mode arguments)
548*795d594fSAndroid Build Coastguard Worker * u - const char* (Modified UTF-8)
549*795d594fSAndroid Build Coastguard Worker * z - jsize (for lengths; use i if negative values are okay)
550*795d594fSAndroid Build Coastguard Worker * v - JavaVM*
551*795d594fSAndroid Build Coastguard Worker * E - JNIEnv*
552*795d594fSAndroid Build Coastguard Worker * . - VarArgs* for Jni calls with variable length arguments
553*795d594fSAndroid Build Coastguard Worker *
554*795d594fSAndroid Build Coastguard Worker * Use the kFlag_NullableUtf flag where 'u' field(s) are nullable.
555*795d594fSAndroid Build Coastguard Worker */
Check(ScopedObjectAccess & soa,bool entry,const char * fmt,JniValueType * args)556*795d594fSAndroid Build Coastguard Worker bool Check(ScopedObjectAccess& soa, bool entry, const char* fmt, JniValueType* args)
557*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
558*795d594fSAndroid Build Coastguard Worker ArtMethod* traceMethod = nullptr;
559*795d594fSAndroid Build Coastguard Worker if (has_method_ && soa.Vm()->IsTracingEnabled()) {
560*795d594fSAndroid Build Coastguard Worker // We need to guard some of the invocation interface's calls: a bad caller might
561*795d594fSAndroid Build Coastguard Worker // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
562*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
563*795d594fSAndroid Build Coastguard Worker if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
564*795d594fSAndroid Build Coastguard Worker traceMethod = self->GetCurrentMethod(nullptr);
565*795d594fSAndroid Build Coastguard Worker }
566*795d594fSAndroid Build Coastguard Worker }
567*795d594fSAndroid Build Coastguard Worker
568*795d594fSAndroid Build Coastguard Worker if (((flags_ & kFlag_ForceTrace) != 0) ||
569*795d594fSAndroid Build Coastguard Worker (traceMethod != nullptr && soa.Vm()->ShouldTrace(traceMethod))) {
570*795d594fSAndroid Build Coastguard Worker std::string msg;
571*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; fmt[i] != '\0'; ++i) {
572*795d594fSAndroid Build Coastguard Worker TracePossibleHeapValue(soa, entry, fmt[i], args[i], &msg);
573*795d594fSAndroid Build Coastguard Worker if (fmt[i + 1] != '\0') {
574*795d594fSAndroid Build Coastguard Worker StringAppendF(&msg, ", ");
575*795d594fSAndroid Build Coastguard Worker }
576*795d594fSAndroid Build Coastguard Worker }
577*795d594fSAndroid Build Coastguard Worker
578*795d594fSAndroid Build Coastguard Worker if ((flags_ & kFlag_ForceTrace) != 0) {
579*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
580*795d594fSAndroid Build Coastguard Worker } else if (entry) {
581*795d594fSAndroid Build Coastguard Worker if (has_method_) {
582*795d594fSAndroid Build Coastguard Worker std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
583*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
584*795d594fSAndroid Build Coastguard Worker indent_ = methodName.size() + 1;
585*795d594fSAndroid Build Coastguard Worker } else {
586*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
587*795d594fSAndroid Build Coastguard Worker indent_ = 0;
588*795d594fSAndroid Build Coastguard Worker }
589*795d594fSAndroid Build Coastguard Worker } else {
590*795d594fSAndroid Build Coastguard Worker LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
591*795d594fSAndroid Build Coastguard Worker }
592*795d594fSAndroid Build Coastguard Worker }
593*795d594fSAndroid Build Coastguard Worker
594*795d594fSAndroid Build Coastguard Worker // We always do the thorough checks on entry, and never on exit...
595*795d594fSAndroid Build Coastguard Worker if (entry) {
596*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; fmt[i] != '\0'; ++i) {
597*795d594fSAndroid Build Coastguard Worker if (!CheckPossibleHeapValue(soa, fmt[i], args[i])) {
598*795d594fSAndroid Build Coastguard Worker return false;
599*795d594fSAndroid Build Coastguard Worker }
600*795d594fSAndroid Build Coastguard Worker }
601*795d594fSAndroid Build Coastguard Worker }
602*795d594fSAndroid Build Coastguard Worker return true;
603*795d594fSAndroid Build Coastguard Worker }
604*795d594fSAndroid Build Coastguard Worker
CheckNonHeap(JavaVMExt * vm,bool entry,const char * fmt,JniValueType * args)605*795d594fSAndroid Build Coastguard Worker bool CheckNonHeap(JavaVMExt* vm, bool entry, const char* fmt, JniValueType* args) {
606*795d594fSAndroid Build Coastguard Worker bool should_trace = (flags_ & kFlag_ForceTrace) != 0;
607*795d594fSAndroid Build Coastguard Worker if (!should_trace && vm != nullptr && vm->IsTracingEnabled()) {
608*795d594fSAndroid Build Coastguard Worker // We need to guard some of the invocation interface's calls: a bad caller might
609*795d594fSAndroid Build Coastguard Worker // use DetachCurrentThread or GetEnv on a thread that's not yet attached.
610*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
611*795d594fSAndroid Build Coastguard Worker if ((flags_ & kFlag_Invocation) == 0 || self != nullptr) {
612*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
613*795d594fSAndroid Build Coastguard Worker ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
614*795d594fSAndroid Build Coastguard Worker should_trace = (traceMethod != nullptr && vm->ShouldTrace(traceMethod));
615*795d594fSAndroid Build Coastguard Worker }
616*795d594fSAndroid Build Coastguard Worker }
617*795d594fSAndroid Build Coastguard Worker if (should_trace) {
618*795d594fSAndroid Build Coastguard Worker std::string msg;
619*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; fmt[i] != '\0'; ++i) {
620*795d594fSAndroid Build Coastguard Worker TraceNonHeapValue(fmt[i], args[i], &msg);
621*795d594fSAndroid Build Coastguard Worker if (fmt[i + 1] != '\0') {
622*795d594fSAndroid Build Coastguard Worker StringAppendF(&msg, ", ");
623*795d594fSAndroid Build Coastguard Worker }
624*795d594fSAndroid Build Coastguard Worker }
625*795d594fSAndroid Build Coastguard Worker
626*795d594fSAndroid Build Coastguard Worker if ((flags_ & kFlag_ForceTrace) != 0) {
627*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JNI: call to " << function_name_ << "(" << msg << ")";
628*795d594fSAndroid Build Coastguard Worker } else if (entry) {
629*795d594fSAndroid Build Coastguard Worker if (has_method_) {
630*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
631*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
632*795d594fSAndroid Build Coastguard Worker ArtMethod* traceMethod = self->GetCurrentMethod(nullptr);
633*795d594fSAndroid Build Coastguard Worker std::string methodName(ArtMethod::PrettyMethod(traceMethod, false));
634*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JNI: " << methodName << " -> " << function_name_ << "(" << msg << ")";
635*795d594fSAndroid Build Coastguard Worker indent_ = methodName.size() + 1;
636*795d594fSAndroid Build Coastguard Worker } else {
637*795d594fSAndroid Build Coastguard Worker LOG(INFO) << "JNI: -> " << function_name_ << "(" << msg << ")";
638*795d594fSAndroid Build Coastguard Worker indent_ = 0;
639*795d594fSAndroid Build Coastguard Worker }
640*795d594fSAndroid Build Coastguard Worker } else {
641*795d594fSAndroid Build Coastguard Worker LOG(INFO) << StringPrintf("JNI: %*s<- %s returned %s", indent_, "", function_name_, msg.c_str());
642*795d594fSAndroid Build Coastguard Worker }
643*795d594fSAndroid Build Coastguard Worker }
644*795d594fSAndroid Build Coastguard Worker
645*795d594fSAndroid Build Coastguard Worker // We always do the thorough checks on entry, and never on exit...
646*795d594fSAndroid Build Coastguard Worker if (entry) {
647*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; fmt[i] != '\0'; ++i) {
648*795d594fSAndroid Build Coastguard Worker if (!CheckNonHeapValue(fmt[i], args[i])) {
649*795d594fSAndroid Build Coastguard Worker return false;
650*795d594fSAndroid Build Coastguard Worker }
651*795d594fSAndroid Build Coastguard Worker }
652*795d594fSAndroid Build Coastguard Worker }
653*795d594fSAndroid Build Coastguard Worker return true;
654*795d594fSAndroid Build Coastguard Worker }
655*795d594fSAndroid Build Coastguard Worker
CheckReflectedMethod(ScopedObjectAccess & soa,jobject jmethod)656*795d594fSAndroid Build Coastguard Worker bool CheckReflectedMethod(ScopedObjectAccess& soa, jobject jmethod)
657*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
658*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> method = soa.Decode<mirror::Object>(jmethod);
659*795d594fSAndroid Build Coastguard Worker if (method == nullptr) {
660*795d594fSAndroid Build Coastguard Worker AbortF("expected non-null method");
661*795d594fSAndroid Build Coastguard Worker return false;
662*795d594fSAndroid Build Coastguard Worker }
663*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
664*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetClassLinker()->GetClassRoots();
665*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = method->GetClass();
666*795d594fSAndroid Build Coastguard Worker if (c != GetClassRoot<mirror::Method>(class_roots) &&
667*795d594fSAndroid Build Coastguard Worker c != GetClassRoot<mirror::Constructor>(class_roots)) {
668*795d594fSAndroid Build Coastguard Worker AbortF("expected java.lang.reflect.Method or "
669*795d594fSAndroid Build Coastguard Worker "java.lang.reflect.Constructor but got object of type %s: %p",
670*795d594fSAndroid Build Coastguard Worker method->PrettyTypeOf().c_str(), jmethod);
671*795d594fSAndroid Build Coastguard Worker return false;
672*795d594fSAndroid Build Coastguard Worker }
673*795d594fSAndroid Build Coastguard Worker return true;
674*795d594fSAndroid Build Coastguard Worker }
675*795d594fSAndroid Build Coastguard Worker
CheckConstructor(jmethodID mid)676*795d594fSAndroid Build Coastguard Worker bool CheckConstructor(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
677*795d594fSAndroid Build Coastguard Worker ArtMethod* method = jni::DecodeArtMethod(mid);
678*795d594fSAndroid Build Coastguard Worker if (method == nullptr) {
679*795d594fSAndroid Build Coastguard Worker AbortF("expected non-null constructor");
680*795d594fSAndroid Build Coastguard Worker return false;
681*795d594fSAndroid Build Coastguard Worker }
682*795d594fSAndroid Build Coastguard Worker if (!method->IsConstructor() || method->IsStatic()) {
683*795d594fSAndroid Build Coastguard Worker AbortF("expected a constructor but %s: %p", method->PrettyMethod().c_str(), mid);
684*795d594fSAndroid Build Coastguard Worker return false;
685*795d594fSAndroid Build Coastguard Worker }
686*795d594fSAndroid Build Coastguard Worker return true;
687*795d594fSAndroid Build Coastguard Worker }
688*795d594fSAndroid Build Coastguard Worker
CheckReflectedField(ScopedObjectAccess & soa,jobject jfield)689*795d594fSAndroid Build Coastguard Worker bool CheckReflectedField(ScopedObjectAccess& soa, jobject jfield)
690*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
691*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> field = soa.Decode<mirror::Object>(jfield);
692*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
693*795d594fSAndroid Build Coastguard Worker AbortF("expected non-null java.lang.reflect.Field");
694*795d594fSAndroid Build Coastguard Worker return false;
695*795d594fSAndroid Build Coastguard Worker }
696*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = field->GetClass();
697*795d594fSAndroid Build Coastguard Worker if (GetClassRoot<mirror::Field>() != c) {
698*795d594fSAndroid Build Coastguard Worker AbortF("expected java.lang.reflect.Field but got object of type %s: %p",
699*795d594fSAndroid Build Coastguard Worker field->PrettyTypeOf().c_str(), jfield);
700*795d594fSAndroid Build Coastguard Worker return false;
701*795d594fSAndroid Build Coastguard Worker }
702*795d594fSAndroid Build Coastguard Worker return true;
703*795d594fSAndroid Build Coastguard Worker }
704*795d594fSAndroid Build Coastguard Worker
CheckThrowable(ScopedObjectAccess & soa,jthrowable jobj)705*795d594fSAndroid Build Coastguard Worker bool CheckThrowable(ScopedObjectAccess& soa, jthrowable jobj)
706*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
707*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(jobj);
708*795d594fSAndroid Build Coastguard Worker if (!obj->GetClass()->IsThrowableClass()) {
709*795d594fSAndroid Build Coastguard Worker AbortF("expected java.lang.Throwable but got object of type "
710*795d594fSAndroid Build Coastguard Worker "%s: %p", obj->PrettyTypeOf().c_str(), obj.Ptr());
711*795d594fSAndroid Build Coastguard Worker return false;
712*795d594fSAndroid Build Coastguard Worker }
713*795d594fSAndroid Build Coastguard Worker return true;
714*795d594fSAndroid Build Coastguard Worker }
715*795d594fSAndroid Build Coastguard Worker
CheckThrowableClass(ScopedObjectAccess & soa,jclass jc)716*795d594fSAndroid Build Coastguard Worker bool CheckThrowableClass(ScopedObjectAccess& soa, jclass jc)
717*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
718*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
719*795d594fSAndroid Build Coastguard Worker if (!c->IsThrowableClass()) {
720*795d594fSAndroid Build Coastguard Worker AbortF("expected java.lang.Throwable class but got object of "
721*795d594fSAndroid Build Coastguard Worker "type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
722*795d594fSAndroid Build Coastguard Worker return false;
723*795d594fSAndroid Build Coastguard Worker }
724*795d594fSAndroid Build Coastguard Worker return true;
725*795d594fSAndroid Build Coastguard Worker }
726*795d594fSAndroid Build Coastguard Worker
CheckReferenceKind(IndirectRefKind expected_kind,Thread * self,jobject obj)727*795d594fSAndroid Build Coastguard Worker bool CheckReferenceKind(IndirectRefKind expected_kind, Thread* self, jobject obj)
728*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
729*795d594fSAndroid Build Coastguard Worker IndirectRefKind found_kind;
730*795d594fSAndroid Build Coastguard Worker if (expected_kind == kLocal) {
731*795d594fSAndroid Build Coastguard Worker found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
732*795d594fSAndroid Build Coastguard Worker if (found_kind == kJniTransition &&
733*795d594fSAndroid Build Coastguard Worker obj != nullptr &&
734*795d594fSAndroid Build Coastguard Worker self->IsJniTransitionReference(obj)) {
735*795d594fSAndroid Build Coastguard Worker found_kind = kLocal;
736*795d594fSAndroid Build Coastguard Worker }
737*795d594fSAndroid Build Coastguard Worker } else {
738*795d594fSAndroid Build Coastguard Worker found_kind = IndirectReferenceTable::GetIndirectRefKind(obj);
739*795d594fSAndroid Build Coastguard Worker }
740*795d594fSAndroid Build Coastguard Worker if (obj != nullptr && found_kind != expected_kind) {
741*795d594fSAndroid Build Coastguard Worker AbortF("expected reference of kind %s but found %s: %p",
742*795d594fSAndroid Build Coastguard Worker GetIndirectRefKindString(expected_kind),
743*795d594fSAndroid Build Coastguard Worker GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(obj)),
744*795d594fSAndroid Build Coastguard Worker obj);
745*795d594fSAndroid Build Coastguard Worker return false;
746*795d594fSAndroid Build Coastguard Worker }
747*795d594fSAndroid Build Coastguard Worker return true;
748*795d594fSAndroid Build Coastguard Worker }
749*795d594fSAndroid Build Coastguard Worker
CheckInstantiableNonArray(ScopedObjectAccess & soa,jclass jc)750*795d594fSAndroid Build Coastguard Worker bool CheckInstantiableNonArray(ScopedObjectAccess& soa, jclass jc)
751*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
752*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
753*795d594fSAndroid Build Coastguard Worker if (!c->IsInstantiableNonArray()) {
754*795d594fSAndroid Build Coastguard Worker AbortF("can't make objects of type %s: %p", c->PrettyDescriptor().c_str(), c.Ptr());
755*795d594fSAndroid Build Coastguard Worker return false;
756*795d594fSAndroid Build Coastguard Worker }
757*795d594fSAndroid Build Coastguard Worker return true;
758*795d594fSAndroid Build Coastguard Worker }
759*795d594fSAndroid Build Coastguard Worker
CheckPrimitiveArrayType(ScopedObjectAccess & soa,jarray array,Primitive::Type type)760*795d594fSAndroid Build Coastguard Worker bool CheckPrimitiveArrayType(ScopedObjectAccess& soa, jarray array, Primitive::Type type)
761*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
762*795d594fSAndroid Build Coastguard Worker if (!CheckArray(soa, array)) {
763*795d594fSAndroid Build Coastguard Worker return false;
764*795d594fSAndroid Build Coastguard Worker }
765*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(array);
766*795d594fSAndroid Build Coastguard Worker if (a->GetClass()->GetComponentType()->GetPrimitiveType() != type) {
767*795d594fSAndroid Build Coastguard Worker AbortF("incompatible array type %s expected %s[]: %p",
768*795d594fSAndroid Build Coastguard Worker a->GetClass()->PrettyDescriptor().c_str(), PrettyDescriptor(type).c_str(), array);
769*795d594fSAndroid Build Coastguard Worker return false;
770*795d594fSAndroid Build Coastguard Worker }
771*795d594fSAndroid Build Coastguard Worker return true;
772*795d594fSAndroid Build Coastguard Worker }
773*795d594fSAndroid Build Coastguard Worker
CheckFieldAccess(ScopedObjectAccess & soa,jobject obj,jfieldID fid,bool is_static,Primitive::Type type)774*795d594fSAndroid Build Coastguard Worker bool CheckFieldAccess(ScopedObjectAccess& soa, jobject obj, jfieldID fid, bool is_static,
775*795d594fSAndroid Build Coastguard Worker Primitive::Type type)
776*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
777*795d594fSAndroid Build Coastguard Worker if (is_static && !CheckStaticFieldID(soa, down_cast<jclass>(obj), fid)) {
778*795d594fSAndroid Build Coastguard Worker return false;
779*795d594fSAndroid Build Coastguard Worker }
780*795d594fSAndroid Build Coastguard Worker if (!is_static && !CheckInstanceFieldID(soa, obj, fid)) {
781*795d594fSAndroid Build Coastguard Worker return false;
782*795d594fSAndroid Build Coastguard Worker }
783*795d594fSAndroid Build Coastguard Worker ArtField* field = jni::DecodeArtField(fid);
784*795d594fSAndroid Build Coastguard Worker DCHECK(field != nullptr); // Already checked by Check.
785*795d594fSAndroid Build Coastguard Worker if (is_static != field->IsStatic()) {
786*795d594fSAndroid Build Coastguard Worker AbortF("attempt to access %s field %s: %p",
787*795d594fSAndroid Build Coastguard Worker field->IsStatic() ? "static" : "non-static", field->PrettyField().c_str(), fid);
788*795d594fSAndroid Build Coastguard Worker return false;
789*795d594fSAndroid Build Coastguard Worker }
790*795d594fSAndroid Build Coastguard Worker if (type != field->GetTypeAsPrimitiveType()) {
791*795d594fSAndroid Build Coastguard Worker AbortF("attempt to access field %s of type %s with the wrong type %s: %p",
792*795d594fSAndroid Build Coastguard Worker field->PrettyField().c_str(),
793*795d594fSAndroid Build Coastguard Worker PrettyDescriptor(field->GetTypeDescriptor()).c_str(),
794*795d594fSAndroid Build Coastguard Worker PrettyDescriptor(type).c_str(), fid);
795*795d594fSAndroid Build Coastguard Worker return false;
796*795d594fSAndroid Build Coastguard Worker }
797*795d594fSAndroid Build Coastguard Worker if (is_static) {
798*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
799*795d594fSAndroid Build Coastguard Worker if (o == nullptr || !o->IsClass()) {
800*795d594fSAndroid Build Coastguard Worker AbortF("attempt to access static field %s with a class argument of type %s: %p",
801*795d594fSAndroid Build Coastguard Worker field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
802*795d594fSAndroid Build Coastguard Worker return false;
803*795d594fSAndroid Build Coastguard Worker }
804*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = o->AsClass();
805*795d594fSAndroid Build Coastguard Worker if (!field->GetDeclaringClass()->IsAssignableFrom(c)) {
806*795d594fSAndroid Build Coastguard Worker AbortF("attempt to access static field %s with an incompatible class argument of %s: %p",
807*795d594fSAndroid Build Coastguard Worker field->PrettyField().c_str(), mirror::Class::PrettyDescriptor(c).c_str(), fid);
808*795d594fSAndroid Build Coastguard Worker return false;
809*795d594fSAndroid Build Coastguard Worker }
810*795d594fSAndroid Build Coastguard Worker } else {
811*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj);
812*795d594fSAndroid Build Coastguard Worker if (o == nullptr || !field->GetDeclaringClass()->IsAssignableFrom(o->GetClass())) {
813*795d594fSAndroid Build Coastguard Worker AbortF("attempt to access field %s from an object argument of type %s: %p",
814*795d594fSAndroid Build Coastguard Worker field->PrettyField().c_str(), o->PrettyTypeOf().c_str(), fid);
815*795d594fSAndroid Build Coastguard Worker return false;
816*795d594fSAndroid Build Coastguard Worker }
817*795d594fSAndroid Build Coastguard Worker }
818*795d594fSAndroid Build Coastguard Worker return true;
819*795d594fSAndroid Build Coastguard Worker }
820*795d594fSAndroid Build Coastguard Worker
821*795d594fSAndroid Build Coastguard Worker private:
822*795d594fSAndroid Build Coastguard Worker enum InstanceKind {
823*795d594fSAndroid Build Coastguard Worker kClass,
824*795d594fSAndroid Build Coastguard Worker kDirectByteBuffer,
825*795d594fSAndroid Build Coastguard Worker kObject,
826*795d594fSAndroid Build Coastguard Worker kString,
827*795d594fSAndroid Build Coastguard Worker kThrowable,
828*795d594fSAndroid Build Coastguard Worker };
829*795d594fSAndroid Build Coastguard Worker
830*795d594fSAndroid Build Coastguard Worker /*
831*795d594fSAndroid Build Coastguard Worker * Verify that "jobj" is a valid non-null object reference, and points to
832*795d594fSAndroid Build Coastguard Worker * an instance of expectedClass.
833*795d594fSAndroid Build Coastguard Worker *
834*795d594fSAndroid Build Coastguard Worker * Because we're looking at an object on the GC heap, we have to switch
835*795d594fSAndroid Build Coastguard Worker * to "running" mode before doing the checks.
836*795d594fSAndroid Build Coastguard Worker */
CheckInstance(ScopedObjectAccess & soa,InstanceKind kind,jobject java_object,bool null_ok)837*795d594fSAndroid Build Coastguard Worker bool CheckInstance(ScopedObjectAccess& soa, InstanceKind kind, jobject java_object, bool null_ok)
838*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
839*795d594fSAndroid Build Coastguard Worker const char* what = nullptr;
840*795d594fSAndroid Build Coastguard Worker switch (kind) {
841*795d594fSAndroid Build Coastguard Worker case kClass:
842*795d594fSAndroid Build Coastguard Worker what = "jclass";
843*795d594fSAndroid Build Coastguard Worker break;
844*795d594fSAndroid Build Coastguard Worker case kDirectByteBuffer:
845*795d594fSAndroid Build Coastguard Worker what = "direct ByteBuffer";
846*795d594fSAndroid Build Coastguard Worker break;
847*795d594fSAndroid Build Coastguard Worker case kObject:
848*795d594fSAndroid Build Coastguard Worker what = "jobject";
849*795d594fSAndroid Build Coastguard Worker break;
850*795d594fSAndroid Build Coastguard Worker case kString:
851*795d594fSAndroid Build Coastguard Worker what = "jstring";
852*795d594fSAndroid Build Coastguard Worker break;
853*795d594fSAndroid Build Coastguard Worker case kThrowable:
854*795d594fSAndroid Build Coastguard Worker what = "jthrowable";
855*795d594fSAndroid Build Coastguard Worker break;
856*795d594fSAndroid Build Coastguard Worker }
857*795d594fSAndroid Build Coastguard Worker
858*795d594fSAndroid Build Coastguard Worker if (java_object == nullptr) {
859*795d594fSAndroid Build Coastguard Worker if (null_ok) {
860*795d594fSAndroid Build Coastguard Worker return true;
861*795d594fSAndroid Build Coastguard Worker } else {
862*795d594fSAndroid Build Coastguard Worker AbortF("%s received NULL %s", function_name_, what);
863*795d594fSAndroid Build Coastguard Worker return false;
864*795d594fSAndroid Build Coastguard Worker }
865*795d594fSAndroid Build Coastguard Worker }
866*795d594fSAndroid Build Coastguard Worker
867*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Object> obj = nullptr;
868*795d594fSAndroid Build Coastguard Worker IndirectRef ref = reinterpret_cast<IndirectRef>(java_object);
869*795d594fSAndroid Build Coastguard Worker IndirectRefKind ref_kind = IndirectReferenceTable::GetIndirectRefKind(ref);
870*795d594fSAndroid Build Coastguard Worker bool expect_null = false;
871*795d594fSAndroid Build Coastguard Worker bool okay = true;
872*795d594fSAndroid Build Coastguard Worker std::string error_msg;
873*795d594fSAndroid Build Coastguard Worker if (ref_kind == kJniTransition) {
874*795d594fSAndroid Build Coastguard Worker if (!soa.Self()->IsJniTransitionReference(java_object)) {
875*795d594fSAndroid Build Coastguard Worker okay = false;
876*795d594fSAndroid Build Coastguard Worker error_msg = "use of invalid jobject";
877*795d594fSAndroid Build Coastguard Worker } else {
878*795d594fSAndroid Build Coastguard Worker obj = soa.Decode<mirror::Object>(java_object);
879*795d594fSAndroid Build Coastguard Worker }
880*795d594fSAndroid Build Coastguard Worker } else if (ref_kind == kLocal) {
881*795d594fSAndroid Build Coastguard Worker jni::LocalReferenceTable* lrt = GetLocalReferenceTable(soa);
882*795d594fSAndroid Build Coastguard Worker okay = lrt->IsValidReference(java_object, &error_msg);
883*795d594fSAndroid Build Coastguard Worker if (okay) {
884*795d594fSAndroid Build Coastguard Worker obj = lrt->Get(ref);
885*795d594fSAndroid Build Coastguard Worker }
886*795d594fSAndroid Build Coastguard Worker } else {
887*795d594fSAndroid Build Coastguard Worker IndirectReferenceTable* irt = GetIndirectReferenceTable(soa, ref_kind);
888*795d594fSAndroid Build Coastguard Worker okay = irt->IsValidReference(java_object, &error_msg);
889*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(okay, error_msg.empty());
890*795d594fSAndroid Build Coastguard Worker if (okay) {
891*795d594fSAndroid Build Coastguard Worker // Note: The `IsValidReference()` checks for null but we do not prevent races,
892*795d594fSAndroid Build Coastguard Worker // so the null check below can still fail. Even if it succeeds, another thread
893*795d594fSAndroid Build Coastguard Worker // could delete the global or weak global before it's used by JNI.
894*795d594fSAndroid Build Coastguard Worker if (ref_kind == kGlobal) {
895*795d594fSAndroid Build Coastguard Worker obj = soa.Env()->GetVm()->DecodeGlobal(ref);
896*795d594fSAndroid Build Coastguard Worker } else {
897*795d594fSAndroid Build Coastguard Worker obj = soa.Env()->GetVm()->DecodeWeakGlobal(soa.Self(), ref);
898*795d594fSAndroid Build Coastguard Worker if (Runtime::Current()->IsClearedJniWeakGlobal(obj)) {
899*795d594fSAndroid Build Coastguard Worker obj = nullptr;
900*795d594fSAndroid Build Coastguard Worker expect_null = true;
901*795d594fSAndroid Build Coastguard Worker }
902*795d594fSAndroid Build Coastguard Worker }
903*795d594fSAndroid Build Coastguard Worker }
904*795d594fSAndroid Build Coastguard Worker }
905*795d594fSAndroid Build Coastguard Worker if (okay) {
906*795d594fSAndroid Build Coastguard Worker if (!expect_null && obj == nullptr) {
907*795d594fSAndroid Build Coastguard Worker okay = false;
908*795d594fSAndroid Build Coastguard Worker error_msg = "deleted reference";
909*795d594fSAndroid Build Coastguard Worker }
910*795d594fSAndroid Build Coastguard Worker if (expect_null && !null_ok) {
911*795d594fSAndroid Build Coastguard Worker okay = false;
912*795d594fSAndroid Build Coastguard Worker error_msg = "cleared weak reference";
913*795d594fSAndroid Build Coastguard Worker }
914*795d594fSAndroid Build Coastguard Worker }
915*795d594fSAndroid Build Coastguard Worker if (!okay) {
916*795d594fSAndroid Build Coastguard Worker AbortF("JNI ERROR (app bug): %s is an invalid %s: %p (%s)",
917*795d594fSAndroid Build Coastguard Worker what,
918*795d594fSAndroid Build Coastguard Worker ToStr<IndirectRefKind>(ref_kind).c_str(),
919*795d594fSAndroid Build Coastguard Worker java_object,
920*795d594fSAndroid Build Coastguard Worker error_msg.c_str());
921*795d594fSAndroid Build Coastguard Worker return false;
922*795d594fSAndroid Build Coastguard Worker }
923*795d594fSAndroid Build Coastguard Worker
924*795d594fSAndroid Build Coastguard Worker if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(obj.Ptr())) {
925*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
926*795d594fSAndroid Build Coastguard Worker AbortF("%s is an invalid %s: %p (%p)",
927*795d594fSAndroid Build Coastguard Worker what,
928*795d594fSAndroid Build Coastguard Worker GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_object)),
929*795d594fSAndroid Build Coastguard Worker java_object,
930*795d594fSAndroid Build Coastguard Worker obj.Ptr());
931*795d594fSAndroid Build Coastguard Worker return false;
932*795d594fSAndroid Build Coastguard Worker }
933*795d594fSAndroid Build Coastguard Worker
934*795d594fSAndroid Build Coastguard Worker switch (kind) {
935*795d594fSAndroid Build Coastguard Worker case kClass:
936*795d594fSAndroid Build Coastguard Worker okay = obj->IsClass();
937*795d594fSAndroid Build Coastguard Worker break;
938*795d594fSAndroid Build Coastguard Worker case kDirectByteBuffer:
939*795d594fSAndroid Build Coastguard Worker UNIMPLEMENTED(FATAL);
940*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
941*795d594fSAndroid Build Coastguard Worker case kString:
942*795d594fSAndroid Build Coastguard Worker okay = obj->GetClass()->IsStringClass();
943*795d594fSAndroid Build Coastguard Worker break;
944*795d594fSAndroid Build Coastguard Worker case kThrowable:
945*795d594fSAndroid Build Coastguard Worker okay = obj->GetClass()->IsThrowableClass();
946*795d594fSAndroid Build Coastguard Worker break;
947*795d594fSAndroid Build Coastguard Worker case kObject:
948*795d594fSAndroid Build Coastguard Worker break;
949*795d594fSAndroid Build Coastguard Worker }
950*795d594fSAndroid Build Coastguard Worker if (!okay) {
951*795d594fSAndroid Build Coastguard Worker AbortF("%s has wrong type: %s", what, mirror::Object::PrettyTypeOf(obj).c_str());
952*795d594fSAndroid Build Coastguard Worker return false;
953*795d594fSAndroid Build Coastguard Worker }
954*795d594fSAndroid Build Coastguard Worker
955*795d594fSAndroid Build Coastguard Worker return true;
956*795d594fSAndroid Build Coastguard Worker }
957*795d594fSAndroid Build Coastguard Worker
958*795d594fSAndroid Build Coastguard Worker /*
959*795d594fSAndroid Build Coastguard Worker * Verify that the "mode" argument passed to a primitive array Release
960*795d594fSAndroid Build Coastguard Worker * function is one of the valid values.
961*795d594fSAndroid Build Coastguard Worker */
CheckReleaseMode(jint mode)962*795d594fSAndroid Build Coastguard Worker bool CheckReleaseMode(jint mode) {
963*795d594fSAndroid Build Coastguard Worker if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
964*795d594fSAndroid Build Coastguard Worker AbortF("unknown value for release mode: %d", mode);
965*795d594fSAndroid Build Coastguard Worker return false;
966*795d594fSAndroid Build Coastguard Worker }
967*795d594fSAndroid Build Coastguard Worker return true;
968*795d594fSAndroid Build Coastguard Worker }
969*795d594fSAndroid Build Coastguard Worker
CheckPossibleHeapValue(ScopedObjectAccess & soa,char fmt,JniValueType arg)970*795d594fSAndroid Build Coastguard Worker bool CheckPossibleHeapValue(ScopedObjectAccess& soa, char fmt, JniValueType arg)
971*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
972*795d594fSAndroid Build Coastguard Worker switch (fmt) {
973*795d594fSAndroid Build Coastguard Worker case 'a': // jarray
974*795d594fSAndroid Build Coastguard Worker return CheckArray(soa, arg.a);
975*795d594fSAndroid Build Coastguard Worker case 'c': // jclass
976*795d594fSAndroid Build Coastguard Worker return CheckInstance(soa, kClass, arg.c, false);
977*795d594fSAndroid Build Coastguard Worker case 'f': // jfieldID
978*795d594fSAndroid Build Coastguard Worker return CheckFieldID(arg.f) != nullptr;
979*795d594fSAndroid Build Coastguard Worker case 'm': // jmethodID
980*795d594fSAndroid Build Coastguard Worker return CheckMethodID(arg.m) != nullptr;
981*795d594fSAndroid Build Coastguard Worker case 'r': // release int
982*795d594fSAndroid Build Coastguard Worker return CheckReleaseMode(arg.r);
983*795d594fSAndroid Build Coastguard Worker case 's': // jstring
984*795d594fSAndroid Build Coastguard Worker return CheckInstance(soa, kString, arg.s, false);
985*795d594fSAndroid Build Coastguard Worker case 't': // jthrowable
986*795d594fSAndroid Build Coastguard Worker return CheckInstance(soa, kThrowable, arg.t, false);
987*795d594fSAndroid Build Coastguard Worker case 'E': // JNIEnv*
988*795d594fSAndroid Build Coastguard Worker return CheckThread(arg.E);
989*795d594fSAndroid Build Coastguard Worker case 'L': // jobject
990*795d594fSAndroid Build Coastguard Worker return CheckInstance(soa, kObject, arg.L, true);
991*795d594fSAndroid Build Coastguard Worker case '.': // A VarArgs list
992*795d594fSAndroid Build Coastguard Worker return CheckVarArgs(soa, arg.va);
993*795d594fSAndroid Build Coastguard Worker default:
994*795d594fSAndroid Build Coastguard Worker return CheckNonHeapValue(fmt, arg);
995*795d594fSAndroid Build Coastguard Worker }
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker
CheckVarArgs(ScopedObjectAccess & soa,const VarArgs * args_p)998*795d594fSAndroid Build Coastguard Worker bool CheckVarArgs(ScopedObjectAccess& soa, const VarArgs* args_p)
999*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
1000*795d594fSAndroid Build Coastguard Worker CHECK(args_p != nullptr);
1001*795d594fSAndroid Build Coastguard Worker VarArgs args(args_p->Clone());
1002*795d594fSAndroid Build Coastguard Worker ArtMethod* m = CheckMethodID(args.GetMethodID());
1003*795d594fSAndroid Build Coastguard Worker if (m == nullptr) {
1004*795d594fSAndroid Build Coastguard Worker return false;
1005*795d594fSAndroid Build Coastguard Worker }
1006*795d594fSAndroid Build Coastguard Worker uint32_t len = 0;
1007*795d594fSAndroid Build Coastguard Worker const char* shorty = m->GetShorty(&len);
1008*795d594fSAndroid Build Coastguard Worker // Skip the return type
1009*795d594fSAndroid Build Coastguard Worker CHECK_GE(len, 1u);
1010*795d594fSAndroid Build Coastguard Worker len--;
1011*795d594fSAndroid Build Coastguard Worker shorty++;
1012*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < len; i++) {
1013*795d594fSAndroid Build Coastguard Worker if (!CheckPossibleHeapValue(soa, shorty[i], args.GetValue(shorty[i]))) {
1014*795d594fSAndroid Build Coastguard Worker return false;
1015*795d594fSAndroid Build Coastguard Worker }
1016*795d594fSAndroid Build Coastguard Worker }
1017*795d594fSAndroid Build Coastguard Worker return true;
1018*795d594fSAndroid Build Coastguard Worker }
1019*795d594fSAndroid Build Coastguard Worker
CheckNonHeapValue(char fmt,JniValueType arg)1020*795d594fSAndroid Build Coastguard Worker bool CheckNonHeapValue(char fmt, JniValueType arg) {
1021*795d594fSAndroid Build Coastguard Worker switch (fmt) {
1022*795d594fSAndroid Build Coastguard Worker case 'p': // TODO: pointer - null or readable?
1023*795d594fSAndroid Build Coastguard Worker case 'v': // JavaVM*
1024*795d594fSAndroid Build Coastguard Worker case 'D': // jdouble
1025*795d594fSAndroid Build Coastguard Worker case 'F': // jfloat
1026*795d594fSAndroid Build Coastguard Worker case 'J': // jlong
1027*795d594fSAndroid Build Coastguard Worker case 'I': // jint
1028*795d594fSAndroid Build Coastguard Worker break; // Ignored.
1029*795d594fSAndroid Build Coastguard Worker case 'b': // jboolean, why two? Fall-through.
1030*795d594fSAndroid Build Coastguard Worker case 'Z':
1031*795d594fSAndroid Build Coastguard Worker return CheckBoolean(arg.I);
1032*795d594fSAndroid Build Coastguard Worker case 'B': // jbyte
1033*795d594fSAndroid Build Coastguard Worker return CheckByte(arg.I);
1034*795d594fSAndroid Build Coastguard Worker case 'C': // jchar
1035*795d594fSAndroid Build Coastguard Worker return CheckChar(arg.I);
1036*795d594fSAndroid Build Coastguard Worker case 'S': // jshort
1037*795d594fSAndroid Build Coastguard Worker return CheckShort(arg.I);
1038*795d594fSAndroid Build Coastguard Worker case 'u': // utf8
1039*795d594fSAndroid Build Coastguard Worker if ((flags_ & kFlag_Release) != 0) {
1040*795d594fSAndroid Build Coastguard Worker return CheckNonNull(arg.u);
1041*795d594fSAndroid Build Coastguard Worker } else {
1042*795d594fSAndroid Build Coastguard Worker bool nullable = ((flags_ & kFlag_NullableUtf) != 0);
1043*795d594fSAndroid Build Coastguard Worker return CheckUtfString(arg.u, nullable);
1044*795d594fSAndroid Build Coastguard Worker }
1045*795d594fSAndroid Build Coastguard Worker case 'w': // jobjectRefType
1046*795d594fSAndroid Build Coastguard Worker switch (arg.w) {
1047*795d594fSAndroid Build Coastguard Worker case JNIInvalidRefType:
1048*795d594fSAndroid Build Coastguard Worker case JNILocalRefType:
1049*795d594fSAndroid Build Coastguard Worker case JNIGlobalRefType:
1050*795d594fSAndroid Build Coastguard Worker case JNIWeakGlobalRefType:
1051*795d594fSAndroid Build Coastguard Worker break;
1052*795d594fSAndroid Build Coastguard Worker default:
1053*795d594fSAndroid Build Coastguard Worker AbortF("Unknown reference type");
1054*795d594fSAndroid Build Coastguard Worker return false;
1055*795d594fSAndroid Build Coastguard Worker }
1056*795d594fSAndroid Build Coastguard Worker break;
1057*795d594fSAndroid Build Coastguard Worker case 'z': // jsize
1058*795d594fSAndroid Build Coastguard Worker return CheckLengthPositive(arg.z);
1059*795d594fSAndroid Build Coastguard Worker default:
1060*795d594fSAndroid Build Coastguard Worker AbortF("unknown format specifier: '%c'", fmt);
1061*795d594fSAndroid Build Coastguard Worker return false;
1062*795d594fSAndroid Build Coastguard Worker }
1063*795d594fSAndroid Build Coastguard Worker return true;
1064*795d594fSAndroid Build Coastguard Worker }
1065*795d594fSAndroid Build Coastguard Worker
TracePossibleHeapValue(ScopedObjectAccess & soa,bool entry,char fmt,JniValueType arg,std::string * msg)1066*795d594fSAndroid Build Coastguard Worker void TracePossibleHeapValue(ScopedObjectAccess& soa, bool entry, char fmt, JniValueType arg,
1067*795d594fSAndroid Build Coastguard Worker std::string* msg)
1068*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
1069*795d594fSAndroid Build Coastguard Worker switch (fmt) {
1070*795d594fSAndroid Build Coastguard Worker case 'L': // jobject fall-through.
1071*795d594fSAndroid Build Coastguard Worker case 'a': // jarray fall-through.
1072*795d594fSAndroid Build Coastguard Worker case 's': // jstring fall-through.
1073*795d594fSAndroid Build Coastguard Worker case 't': // jthrowable fall-through.
1074*795d594fSAndroid Build Coastguard Worker if (arg.L == nullptr) {
1075*795d594fSAndroid Build Coastguard Worker *msg += "NULL";
1076*795d594fSAndroid Build Coastguard Worker } else {
1077*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%p", arg.L);
1078*795d594fSAndroid Build Coastguard Worker }
1079*795d594fSAndroid Build Coastguard Worker break;
1080*795d594fSAndroid Build Coastguard Worker case 'c': { // jclass
1081*795d594fSAndroid Build Coastguard Worker jclass jc = arg.c;
1082*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(jc);
1083*795d594fSAndroid Build Coastguard Worker if (c == nullptr) {
1084*795d594fSAndroid Build Coastguard Worker *msg += "NULL";
1085*795d594fSAndroid Build Coastguard Worker } else if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(c.Ptr())) {
1086*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "INVALID POINTER:%p", jc);
1087*795d594fSAndroid Build Coastguard Worker } else if (!c->IsClass()) {
1088*795d594fSAndroid Build Coastguard Worker *msg += "INVALID NON-CLASS OBJECT OF TYPE:" + c->PrettyTypeOf();
1089*795d594fSAndroid Build Coastguard Worker } else {
1090*795d594fSAndroid Build Coastguard Worker *msg += c->PrettyClass();
1091*795d594fSAndroid Build Coastguard Worker if (!entry) {
1092*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, " (%p)", jc);
1093*795d594fSAndroid Build Coastguard Worker }
1094*795d594fSAndroid Build Coastguard Worker }
1095*795d594fSAndroid Build Coastguard Worker break;
1096*795d594fSAndroid Build Coastguard Worker }
1097*795d594fSAndroid Build Coastguard Worker case 'f': { // jfieldID
1098*795d594fSAndroid Build Coastguard Worker jfieldID fid = arg.f;
1099*795d594fSAndroid Build Coastguard Worker ArtField* f = jni::DecodeArtField(fid);
1100*795d594fSAndroid Build Coastguard Worker *msg += ArtField::PrettyField(f);
1101*795d594fSAndroid Build Coastguard Worker if (!entry) {
1102*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, " (%p)", fid);
1103*795d594fSAndroid Build Coastguard Worker }
1104*795d594fSAndroid Build Coastguard Worker break;
1105*795d594fSAndroid Build Coastguard Worker }
1106*795d594fSAndroid Build Coastguard Worker case 'm': { // jmethodID
1107*795d594fSAndroid Build Coastguard Worker jmethodID mid = arg.m;
1108*795d594fSAndroid Build Coastguard Worker ArtMethod* m = jni::DecodeArtMethod(mid);
1109*795d594fSAndroid Build Coastguard Worker *msg += ArtMethod::PrettyMethod(m);
1110*795d594fSAndroid Build Coastguard Worker if (!entry) {
1111*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, " (%p)", mid);
1112*795d594fSAndroid Build Coastguard Worker }
1113*795d594fSAndroid Build Coastguard Worker break;
1114*795d594fSAndroid Build Coastguard Worker }
1115*795d594fSAndroid Build Coastguard Worker case '.': {
1116*795d594fSAndroid Build Coastguard Worker const VarArgs* va = arg.va;
1117*795d594fSAndroid Build Coastguard Worker VarArgs args(va->Clone());
1118*795d594fSAndroid Build Coastguard Worker ArtMethod* m = jni::DecodeArtMethod(args.GetMethodID());
1119*795d594fSAndroid Build Coastguard Worker uint32_t len;
1120*795d594fSAndroid Build Coastguard Worker const char* shorty = m->GetShorty(&len);
1121*795d594fSAndroid Build Coastguard Worker CHECK_GE(len, 1u);
1122*795d594fSAndroid Build Coastguard Worker // Skip past return value.
1123*795d594fSAndroid Build Coastguard Worker len--;
1124*795d594fSAndroid Build Coastguard Worker shorty++;
1125*795d594fSAndroid Build Coastguard Worker // Remove the previous ', ' from the message.
1126*795d594fSAndroid Build Coastguard Worker msg->erase(msg->length() - 2);
1127*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < len; i++) {
1128*795d594fSAndroid Build Coastguard Worker *msg += ", ";
1129*795d594fSAndroid Build Coastguard Worker TracePossibleHeapValue(soa, entry, shorty[i], args.GetValue(shorty[i]), msg);
1130*795d594fSAndroid Build Coastguard Worker }
1131*795d594fSAndroid Build Coastguard Worker break;
1132*795d594fSAndroid Build Coastguard Worker }
1133*795d594fSAndroid Build Coastguard Worker default:
1134*795d594fSAndroid Build Coastguard Worker TraceNonHeapValue(fmt, arg, msg);
1135*795d594fSAndroid Build Coastguard Worker break;
1136*795d594fSAndroid Build Coastguard Worker }
1137*795d594fSAndroid Build Coastguard Worker }
1138*795d594fSAndroid Build Coastguard Worker
TraceNonHeapValue(char fmt,JniValueType arg,std::string * msg)1139*795d594fSAndroid Build Coastguard Worker void TraceNonHeapValue(char fmt, JniValueType arg, std::string* msg) {
1140*795d594fSAndroid Build Coastguard Worker switch (fmt) {
1141*795d594fSAndroid Build Coastguard Worker case 'B': // jbyte
1142*795d594fSAndroid Build Coastguard Worker if (arg.B >= 0 && arg.B < 10) {
1143*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%d", arg.B);
1144*795d594fSAndroid Build Coastguard Worker } else {
1145*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%#x (%d)", arg.B, arg.B);
1146*795d594fSAndroid Build Coastguard Worker }
1147*795d594fSAndroid Build Coastguard Worker break;
1148*795d594fSAndroid Build Coastguard Worker case 'C': // jchar
1149*795d594fSAndroid Build Coastguard Worker if (arg.C < 0x7f && arg.C >= ' ') {
1150*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "U+%x ('%c')", arg.C, arg.C);
1151*795d594fSAndroid Build Coastguard Worker } else {
1152*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "U+%x", arg.C);
1153*795d594fSAndroid Build Coastguard Worker }
1154*795d594fSAndroid Build Coastguard Worker break;
1155*795d594fSAndroid Build Coastguard Worker case 'F': // jfloat
1156*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%g", arg.F);
1157*795d594fSAndroid Build Coastguard Worker break;
1158*795d594fSAndroid Build Coastguard Worker case 'D': // jdouble
1159*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%g", arg.D);
1160*795d594fSAndroid Build Coastguard Worker break;
1161*795d594fSAndroid Build Coastguard Worker case 'S': // jshort
1162*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%d", arg.S);
1163*795d594fSAndroid Build Coastguard Worker break;
1164*795d594fSAndroid Build Coastguard Worker case 'i': // jint - fall-through.
1165*795d594fSAndroid Build Coastguard Worker case 'I': // jint
1166*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%d", arg.I);
1167*795d594fSAndroid Build Coastguard Worker break;
1168*795d594fSAndroid Build Coastguard Worker case 'J': // jlong
1169*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%" PRId64, arg.J);
1170*795d594fSAndroid Build Coastguard Worker break;
1171*795d594fSAndroid Build Coastguard Worker case 'Z': // jboolean
1172*795d594fSAndroid Build Coastguard Worker case 'b': // jboolean (JNI-style)
1173*795d594fSAndroid Build Coastguard Worker *msg += arg.b == JNI_TRUE ? "true" : "false";
1174*795d594fSAndroid Build Coastguard Worker break;
1175*795d594fSAndroid Build Coastguard Worker case 'V': // void
1176*795d594fSAndroid Build Coastguard Worker DCHECK(arg.V == nullptr);
1177*795d594fSAndroid Build Coastguard Worker *msg += "void";
1178*795d594fSAndroid Build Coastguard Worker break;
1179*795d594fSAndroid Build Coastguard Worker case 'v': // JavaVM*
1180*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "(JavaVM*)%p", arg.v);
1181*795d594fSAndroid Build Coastguard Worker break;
1182*795d594fSAndroid Build Coastguard Worker case 'E':
1183*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "(JNIEnv*)%p", arg.E);
1184*795d594fSAndroid Build Coastguard Worker break;
1185*795d594fSAndroid Build Coastguard Worker case 'z': // non-negative jsize
1186*795d594fSAndroid Build Coastguard Worker // You might expect jsize to be size_t, but it's not; it's the same as jint.
1187*795d594fSAndroid Build Coastguard Worker // We only treat this specially so we can do the non-negative check.
1188*795d594fSAndroid Build Coastguard Worker // TODO: maybe this wasn't worth it?
1189*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "%d", arg.z);
1190*795d594fSAndroid Build Coastguard Worker break;
1191*795d594fSAndroid Build Coastguard Worker case 'p': // void* ("pointer")
1192*795d594fSAndroid Build Coastguard Worker if (arg.p == nullptr) {
1193*795d594fSAndroid Build Coastguard Worker *msg += "NULL";
1194*795d594fSAndroid Build Coastguard Worker } else {
1195*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "(void*) %p", arg.p);
1196*795d594fSAndroid Build Coastguard Worker }
1197*795d594fSAndroid Build Coastguard Worker break;
1198*795d594fSAndroid Build Coastguard Worker case 'r': { // jint (release mode)
1199*795d594fSAndroid Build Coastguard Worker jint releaseMode = arg.r;
1200*795d594fSAndroid Build Coastguard Worker if (releaseMode == 0) {
1201*795d594fSAndroid Build Coastguard Worker *msg += "0";
1202*795d594fSAndroid Build Coastguard Worker } else if (releaseMode == JNI_ABORT) {
1203*795d594fSAndroid Build Coastguard Worker *msg += "JNI_ABORT";
1204*795d594fSAndroid Build Coastguard Worker } else if (releaseMode == JNI_COMMIT) {
1205*795d594fSAndroid Build Coastguard Worker *msg += "JNI_COMMIT";
1206*795d594fSAndroid Build Coastguard Worker } else {
1207*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "invalid release mode %d", releaseMode);
1208*795d594fSAndroid Build Coastguard Worker }
1209*795d594fSAndroid Build Coastguard Worker break;
1210*795d594fSAndroid Build Coastguard Worker }
1211*795d594fSAndroid Build Coastguard Worker case 'u': // const char* (Modified UTF-8)
1212*795d594fSAndroid Build Coastguard Worker if (arg.u == nullptr) {
1213*795d594fSAndroid Build Coastguard Worker *msg += "NULL";
1214*795d594fSAndroid Build Coastguard Worker } else {
1215*795d594fSAndroid Build Coastguard Worker StringAppendF(msg, "\"%s\"", arg.u);
1216*795d594fSAndroid Build Coastguard Worker }
1217*795d594fSAndroid Build Coastguard Worker break;
1218*795d594fSAndroid Build Coastguard Worker case 'w': // jobjectRefType
1219*795d594fSAndroid Build Coastguard Worker switch (arg.w) {
1220*795d594fSAndroid Build Coastguard Worker case JNIInvalidRefType:
1221*795d594fSAndroid Build Coastguard Worker *msg += "invalid reference type";
1222*795d594fSAndroid Build Coastguard Worker break;
1223*795d594fSAndroid Build Coastguard Worker case JNILocalRefType:
1224*795d594fSAndroid Build Coastguard Worker *msg += "local ref type";
1225*795d594fSAndroid Build Coastguard Worker break;
1226*795d594fSAndroid Build Coastguard Worker case JNIGlobalRefType:
1227*795d594fSAndroid Build Coastguard Worker *msg += "global ref type";
1228*795d594fSAndroid Build Coastguard Worker break;
1229*795d594fSAndroid Build Coastguard Worker case JNIWeakGlobalRefType:
1230*795d594fSAndroid Build Coastguard Worker *msg += "weak global ref type";
1231*795d594fSAndroid Build Coastguard Worker break;
1232*795d594fSAndroid Build Coastguard Worker default:
1233*795d594fSAndroid Build Coastguard Worker *msg += "unknown ref type";
1234*795d594fSAndroid Build Coastguard Worker break;
1235*795d594fSAndroid Build Coastguard Worker }
1236*795d594fSAndroid Build Coastguard Worker break;
1237*795d594fSAndroid Build Coastguard Worker default:
1238*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << function_name_ << ": unknown trace format specifier: '" << fmt << "'";
1239*795d594fSAndroid Build Coastguard Worker }
1240*795d594fSAndroid Build Coastguard Worker }
1241*795d594fSAndroid Build Coastguard Worker /*
1242*795d594fSAndroid Build Coastguard Worker * Verify that "array" is non-null and points to an Array object.
1243*795d594fSAndroid Build Coastguard Worker *
1244*795d594fSAndroid Build Coastguard Worker * Since we're dealing with objects, switch to "running" mode.
1245*795d594fSAndroid Build Coastguard Worker */
CheckArray(ScopedObjectAccess & soa,jarray java_array)1246*795d594fSAndroid Build Coastguard Worker bool CheckArray(ScopedObjectAccess& soa, jarray java_array)
1247*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
1248*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(java_array == nullptr)) {
1249*795d594fSAndroid Build Coastguard Worker AbortF("jarray was NULL");
1250*795d594fSAndroid Build Coastguard Worker return false;
1251*795d594fSAndroid Build Coastguard Worker }
1252*795d594fSAndroid Build Coastguard Worker
1253*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
1254*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!Runtime::Current()->GetHeap()->IsValidObjectAddress(a.Ptr()))) {
1255*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1256*795d594fSAndroid Build Coastguard Worker AbortF("jarray is an invalid %s: %p (%p)",
1257*795d594fSAndroid Build Coastguard Worker GetIndirectRefKindString(IndirectReferenceTable::GetIndirectRefKind(java_array)),
1258*795d594fSAndroid Build Coastguard Worker java_array,
1259*795d594fSAndroid Build Coastguard Worker a.Ptr());
1260*795d594fSAndroid Build Coastguard Worker return false;
1261*795d594fSAndroid Build Coastguard Worker } else if (!a->IsArrayInstance()) {
1262*795d594fSAndroid Build Coastguard Worker AbortF("jarray argument has non-array type: %s", a->PrettyTypeOf().c_str());
1263*795d594fSAndroid Build Coastguard Worker return false;
1264*795d594fSAndroid Build Coastguard Worker }
1265*795d594fSAndroid Build Coastguard Worker return true;
1266*795d594fSAndroid Build Coastguard Worker }
1267*795d594fSAndroid Build Coastguard Worker
CheckBoolean(jint z)1268*795d594fSAndroid Build Coastguard Worker bool CheckBoolean(jint z) {
1269*795d594fSAndroid Build Coastguard Worker if (z != JNI_TRUE && z != JNI_FALSE) {
1270*795d594fSAndroid Build Coastguard Worker // Note, broken booleans are always fatal.
1271*795d594fSAndroid Build Coastguard Worker AbortF("unexpected jboolean value: %d", z);
1272*795d594fSAndroid Build Coastguard Worker return false;
1273*795d594fSAndroid Build Coastguard Worker }
1274*795d594fSAndroid Build Coastguard Worker return true;
1275*795d594fSAndroid Build Coastguard Worker }
1276*795d594fSAndroid Build Coastguard Worker
CheckByte(jint b)1277*795d594fSAndroid Build Coastguard Worker bool CheckByte(jint b) {
1278*795d594fSAndroid Build Coastguard Worker if (b < std::numeric_limits<jbyte>::min() ||
1279*795d594fSAndroid Build Coastguard Worker b > std::numeric_limits<jbyte>::max()) {
1280*795d594fSAndroid Build Coastguard Worker if (kBrokenPrimitivesAreFatal) {
1281*795d594fSAndroid Build Coastguard Worker AbortF("unexpected jbyte value: %d", b);
1282*795d594fSAndroid Build Coastguard Worker return false;
1283*795d594fSAndroid Build Coastguard Worker } else {
1284*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Unexpected jbyte value: " << b;
1285*795d594fSAndroid Build Coastguard Worker }
1286*795d594fSAndroid Build Coastguard Worker }
1287*795d594fSAndroid Build Coastguard Worker return true;
1288*795d594fSAndroid Build Coastguard Worker }
1289*795d594fSAndroid Build Coastguard Worker
CheckShort(jint s)1290*795d594fSAndroid Build Coastguard Worker bool CheckShort(jint s) {
1291*795d594fSAndroid Build Coastguard Worker if (s < std::numeric_limits<jshort>::min() ||
1292*795d594fSAndroid Build Coastguard Worker s > std::numeric_limits<jshort>::max()) {
1293*795d594fSAndroid Build Coastguard Worker if (kBrokenPrimitivesAreFatal) {
1294*795d594fSAndroid Build Coastguard Worker AbortF("unexpected jshort value: %d", s);
1295*795d594fSAndroid Build Coastguard Worker return false;
1296*795d594fSAndroid Build Coastguard Worker } else {
1297*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Unexpected jshort value: " << s;
1298*795d594fSAndroid Build Coastguard Worker }
1299*795d594fSAndroid Build Coastguard Worker }
1300*795d594fSAndroid Build Coastguard Worker return true;
1301*795d594fSAndroid Build Coastguard Worker }
1302*795d594fSAndroid Build Coastguard Worker
CheckChar(jint c)1303*795d594fSAndroid Build Coastguard Worker bool CheckChar(jint c) {
1304*795d594fSAndroid Build Coastguard Worker if (c < std::numeric_limits<jchar>::min() ||
1305*795d594fSAndroid Build Coastguard Worker c > std::numeric_limits<jchar>::max()) {
1306*795d594fSAndroid Build Coastguard Worker if (kBrokenPrimitivesAreFatal) {
1307*795d594fSAndroid Build Coastguard Worker AbortF("unexpected jchar value: %d", c);
1308*795d594fSAndroid Build Coastguard Worker return false;
1309*795d594fSAndroid Build Coastguard Worker } else {
1310*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Unexpected jchar value: " << c;
1311*795d594fSAndroid Build Coastguard Worker }
1312*795d594fSAndroid Build Coastguard Worker }
1313*795d594fSAndroid Build Coastguard Worker return true;
1314*795d594fSAndroid Build Coastguard Worker }
1315*795d594fSAndroid Build Coastguard Worker
CheckLengthPositive(jsize length)1316*795d594fSAndroid Build Coastguard Worker bool CheckLengthPositive(jsize length) {
1317*795d594fSAndroid Build Coastguard Worker if (length < 0) {
1318*795d594fSAndroid Build Coastguard Worker AbortF("negative jsize: %d", length);
1319*795d594fSAndroid Build Coastguard Worker return false;
1320*795d594fSAndroid Build Coastguard Worker }
1321*795d594fSAndroid Build Coastguard Worker return true;
1322*795d594fSAndroid Build Coastguard Worker }
1323*795d594fSAndroid Build Coastguard Worker
CheckFieldID(jfieldID fid)1324*795d594fSAndroid Build Coastguard Worker ArtField* CheckFieldID(jfieldID fid) REQUIRES_SHARED(Locks::mutator_lock_) {
1325*795d594fSAndroid Build Coastguard Worker if (fid == nullptr) {
1326*795d594fSAndroid Build Coastguard Worker AbortF("jfieldID was NULL");
1327*795d594fSAndroid Build Coastguard Worker return nullptr;
1328*795d594fSAndroid Build Coastguard Worker }
1329*795d594fSAndroid Build Coastguard Worker ArtField* f = jni::DecodeArtField(fid);
1330*795d594fSAndroid Build Coastguard Worker // TODO: Better check here.
1331*795d594fSAndroid Build Coastguard Worker if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(f->GetDeclaringClass().Ptr())) {
1332*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1333*795d594fSAndroid Build Coastguard Worker AbortF("invalid jfieldID: %p", fid);
1334*795d594fSAndroid Build Coastguard Worker return nullptr;
1335*795d594fSAndroid Build Coastguard Worker }
1336*795d594fSAndroid Build Coastguard Worker return f;
1337*795d594fSAndroid Build Coastguard Worker }
1338*795d594fSAndroid Build Coastguard Worker
CheckMethodID(jmethodID mid)1339*795d594fSAndroid Build Coastguard Worker ArtMethod* CheckMethodID(jmethodID mid) REQUIRES_SHARED(Locks::mutator_lock_) {
1340*795d594fSAndroid Build Coastguard Worker if (mid == nullptr) {
1341*795d594fSAndroid Build Coastguard Worker AbortF("jmethodID was NULL");
1342*795d594fSAndroid Build Coastguard Worker return nullptr;
1343*795d594fSAndroid Build Coastguard Worker }
1344*795d594fSAndroid Build Coastguard Worker ArtMethod* m = jni::DecodeArtMethod(mid);
1345*795d594fSAndroid Build Coastguard Worker // TODO: Better check here.
1346*795d594fSAndroid Build Coastguard Worker if (!Runtime::Current()->GetHeap()->IsValidObjectAddress(m->GetDeclaringClass().Ptr())) {
1347*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetHeap()->DumpSpaces(LOG_STREAM(ERROR));
1348*795d594fSAndroid Build Coastguard Worker AbortF("invalid jmethodID: %p", mid);
1349*795d594fSAndroid Build Coastguard Worker return nullptr;
1350*795d594fSAndroid Build Coastguard Worker }
1351*795d594fSAndroid Build Coastguard Worker return m;
1352*795d594fSAndroid Build Coastguard Worker }
1353*795d594fSAndroid Build Coastguard Worker
CheckThread(JNIEnv * env)1354*795d594fSAndroid Build Coastguard Worker bool CheckThread(JNIEnv* env) REQUIRES_SHARED(Locks::mutator_lock_) {
1355*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
1356*795d594fSAndroid Build Coastguard Worker CHECK(self != nullptr);
1357*795d594fSAndroid Build Coastguard Worker
1358*795d594fSAndroid Build Coastguard Worker // Get the current thread's JNIEnv by going through our TLS pointer.
1359*795d594fSAndroid Build Coastguard Worker JNIEnvExt* threadEnv = self->GetJniEnv();
1360*795d594fSAndroid Build Coastguard Worker
1361*795d594fSAndroid Build Coastguard Worker // Verify that the current thread is (a) attached and (b) associated with
1362*795d594fSAndroid Build Coastguard Worker // this particular instance of JNIEnv.
1363*795d594fSAndroid Build Coastguard Worker if (env != threadEnv) {
1364*795d594fSAndroid Build Coastguard Worker // Get the thread owning the JNIEnv that's being used.
1365*795d594fSAndroid Build Coastguard Worker Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
1366*795d594fSAndroid Build Coastguard Worker AbortF("thread %s using JNIEnv* from thread %s",
1367*795d594fSAndroid Build Coastguard Worker ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
1368*795d594fSAndroid Build Coastguard Worker return false;
1369*795d594fSAndroid Build Coastguard Worker }
1370*795d594fSAndroid Build Coastguard Worker
1371*795d594fSAndroid Build Coastguard Worker // Verify that, if this thread previously made a critical "get" call, we
1372*795d594fSAndroid Build Coastguard Worker // do the corresponding "release" call before we try anything else.
1373*795d594fSAndroid Build Coastguard Worker switch (flags_ & kFlag_CritMask) {
1374*795d594fSAndroid Build Coastguard Worker case kFlag_CritOkay: // okay to call this method
1375*795d594fSAndroid Build Coastguard Worker break;
1376*795d594fSAndroid Build Coastguard Worker case kFlag_CritBad: // not okay to call
1377*795d594fSAndroid Build Coastguard Worker if (threadEnv->GetCritical() > 0) {
1378*795d594fSAndroid Build Coastguard Worker AbortF("thread %s using JNI after critical get",
1379*795d594fSAndroid Build Coastguard Worker ToStr<Thread>(*self).c_str());
1380*795d594fSAndroid Build Coastguard Worker return false;
1381*795d594fSAndroid Build Coastguard Worker }
1382*795d594fSAndroid Build Coastguard Worker break;
1383*795d594fSAndroid Build Coastguard Worker case kFlag_CritGet: // this is a "get" call
1384*795d594fSAndroid Build Coastguard Worker // Don't check here; we allow nested gets.
1385*795d594fSAndroid Build Coastguard Worker if (threadEnv->GetCritical() == 0) {
1386*795d594fSAndroid Build Coastguard Worker threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
1387*795d594fSAndroid Build Coastguard Worker }
1388*795d594fSAndroid Build Coastguard Worker threadEnv->SetCritical(threadEnv->GetCritical() + 1);
1389*795d594fSAndroid Build Coastguard Worker break;
1390*795d594fSAndroid Build Coastguard Worker case kFlag_CritRelease: // this is a "release" call
1391*795d594fSAndroid Build Coastguard Worker if (threadEnv->GetCritical() == 0) {
1392*795d594fSAndroid Build Coastguard Worker AbortF("thread %s called too many critical releases",
1393*795d594fSAndroid Build Coastguard Worker ToStr<Thread>(*self).c_str());
1394*795d594fSAndroid Build Coastguard Worker return false;
1395*795d594fSAndroid Build Coastguard Worker } else if (threadEnv->GetCritical() == 1) {
1396*795d594fSAndroid Build Coastguard Worker // Leaving the critical region, possibly warn about long critical regions.
1397*795d594fSAndroid Build Coastguard Worker uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
1398*795d594fSAndroid Build Coastguard Worker if (critical_duration_us > kCriticalWarnTimeUs) {
1399*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "JNI critical lock held for "
1400*795d594fSAndroid Build Coastguard Worker << PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
1401*795d594fSAndroid Build Coastguard Worker }
1402*795d594fSAndroid Build Coastguard Worker }
1403*795d594fSAndroid Build Coastguard Worker threadEnv->SetCritical(threadEnv->GetCritical() - 1);
1404*795d594fSAndroid Build Coastguard Worker break;
1405*795d594fSAndroid Build Coastguard Worker default:
1406*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Bad flags (internal error): " << flags_;
1407*795d594fSAndroid Build Coastguard Worker }
1408*795d594fSAndroid Build Coastguard Worker
1409*795d594fSAndroid Build Coastguard Worker // Verify that, if an exception has been raised, the native code doesn't
1410*795d594fSAndroid Build Coastguard Worker // make any JNI calls other than the Exception* methods.
1411*795d594fSAndroid Build Coastguard Worker if ((flags_ & kFlag_ExcepOkay) == 0 && self->IsExceptionPending()) {
1412*795d594fSAndroid Build Coastguard Worker mirror::Throwable* exception = self->GetException();
1413*795d594fSAndroid Build Coastguard Worker AbortF("JNI %s called with pending exception %s",
1414*795d594fSAndroid Build Coastguard Worker function_name_,
1415*795d594fSAndroid Build Coastguard Worker exception->Dump().c_str());
1416*795d594fSAndroid Build Coastguard Worker return false;
1417*795d594fSAndroid Build Coastguard Worker }
1418*795d594fSAndroid Build Coastguard Worker return true;
1419*795d594fSAndroid Build Coastguard Worker }
1420*795d594fSAndroid Build Coastguard Worker
1421*795d594fSAndroid Build Coastguard Worker // Verifies that "bytes" points to valid Modified UTF-8 data.
CheckUtfString(const char * bytes,bool nullable)1422*795d594fSAndroid Build Coastguard Worker bool CheckUtfString(const char* bytes, bool nullable) {
1423*795d594fSAndroid Build Coastguard Worker if (bytes == nullptr) {
1424*795d594fSAndroid Build Coastguard Worker if (!nullable) {
1425*795d594fSAndroid Build Coastguard Worker AbortF("non-nullable const char* was NULL");
1426*795d594fSAndroid Build Coastguard Worker return false;
1427*795d594fSAndroid Build Coastguard Worker }
1428*795d594fSAndroid Build Coastguard Worker return true;
1429*795d594fSAndroid Build Coastguard Worker }
1430*795d594fSAndroid Build Coastguard Worker
1431*795d594fSAndroid Build Coastguard Worker const char* errorKind = nullptr;
1432*795d594fSAndroid Build Coastguard Worker const uint8_t* utf8 = CheckUtfBytes(bytes, &errorKind);
1433*795d594fSAndroid Build Coastguard Worker if (errorKind != nullptr) {
1434*795d594fSAndroid Build Coastguard Worker // This is an expensive loop that will resize often, but this isn't supposed to hit in
1435*795d594fSAndroid Build Coastguard Worker // practice anyways.
1436*795d594fSAndroid Build Coastguard Worker std::ostringstream oss;
1437*795d594fSAndroid Build Coastguard Worker oss << std::hex;
1438*795d594fSAndroid Build Coastguard Worker const uint8_t* tmp = reinterpret_cast<const uint8_t*>(bytes);
1439*795d594fSAndroid Build Coastguard Worker while (*tmp != 0) {
1440*795d594fSAndroid Build Coastguard Worker if (tmp == utf8) {
1441*795d594fSAndroid Build Coastguard Worker oss << "<";
1442*795d594fSAndroid Build Coastguard Worker }
1443*795d594fSAndroid Build Coastguard Worker oss << "0x" << std::setfill('0') << std::setw(2) << static_cast<uint32_t>(*tmp);
1444*795d594fSAndroid Build Coastguard Worker if (tmp == utf8) {
1445*795d594fSAndroid Build Coastguard Worker oss << '>';
1446*795d594fSAndroid Build Coastguard Worker }
1447*795d594fSAndroid Build Coastguard Worker tmp++;
1448*795d594fSAndroid Build Coastguard Worker if (*tmp != 0) {
1449*795d594fSAndroid Build Coastguard Worker oss << ' ';
1450*795d594fSAndroid Build Coastguard Worker }
1451*795d594fSAndroid Build Coastguard Worker }
1452*795d594fSAndroid Build Coastguard Worker
1453*795d594fSAndroid Build Coastguard Worker AbortF("input is not valid Modified UTF-8: illegal %s byte %#x\n"
1454*795d594fSAndroid Build Coastguard Worker " string: '%s'\n input: '%s'", errorKind, *utf8, bytes, oss.str().c_str());
1455*795d594fSAndroid Build Coastguard Worker return false;
1456*795d594fSAndroid Build Coastguard Worker }
1457*795d594fSAndroid Build Coastguard Worker return true;
1458*795d594fSAndroid Build Coastguard Worker }
1459*795d594fSAndroid Build Coastguard Worker
1460*795d594fSAndroid Build Coastguard Worker // Checks whether |bytes| is valid modified UTF-8. We also accept 4 byte UTF
1461*795d594fSAndroid Build Coastguard Worker // sequences in place of encoded surrogate pairs.
CheckUtfBytes(const char * bytes,const char ** errorKind)1462*795d594fSAndroid Build Coastguard Worker static const uint8_t* CheckUtfBytes(const char* bytes, const char** errorKind) {
1463*795d594fSAndroid Build Coastguard Worker while (*bytes != '\0') {
1464*795d594fSAndroid Build Coastguard Worker const uint8_t* utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1465*795d594fSAndroid Build Coastguard Worker // Switch on the high four bits.
1466*795d594fSAndroid Build Coastguard Worker switch (*utf8 >> 4) {
1467*795d594fSAndroid Build Coastguard Worker case 0x00:
1468*795d594fSAndroid Build Coastguard Worker case 0x01:
1469*795d594fSAndroid Build Coastguard Worker case 0x02:
1470*795d594fSAndroid Build Coastguard Worker case 0x03:
1471*795d594fSAndroid Build Coastguard Worker case 0x04:
1472*795d594fSAndroid Build Coastguard Worker case 0x05:
1473*795d594fSAndroid Build Coastguard Worker case 0x06:
1474*795d594fSAndroid Build Coastguard Worker case 0x07:
1475*795d594fSAndroid Build Coastguard Worker // Bit pattern 0xxx. No need for any extra bytes.
1476*795d594fSAndroid Build Coastguard Worker break;
1477*795d594fSAndroid Build Coastguard Worker case 0x08:
1478*795d594fSAndroid Build Coastguard Worker case 0x09:
1479*795d594fSAndroid Build Coastguard Worker case 0x0a:
1480*795d594fSAndroid Build Coastguard Worker case 0x0b:
1481*795d594fSAndroid Build Coastguard Worker // Bit patterns 10xx, which are illegal start bytes.
1482*795d594fSAndroid Build Coastguard Worker *errorKind = "start";
1483*795d594fSAndroid Build Coastguard Worker return utf8;
1484*795d594fSAndroid Build Coastguard Worker case 0x0f:
1485*795d594fSAndroid Build Coastguard Worker // Bit pattern 1111, which might be the start of a 4 byte sequence.
1486*795d594fSAndroid Build Coastguard Worker if ((*utf8 & 0x08) == 0) {
1487*795d594fSAndroid Build Coastguard Worker // Bit pattern 1111 0xxx, which is the start of a 4 byte sequence.
1488*795d594fSAndroid Build Coastguard Worker // We consume one continuation byte here, and fall through to consume two more.
1489*795d594fSAndroid Build Coastguard Worker utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1490*795d594fSAndroid Build Coastguard Worker if ((*utf8 & 0xc0) != 0x80) {
1491*795d594fSAndroid Build Coastguard Worker *errorKind = "continuation";
1492*795d594fSAndroid Build Coastguard Worker return utf8;
1493*795d594fSAndroid Build Coastguard Worker }
1494*795d594fSAndroid Build Coastguard Worker } else {
1495*795d594fSAndroid Build Coastguard Worker *errorKind = "start";
1496*795d594fSAndroid Build Coastguard Worker return utf8;
1497*795d594fSAndroid Build Coastguard Worker }
1498*795d594fSAndroid Build Coastguard Worker
1499*795d594fSAndroid Build Coastguard Worker // Fall through to the cases below to consume two more continuation bytes.
1500*795d594fSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
1501*795d594fSAndroid Build Coastguard Worker case 0x0e:
1502*795d594fSAndroid Build Coastguard Worker // Bit pattern 1110, so there are two additional bytes.
1503*795d594fSAndroid Build Coastguard Worker utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1504*795d594fSAndroid Build Coastguard Worker if ((*utf8 & 0xc0) != 0x80) {
1505*795d594fSAndroid Build Coastguard Worker *errorKind = "continuation";
1506*795d594fSAndroid Build Coastguard Worker return utf8;
1507*795d594fSAndroid Build Coastguard Worker }
1508*795d594fSAndroid Build Coastguard Worker
1509*795d594fSAndroid Build Coastguard Worker // Fall through to consume one more continuation byte.
1510*795d594fSAndroid Build Coastguard Worker FALLTHROUGH_INTENDED;
1511*795d594fSAndroid Build Coastguard Worker case 0x0c:
1512*795d594fSAndroid Build Coastguard Worker case 0x0d:
1513*795d594fSAndroid Build Coastguard Worker // Bit pattern 110x, so there is one additional byte.
1514*795d594fSAndroid Build Coastguard Worker utf8 = reinterpret_cast<const uint8_t*>(bytes++);
1515*795d594fSAndroid Build Coastguard Worker if ((*utf8 & 0xc0) != 0x80) {
1516*795d594fSAndroid Build Coastguard Worker *errorKind = "continuation";
1517*795d594fSAndroid Build Coastguard Worker return utf8;
1518*795d594fSAndroid Build Coastguard Worker }
1519*795d594fSAndroid Build Coastguard Worker break;
1520*795d594fSAndroid Build Coastguard Worker }
1521*795d594fSAndroid Build Coastguard Worker }
1522*795d594fSAndroid Build Coastguard Worker return nullptr;
1523*795d594fSAndroid Build Coastguard Worker }
1524*795d594fSAndroid Build Coastguard Worker
AbortF(const char * fmt,...)1525*795d594fSAndroid Build Coastguard Worker void AbortF(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
1526*795d594fSAndroid Build Coastguard Worker va_list args;
1527*795d594fSAndroid Build Coastguard Worker va_start(args, fmt);
1528*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetJavaVM()->JniAbortV(function_name_, fmt, args);
1529*795d594fSAndroid Build Coastguard Worker va_end(args);
1530*795d594fSAndroid Build Coastguard Worker }
1531*795d594fSAndroid Build Coastguard Worker
1532*795d594fSAndroid Build Coastguard Worker // The name of the JNI function being checked.
1533*795d594fSAndroid Build Coastguard Worker const char* const function_name_;
1534*795d594fSAndroid Build Coastguard Worker
1535*795d594fSAndroid Build Coastguard Worker int indent_;
1536*795d594fSAndroid Build Coastguard Worker
1537*795d594fSAndroid Build Coastguard Worker const uint16_t flags_;
1538*795d594fSAndroid Build Coastguard Worker
1539*795d594fSAndroid Build Coastguard Worker const bool has_method_;
1540*795d594fSAndroid Build Coastguard Worker
1541*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ScopedCheck);
1542*795d594fSAndroid Build Coastguard Worker };
1543*795d594fSAndroid Build Coastguard Worker
1544*795d594fSAndroid Build Coastguard Worker /*
1545*795d594fSAndroid Build Coastguard Worker * ===========================================================================
1546*795d594fSAndroid Build Coastguard Worker * Guarded arrays
1547*795d594fSAndroid Build Coastguard Worker * ===========================================================================
1548*795d594fSAndroid Build Coastguard Worker */
1549*795d594fSAndroid Build Coastguard Worker
1550*795d594fSAndroid Build Coastguard Worker /* this gets tucked in at the start of the buffer; struct size must be even */
1551*795d594fSAndroid Build Coastguard Worker class GuardedCopy {
1552*795d594fSAndroid Build Coastguard Worker public:
1553*795d594fSAndroid Build Coastguard Worker /*
1554*795d594fSAndroid Build Coastguard Worker * Create an over-sized buffer to hold the contents of "buf". Copy it in,
1555*795d594fSAndroid Build Coastguard Worker * filling in the area around it with guard data.
1556*795d594fSAndroid Build Coastguard Worker */
Create(void * original_buf,size_t len,bool mod_okay)1557*795d594fSAndroid Build Coastguard Worker static void* Create(void* original_buf, size_t len, bool mod_okay) {
1558*795d594fSAndroid Build Coastguard Worker const size_t new_len = LengthIncludingRedZones(len);
1559*795d594fSAndroid Build Coastguard Worker uint8_t* const new_buf = DebugAlloc(new_len);
1560*795d594fSAndroid Build Coastguard Worker
1561*795d594fSAndroid Build Coastguard Worker // If modification is not expected, grab a checksum.
1562*795d594fSAndroid Build Coastguard Worker uLong adler = 0;
1563*795d594fSAndroid Build Coastguard Worker if (!mod_okay) {
1564*795d594fSAndroid Build Coastguard Worker adler = adler32(adler32(0L, Z_NULL, 0), reinterpret_cast<const Bytef*>(original_buf), len);
1565*795d594fSAndroid Build Coastguard Worker }
1566*795d594fSAndroid Build Coastguard Worker
1567*795d594fSAndroid Build Coastguard Worker GuardedCopy* copy = new (new_buf) GuardedCopy(original_buf, len, adler);
1568*795d594fSAndroid Build Coastguard Worker
1569*795d594fSAndroid Build Coastguard Worker // Fill begin region with canary pattern.
1570*795d594fSAndroid Build Coastguard Worker const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1571*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1572*795d594fSAndroid Build Coastguard Worker const_cast<char*>(copy->StartRedZone())[i] = kCanary[j];
1573*795d594fSAndroid Build Coastguard Worker if (kCanary[j] == '\0') {
1574*795d594fSAndroid Build Coastguard Worker j = 0;
1575*795d594fSAndroid Build Coastguard Worker } else {
1576*795d594fSAndroid Build Coastguard Worker j++;
1577*795d594fSAndroid Build Coastguard Worker }
1578*795d594fSAndroid Build Coastguard Worker }
1579*795d594fSAndroid Build Coastguard Worker
1580*795d594fSAndroid Build Coastguard Worker // Copy the data in; note "len" could be zero.
1581*795d594fSAndroid Build Coastguard Worker memcpy(const_cast<uint8_t*>(copy->BufferWithinRedZones()), original_buf, len);
1582*795d594fSAndroid Build Coastguard Worker
1583*795d594fSAndroid Build Coastguard Worker // Fill end region with canary pattern.
1584*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1585*795d594fSAndroid Build Coastguard Worker const_cast<char*>(copy->EndRedZone())[i] = kCanary[j];
1586*795d594fSAndroid Build Coastguard Worker if (kCanary[j] == '\0') {
1587*795d594fSAndroid Build Coastguard Worker j = 0;
1588*795d594fSAndroid Build Coastguard Worker } else {
1589*795d594fSAndroid Build Coastguard Worker j++;
1590*795d594fSAndroid Build Coastguard Worker }
1591*795d594fSAndroid Build Coastguard Worker }
1592*795d594fSAndroid Build Coastguard Worker
1593*795d594fSAndroid Build Coastguard Worker return const_cast<uint8_t*>(copy->BufferWithinRedZones());
1594*795d594fSAndroid Build Coastguard Worker }
1595*795d594fSAndroid Build Coastguard Worker
1596*795d594fSAndroid Build Coastguard Worker /*
1597*795d594fSAndroid Build Coastguard Worker * Create a guarded copy of a primitive array. Modifications to the copied
1598*795d594fSAndroid Build Coastguard Worker * data are allowed. Returns a pointer to the copied data.
1599*795d594fSAndroid Build Coastguard Worker */
CreateGuardedPACopy(JNIEnv * env,const jarray java_array,jboolean * is_copy,void * original_ptr)1600*795d594fSAndroid Build Coastguard Worker static void* CreateGuardedPACopy(JNIEnv* env, const jarray java_array, jboolean* is_copy,
1601*795d594fSAndroid Build Coastguard Worker void* original_ptr) {
1602*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1603*795d594fSAndroid Build Coastguard Worker
1604*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Array> a = soa.Decode<mirror::Array>(java_array);
1605*795d594fSAndroid Build Coastguard Worker size_t component_size = a->GetClass()->GetComponentSize();
1606*795d594fSAndroid Build Coastguard Worker size_t byte_count = a->GetLength() * component_size;
1607*795d594fSAndroid Build Coastguard Worker void* result = Create(original_ptr, byte_count, true);
1608*795d594fSAndroid Build Coastguard Worker if (is_copy != nullptr) {
1609*795d594fSAndroid Build Coastguard Worker *is_copy = JNI_TRUE;
1610*795d594fSAndroid Build Coastguard Worker }
1611*795d594fSAndroid Build Coastguard Worker return result;
1612*795d594fSAndroid Build Coastguard Worker }
1613*795d594fSAndroid Build Coastguard Worker
1614*795d594fSAndroid Build Coastguard Worker /*
1615*795d594fSAndroid Build Coastguard Worker * Perform the array "release" operation, which may or may not copy data
1616*795d594fSAndroid Build Coastguard Worker * back into the managed heap, and may or may not release the underlying storage.
1617*795d594fSAndroid Build Coastguard Worker */
ReleaseGuardedPACopy(const char * function_name,JNIEnv * env,jarray java_array,void * embedded_buf,int mode)1618*795d594fSAndroid Build Coastguard Worker static void* ReleaseGuardedPACopy(const char* function_name,
1619*795d594fSAndroid Build Coastguard Worker JNIEnv* env,
1620*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jarray java_array,
1621*795d594fSAndroid Build Coastguard Worker void* embedded_buf,
1622*795d594fSAndroid Build Coastguard Worker int mode) {
1623*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1624*795d594fSAndroid Build Coastguard Worker if (!GuardedCopy::Check(function_name, embedded_buf, true)) {
1625*795d594fSAndroid Build Coastguard Worker return nullptr;
1626*795d594fSAndroid Build Coastguard Worker }
1627*795d594fSAndroid Build Coastguard Worker GuardedCopy* const copy = FromEmbedded(embedded_buf);
1628*795d594fSAndroid Build Coastguard Worker void* original_ptr = copy->original_ptr_;
1629*795d594fSAndroid Build Coastguard Worker if (mode != JNI_ABORT) {
1630*795d594fSAndroid Build Coastguard Worker memcpy(original_ptr, embedded_buf, copy->original_length_);
1631*795d594fSAndroid Build Coastguard Worker }
1632*795d594fSAndroid Build Coastguard Worker if (mode != JNI_COMMIT) {
1633*795d594fSAndroid Build Coastguard Worker Destroy(embedded_buf);
1634*795d594fSAndroid Build Coastguard Worker }
1635*795d594fSAndroid Build Coastguard Worker return original_ptr;
1636*795d594fSAndroid Build Coastguard Worker }
1637*795d594fSAndroid Build Coastguard Worker
1638*795d594fSAndroid Build Coastguard Worker /*
1639*795d594fSAndroid Build Coastguard Worker * Free up the guard buffer, scrub it, and return the original pointer.
1640*795d594fSAndroid Build Coastguard Worker */
Destroy(void * embedded_buf)1641*795d594fSAndroid Build Coastguard Worker static void* Destroy(void* embedded_buf) {
1642*795d594fSAndroid Build Coastguard Worker GuardedCopy* copy = FromEmbedded(embedded_buf);
1643*795d594fSAndroid Build Coastguard Worker void* original_ptr = const_cast<void*>(copy->original_ptr_);
1644*795d594fSAndroid Build Coastguard Worker size_t len = LengthIncludingRedZones(copy->original_length_);
1645*795d594fSAndroid Build Coastguard Worker DebugFree(copy, len);
1646*795d594fSAndroid Build Coastguard Worker return original_ptr;
1647*795d594fSAndroid Build Coastguard Worker }
1648*795d594fSAndroid Build Coastguard Worker
1649*795d594fSAndroid Build Coastguard Worker /*
1650*795d594fSAndroid Build Coastguard Worker * Verify the guard area and, if "modOkay" is false, that the data itself
1651*795d594fSAndroid Build Coastguard Worker * has not been altered.
1652*795d594fSAndroid Build Coastguard Worker *
1653*795d594fSAndroid Build Coastguard Worker * The caller has already checked that "dataBuf" is non-null.
1654*795d594fSAndroid Build Coastguard Worker */
Check(const char * function_name,const void * embedded_buf,bool mod_okay)1655*795d594fSAndroid Build Coastguard Worker static bool Check(const char* function_name, const void* embedded_buf, bool mod_okay) {
1656*795d594fSAndroid Build Coastguard Worker const GuardedCopy* copy = FromEmbedded(embedded_buf);
1657*795d594fSAndroid Build Coastguard Worker return copy->CheckHeader(function_name, mod_okay) && copy->CheckRedZones(function_name);
1658*795d594fSAndroid Build Coastguard Worker }
1659*795d594fSAndroid Build Coastguard Worker
1660*795d594fSAndroid Build Coastguard Worker private:
GuardedCopy(void * original_buf,size_t len,uLong adler)1661*795d594fSAndroid Build Coastguard Worker GuardedCopy(void* original_buf, size_t len, uLong adler) :
1662*795d594fSAndroid Build Coastguard Worker magic_(kGuardMagic), adler_(adler), original_ptr_(original_buf), original_length_(len) {
1663*795d594fSAndroid Build Coastguard Worker }
1664*795d594fSAndroid Build Coastguard Worker
DebugAlloc(size_t len)1665*795d594fSAndroid Build Coastguard Worker static uint8_t* DebugAlloc(size_t len) {
1666*795d594fSAndroid Build Coastguard Worker void* result = mmap(nullptr, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
1667*795d594fSAndroid Build Coastguard Worker if (result == MAP_FAILED) {
1668*795d594fSAndroid Build Coastguard Worker PLOG(FATAL) << "GuardedCopy::create mmap(" << len << ") failed";
1669*795d594fSAndroid Build Coastguard Worker }
1670*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<uint8_t*>(result);
1671*795d594fSAndroid Build Coastguard Worker }
1672*795d594fSAndroid Build Coastguard Worker
DebugFree(void * buf,size_t len)1673*795d594fSAndroid Build Coastguard Worker static void DebugFree(void* buf, size_t len) {
1674*795d594fSAndroid Build Coastguard Worker if (munmap(buf, len) != 0) {
1675*795d594fSAndroid Build Coastguard Worker PLOG(FATAL) << "munmap(" << buf << ", " << len << ") failed";
1676*795d594fSAndroid Build Coastguard Worker }
1677*795d594fSAndroid Build Coastguard Worker }
1678*795d594fSAndroid Build Coastguard Worker
LengthIncludingRedZones(size_t len)1679*795d594fSAndroid Build Coastguard Worker static size_t LengthIncludingRedZones(size_t len) {
1680*795d594fSAndroid Build Coastguard Worker return len + kRedZoneSize;
1681*795d594fSAndroid Build Coastguard Worker }
1682*795d594fSAndroid Build Coastguard Worker
1683*795d594fSAndroid Build Coastguard Worker // Get the GuardedCopy from the interior pointer.
FromEmbedded(void * embedded_buf)1684*795d594fSAndroid Build Coastguard Worker static GuardedCopy* FromEmbedded(void* embedded_buf) {
1685*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<GuardedCopy*>(
1686*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1687*795d594fSAndroid Build Coastguard Worker }
1688*795d594fSAndroid Build Coastguard Worker
FromEmbedded(const void * embedded_buf)1689*795d594fSAndroid Build Coastguard Worker static const GuardedCopy* FromEmbedded(const void* embedded_buf) {
1690*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const GuardedCopy*>(
1691*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const uint8_t*>(embedded_buf) - (kRedZoneSize / 2));
1692*795d594fSAndroid Build Coastguard Worker }
1693*795d594fSAndroid Build Coastguard Worker
AbortF(const char * jni_function_name,const char * fmt,...)1694*795d594fSAndroid Build Coastguard Worker static void AbortF(const char* jni_function_name, const char* fmt, ...) {
1695*795d594fSAndroid Build Coastguard Worker va_list args;
1696*795d594fSAndroid Build Coastguard Worker va_start(args, fmt);
1697*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetJavaVM()->JniAbortV(jni_function_name, fmt, args);
1698*795d594fSAndroid Build Coastguard Worker va_end(args);
1699*795d594fSAndroid Build Coastguard Worker }
1700*795d594fSAndroid Build Coastguard Worker
CheckHeader(const char * function_name,bool mod_okay) const1701*795d594fSAndroid Build Coastguard Worker bool CheckHeader(const char* function_name, bool mod_okay) const {
1702*795d594fSAndroid Build Coastguard Worker static const uint32_t kMagicCmp = kGuardMagic;
1703*795d594fSAndroid Build Coastguard Worker
1704*795d594fSAndroid Build Coastguard Worker // Before we do anything with "pExtra", check the magic number. We
1705*795d594fSAndroid Build Coastguard Worker // do the check with memcmp rather than "==" in case the pointer is
1706*795d594fSAndroid Build Coastguard Worker // unaligned. If it points to completely bogus memory we're going
1707*795d594fSAndroid Build Coastguard Worker // to crash, but there's no easy way around that.
1708*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(memcmp(&magic_, &kMagicCmp, 4) != 0)) {
1709*795d594fSAndroid Build Coastguard Worker uint8_t buf[4];
1710*795d594fSAndroid Build Coastguard Worker memcpy(buf, &magic_, 4);
1711*795d594fSAndroid Build Coastguard Worker AbortF(function_name,
1712*795d594fSAndroid Build Coastguard Worker "guard magic does not match (found 0x%02x%02x%02x%02x) -- incorrect data pointer %p?",
1713*795d594fSAndroid Build Coastguard Worker buf[3], buf[2], buf[1], buf[0], this); // Assumes little-endian.
1714*795d594fSAndroid Build Coastguard Worker return false;
1715*795d594fSAndroid Build Coastguard Worker }
1716*795d594fSAndroid Build Coastguard Worker
1717*795d594fSAndroid Build Coastguard Worker // If modification is not expected, verify checksum. Strictly speaking this is wrong: if we
1718*795d594fSAndroid Build Coastguard Worker // told the client that we made a copy, there's no reason they can't alter the buffer.
1719*795d594fSAndroid Build Coastguard Worker if (!mod_okay) {
1720*795d594fSAndroid Build Coastguard Worker uLong computed_adler =
1721*795d594fSAndroid Build Coastguard Worker adler32(adler32(0L, Z_NULL, 0), BufferWithinRedZones(), original_length_);
1722*795d594fSAndroid Build Coastguard Worker if (computed_adler != adler_) {
1723*795d594fSAndroid Build Coastguard Worker AbortF(function_name, "buffer modified (0x%08lx vs 0x%08lx) at address %p",
1724*795d594fSAndroid Build Coastguard Worker computed_adler, adler_, this);
1725*795d594fSAndroid Build Coastguard Worker return false;
1726*795d594fSAndroid Build Coastguard Worker }
1727*795d594fSAndroid Build Coastguard Worker }
1728*795d594fSAndroid Build Coastguard Worker return true;
1729*795d594fSAndroid Build Coastguard Worker }
1730*795d594fSAndroid Build Coastguard Worker
CheckRedZones(const char * function_name) const1731*795d594fSAndroid Build Coastguard Worker bool CheckRedZones(const char* function_name) const {
1732*795d594fSAndroid Build Coastguard Worker // Check the begin red zone.
1733*795d594fSAndroid Build Coastguard Worker const size_t kStartCanaryLength = (GuardedCopy::kRedZoneSize / 2) - sizeof(GuardedCopy);
1734*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, j = 0; i < kStartCanaryLength; ++i) {
1735*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(StartRedZone()[i] != kCanary[j])) {
1736*795d594fSAndroid Build Coastguard Worker AbortF(function_name, "guard pattern before buffer disturbed at %p +%zd", this, i);
1737*795d594fSAndroid Build Coastguard Worker return false;
1738*795d594fSAndroid Build Coastguard Worker }
1739*795d594fSAndroid Build Coastguard Worker if (kCanary[j] == '\0') {
1740*795d594fSAndroid Build Coastguard Worker j = 0;
1741*795d594fSAndroid Build Coastguard Worker } else {
1742*795d594fSAndroid Build Coastguard Worker j++;
1743*795d594fSAndroid Build Coastguard Worker }
1744*795d594fSAndroid Build Coastguard Worker }
1745*795d594fSAndroid Build Coastguard Worker
1746*795d594fSAndroid Build Coastguard Worker // Check end region.
1747*795d594fSAndroid Build Coastguard Worker for (size_t i = 0, j = 0; i < kEndCanaryLength; ++i) {
1748*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(EndRedZone()[i] != kCanary[j])) {
1749*795d594fSAndroid Build Coastguard Worker size_t offset_from_buffer_start =
1750*795d594fSAndroid Build Coastguard Worker &(EndRedZone()[i]) - &(StartRedZone()[kStartCanaryLength]);
1751*795d594fSAndroid Build Coastguard Worker AbortF(function_name, "guard pattern after buffer disturbed at %p +%zd", this,
1752*795d594fSAndroid Build Coastguard Worker offset_from_buffer_start);
1753*795d594fSAndroid Build Coastguard Worker return false;
1754*795d594fSAndroid Build Coastguard Worker }
1755*795d594fSAndroid Build Coastguard Worker if (kCanary[j] == '\0') {
1756*795d594fSAndroid Build Coastguard Worker j = 0;
1757*795d594fSAndroid Build Coastguard Worker } else {
1758*795d594fSAndroid Build Coastguard Worker j++;
1759*795d594fSAndroid Build Coastguard Worker }
1760*795d594fSAndroid Build Coastguard Worker }
1761*795d594fSAndroid Build Coastguard Worker return true;
1762*795d594fSAndroid Build Coastguard Worker }
1763*795d594fSAndroid Build Coastguard Worker
1764*795d594fSAndroid Build Coastguard Worker // Location that canary value will be written before the guarded region.
StartRedZone() const1765*795d594fSAndroid Build Coastguard Worker const char* StartRedZone() const {
1766*795d594fSAndroid Build Coastguard Worker const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1767*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const char*>(buf + sizeof(GuardedCopy));
1768*795d594fSAndroid Build Coastguard Worker }
1769*795d594fSAndroid Build Coastguard Worker
1770*795d594fSAndroid Build Coastguard Worker // Return the interior embedded buffer.
BufferWithinRedZones() const1771*795d594fSAndroid Build Coastguard Worker const uint8_t* BufferWithinRedZones() const {
1772*795d594fSAndroid Build Coastguard Worker const uint8_t* embedded_buf = reinterpret_cast<const uint8_t*>(this) + (kRedZoneSize / 2);
1773*795d594fSAndroid Build Coastguard Worker return embedded_buf;
1774*795d594fSAndroid Build Coastguard Worker }
1775*795d594fSAndroid Build Coastguard Worker
1776*795d594fSAndroid Build Coastguard Worker // Location that canary value will be written after the guarded region.
EndRedZone() const1777*795d594fSAndroid Build Coastguard Worker const char* EndRedZone() const {
1778*795d594fSAndroid Build Coastguard Worker const uint8_t* buf = reinterpret_cast<const uint8_t*>(this);
1779*795d594fSAndroid Build Coastguard Worker size_t buf_len = LengthIncludingRedZones(original_length_);
1780*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const char*>(buf + (buf_len - (kRedZoneSize / 2)));
1781*795d594fSAndroid Build Coastguard Worker }
1782*795d594fSAndroid Build Coastguard Worker
1783*795d594fSAndroid Build Coastguard Worker static constexpr size_t kRedZoneSize = 512;
1784*795d594fSAndroid Build Coastguard Worker static constexpr size_t kEndCanaryLength = kRedZoneSize / 2;
1785*795d594fSAndroid Build Coastguard Worker
1786*795d594fSAndroid Build Coastguard Worker // Value written before and after the guarded array.
1787*795d594fSAndroid Build Coastguard Worker static const char* const kCanary;
1788*795d594fSAndroid Build Coastguard Worker
1789*795d594fSAndroid Build Coastguard Worker static constexpr uint32_t kGuardMagic = 0xffd5aa96;
1790*795d594fSAndroid Build Coastguard Worker
1791*795d594fSAndroid Build Coastguard Worker const uint32_t magic_;
1792*795d594fSAndroid Build Coastguard Worker const uLong adler_;
1793*795d594fSAndroid Build Coastguard Worker void* const original_ptr_;
1794*795d594fSAndroid Build Coastguard Worker const size_t original_length_;
1795*795d594fSAndroid Build Coastguard Worker };
1796*795d594fSAndroid Build Coastguard Worker const char* const GuardedCopy::kCanary = "JNI BUFFER RED ZONE";
1797*795d594fSAndroid Build Coastguard Worker
1798*795d594fSAndroid Build Coastguard Worker /*
1799*795d594fSAndroid Build Coastguard Worker * ===========================================================================
1800*795d594fSAndroid Build Coastguard Worker * JNI functions
1801*795d594fSAndroid Build Coastguard Worker * ===========================================================================
1802*795d594fSAndroid Build Coastguard Worker */
1803*795d594fSAndroid Build Coastguard Worker
1804*795d594fSAndroid Build Coastguard Worker class CheckJNI {
1805*795d594fSAndroid Build Coastguard Worker public:
GetVersion(JNIEnv * env)1806*795d594fSAndroid Build Coastguard Worker static jint GetVersion(JNIEnv* env) {
1807*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1808*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1809*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1810*795d594fSAndroid Build Coastguard Worker JniValueType args[1] = {{.E = env }};
1811*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "E", args)) {
1812*795d594fSAndroid Build Coastguard Worker JniValueType result;
1813*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->GetVersion(env);
1814*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "I", &result)) {
1815*795d594fSAndroid Build Coastguard Worker return result.I;
1816*795d594fSAndroid Build Coastguard Worker }
1817*795d594fSAndroid Build Coastguard Worker }
1818*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
1819*795d594fSAndroid Build Coastguard Worker }
1820*795d594fSAndroid Build Coastguard Worker
GetJavaVM(JNIEnv * env,JavaVM ** vm)1821*795d594fSAndroid Build Coastguard Worker static jint GetJavaVM(JNIEnv *env, JavaVM **vm) {
1822*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1823*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1824*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1825*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env }, {.p = vm}};
1826*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ep", args)) {
1827*795d594fSAndroid Build Coastguard Worker JniValueType result;
1828*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->GetJavaVM(env, vm);
1829*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
1830*795d594fSAndroid Build Coastguard Worker return result.i;
1831*795d594fSAndroid Build Coastguard Worker }
1832*795d594fSAndroid Build Coastguard Worker }
1833*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
1834*795d594fSAndroid Build Coastguard Worker }
1835*795d594fSAndroid Build Coastguard Worker
RegisterNatives(JNIEnv * env,jclass c,const JNINativeMethod * methods,jint nMethods)1836*795d594fSAndroid Build Coastguard Worker static jint RegisterNatives(JNIEnv* env, jclass c, const JNINativeMethod* methods, jint nMethods) {
1837*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1838*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1839*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1840*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env }, {.c = c}, {.p = methods}, {.I = nMethods}};
1841*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EcpI", args)) {
1842*795d594fSAndroid Build Coastguard Worker JniValueType result;
1843*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->RegisterNatives(env, c, methods, nMethods);
1844*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
1845*795d594fSAndroid Build Coastguard Worker return result.i;
1846*795d594fSAndroid Build Coastguard Worker }
1847*795d594fSAndroid Build Coastguard Worker }
1848*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
1849*795d594fSAndroid Build Coastguard Worker }
1850*795d594fSAndroid Build Coastguard Worker
UnregisterNatives(JNIEnv * env,jclass c)1851*795d594fSAndroid Build Coastguard Worker static jint UnregisterNatives(JNIEnv* env, jclass c) {
1852*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
1853*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1854*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1855*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env }, {.c = c}};
1856*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ec", args)) {
1857*795d594fSAndroid Build Coastguard Worker JniValueType result;
1858*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->UnregisterNatives(env, c);
1859*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
1860*795d594fSAndroid Build Coastguard Worker return result.i;
1861*795d594fSAndroid Build Coastguard Worker }
1862*795d594fSAndroid Build Coastguard Worker }
1863*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
1864*795d594fSAndroid Build Coastguard Worker }
1865*795d594fSAndroid Build Coastguard Worker
GetObjectRefType(JNIEnv * env,jobject obj)1866*795d594fSAndroid Build Coastguard Worker static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj) {
1867*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNIInvalidRefType);
1868*795d594fSAndroid Build Coastguard Worker // Note: we use "EL" here but "Ep" has been used in the past on the basis that we'd like to
1869*795d594fSAndroid Build Coastguard Worker // know the object is invalid. The spec says that passing invalid objects or even ones that
1870*795d594fSAndroid Build Coastguard Worker // are deleted isn't supported.
1871*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1872*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1873*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env }, {.L = obj}};
1874*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
1875*795d594fSAndroid Build Coastguard Worker JniValueType result;
1876*795d594fSAndroid Build Coastguard Worker result.w = baseEnv(env)->GetObjectRefType(env, obj);
1877*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "w", &result)) {
1878*795d594fSAndroid Build Coastguard Worker return result.w;
1879*795d594fSAndroid Build Coastguard Worker }
1880*795d594fSAndroid Build Coastguard Worker }
1881*795d594fSAndroid Build Coastguard Worker return JNIInvalidRefType;
1882*795d594fSAndroid Build Coastguard Worker }
1883*795d594fSAndroid Build Coastguard Worker
DefineClass(JNIEnv * env,const char * name,jobject loader,const jbyte * buf,jsize bufLen)1884*795d594fSAndroid Build Coastguard Worker static jclass DefineClass(JNIEnv* env, const char* name, jobject loader, const jbyte* buf,
1885*795d594fSAndroid Build Coastguard Worker jsize bufLen) {
1886*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1887*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1888*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1889*795d594fSAndroid Build Coastguard Worker JniValueType args[5] = {{.E = env}, {.u = name}, {.L = loader}, {.p = buf}, {.z = bufLen}};
1890*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EuLpz", args) && sc.CheckClassName(name)) {
1891*795d594fSAndroid Build Coastguard Worker JniValueType result;
1892*795d594fSAndroid Build Coastguard Worker result.c = baseEnv(env)->DefineClass(env, name, loader, buf, bufLen);
1893*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "c", &result)) {
1894*795d594fSAndroid Build Coastguard Worker return result.c;
1895*795d594fSAndroid Build Coastguard Worker }
1896*795d594fSAndroid Build Coastguard Worker }
1897*795d594fSAndroid Build Coastguard Worker return nullptr;
1898*795d594fSAndroid Build Coastguard Worker }
1899*795d594fSAndroid Build Coastguard Worker
FindClass(JNIEnv * env,const char * name)1900*795d594fSAndroid Build Coastguard Worker static jclass FindClass(JNIEnv* env, const char* name) {
1901*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1902*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1903*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1904*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.u = name}};
1905*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eu", args) && sc.CheckClassName(name)) {
1906*795d594fSAndroid Build Coastguard Worker JniValueType result;
1907*795d594fSAndroid Build Coastguard Worker result.c = baseEnv(env)->FindClass(env, name);
1908*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "c", &result)) {
1909*795d594fSAndroid Build Coastguard Worker return result.c;
1910*795d594fSAndroid Build Coastguard Worker }
1911*795d594fSAndroid Build Coastguard Worker }
1912*795d594fSAndroid Build Coastguard Worker return nullptr;
1913*795d594fSAndroid Build Coastguard Worker }
1914*795d594fSAndroid Build Coastguard Worker
GetSuperclass(JNIEnv * env,jclass c)1915*795d594fSAndroid Build Coastguard Worker static jclass GetSuperclass(JNIEnv* env, jclass c) {
1916*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1917*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1918*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1919*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.c = c}};
1920*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ec", args)) {
1921*795d594fSAndroid Build Coastguard Worker JniValueType result;
1922*795d594fSAndroid Build Coastguard Worker result.c = baseEnv(env)->GetSuperclass(env, c);
1923*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "c", &result)) {
1924*795d594fSAndroid Build Coastguard Worker return result.c;
1925*795d594fSAndroid Build Coastguard Worker }
1926*795d594fSAndroid Build Coastguard Worker }
1927*795d594fSAndroid Build Coastguard Worker return nullptr;
1928*795d594fSAndroid Build Coastguard Worker }
1929*795d594fSAndroid Build Coastguard Worker
IsAssignableFrom(JNIEnv * env,jclass c1,jclass c2)1930*795d594fSAndroid Build Coastguard Worker static jboolean IsAssignableFrom(JNIEnv* env, jclass c1, jclass c2) {
1931*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
1932*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1933*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1934*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.c = c1}, {.c = c2}};
1935*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecc", args)) {
1936*795d594fSAndroid Build Coastguard Worker JniValueType result;
1937*795d594fSAndroid Build Coastguard Worker result.b = baseEnv(env)->IsAssignableFrom(env, c1, c2);
1938*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "b", &result)) {
1939*795d594fSAndroid Build Coastguard Worker return result.b;
1940*795d594fSAndroid Build Coastguard Worker }
1941*795d594fSAndroid Build Coastguard Worker }
1942*795d594fSAndroid Build Coastguard Worker return JNI_FALSE;
1943*795d594fSAndroid Build Coastguard Worker }
1944*795d594fSAndroid Build Coastguard Worker
FromReflectedMethod(JNIEnv * env,jobject method)1945*795d594fSAndroid Build Coastguard Worker static jmethodID FromReflectedMethod(JNIEnv* env, jobject method) {
1946*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1947*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1948*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1949*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = method}};
1950*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedMethod(soa, method)) {
1951*795d594fSAndroid Build Coastguard Worker JniValueType result;
1952*795d594fSAndroid Build Coastguard Worker result.m = baseEnv(env)->FromReflectedMethod(env, method);
1953*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "m", &result)) {
1954*795d594fSAndroid Build Coastguard Worker return result.m;
1955*795d594fSAndroid Build Coastguard Worker }
1956*795d594fSAndroid Build Coastguard Worker }
1957*795d594fSAndroid Build Coastguard Worker return nullptr;
1958*795d594fSAndroid Build Coastguard Worker }
1959*795d594fSAndroid Build Coastguard Worker
FromReflectedField(JNIEnv * env,jobject field)1960*795d594fSAndroid Build Coastguard Worker static jfieldID FromReflectedField(JNIEnv* env, jobject field) {
1961*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1962*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1963*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1964*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = field}};
1965*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args) && sc.CheckReflectedField(soa, field)) {
1966*795d594fSAndroid Build Coastguard Worker JniValueType result;
1967*795d594fSAndroid Build Coastguard Worker result.f = baseEnv(env)->FromReflectedField(env, field);
1968*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "f", &result)) {
1969*795d594fSAndroid Build Coastguard Worker return result.f;
1970*795d594fSAndroid Build Coastguard Worker }
1971*795d594fSAndroid Build Coastguard Worker }
1972*795d594fSAndroid Build Coastguard Worker return nullptr;
1973*795d594fSAndroid Build Coastguard Worker }
1974*795d594fSAndroid Build Coastguard Worker
ToReflectedMethod(JNIEnv * env,jclass cls,jmethodID mid,jboolean isStatic)1975*795d594fSAndroid Build Coastguard Worker static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID mid, jboolean isStatic) {
1976*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1977*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1978*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1979*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.c = cls}, {.m = mid}, {.I = isStatic}};
1980*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecmb", args)) {
1981*795d594fSAndroid Build Coastguard Worker JniValueType result;
1982*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->ToReflectedMethod(env, cls, mid, isStatic);
1983*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
1984*795d594fSAndroid Build Coastguard Worker DCHECK(sc.CheckReflectedMethod(soa, result.L));
1985*795d594fSAndroid Build Coastguard Worker return result.L;
1986*795d594fSAndroid Build Coastguard Worker }
1987*795d594fSAndroid Build Coastguard Worker }
1988*795d594fSAndroid Build Coastguard Worker return nullptr;
1989*795d594fSAndroid Build Coastguard Worker }
1990*795d594fSAndroid Build Coastguard Worker
ToReflectedField(JNIEnv * env,jclass cls,jfieldID fid,jboolean isStatic)1991*795d594fSAndroid Build Coastguard Worker static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fid, jboolean isStatic) {
1992*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
1993*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
1994*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
1995*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.c = cls}, {.f = fid}, {.I = isStatic}};
1996*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecfb", args)) {
1997*795d594fSAndroid Build Coastguard Worker JniValueType result;
1998*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->ToReflectedField(env, cls, fid, isStatic);
1999*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result) && (result.L != nullptr)) {
2000*795d594fSAndroid Build Coastguard Worker DCHECK(sc.CheckReflectedField(soa, result.L));
2001*795d594fSAndroid Build Coastguard Worker return result.L;
2002*795d594fSAndroid Build Coastguard Worker }
2003*795d594fSAndroid Build Coastguard Worker }
2004*795d594fSAndroid Build Coastguard Worker return nullptr;
2005*795d594fSAndroid Build Coastguard Worker }
2006*795d594fSAndroid Build Coastguard Worker
Throw(JNIEnv * env,jthrowable obj)2007*795d594fSAndroid Build Coastguard Worker static jint Throw(JNIEnv* env, jthrowable obj) {
2008*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2009*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2010*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2011*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.t = obj}};
2012*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Et", args) && sc.CheckThrowable(soa, obj)) {
2013*795d594fSAndroid Build Coastguard Worker JniValueType result;
2014*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->Throw(env, obj);
2015*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
2016*795d594fSAndroid Build Coastguard Worker return result.i;
2017*795d594fSAndroid Build Coastguard Worker }
2018*795d594fSAndroid Build Coastguard Worker }
2019*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2020*795d594fSAndroid Build Coastguard Worker }
2021*795d594fSAndroid Build Coastguard Worker
ThrowNew(JNIEnv * env,jclass c,const char * message)2022*795d594fSAndroid Build Coastguard Worker static jint ThrowNew(JNIEnv* env, jclass c, const char* message) {
2023*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2024*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2025*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2026*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.c = c}, {.u = message}};
2027*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecu", args) && sc.CheckThrowableClass(soa, c)) {
2028*795d594fSAndroid Build Coastguard Worker JniValueType result;
2029*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->ThrowNew(env, c, message);
2030*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
2031*795d594fSAndroid Build Coastguard Worker return result.i;
2032*795d594fSAndroid Build Coastguard Worker }
2033*795d594fSAndroid Build Coastguard Worker }
2034*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2035*795d594fSAndroid Build Coastguard Worker }
2036*795d594fSAndroid Build Coastguard Worker
ExceptionOccurred(JNIEnv * env)2037*795d594fSAndroid Build Coastguard Worker static jthrowable ExceptionOccurred(JNIEnv* env) {
2038*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2039*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2040*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2041*795d594fSAndroid Build Coastguard Worker JniValueType args[1] = {{.E = env}};
2042*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "E", args)) {
2043*795d594fSAndroid Build Coastguard Worker JniValueType result;
2044*795d594fSAndroid Build Coastguard Worker result.t = baseEnv(env)->ExceptionOccurred(env);
2045*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "t", &result)) {
2046*795d594fSAndroid Build Coastguard Worker return result.t;
2047*795d594fSAndroid Build Coastguard Worker }
2048*795d594fSAndroid Build Coastguard Worker }
2049*795d594fSAndroid Build Coastguard Worker return nullptr;
2050*795d594fSAndroid Build Coastguard Worker }
2051*795d594fSAndroid Build Coastguard Worker
ExceptionDescribe(JNIEnv * env)2052*795d594fSAndroid Build Coastguard Worker static void ExceptionDescribe(JNIEnv* env) {
2053*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2054*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2055*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2056*795d594fSAndroid Build Coastguard Worker JniValueType args[1] = {{.E = env}};
2057*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "E", args)) {
2058*795d594fSAndroid Build Coastguard Worker JniValueType result;
2059*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ExceptionDescribe(env);
2060*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2061*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2062*795d594fSAndroid Build Coastguard Worker }
2063*795d594fSAndroid Build Coastguard Worker }
2064*795d594fSAndroid Build Coastguard Worker
ExceptionClear(JNIEnv * env)2065*795d594fSAndroid Build Coastguard Worker static void ExceptionClear(JNIEnv* env) {
2066*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2067*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2068*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2069*795d594fSAndroid Build Coastguard Worker JniValueType args[1] = {{.E = env}};
2070*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "E", args)) {
2071*795d594fSAndroid Build Coastguard Worker JniValueType result;
2072*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ExceptionClear(env);
2073*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2074*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2075*795d594fSAndroid Build Coastguard Worker }
2076*795d594fSAndroid Build Coastguard Worker }
2077*795d594fSAndroid Build Coastguard Worker
ExceptionCheck(JNIEnv * env)2078*795d594fSAndroid Build Coastguard Worker static jboolean ExceptionCheck(JNIEnv* env) {
2079*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
2080*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2081*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritOkay | kFlag_ExcepOkay, __FUNCTION__);
2082*795d594fSAndroid Build Coastguard Worker JniValueType args[1] = {{.E = env}};
2083*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "E", args)) {
2084*795d594fSAndroid Build Coastguard Worker JniValueType result;
2085*795d594fSAndroid Build Coastguard Worker result.b = baseEnv(env)->ExceptionCheck(env);
2086*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "b", &result)) {
2087*795d594fSAndroid Build Coastguard Worker return result.b;
2088*795d594fSAndroid Build Coastguard Worker }
2089*795d594fSAndroid Build Coastguard Worker }
2090*795d594fSAndroid Build Coastguard Worker return JNI_FALSE;
2091*795d594fSAndroid Build Coastguard Worker }
2092*795d594fSAndroid Build Coastguard Worker
FatalError(JNIEnv * env,const char * msg)2093*795d594fSAndroid Build Coastguard Worker static void FatalError(JNIEnv* env, const char* msg) {
2094*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2095*795d594fSAndroid Build Coastguard Worker // The JNI specification doesn't say it's okay to call FatalError with a pending exception,
2096*795d594fSAndroid Build Coastguard Worker // but you're about to abort anyway, and it's quite likely that you have a pending exception,
2097*795d594fSAndroid Build Coastguard Worker // and it's not unimaginable that you don't know that you do. So we allow it.
2098*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2099*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay | kFlag_NullableUtf, __FUNCTION__);
2100*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.u = msg}};
2101*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eu", args)) {
2102*795d594fSAndroid Build Coastguard Worker JniValueType result;
2103*795d594fSAndroid Build Coastguard Worker baseEnv(env)->FatalError(env, msg);
2104*795d594fSAndroid Build Coastguard Worker // Unreachable.
2105*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2106*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2107*795d594fSAndroid Build Coastguard Worker }
2108*795d594fSAndroid Build Coastguard Worker }
2109*795d594fSAndroid Build Coastguard Worker
PushLocalFrame(JNIEnv * env,jint capacity)2110*795d594fSAndroid Build Coastguard Worker static jint PushLocalFrame(JNIEnv* env, jint capacity) {
2111*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2112*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2113*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2114*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.I = capacity}};
2115*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EI", args)) {
2116*795d594fSAndroid Build Coastguard Worker JniValueType result;
2117*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->PushLocalFrame(env, capacity);
2118*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
2119*795d594fSAndroid Build Coastguard Worker return result.i;
2120*795d594fSAndroid Build Coastguard Worker }
2121*795d594fSAndroid Build Coastguard Worker }
2122*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2123*795d594fSAndroid Build Coastguard Worker }
2124*795d594fSAndroid Build Coastguard Worker
PopLocalFrame(JNIEnv * env,jobject res)2125*795d594fSAndroid Build Coastguard Worker static jobject PopLocalFrame(JNIEnv* env, jobject res) {
2126*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2127*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2128*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2129*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = res}};
2130*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
2131*795d594fSAndroid Build Coastguard Worker JniValueType result;
2132*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->PopLocalFrame(env, res);
2133*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "L", &result);
2134*795d594fSAndroid Build Coastguard Worker return result.L;
2135*795d594fSAndroid Build Coastguard Worker }
2136*795d594fSAndroid Build Coastguard Worker return nullptr;
2137*795d594fSAndroid Build Coastguard Worker }
2138*795d594fSAndroid Build Coastguard Worker
NewGlobalRef(JNIEnv * env,jobject obj)2139*795d594fSAndroid Build Coastguard Worker static jobject NewGlobalRef(JNIEnv* env, jobject obj) {
2140*795d594fSAndroid Build Coastguard Worker return NewRef(__FUNCTION__, env, obj, kGlobal);
2141*795d594fSAndroid Build Coastguard Worker }
2142*795d594fSAndroid Build Coastguard Worker
NewLocalRef(JNIEnv * env,jobject obj)2143*795d594fSAndroid Build Coastguard Worker static jobject NewLocalRef(JNIEnv* env, jobject obj) {
2144*795d594fSAndroid Build Coastguard Worker return NewRef(__FUNCTION__, env, obj, kLocal);
2145*795d594fSAndroid Build Coastguard Worker }
2146*795d594fSAndroid Build Coastguard Worker
NewWeakGlobalRef(JNIEnv * env,jobject obj)2147*795d594fSAndroid Build Coastguard Worker static jweak NewWeakGlobalRef(JNIEnv* env, jobject obj) {
2148*795d594fSAndroid Build Coastguard Worker return NewRef(__FUNCTION__, env, obj, kWeakGlobal);
2149*795d594fSAndroid Build Coastguard Worker }
2150*795d594fSAndroid Build Coastguard Worker
DeleteGlobalRef(JNIEnv * env,jobject obj)2151*795d594fSAndroid Build Coastguard Worker static void DeleteGlobalRef(JNIEnv* env, jobject obj) {
2152*795d594fSAndroid Build Coastguard Worker DeleteRef(__FUNCTION__, env, obj, kGlobal);
2153*795d594fSAndroid Build Coastguard Worker }
2154*795d594fSAndroid Build Coastguard Worker
DeleteWeakGlobalRef(JNIEnv * env,jweak obj)2155*795d594fSAndroid Build Coastguard Worker static void DeleteWeakGlobalRef(JNIEnv* env, jweak obj) {
2156*795d594fSAndroid Build Coastguard Worker DeleteRef(__FUNCTION__, env, obj, kWeakGlobal);
2157*795d594fSAndroid Build Coastguard Worker }
2158*795d594fSAndroid Build Coastguard Worker
DeleteLocalRef(JNIEnv * env,jobject obj)2159*795d594fSAndroid Build Coastguard Worker static void DeleteLocalRef(JNIEnv* env, jobject obj) {
2160*795d594fSAndroid Build Coastguard Worker DeleteRef(__FUNCTION__, env, obj, kLocal);
2161*795d594fSAndroid Build Coastguard Worker }
2162*795d594fSAndroid Build Coastguard Worker
EnsureLocalCapacity(JNIEnv * env,jint capacity)2163*795d594fSAndroid Build Coastguard Worker static jint EnsureLocalCapacity(JNIEnv *env, jint capacity) {
2164*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2165*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2166*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2167*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.I = capacity}};
2168*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EI", args)) {
2169*795d594fSAndroid Build Coastguard Worker JniValueType result;
2170*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->EnsureLocalCapacity(env, capacity);
2171*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
2172*795d594fSAndroid Build Coastguard Worker return result.i;
2173*795d594fSAndroid Build Coastguard Worker }
2174*795d594fSAndroid Build Coastguard Worker }
2175*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2176*795d594fSAndroid Build Coastguard Worker }
2177*795d594fSAndroid Build Coastguard Worker
IsSameObject(JNIEnv * env,jobject ref1,jobject ref2)2178*795d594fSAndroid Build Coastguard Worker static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2) {
2179*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
2180*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2181*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2182*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.L = ref1}, {.L = ref2}};
2183*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "ELL", args)) {
2184*795d594fSAndroid Build Coastguard Worker JniValueType result;
2185*795d594fSAndroid Build Coastguard Worker result.b = baseEnv(env)->IsSameObject(env, ref1, ref2);
2186*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "b", &result)) {
2187*795d594fSAndroid Build Coastguard Worker return result.b;
2188*795d594fSAndroid Build Coastguard Worker }
2189*795d594fSAndroid Build Coastguard Worker }
2190*795d594fSAndroid Build Coastguard Worker return JNI_FALSE;
2191*795d594fSAndroid Build Coastguard Worker }
2192*795d594fSAndroid Build Coastguard Worker
AllocObject(JNIEnv * env,jclass c)2193*795d594fSAndroid Build Coastguard Worker static jobject AllocObject(JNIEnv* env, jclass c) {
2194*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2195*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2196*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2197*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.c = c}};
2198*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ec", args) && sc.CheckInstantiableNonArray(soa, c)) {
2199*795d594fSAndroid Build Coastguard Worker JniValueType result;
2200*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->AllocObject(env, c);
2201*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result)) {
2202*795d594fSAndroid Build Coastguard Worker return result.L;
2203*795d594fSAndroid Build Coastguard Worker }
2204*795d594fSAndroid Build Coastguard Worker }
2205*795d594fSAndroid Build Coastguard Worker return nullptr;
2206*795d594fSAndroid Build Coastguard Worker }
2207*795d594fSAndroid Build Coastguard Worker
NewObjectV(JNIEnv * env,jclass c,jmethodID mid,va_list vargs)2208*795d594fSAndroid Build Coastguard Worker static jobject NewObjectV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2209*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2210*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2211*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2212*795d594fSAndroid Build Coastguard Worker VarArgs rest(mid, vargs);
2213*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2214*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
2215*795d594fSAndroid Build Coastguard Worker sc.CheckConstructor(mid)) {
2216*795d594fSAndroid Build Coastguard Worker JniValueType result;
2217*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->NewObjectV(env, c, mid, vargs);
2218*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result)) {
2219*795d594fSAndroid Build Coastguard Worker return result.L;
2220*795d594fSAndroid Build Coastguard Worker }
2221*795d594fSAndroid Build Coastguard Worker }
2222*795d594fSAndroid Build Coastguard Worker return nullptr;
2223*795d594fSAndroid Build Coastguard Worker }
2224*795d594fSAndroid Build Coastguard Worker
NewObject(JNIEnv * env,jclass c,jmethodID mid,...)2225*795d594fSAndroid Build Coastguard Worker static jobject NewObject(JNIEnv* env, jclass c, jmethodID mid, ...) {
2226*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2227*795d594fSAndroid Build Coastguard Worker va_list args;
2228*795d594fSAndroid Build Coastguard Worker va_start(args, mid);
2229*795d594fSAndroid Build Coastguard Worker jobject result = NewObjectV(env, c, mid, args);
2230*795d594fSAndroid Build Coastguard Worker va_end(args);
2231*795d594fSAndroid Build Coastguard Worker return result;
2232*795d594fSAndroid Build Coastguard Worker }
2233*795d594fSAndroid Build Coastguard Worker
NewObjectA(JNIEnv * env,jclass c,jmethodID mid,const jvalue * vargs)2234*795d594fSAndroid Build Coastguard Worker static jobject NewObjectA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) {
2235*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2236*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2237*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2238*795d594fSAndroid Build Coastguard Worker VarArgs rest(mid, vargs);
2239*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = &rest}};
2240*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecm.", args) && sc.CheckInstantiableNonArray(soa, c) &&
2241*795d594fSAndroid Build Coastguard Worker sc.CheckConstructor(mid)) {
2242*795d594fSAndroid Build Coastguard Worker JniValueType result;
2243*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->NewObjectA(env, c, mid, vargs);
2244*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result)) {
2245*795d594fSAndroid Build Coastguard Worker return result.L;
2246*795d594fSAndroid Build Coastguard Worker }
2247*795d594fSAndroid Build Coastguard Worker }
2248*795d594fSAndroid Build Coastguard Worker return nullptr;
2249*795d594fSAndroid Build Coastguard Worker }
2250*795d594fSAndroid Build Coastguard Worker
GetObjectClass(JNIEnv * env,jobject obj)2251*795d594fSAndroid Build Coastguard Worker static jclass GetObjectClass(JNIEnv* env, jobject obj) {
2252*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2253*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2254*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2255*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = obj}};
2256*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
2257*795d594fSAndroid Build Coastguard Worker JniValueType result;
2258*795d594fSAndroid Build Coastguard Worker result.c = baseEnv(env)->GetObjectClass(env, obj);
2259*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "c", &result)) {
2260*795d594fSAndroid Build Coastguard Worker return result.c;
2261*795d594fSAndroid Build Coastguard Worker }
2262*795d594fSAndroid Build Coastguard Worker }
2263*795d594fSAndroid Build Coastguard Worker return nullptr;
2264*795d594fSAndroid Build Coastguard Worker }
2265*795d594fSAndroid Build Coastguard Worker
IsInstanceOf(JNIEnv * env,jobject obj,jclass c)2266*795d594fSAndroid Build Coastguard Worker static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass c) {
2267*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_FALSE);
2268*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2269*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2270*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.L = obj}, {.c = c}};
2271*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "ELc", args)) {
2272*795d594fSAndroid Build Coastguard Worker JniValueType result;
2273*795d594fSAndroid Build Coastguard Worker result.b = baseEnv(env)->IsInstanceOf(env, obj, c);
2274*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "b", &result)) {
2275*795d594fSAndroid Build Coastguard Worker return result.b;
2276*795d594fSAndroid Build Coastguard Worker }
2277*795d594fSAndroid Build Coastguard Worker }
2278*795d594fSAndroid Build Coastguard Worker return JNI_FALSE;
2279*795d594fSAndroid Build Coastguard Worker }
2280*795d594fSAndroid Build Coastguard Worker
GetMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)2281*795d594fSAndroid Build Coastguard Worker static jmethodID GetMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2282*795d594fSAndroid Build Coastguard Worker return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, false);
2283*795d594fSAndroid Build Coastguard Worker }
2284*795d594fSAndroid Build Coastguard Worker
GetStaticMethodID(JNIEnv * env,jclass c,const char * name,const char * sig)2285*795d594fSAndroid Build Coastguard Worker static jmethodID GetStaticMethodID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2286*795d594fSAndroid Build Coastguard Worker return GetMethodIDInternal(__FUNCTION__, env, c, name, sig, true);
2287*795d594fSAndroid Build Coastguard Worker }
2288*795d594fSAndroid Build Coastguard Worker
GetFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)2289*795d594fSAndroid Build Coastguard Worker static jfieldID GetFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2290*795d594fSAndroid Build Coastguard Worker return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, false);
2291*795d594fSAndroid Build Coastguard Worker }
2292*795d594fSAndroid Build Coastguard Worker
GetStaticFieldID(JNIEnv * env,jclass c,const char * name,const char * sig)2293*795d594fSAndroid Build Coastguard Worker static jfieldID GetStaticFieldID(JNIEnv* env, jclass c, const char* name, const char* sig) {
2294*795d594fSAndroid Build Coastguard Worker return GetFieldIDInternal(__FUNCTION__, env, c, name, sig, true);
2295*795d594fSAndroid Build Coastguard Worker }
2296*795d594fSAndroid Build Coastguard Worker
2297*795d594fSAndroid Build Coastguard Worker #define FIELD_ACCESSORS(jtype, name, ptype, shorty, slot_sized_shorty) \
2298*795d594fSAndroid Build Coastguard Worker static jtype GetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid) { \
2299*795d594fSAndroid Build Coastguard Worker return GetField(__FUNCTION__, env, c, fid, true, ptype).shorty; \
2300*795d594fSAndroid Build Coastguard Worker } \
2301*795d594fSAndroid Build Coastguard Worker \
2302*795d594fSAndroid Build Coastguard Worker static jtype Get##name##Field(JNIEnv* env, jobject obj, jfieldID fid) { \
2303*795d594fSAndroid Build Coastguard Worker return GetField(__FUNCTION__, env, obj, fid, false, ptype).shorty; \
2304*795d594fSAndroid Build Coastguard Worker } \
2305*795d594fSAndroid Build Coastguard Worker \
2306*795d594fSAndroid Build Coastguard Worker static void SetStatic##name##Field(JNIEnv* env, jclass c, jfieldID fid, jtype v) { \
2307*795d594fSAndroid Build Coastguard Worker JniValueType value; \
2308*795d594fSAndroid Build Coastguard Worker value.slot_sized_shorty = v; \
2309*795d594fSAndroid Build Coastguard Worker SetField(__FUNCTION__, env, c, fid, true, ptype, value); \
2310*795d594fSAndroid Build Coastguard Worker } \
2311*795d594fSAndroid Build Coastguard Worker \
2312*795d594fSAndroid Build Coastguard Worker static void Set##name##Field(JNIEnv* env, jobject obj, jfieldID fid, jtype v) { \
2313*795d594fSAndroid Build Coastguard Worker JniValueType value; \
2314*795d594fSAndroid Build Coastguard Worker value.slot_sized_shorty = v; \
2315*795d594fSAndroid Build Coastguard Worker SetField(__FUNCTION__, env, obj, fid, false, ptype, value); \
2316*795d594fSAndroid Build Coastguard Worker }
2317*795d594fSAndroid Build Coastguard Worker
FIELD_ACCESSORS(jobject,Object,Primitive::kPrimNot,L,L)2318*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jobject, Object, Primitive::kPrimNot, L, L)
2319*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jboolean, Boolean, Primitive::kPrimBoolean, Z, I)
2320*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jbyte, Byte, Primitive::kPrimByte, B, I)
2321*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jchar, Char, Primitive::kPrimChar, C, I)
2322*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jshort, Short, Primitive::kPrimShort, S, I)
2323*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jint, Int, Primitive::kPrimInt, I, I)
2324*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jlong, Long, Primitive::kPrimLong, J, J)
2325*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jfloat, Float, Primitive::kPrimFloat, F, F)
2326*795d594fSAndroid Build Coastguard Worker FIELD_ACCESSORS(jdouble, Double, Primitive::kPrimDouble, D, D)
2327*795d594fSAndroid Build Coastguard Worker #undef FIELD_ACCESSORS
2328*795d594fSAndroid Build Coastguard Worker
2329*795d594fSAndroid Build Coastguard Worker static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) {
2330*795d594fSAndroid Build Coastguard Worker CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2331*795d594fSAndroid Build Coastguard Worker }
2332*795d594fSAndroid Build Coastguard Worker
CallNonvirtualVoidMethodA(JNIEnv * env,jobject obj,jclass c,jmethodID mid,const jvalue * vargs)2333*795d594fSAndroid Build Coastguard Worker static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2334*795d594fSAndroid Build Coastguard Worker const jvalue* vargs) {
2335*795d594fSAndroid Build Coastguard Worker CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2336*795d594fSAndroid Build Coastguard Worker }
2337*795d594fSAndroid Build Coastguard Worker
CallStaticVoidMethodA(JNIEnv * env,jclass c,jmethodID mid,const jvalue * vargs)2338*795d594fSAndroid Build Coastguard Worker static void CallStaticVoidMethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) {
2339*795d594fSAndroid Build Coastguard Worker CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2340*795d594fSAndroid Build Coastguard Worker }
2341*795d594fSAndroid Build Coastguard Worker
CallVoidMethodV(JNIEnv * env,jobject obj,jmethodID mid,va_list vargs)2342*795d594fSAndroid Build Coastguard Worker static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) {
2343*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2344*795d594fSAndroid Build Coastguard Worker }
2345*795d594fSAndroid Build Coastguard Worker
CallNonvirtualVoidMethodV(JNIEnv * env,jobject obj,jclass c,jmethodID mid,va_list vargs)2346*795d594fSAndroid Build Coastguard Worker static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid,
2347*795d594fSAndroid Build Coastguard Worker va_list vargs) {
2348*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2349*795d594fSAndroid Build Coastguard Worker }
2350*795d594fSAndroid Build Coastguard Worker
2351*795d594fSAndroid Build Coastguard Worker NO_STACK_PROTECTOR
CallStaticVoidMethodV(JNIEnv * env,jclass c,jmethodID mid,va_list vargs)2352*795d594fSAndroid Build Coastguard Worker static void CallStaticVoidMethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) {
2353*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2354*795d594fSAndroid Build Coastguard Worker }
2355*795d594fSAndroid Build Coastguard Worker
CallVoidMethod(JNIEnv * env,jobject obj,jmethodID mid,...)2356*795d594fSAndroid Build Coastguard Worker static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) {
2357*795d594fSAndroid Build Coastguard Worker va_list vargs;
2358*795d594fSAndroid Build Coastguard Worker va_start(vargs, mid);
2359*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, Primitive::kPrimVoid, kVirtual);
2360*795d594fSAndroid Build Coastguard Worker va_end(vargs);
2361*795d594fSAndroid Build Coastguard Worker }
2362*795d594fSAndroid Build Coastguard Worker
CallNonvirtualVoidMethod(JNIEnv * env,jobject obj,jclass c,jmethodID mid,...)2363*795d594fSAndroid Build Coastguard Worker static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass c, jmethodID mid, ...) {
2364*795d594fSAndroid Build Coastguard Worker va_list vargs;
2365*795d594fSAndroid Build Coastguard Worker va_start(vargs, mid);
2366*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, Primitive::kPrimVoid, kDirect);
2367*795d594fSAndroid Build Coastguard Worker va_end(vargs);
2368*795d594fSAndroid Build Coastguard Worker }
2369*795d594fSAndroid Build Coastguard Worker
CallStaticVoidMethod(JNIEnv * env,jclass c,jmethodID mid,...)2370*795d594fSAndroid Build Coastguard Worker static void CallStaticVoidMethod(JNIEnv* env, jclass c, jmethodID mid, ...) {
2371*795d594fSAndroid Build Coastguard Worker va_list vargs;
2372*795d594fSAndroid Build Coastguard Worker va_start(vargs, mid);
2373*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, Primitive::kPrimVoid, kStatic);
2374*795d594fSAndroid Build Coastguard Worker va_end(vargs);
2375*795d594fSAndroid Build Coastguard Worker }
2376*795d594fSAndroid Build Coastguard Worker
2377*795d594fSAndroid Build Coastguard Worker #define CALL(rtype, name, ptype, shorty) \
2378*795d594fSAndroid Build Coastguard Worker static rtype Call##name##MethodA(JNIEnv* env, jobject obj, jmethodID mid, const jvalue* vargs) { \
2379*795d594fSAndroid Build Coastguard Worker return CallMethodA(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2380*795d594fSAndroid Build Coastguard Worker } \
2381*795d594fSAndroid Build Coastguard Worker \
2382*795d594fSAndroid Build Coastguard Worker static rtype CallNonvirtual##name##MethodA(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2383*795d594fSAndroid Build Coastguard Worker const jvalue* vargs) { \
2384*795d594fSAndroid Build Coastguard Worker return CallMethodA(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2385*795d594fSAndroid Build Coastguard Worker } \
2386*795d594fSAndroid Build Coastguard Worker \
2387*795d594fSAndroid Build Coastguard Worker static rtype CallStatic##name##MethodA(JNIEnv* env, jclass c, jmethodID mid, const jvalue* vargs) { \
2388*795d594fSAndroid Build Coastguard Worker return CallMethodA(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2389*795d594fSAndroid Build Coastguard Worker } \
2390*795d594fSAndroid Build Coastguard Worker \
2391*795d594fSAndroid Build Coastguard Worker static rtype Call##name##MethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list vargs) { \
2392*795d594fSAndroid Build Coastguard Worker return CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2393*795d594fSAndroid Build Coastguard Worker } \
2394*795d594fSAndroid Build Coastguard Worker \
2395*795d594fSAndroid Build Coastguard Worker static rtype CallNonvirtual##name##MethodV(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2396*795d594fSAndroid Build Coastguard Worker va_list vargs) { \
2397*795d594fSAndroid Build Coastguard Worker return CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2398*795d594fSAndroid Build Coastguard Worker } \
2399*795d594fSAndroid Build Coastguard Worker \
2400*795d594fSAndroid Build Coastguard Worker static rtype CallStatic##name##MethodV(JNIEnv* env, jclass c, jmethodID mid, va_list vargs) { \
2401*795d594fSAndroid Build Coastguard Worker return CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2402*795d594fSAndroid Build Coastguard Worker } \
2403*795d594fSAndroid Build Coastguard Worker \
2404*795d594fSAndroid Build Coastguard Worker static rtype Call##name##Method(JNIEnv* env, jobject obj, jmethodID mid, ...) { \
2405*795d594fSAndroid Build Coastguard Worker va_list vargs; \
2406*795d594fSAndroid Build Coastguard Worker va_start(vargs, mid); \
2407*795d594fSAndroid Build Coastguard Worker rtype result = \
2408*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, obj, nullptr, mid, vargs, ptype, kVirtual).shorty; \
2409*795d594fSAndroid Build Coastguard Worker va_end(vargs); \
2410*795d594fSAndroid Build Coastguard Worker return result; \
2411*795d594fSAndroid Build Coastguard Worker } \
2412*795d594fSAndroid Build Coastguard Worker \
2413*795d594fSAndroid Build Coastguard Worker static rtype CallNonvirtual##name##Method(JNIEnv* env, jobject obj, jclass c, jmethodID mid, \
2414*795d594fSAndroid Build Coastguard Worker ...) { \
2415*795d594fSAndroid Build Coastguard Worker va_list vargs; \
2416*795d594fSAndroid Build Coastguard Worker va_start(vargs, mid); \
2417*795d594fSAndroid Build Coastguard Worker rtype result = \
2418*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, obj, c, mid, vargs, ptype, kDirect).shorty; \
2419*795d594fSAndroid Build Coastguard Worker va_end(vargs); \
2420*795d594fSAndroid Build Coastguard Worker return result; \
2421*795d594fSAndroid Build Coastguard Worker } \
2422*795d594fSAndroid Build Coastguard Worker \
2423*795d594fSAndroid Build Coastguard Worker static rtype CallStatic##name##Method(JNIEnv* env, jclass c, jmethodID mid, ...) { \
2424*795d594fSAndroid Build Coastguard Worker va_list vargs; \
2425*795d594fSAndroid Build Coastguard Worker va_start(vargs, mid); \
2426*795d594fSAndroid Build Coastguard Worker rtype result = \
2427*795d594fSAndroid Build Coastguard Worker CallMethodV(__FUNCTION__, env, nullptr, c, mid, vargs, ptype, kStatic).shorty; \
2428*795d594fSAndroid Build Coastguard Worker va_end(vargs); \
2429*795d594fSAndroid Build Coastguard Worker return result; \
2430*795d594fSAndroid Build Coastguard Worker }
2431*795d594fSAndroid Build Coastguard Worker
CALL(jobject,Object,Primitive::kPrimNot,L)2432*795d594fSAndroid Build Coastguard Worker CALL(jobject, Object, Primitive::kPrimNot, L)
2433*795d594fSAndroid Build Coastguard Worker CALL(jboolean, Boolean, Primitive::kPrimBoolean, Z)
2434*795d594fSAndroid Build Coastguard Worker CALL(jbyte, Byte, Primitive::kPrimByte, B)
2435*795d594fSAndroid Build Coastguard Worker CALL(jchar, Char, Primitive::kPrimChar, C)
2436*795d594fSAndroid Build Coastguard Worker CALL(jshort, Short, Primitive::kPrimShort, S)
2437*795d594fSAndroid Build Coastguard Worker CALL(jint, Int, Primitive::kPrimInt, I)
2438*795d594fSAndroid Build Coastguard Worker CALL(jlong, Long, Primitive::kPrimLong, J)
2439*795d594fSAndroid Build Coastguard Worker CALL(jfloat, Float, Primitive::kPrimFloat, F)
2440*795d594fSAndroid Build Coastguard Worker CALL(jdouble, Double, Primitive::kPrimDouble, D)
2441*795d594fSAndroid Build Coastguard Worker #undef CALL
2442*795d594fSAndroid Build Coastguard Worker
2443*795d594fSAndroid Build Coastguard Worker static jstring NewString(JNIEnv* env, const jchar* unicode_chars, jsize len) {
2444*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2445*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2446*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2447*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.p = unicode_chars}, {.z = len}};
2448*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Epz", args)) {
2449*795d594fSAndroid Build Coastguard Worker JniValueType result;
2450*795d594fSAndroid Build Coastguard Worker result.s = baseEnv(env)->NewString(env, unicode_chars, len);
2451*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "s", &result)) {
2452*795d594fSAndroid Build Coastguard Worker return result.s;
2453*795d594fSAndroid Build Coastguard Worker }
2454*795d594fSAndroid Build Coastguard Worker }
2455*795d594fSAndroid Build Coastguard Worker return nullptr;
2456*795d594fSAndroid Build Coastguard Worker }
2457*795d594fSAndroid Build Coastguard Worker
NewStringUTF(JNIEnv * env,const char * chars)2458*795d594fSAndroid Build Coastguard Worker static jstring NewStringUTF(JNIEnv* env, const char* chars) {
2459*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2460*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2461*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_NullableUtf, __FUNCTION__);
2462*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.u = chars}};
2463*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eu", args)) {
2464*795d594fSAndroid Build Coastguard Worker JniValueType result;
2465*795d594fSAndroid Build Coastguard Worker // TODO: stale? show pointer and truncate string.
2466*795d594fSAndroid Build Coastguard Worker result.s = baseEnv(env)->NewStringUTF(env, chars);
2467*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "s", &result)) {
2468*795d594fSAndroid Build Coastguard Worker return result.s;
2469*795d594fSAndroid Build Coastguard Worker }
2470*795d594fSAndroid Build Coastguard Worker }
2471*795d594fSAndroid Build Coastguard Worker return nullptr;
2472*795d594fSAndroid Build Coastguard Worker }
2473*795d594fSAndroid Build Coastguard Worker
GetStringLength(JNIEnv * env,jstring string)2474*795d594fSAndroid Build Coastguard Worker static jsize GetStringLength(JNIEnv* env, jstring string) {
2475*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2476*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2477*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2478*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.s = string}};
2479*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Es", args)) {
2480*795d594fSAndroid Build Coastguard Worker JniValueType result;
2481*795d594fSAndroid Build Coastguard Worker result.z = baseEnv(env)->GetStringLength(env, string);
2482*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "z", &result)) {
2483*795d594fSAndroid Build Coastguard Worker return result.z;
2484*795d594fSAndroid Build Coastguard Worker }
2485*795d594fSAndroid Build Coastguard Worker }
2486*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2487*795d594fSAndroid Build Coastguard Worker }
2488*795d594fSAndroid Build Coastguard Worker
GetStringUTFLength(JNIEnv * env,jstring string)2489*795d594fSAndroid Build Coastguard Worker static jsize GetStringUTFLength(JNIEnv* env, jstring string) {
2490*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2491*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2492*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2493*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.s = string}};
2494*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Es", args)) {
2495*795d594fSAndroid Build Coastguard Worker JniValueType result;
2496*795d594fSAndroid Build Coastguard Worker result.z = baseEnv(env)->GetStringUTFLength(env, string);
2497*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "z", &result)) {
2498*795d594fSAndroid Build Coastguard Worker return result.z;
2499*795d594fSAndroid Build Coastguard Worker }
2500*795d594fSAndroid Build Coastguard Worker }
2501*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2502*795d594fSAndroid Build Coastguard Worker }
2503*795d594fSAndroid Build Coastguard Worker
GetStringChars(JNIEnv * env,jstring string,jboolean * is_copy)2504*795d594fSAndroid Build Coastguard Worker static const jchar* GetStringChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2505*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2506*795d594fSAndroid Build Coastguard Worker is_copy, false, false));
2507*795d594fSAndroid Build Coastguard Worker }
2508*795d594fSAndroid Build Coastguard Worker
GetStringUTFChars(JNIEnv * env,jstring string,jboolean * is_copy)2509*795d594fSAndroid Build Coastguard Worker static const char* GetStringUTFChars(JNIEnv* env, jstring string, jboolean* is_copy) {
2510*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const char*>(GetStringCharsInternal(__FUNCTION__, env, string,
2511*795d594fSAndroid Build Coastguard Worker is_copy, true, false));
2512*795d594fSAndroid Build Coastguard Worker }
2513*795d594fSAndroid Build Coastguard Worker
GetStringCritical(JNIEnv * env,jstring string,jboolean * is_copy)2514*795d594fSAndroid Build Coastguard Worker static const jchar* GetStringCritical(JNIEnv* env, jstring string, jboolean* is_copy) {
2515*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<const jchar*>(GetStringCharsInternal(__FUNCTION__, env, string,
2516*795d594fSAndroid Build Coastguard Worker is_copy, false, true));
2517*795d594fSAndroid Build Coastguard Worker }
2518*795d594fSAndroid Build Coastguard Worker
ReleaseStringChars(JNIEnv * env,jstring string,const jchar * chars)2519*795d594fSAndroid Build Coastguard Worker static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars) {
2520*795d594fSAndroid Build Coastguard Worker ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, false);
2521*795d594fSAndroid Build Coastguard Worker }
2522*795d594fSAndroid Build Coastguard Worker
ReleaseStringUTFChars(JNIEnv * env,jstring string,const char * utf)2523*795d594fSAndroid Build Coastguard Worker static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf) {
2524*795d594fSAndroid Build Coastguard Worker ReleaseStringCharsInternal(__FUNCTION__, env, string, utf, true, false);
2525*795d594fSAndroid Build Coastguard Worker }
2526*795d594fSAndroid Build Coastguard Worker
ReleaseStringCritical(JNIEnv * env,jstring string,const jchar * chars)2527*795d594fSAndroid Build Coastguard Worker static void ReleaseStringCritical(JNIEnv* env, jstring string, const jchar* chars) {
2528*795d594fSAndroid Build Coastguard Worker ReleaseStringCharsInternal(__FUNCTION__, env, string, chars, false, true);
2529*795d594fSAndroid Build Coastguard Worker }
2530*795d594fSAndroid Build Coastguard Worker
GetStringRegion(JNIEnv * env,jstring string,jsize start,jsize len,jchar * buf)2531*795d594fSAndroid Build Coastguard Worker static void GetStringRegion(JNIEnv* env, jstring string, jsize start, jsize len, jchar* buf) {
2532*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2533*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2534*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2535*795d594fSAndroid Build Coastguard Worker JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2536*795d594fSAndroid Build Coastguard Worker // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2537*795d594fSAndroid Build Coastguard Worker // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2538*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EsIIp", args)) {
2539*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetStringRegion(env, string, start, len, buf);
2540*795d594fSAndroid Build Coastguard Worker JniValueType result;
2541*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2542*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2543*795d594fSAndroid Build Coastguard Worker }
2544*795d594fSAndroid Build Coastguard Worker }
2545*795d594fSAndroid Build Coastguard Worker
GetStringUTFRegion(JNIEnv * env,jstring string,jsize start,jsize len,char * buf)2546*795d594fSAndroid Build Coastguard Worker static void GetStringUTFRegion(JNIEnv* env, jstring string, jsize start, jsize len, char* buf) {
2547*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2548*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2549*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2550*795d594fSAndroid Build Coastguard Worker JniValueType args[5] = {{.E = env}, {.s = string}, {.z = start}, {.z = len}, {.p = buf}};
2551*795d594fSAndroid Build Coastguard Worker // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
2552*795d594fSAndroid Build Coastguard Worker // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
2553*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EsIIp", args)) {
2554*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetStringUTFRegion(env, string, start, len, buf);
2555*795d594fSAndroid Build Coastguard Worker JniValueType result;
2556*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2557*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2558*795d594fSAndroid Build Coastguard Worker }
2559*795d594fSAndroid Build Coastguard Worker }
2560*795d594fSAndroid Build Coastguard Worker
GetArrayLength(JNIEnv * env,jarray array)2561*795d594fSAndroid Build Coastguard Worker static jsize GetArrayLength(JNIEnv* env, jarray array) {
2562*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2563*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2564*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritOkay, __FUNCTION__);
2565*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.a = array}};
2566*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ea", args)) {
2567*795d594fSAndroid Build Coastguard Worker JniValueType result;
2568*795d594fSAndroid Build Coastguard Worker result.z = baseEnv(env)->GetArrayLength(env, array);
2569*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "z", &result)) {
2570*795d594fSAndroid Build Coastguard Worker return result.z;
2571*795d594fSAndroid Build Coastguard Worker }
2572*795d594fSAndroid Build Coastguard Worker }
2573*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2574*795d594fSAndroid Build Coastguard Worker }
2575*795d594fSAndroid Build Coastguard Worker
NewObjectArray(JNIEnv * env,jsize length,jclass element_class,jobject initial_element)2576*795d594fSAndroid Build Coastguard Worker static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_class,
2577*795d594fSAndroid Build Coastguard Worker jobject initial_element) {
2578*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2579*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2580*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2581*795d594fSAndroid Build Coastguard Worker JniValueType args[4] =
2582*795d594fSAndroid Build Coastguard Worker {{.E = env}, {.z = length}, {.c = element_class}, {.L = initial_element}};
2583*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EzcL", args)) {
2584*795d594fSAndroid Build Coastguard Worker JniValueType result;
2585*795d594fSAndroid Build Coastguard Worker // Note: assignability tests of initial_element are done in the base implementation.
2586*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewObjectArray(env, length, element_class, initial_element);
2587*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "a", &result)) {
2588*795d594fSAndroid Build Coastguard Worker return down_cast<jobjectArray>(result.a);
2589*795d594fSAndroid Build Coastguard Worker }
2590*795d594fSAndroid Build Coastguard Worker }
2591*795d594fSAndroid Build Coastguard Worker return nullptr;
2592*795d594fSAndroid Build Coastguard Worker }
2593*795d594fSAndroid Build Coastguard Worker
GetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index)2594*795d594fSAndroid Build Coastguard Worker static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index) {
2595*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2596*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2597*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2598*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.a = array}, {.z = index}};
2599*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eaz", args)) {
2600*795d594fSAndroid Build Coastguard Worker JniValueType result;
2601*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->GetObjectArrayElement(env, array, index);
2602*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result)) {
2603*795d594fSAndroid Build Coastguard Worker return result.L;
2604*795d594fSAndroid Build Coastguard Worker }
2605*795d594fSAndroid Build Coastguard Worker }
2606*795d594fSAndroid Build Coastguard Worker return nullptr;
2607*795d594fSAndroid Build Coastguard Worker }
2608*795d594fSAndroid Build Coastguard Worker
SetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index,jobject value)2609*795d594fSAndroid Build Coastguard Worker static void SetObjectArrayElement(JNIEnv* env, jobjectArray array, jsize index, jobject value) {
2610*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2611*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2612*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2613*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.a = array}, {.z = index}, {.L = value}};
2614*795d594fSAndroid Build Coastguard Worker // Note: the index arguments is checked as 'I' rather than 'z' as invalid indices result in
2615*795d594fSAndroid Build Coastguard Worker // ArrayIndexOutOfBoundsExceptions in the base implementation. Similarly invalid stores result
2616*795d594fSAndroid Build Coastguard Worker // in ArrayStoreExceptions.
2617*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EaIL", args)) {
2618*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetObjectArrayElement(env, array, index, value);
2619*795d594fSAndroid Build Coastguard Worker JniValueType result;
2620*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2621*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2622*795d594fSAndroid Build Coastguard Worker }
2623*795d594fSAndroid Build Coastguard Worker }
2624*795d594fSAndroid Build Coastguard Worker
NewBooleanArray(JNIEnv * env,jsize length)2625*795d594fSAndroid Build Coastguard Worker static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) {
2626*795d594fSAndroid Build Coastguard Worker return down_cast<jbooleanArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2627*795d594fSAndroid Build Coastguard Worker Primitive::kPrimBoolean));
2628*795d594fSAndroid Build Coastguard Worker }
2629*795d594fSAndroid Build Coastguard Worker
NewByteArray(JNIEnv * env,jsize length)2630*795d594fSAndroid Build Coastguard Worker static jbyteArray NewByteArray(JNIEnv* env, jsize length) {
2631*795d594fSAndroid Build Coastguard Worker return down_cast<jbyteArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2632*795d594fSAndroid Build Coastguard Worker Primitive::kPrimByte));
2633*795d594fSAndroid Build Coastguard Worker }
2634*795d594fSAndroid Build Coastguard Worker
NewCharArray(JNIEnv * env,jsize length)2635*795d594fSAndroid Build Coastguard Worker static jcharArray NewCharArray(JNIEnv* env, jsize length) {
2636*795d594fSAndroid Build Coastguard Worker return down_cast<jcharArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2637*795d594fSAndroid Build Coastguard Worker Primitive::kPrimChar));
2638*795d594fSAndroid Build Coastguard Worker }
2639*795d594fSAndroid Build Coastguard Worker
NewShortArray(JNIEnv * env,jsize length)2640*795d594fSAndroid Build Coastguard Worker static jshortArray NewShortArray(JNIEnv* env, jsize length) {
2641*795d594fSAndroid Build Coastguard Worker return down_cast<jshortArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2642*795d594fSAndroid Build Coastguard Worker Primitive::kPrimShort));
2643*795d594fSAndroid Build Coastguard Worker }
2644*795d594fSAndroid Build Coastguard Worker
NewIntArray(JNIEnv * env,jsize length)2645*795d594fSAndroid Build Coastguard Worker static jintArray NewIntArray(JNIEnv* env, jsize length) {
2646*795d594fSAndroid Build Coastguard Worker return down_cast<jintArray>(NewPrimitiveArray(__FUNCTION__, env, length, Primitive::kPrimInt));
2647*795d594fSAndroid Build Coastguard Worker }
2648*795d594fSAndroid Build Coastguard Worker
NewLongArray(JNIEnv * env,jsize length)2649*795d594fSAndroid Build Coastguard Worker static jlongArray NewLongArray(JNIEnv* env, jsize length) {
2650*795d594fSAndroid Build Coastguard Worker return down_cast<jlongArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2651*795d594fSAndroid Build Coastguard Worker Primitive::kPrimLong));
2652*795d594fSAndroid Build Coastguard Worker }
2653*795d594fSAndroid Build Coastguard Worker
NewFloatArray(JNIEnv * env,jsize length)2654*795d594fSAndroid Build Coastguard Worker static jfloatArray NewFloatArray(JNIEnv* env, jsize length) {
2655*795d594fSAndroid Build Coastguard Worker return down_cast<jfloatArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2656*795d594fSAndroid Build Coastguard Worker Primitive::kPrimFloat));
2657*795d594fSAndroid Build Coastguard Worker }
2658*795d594fSAndroid Build Coastguard Worker
NewDoubleArray(JNIEnv * env,jsize length)2659*795d594fSAndroid Build Coastguard Worker static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) {
2660*795d594fSAndroid Build Coastguard Worker return down_cast<jdoubleArray>(NewPrimitiveArray(__FUNCTION__, env, length,
2661*795d594fSAndroid Build Coastguard Worker Primitive::kPrimDouble));
2662*795d594fSAndroid Build Coastguard Worker }
2663*795d594fSAndroid Build Coastguard Worker
2664*795d594fSAndroid Build Coastguard Worker // NOLINT added to avoid wrong warning/fix from clang-tidy.
2665*795d594fSAndroid Build Coastguard Worker #define PRIMITIVE_ARRAY_FUNCTIONS(ctype, name, ptype) \
2666*795d594fSAndroid Build Coastguard Worker static ctype* Get##name##ArrayElements(JNIEnv* env, ctype##Array array, jboolean* is_copy) { /* NOLINT */ \
2667*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<ctype*>( /* NOLINT */ \
2668*795d594fSAndroid Build Coastguard Worker GetPrimitiveArrayElements(__FUNCTION__, ptype, env, array, is_copy)); \
2669*795d594fSAndroid Build Coastguard Worker } \
2670*795d594fSAndroid Build Coastguard Worker \
2671*795d594fSAndroid Build Coastguard Worker static void Release##name##ArrayElements(JNIEnv* env, ctype##Array array, ctype* elems, /* NOLINT */ \
2672*795d594fSAndroid Build Coastguard Worker jint mode) { \
2673*795d594fSAndroid Build Coastguard Worker ReleasePrimitiveArrayElements(__FUNCTION__, ptype, env, array, elems, mode); \
2674*795d594fSAndroid Build Coastguard Worker } \
2675*795d594fSAndroid Build Coastguard Worker \
2676*795d594fSAndroid Build Coastguard Worker static void Get##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2677*795d594fSAndroid Build Coastguard Worker ctype* buf) { /* NOLINT */ \
2678*795d594fSAndroid Build Coastguard Worker GetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2679*795d594fSAndroid Build Coastguard Worker } \
2680*795d594fSAndroid Build Coastguard Worker \
2681*795d594fSAndroid Build Coastguard Worker static void Set##name##ArrayRegion(JNIEnv* env, ctype##Array array, jsize start, jsize len, \
2682*795d594fSAndroid Build Coastguard Worker const ctype* buf) { \
2683*795d594fSAndroid Build Coastguard Worker SetPrimitiveArrayRegion(__FUNCTION__, ptype, env, array, start, len, buf); \
2684*795d594fSAndroid Build Coastguard Worker }
2685*795d594fSAndroid Build Coastguard Worker
PRIMITIVE_ARRAY_FUNCTIONS(jboolean,Boolean,Primitive::kPrimBoolean)2686*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, Primitive::kPrimBoolean)
2687*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, Primitive::kPrimByte)
2688*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, Primitive::kPrimChar)
2689*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, Primitive::kPrimShort)
2690*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, Primitive::kPrimInt)
2691*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, Primitive::kPrimLong)
2692*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, Primitive::kPrimFloat)
2693*795d594fSAndroid Build Coastguard Worker PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, Primitive::kPrimDouble)
2694*795d594fSAndroid Build Coastguard Worker #undef PRIMITIVE_ARRAY_FUNCTIONS
2695*795d594fSAndroid Build Coastguard Worker
2696*795d594fSAndroid Build Coastguard Worker static jint MonitorEnter(JNIEnv* env, jobject obj) {
2697*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2698*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2699*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2700*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = obj}};
2701*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
2702*795d594fSAndroid Build Coastguard Worker if (obj != nullptr) {
2703*795d594fSAndroid Build Coastguard Worker down_cast<JNIEnvExt*>(env)->RecordMonitorEnter(obj);
2704*795d594fSAndroid Build Coastguard Worker }
2705*795d594fSAndroid Build Coastguard Worker JniValueType result;
2706*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->MonitorEnter(env, obj);
2707*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
2708*795d594fSAndroid Build Coastguard Worker return result.i;
2709*795d594fSAndroid Build Coastguard Worker }
2710*795d594fSAndroid Build Coastguard Worker }
2711*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2712*795d594fSAndroid Build Coastguard Worker }
2713*795d594fSAndroid Build Coastguard Worker
MonitorExit(JNIEnv * env,jobject obj)2714*795d594fSAndroid Build Coastguard Worker static jint MonitorExit(JNIEnv* env, jobject obj) {
2715*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2716*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2717*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, __FUNCTION__);
2718*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = obj}};
2719*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
2720*795d594fSAndroid Build Coastguard Worker if (obj != nullptr) {
2721*795d594fSAndroid Build Coastguard Worker down_cast<JNIEnvExt*>(env)->CheckMonitorRelease(obj);
2722*795d594fSAndroid Build Coastguard Worker }
2723*795d594fSAndroid Build Coastguard Worker JniValueType result;
2724*795d594fSAndroid Build Coastguard Worker result.i = baseEnv(env)->MonitorExit(env, obj);
2725*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "i", &result)) {
2726*795d594fSAndroid Build Coastguard Worker return result.i;
2727*795d594fSAndroid Build Coastguard Worker }
2728*795d594fSAndroid Build Coastguard Worker }
2729*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2730*795d594fSAndroid Build Coastguard Worker }
2731*795d594fSAndroid Build Coastguard Worker
GetPrimitiveArrayCritical(JNIEnv * env,jarray array,jboolean * is_copy)2732*795d594fSAndroid Build Coastguard Worker static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array, jboolean* is_copy) {
2733*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2734*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2735*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritGet, __FUNCTION__);
2736*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
2737*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eap", args)) {
2738*795d594fSAndroid Build Coastguard Worker JniValueType result;
2739*795d594fSAndroid Build Coastguard Worker void* ptr = baseEnv(env)->GetPrimitiveArrayCritical(env, array, is_copy);
2740*795d594fSAndroid Build Coastguard Worker if (ptr != nullptr && soa.ForceCopy()) {
2741*795d594fSAndroid Build Coastguard Worker ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
2742*795d594fSAndroid Build Coastguard Worker }
2743*795d594fSAndroid Build Coastguard Worker result.p = ptr;
2744*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "p", &result)) {
2745*795d594fSAndroid Build Coastguard Worker return const_cast<void*>(result.p);
2746*795d594fSAndroid Build Coastguard Worker }
2747*795d594fSAndroid Build Coastguard Worker }
2748*795d594fSAndroid Build Coastguard Worker return nullptr;
2749*795d594fSAndroid Build Coastguard Worker }
2750*795d594fSAndroid Build Coastguard Worker
ReleasePrimitiveArrayCritical(JNIEnv * env,jarray array,void * carray,jint mode)2751*795d594fSAndroid Build Coastguard Worker static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* carray, jint mode) {
2752*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(__FUNCTION__);
2753*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2754*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_CritRelease | kFlag_ExcepOkay, __FUNCTION__);
2755*795d594fSAndroid Build Coastguard Worker sc.CheckNonNull(carray);
2756*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.a = array}, {.p = carray}, {.r = mode}};
2757*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eapr", args)) {
2758*795d594fSAndroid Build Coastguard Worker if (soa.ForceCopy()) {
2759*795d594fSAndroid Build Coastguard Worker carray = GuardedCopy::ReleaseGuardedPACopy(__FUNCTION__, env, array, carray, mode);
2760*795d594fSAndroid Build Coastguard Worker }
2761*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2762*795d594fSAndroid Build Coastguard Worker JniValueType result;
2763*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2764*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2765*795d594fSAndroid Build Coastguard Worker }
2766*795d594fSAndroid Build Coastguard Worker }
2767*795d594fSAndroid Build Coastguard Worker
NewDirectByteBuffer(JNIEnv * env,void * address,jlong capacity)2768*795d594fSAndroid Build Coastguard Worker static jobject NewDirectByteBuffer(JNIEnv* env, void* address, jlong capacity) {
2769*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2770*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2771*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2772*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.p = address}, {.J = capacity}};
2773*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EpJ", args)) {
2774*795d594fSAndroid Build Coastguard Worker JniValueType result;
2775*795d594fSAndroid Build Coastguard Worker // Note: the validity of address and capacity are checked in the base implementation.
2776*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->NewDirectByteBuffer(env, address, capacity);
2777*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result)) {
2778*795d594fSAndroid Build Coastguard Worker return result.L;
2779*795d594fSAndroid Build Coastguard Worker }
2780*795d594fSAndroid Build Coastguard Worker }
2781*795d594fSAndroid Build Coastguard Worker return nullptr;
2782*795d594fSAndroid Build Coastguard Worker }
2783*795d594fSAndroid Build Coastguard Worker
GetDirectBufferAddress(JNIEnv * env,jobject buf)2784*795d594fSAndroid Build Coastguard Worker static void* GetDirectBufferAddress(JNIEnv* env, jobject buf) {
2785*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, nullptr);
2786*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2787*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2788*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = buf}};
2789*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
2790*795d594fSAndroid Build Coastguard Worker JniValueType result;
2791*795d594fSAndroid Build Coastguard Worker // Note: this is implemented in the base environment by a GetLongField which will check the
2792*795d594fSAndroid Build Coastguard Worker // type of buf in GetLongField above.
2793*795d594fSAndroid Build Coastguard Worker result.p = baseEnv(env)->GetDirectBufferAddress(env, buf);
2794*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "p", &result)) {
2795*795d594fSAndroid Build Coastguard Worker return const_cast<void*>(result.p);
2796*795d594fSAndroid Build Coastguard Worker }
2797*795d594fSAndroid Build Coastguard Worker }
2798*795d594fSAndroid Build Coastguard Worker return nullptr;
2799*795d594fSAndroid Build Coastguard Worker }
2800*795d594fSAndroid Build Coastguard Worker
GetDirectBufferCapacity(JNIEnv * env,jobject buf)2801*795d594fSAndroid Build Coastguard Worker static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf) {
2802*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(__FUNCTION__, JNI_ERR);
2803*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2804*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, __FUNCTION__);
2805*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = buf}};
2806*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
2807*795d594fSAndroid Build Coastguard Worker JniValueType result;
2808*795d594fSAndroid Build Coastguard Worker // Note: this is implemented in the base environment by a GetIntField which will check the
2809*795d594fSAndroid Build Coastguard Worker // type of buf in GetIntField above.
2810*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->GetDirectBufferCapacity(env, buf);
2811*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "J", &result)) {
2812*795d594fSAndroid Build Coastguard Worker return result.J;
2813*795d594fSAndroid Build Coastguard Worker }
2814*795d594fSAndroid Build Coastguard Worker }
2815*795d594fSAndroid Build Coastguard Worker return JNI_ERR;
2816*795d594fSAndroid Build Coastguard Worker }
2817*795d594fSAndroid Build Coastguard Worker
2818*795d594fSAndroid Build Coastguard Worker private:
GetJavaVMExt(JNIEnv * env)2819*795d594fSAndroid Build Coastguard Worker static JavaVMExt* GetJavaVMExt(JNIEnv* env) {
2820*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<JNIEnvExt*>(env)->GetVm();
2821*795d594fSAndroid Build Coastguard Worker }
2822*795d594fSAndroid Build Coastguard Worker
baseEnv(JNIEnv * env)2823*795d594fSAndroid Build Coastguard Worker static const JNINativeInterface* baseEnv(JNIEnv* env) {
2824*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
2825*795d594fSAndroid Build Coastguard Worker }
2826*795d594fSAndroid Build Coastguard Worker
NewRef(const char * function_name,JNIEnv * env,jobject obj,IndirectRefKind kind)2827*795d594fSAndroid Build Coastguard Worker static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2828*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, nullptr);
2829*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2830*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
2831*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = obj}};
2832*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EL", args)) {
2833*795d594fSAndroid Build Coastguard Worker JniValueType result;
2834*795d594fSAndroid Build Coastguard Worker switch (kind) {
2835*795d594fSAndroid Build Coastguard Worker case kGlobal:
2836*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->NewGlobalRef(env, obj);
2837*795d594fSAndroid Build Coastguard Worker break;
2838*795d594fSAndroid Build Coastguard Worker case kLocal:
2839*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->NewLocalRef(env, obj);
2840*795d594fSAndroid Build Coastguard Worker break;
2841*795d594fSAndroid Build Coastguard Worker case kWeakGlobal:
2842*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->NewWeakGlobalRef(env, obj);
2843*795d594fSAndroid Build Coastguard Worker break;
2844*795d594fSAndroid Build Coastguard Worker default:
2845*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected reference kind: " << kind;
2846*795d594fSAndroid Build Coastguard Worker }
2847*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "L", &result)) {
2848*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(IsSameObject(env, obj, result.L), JNI_TRUE);
2849*795d594fSAndroid Build Coastguard Worker DCHECK(sc.CheckReferenceKind(kind, soa.Self(), result.L));
2850*795d594fSAndroid Build Coastguard Worker return result.L;
2851*795d594fSAndroid Build Coastguard Worker }
2852*795d594fSAndroid Build Coastguard Worker }
2853*795d594fSAndroid Build Coastguard Worker return nullptr;
2854*795d594fSAndroid Build Coastguard Worker }
2855*795d594fSAndroid Build Coastguard Worker
DeleteRef(const char * function_name,JNIEnv * env,jobject obj,IndirectRefKind kind)2856*795d594fSAndroid Build Coastguard Worker static void DeleteRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
2857*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(function_name);
2858*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2859*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, function_name);
2860*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.L = obj}};
2861*795d594fSAndroid Build Coastguard Worker sc.Check(soa, true, "EL", args);
2862*795d594fSAndroid Build Coastguard Worker if (sc.CheckReferenceKind(kind, soa.Self(), obj)) {
2863*795d594fSAndroid Build Coastguard Worker JniValueType result;
2864*795d594fSAndroid Build Coastguard Worker switch (kind) {
2865*795d594fSAndroid Build Coastguard Worker case kGlobal:
2866*795d594fSAndroid Build Coastguard Worker baseEnv(env)->DeleteGlobalRef(env, obj);
2867*795d594fSAndroid Build Coastguard Worker break;
2868*795d594fSAndroid Build Coastguard Worker case kLocal:
2869*795d594fSAndroid Build Coastguard Worker baseEnv(env)->DeleteLocalRef(env, obj);
2870*795d594fSAndroid Build Coastguard Worker break;
2871*795d594fSAndroid Build Coastguard Worker case kWeakGlobal:
2872*795d594fSAndroid Build Coastguard Worker baseEnv(env)->DeleteWeakGlobalRef(env, obj);
2873*795d594fSAndroid Build Coastguard Worker break;
2874*795d594fSAndroid Build Coastguard Worker default:
2875*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected reference kind: " << kind;
2876*795d594fSAndroid Build Coastguard Worker }
2877*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
2878*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
2879*795d594fSAndroid Build Coastguard Worker }
2880*795d594fSAndroid Build Coastguard Worker }
2881*795d594fSAndroid Build Coastguard Worker
GetMethodIDInternal(const char * function_name,JNIEnv * env,jclass c,const char * name,const char * sig,bool is_static)2882*795d594fSAndroid Build Coastguard Worker static jmethodID GetMethodIDInternal(const char* function_name, JNIEnv* env, jclass c,
2883*795d594fSAndroid Build Coastguard Worker const char* name, const char* sig, bool is_static) {
2884*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, nullptr);
2885*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2886*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
2887*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2888*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecuu", args)) {
2889*795d594fSAndroid Build Coastguard Worker JniValueType result;
2890*795d594fSAndroid Build Coastguard Worker if (is_static) {
2891*795d594fSAndroid Build Coastguard Worker result.m = baseEnv(env)->GetStaticMethodID(env, c, name, sig);
2892*795d594fSAndroid Build Coastguard Worker } else {
2893*795d594fSAndroid Build Coastguard Worker result.m = baseEnv(env)->GetMethodID(env, c, name, sig);
2894*795d594fSAndroid Build Coastguard Worker }
2895*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "m", &result)) {
2896*795d594fSAndroid Build Coastguard Worker return result.m;
2897*795d594fSAndroid Build Coastguard Worker }
2898*795d594fSAndroid Build Coastguard Worker }
2899*795d594fSAndroid Build Coastguard Worker return nullptr;
2900*795d594fSAndroid Build Coastguard Worker }
2901*795d594fSAndroid Build Coastguard Worker
GetFieldIDInternal(const char * function_name,JNIEnv * env,jclass c,const char * name,const char * sig,bool is_static)2902*795d594fSAndroid Build Coastguard Worker static jfieldID GetFieldIDInternal(const char* function_name, JNIEnv* env, jclass c,
2903*795d594fSAndroid Build Coastguard Worker const char* name, const char* sig, bool is_static) {
2904*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, nullptr);
2905*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2906*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
2907*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.c = c}, {.u = name}, {.u = sig}};
2908*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ecuu", args)) {
2909*795d594fSAndroid Build Coastguard Worker JniValueType result;
2910*795d594fSAndroid Build Coastguard Worker if (is_static) {
2911*795d594fSAndroid Build Coastguard Worker result.f = baseEnv(env)->GetStaticFieldID(env, c, name, sig);
2912*795d594fSAndroid Build Coastguard Worker } else {
2913*795d594fSAndroid Build Coastguard Worker result.f = baseEnv(env)->GetFieldID(env, c, name, sig);
2914*795d594fSAndroid Build Coastguard Worker }
2915*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "f", &result)) {
2916*795d594fSAndroid Build Coastguard Worker return result.f;
2917*795d594fSAndroid Build Coastguard Worker }
2918*795d594fSAndroid Build Coastguard Worker }
2919*795d594fSAndroid Build Coastguard Worker return nullptr;
2920*795d594fSAndroid Build Coastguard Worker }
2921*795d594fSAndroid Build Coastguard Worker
GetField(const char * function_name,JNIEnv * env,jobject obj,jfieldID fid,bool is_static,Primitive::Type type)2922*795d594fSAndroid Build Coastguard Worker static JniValueType GetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
2923*795d594fSAndroid Build Coastguard Worker bool is_static, Primitive::Type type) {
2924*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, JniValueType());
2925*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
2926*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
2927*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.L = obj}, {.f = fid}};
2928*795d594fSAndroid Build Coastguard Worker JniValueType result;
2929*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, is_static ? "Ecf" : "ELf", args) &&
2930*795d594fSAndroid Build Coastguard Worker sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
2931*795d594fSAndroid Build Coastguard Worker const char* result_check = nullptr;
2932*795d594fSAndroid Build Coastguard Worker switch (type) {
2933*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimNot:
2934*795d594fSAndroid Build Coastguard Worker if (is_static) {
2935*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->GetStaticObjectField(env, down_cast<jclass>(obj), fid);
2936*795d594fSAndroid Build Coastguard Worker } else {
2937*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->GetObjectField(env, obj, fid);
2938*795d594fSAndroid Build Coastguard Worker }
2939*795d594fSAndroid Build Coastguard Worker result_check = "L";
2940*795d594fSAndroid Build Coastguard Worker break;
2941*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
2942*795d594fSAndroid Build Coastguard Worker if (is_static) {
2943*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->GetStaticBooleanField(env, down_cast<jclass>(obj), fid);
2944*795d594fSAndroid Build Coastguard Worker } else {
2945*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->GetBooleanField(env, obj, fid);
2946*795d594fSAndroid Build Coastguard Worker }
2947*795d594fSAndroid Build Coastguard Worker result_check = "Z";
2948*795d594fSAndroid Build Coastguard Worker break;
2949*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
2950*795d594fSAndroid Build Coastguard Worker if (is_static) {
2951*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->GetStaticByteField(env, down_cast<jclass>(obj), fid);
2952*795d594fSAndroid Build Coastguard Worker } else {
2953*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->GetByteField(env, obj, fid);
2954*795d594fSAndroid Build Coastguard Worker }
2955*795d594fSAndroid Build Coastguard Worker result_check = "B";
2956*795d594fSAndroid Build Coastguard Worker break;
2957*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
2958*795d594fSAndroid Build Coastguard Worker if (is_static) {
2959*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->GetStaticCharField(env, down_cast<jclass>(obj), fid);
2960*795d594fSAndroid Build Coastguard Worker } else {
2961*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->GetCharField(env, obj, fid);
2962*795d594fSAndroid Build Coastguard Worker }
2963*795d594fSAndroid Build Coastguard Worker result_check = "C";
2964*795d594fSAndroid Build Coastguard Worker break;
2965*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
2966*795d594fSAndroid Build Coastguard Worker if (is_static) {
2967*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->GetStaticShortField(env, down_cast<jclass>(obj), fid);
2968*795d594fSAndroid Build Coastguard Worker } else {
2969*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->GetShortField(env, obj, fid);
2970*795d594fSAndroid Build Coastguard Worker }
2971*795d594fSAndroid Build Coastguard Worker result_check = "S";
2972*795d594fSAndroid Build Coastguard Worker break;
2973*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
2974*795d594fSAndroid Build Coastguard Worker if (is_static) {
2975*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->GetStaticIntField(env, down_cast<jclass>(obj), fid);
2976*795d594fSAndroid Build Coastguard Worker } else {
2977*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->GetIntField(env, obj, fid);
2978*795d594fSAndroid Build Coastguard Worker }
2979*795d594fSAndroid Build Coastguard Worker result_check = "I";
2980*795d594fSAndroid Build Coastguard Worker break;
2981*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
2982*795d594fSAndroid Build Coastguard Worker if (is_static) {
2983*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->GetStaticLongField(env, down_cast<jclass>(obj), fid);
2984*795d594fSAndroid Build Coastguard Worker } else {
2985*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->GetLongField(env, obj, fid);
2986*795d594fSAndroid Build Coastguard Worker }
2987*795d594fSAndroid Build Coastguard Worker result_check = "J";
2988*795d594fSAndroid Build Coastguard Worker break;
2989*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
2990*795d594fSAndroid Build Coastguard Worker if (is_static) {
2991*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->GetStaticFloatField(env, down_cast<jclass>(obj), fid);
2992*795d594fSAndroid Build Coastguard Worker } else {
2993*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->GetFloatField(env, obj, fid);
2994*795d594fSAndroid Build Coastguard Worker }
2995*795d594fSAndroid Build Coastguard Worker result_check = "F";
2996*795d594fSAndroid Build Coastguard Worker break;
2997*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
2998*795d594fSAndroid Build Coastguard Worker if (is_static) {
2999*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->GetStaticDoubleField(env, down_cast<jclass>(obj), fid);
3000*795d594fSAndroid Build Coastguard Worker } else {
3001*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->GetDoubleField(env, obj, fid);
3002*795d594fSAndroid Build Coastguard Worker }
3003*795d594fSAndroid Build Coastguard Worker result_check = "D";
3004*795d594fSAndroid Build Coastguard Worker break;
3005*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimVoid:
3006*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected type: " << type;
3007*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
3008*795d594fSAndroid Build Coastguard Worker }
3009*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, result_check, &result)) {
3010*795d594fSAndroid Build Coastguard Worker return result;
3011*795d594fSAndroid Build Coastguard Worker }
3012*795d594fSAndroid Build Coastguard Worker }
3013*795d594fSAndroid Build Coastguard Worker result.J = 0;
3014*795d594fSAndroid Build Coastguard Worker return result;
3015*795d594fSAndroid Build Coastguard Worker }
3016*795d594fSAndroid Build Coastguard Worker
SetField(const char * function_name,JNIEnv * env,jobject obj,jfieldID fid,bool is_static,Primitive::Type type,JniValueType value)3017*795d594fSAndroid Build Coastguard Worker static void SetField(const char* function_name, JNIEnv* env, jobject obj, jfieldID fid,
3018*795d594fSAndroid Build Coastguard Worker bool is_static, Primitive::Type type, JniValueType value) {
3019*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(function_name);
3020*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3021*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
3022*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.L = obj}, {.f = fid}, value};
3023*795d594fSAndroid Build Coastguard Worker char sig[5] = { 'E', is_static ? 'c' : 'L', 'f',
3024*795d594fSAndroid Build Coastguard Worker type == Primitive::kPrimNot ? 'L' : Primitive::Descriptor(type)[0], '\0'};
3025*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, sig, args) &&
3026*795d594fSAndroid Build Coastguard Worker sc.CheckFieldAccess(soa, obj, fid, is_static, type)) {
3027*795d594fSAndroid Build Coastguard Worker switch (type) {
3028*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimNot:
3029*795d594fSAndroid Build Coastguard Worker if (is_static) {
3030*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticObjectField(env, down_cast<jclass>(obj), fid, value.L);
3031*795d594fSAndroid Build Coastguard Worker } else {
3032*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetObjectField(env, obj, fid, value.L);
3033*795d594fSAndroid Build Coastguard Worker }
3034*795d594fSAndroid Build Coastguard Worker break;
3035*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3036*795d594fSAndroid Build Coastguard Worker if (is_static) {
3037*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticBooleanField(env, down_cast<jclass>(obj), fid, value.Z);
3038*795d594fSAndroid Build Coastguard Worker } else {
3039*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetBooleanField(env, obj, fid, value.Z);
3040*795d594fSAndroid Build Coastguard Worker }
3041*795d594fSAndroid Build Coastguard Worker break;
3042*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3043*795d594fSAndroid Build Coastguard Worker if (is_static) {
3044*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticByteField(env, down_cast<jclass>(obj), fid, value.B);
3045*795d594fSAndroid Build Coastguard Worker } else {
3046*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetByteField(env, obj, fid, value.B);
3047*795d594fSAndroid Build Coastguard Worker }
3048*795d594fSAndroid Build Coastguard Worker break;
3049*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3050*795d594fSAndroid Build Coastguard Worker if (is_static) {
3051*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticCharField(env, down_cast<jclass>(obj), fid, value.C);
3052*795d594fSAndroid Build Coastguard Worker } else {
3053*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetCharField(env, obj, fid, value.C);
3054*795d594fSAndroid Build Coastguard Worker }
3055*795d594fSAndroid Build Coastguard Worker break;
3056*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3057*795d594fSAndroid Build Coastguard Worker if (is_static) {
3058*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticShortField(env, down_cast<jclass>(obj), fid, value.S);
3059*795d594fSAndroid Build Coastguard Worker } else {
3060*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetShortField(env, obj, fid, value.S);
3061*795d594fSAndroid Build Coastguard Worker }
3062*795d594fSAndroid Build Coastguard Worker break;
3063*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3064*795d594fSAndroid Build Coastguard Worker if (is_static) {
3065*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticIntField(env, down_cast<jclass>(obj), fid, value.I);
3066*795d594fSAndroid Build Coastguard Worker } else {
3067*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetIntField(env, obj, fid, value.I);
3068*795d594fSAndroid Build Coastguard Worker }
3069*795d594fSAndroid Build Coastguard Worker break;
3070*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3071*795d594fSAndroid Build Coastguard Worker if (is_static) {
3072*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticLongField(env, down_cast<jclass>(obj), fid, value.J);
3073*795d594fSAndroid Build Coastguard Worker } else {
3074*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetLongField(env, obj, fid, value.J);
3075*795d594fSAndroid Build Coastguard Worker }
3076*795d594fSAndroid Build Coastguard Worker break;
3077*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3078*795d594fSAndroid Build Coastguard Worker if (is_static) {
3079*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticFloatField(env, down_cast<jclass>(obj), fid, value.F);
3080*795d594fSAndroid Build Coastguard Worker } else {
3081*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetFloatField(env, obj, fid, value.F);
3082*795d594fSAndroid Build Coastguard Worker }
3083*795d594fSAndroid Build Coastguard Worker break;
3084*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3085*795d594fSAndroid Build Coastguard Worker if (is_static) {
3086*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetStaticDoubleField(env, down_cast<jclass>(obj), fid, value.D);
3087*795d594fSAndroid Build Coastguard Worker } else {
3088*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetDoubleField(env, obj, fid, value.D);
3089*795d594fSAndroid Build Coastguard Worker }
3090*795d594fSAndroid Build Coastguard Worker break;
3091*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimVoid:
3092*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected type: " << type;
3093*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
3094*795d594fSAndroid Build Coastguard Worker }
3095*795d594fSAndroid Build Coastguard Worker JniValueType result;
3096*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
3097*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
3098*795d594fSAndroid Build Coastguard Worker }
3099*795d594fSAndroid Build Coastguard Worker }
3100*795d594fSAndroid Build Coastguard Worker
CheckCallArgs(ScopedObjectAccess & soa,ScopedCheck & sc,JNIEnv * env,jobject obj,jclass c,jmethodID mid,InvokeType invoke,const VarArgs * vargs)3101*795d594fSAndroid Build Coastguard Worker static bool CheckCallArgs(ScopedObjectAccess& soa, ScopedCheck& sc, JNIEnv* env, jobject obj,
3102*795d594fSAndroid Build Coastguard Worker jclass c, jmethodID mid, InvokeType invoke, const VarArgs* vargs)
3103*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
3104*795d594fSAndroid Build Coastguard Worker bool checked;
3105*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3106*795d594fSAndroid Build Coastguard Worker case kVirtual: {
3107*795d594fSAndroid Build Coastguard Worker DCHECK(c == nullptr);
3108*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.L = obj}, {.m = mid}, {.va = vargs}};
3109*795d594fSAndroid Build Coastguard Worker checked = sc.Check(soa, true, "ELm.", args);
3110*795d594fSAndroid Build Coastguard Worker break;
3111*795d594fSAndroid Build Coastguard Worker }
3112*795d594fSAndroid Build Coastguard Worker case kDirect: {
3113*795d594fSAndroid Build Coastguard Worker JniValueType args[5] = {{.E = env}, {.L = obj}, {.c = c}, {.m = mid}, {.va = vargs}};
3114*795d594fSAndroid Build Coastguard Worker checked = sc.Check(soa, true, "ELcm.", args);
3115*795d594fSAndroid Build Coastguard Worker break;
3116*795d594fSAndroid Build Coastguard Worker }
3117*795d594fSAndroid Build Coastguard Worker case kStatic: {
3118*795d594fSAndroid Build Coastguard Worker DCHECK(obj == nullptr);
3119*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.c = c}, {.m = mid}, {.va = vargs}};
3120*795d594fSAndroid Build Coastguard Worker checked = sc.Check(soa, true, "Ecm.", args);
3121*795d594fSAndroid Build Coastguard Worker break;
3122*795d594fSAndroid Build Coastguard Worker }
3123*795d594fSAndroid Build Coastguard Worker default:
3124*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3125*795d594fSAndroid Build Coastguard Worker checked = false;
3126*795d594fSAndroid Build Coastguard Worker break;
3127*795d594fSAndroid Build Coastguard Worker }
3128*795d594fSAndroid Build Coastguard Worker return checked;
3129*795d594fSAndroid Build Coastguard Worker }
3130*795d594fSAndroid Build Coastguard Worker
CallMethodA(const char * function_name,JNIEnv * env,jobject obj,jclass c,jmethodID mid,const jvalue * vargs,Primitive::Type type,InvokeType invoke)3131*795d594fSAndroid Build Coastguard Worker static JniValueType CallMethodA(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3132*795d594fSAndroid Build Coastguard Worker jmethodID mid, const jvalue* vargs, Primitive::Type type,
3133*795d594fSAndroid Build Coastguard Worker InvokeType invoke) {
3134*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, JniValueType());
3135*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3136*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
3137*795d594fSAndroid Build Coastguard Worker JniValueType result;
3138*795d594fSAndroid Build Coastguard Worker VarArgs rest(mid, vargs);
3139*795d594fSAndroid Build Coastguard Worker if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
3140*795d594fSAndroid Build Coastguard Worker sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3141*795d594fSAndroid Build Coastguard Worker const char* result_check;
3142*795d594fSAndroid Build Coastguard Worker switch (type) {
3143*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimNot:
3144*795d594fSAndroid Build Coastguard Worker result_check = "L";
3145*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3146*795d594fSAndroid Build Coastguard Worker case kVirtual:
3147*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->CallObjectMethodA(env, obj, mid, vargs);
3148*795d594fSAndroid Build Coastguard Worker break;
3149*795d594fSAndroid Build Coastguard Worker case kDirect:
3150*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->CallNonvirtualObjectMethodA(env, obj, c, mid, vargs);
3151*795d594fSAndroid Build Coastguard Worker break;
3152*795d594fSAndroid Build Coastguard Worker case kStatic:
3153*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->CallStaticObjectMethodA(env, c, mid, vargs);
3154*795d594fSAndroid Build Coastguard Worker break;
3155*795d594fSAndroid Build Coastguard Worker default:
3156*795d594fSAndroid Build Coastguard Worker break;
3157*795d594fSAndroid Build Coastguard Worker }
3158*795d594fSAndroid Build Coastguard Worker break;
3159*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3160*795d594fSAndroid Build Coastguard Worker result_check = "Z";
3161*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3162*795d594fSAndroid Build Coastguard Worker case kVirtual:
3163*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->CallBooleanMethodA(env, obj, mid, vargs);
3164*795d594fSAndroid Build Coastguard Worker break;
3165*795d594fSAndroid Build Coastguard Worker case kDirect:
3166*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->CallNonvirtualBooleanMethodA(env, obj, c, mid, vargs);
3167*795d594fSAndroid Build Coastguard Worker break;
3168*795d594fSAndroid Build Coastguard Worker case kStatic:
3169*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->CallStaticBooleanMethodA(env, c, mid, vargs);
3170*795d594fSAndroid Build Coastguard Worker break;
3171*795d594fSAndroid Build Coastguard Worker default:
3172*795d594fSAndroid Build Coastguard Worker break;
3173*795d594fSAndroid Build Coastguard Worker }
3174*795d594fSAndroid Build Coastguard Worker break;
3175*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3176*795d594fSAndroid Build Coastguard Worker result_check = "B";
3177*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3178*795d594fSAndroid Build Coastguard Worker case kVirtual:
3179*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->CallByteMethodA(env, obj, mid, vargs);
3180*795d594fSAndroid Build Coastguard Worker break;
3181*795d594fSAndroid Build Coastguard Worker case kDirect:
3182*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->CallNonvirtualByteMethodA(env, obj, c, mid, vargs);
3183*795d594fSAndroid Build Coastguard Worker break;
3184*795d594fSAndroid Build Coastguard Worker case kStatic:
3185*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->CallStaticByteMethodA(env, c, mid, vargs);
3186*795d594fSAndroid Build Coastguard Worker break;
3187*795d594fSAndroid Build Coastguard Worker default:
3188*795d594fSAndroid Build Coastguard Worker break;
3189*795d594fSAndroid Build Coastguard Worker }
3190*795d594fSAndroid Build Coastguard Worker break;
3191*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3192*795d594fSAndroid Build Coastguard Worker result_check = "C";
3193*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3194*795d594fSAndroid Build Coastguard Worker case kVirtual:
3195*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->CallCharMethodA(env, obj, mid, vargs);
3196*795d594fSAndroid Build Coastguard Worker break;
3197*795d594fSAndroid Build Coastguard Worker case kDirect:
3198*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->CallNonvirtualCharMethodA(env, obj, c, mid, vargs);
3199*795d594fSAndroid Build Coastguard Worker break;
3200*795d594fSAndroid Build Coastguard Worker case kStatic:
3201*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->CallStaticCharMethodA(env, c, mid, vargs);
3202*795d594fSAndroid Build Coastguard Worker break;
3203*795d594fSAndroid Build Coastguard Worker default:
3204*795d594fSAndroid Build Coastguard Worker break;
3205*795d594fSAndroid Build Coastguard Worker }
3206*795d594fSAndroid Build Coastguard Worker break;
3207*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3208*795d594fSAndroid Build Coastguard Worker result_check = "S";
3209*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3210*795d594fSAndroid Build Coastguard Worker case kVirtual:
3211*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->CallShortMethodA(env, obj, mid, vargs);
3212*795d594fSAndroid Build Coastguard Worker break;
3213*795d594fSAndroid Build Coastguard Worker case kDirect:
3214*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->CallNonvirtualShortMethodA(env, obj, c, mid, vargs);
3215*795d594fSAndroid Build Coastguard Worker break;
3216*795d594fSAndroid Build Coastguard Worker case kStatic:
3217*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->CallStaticShortMethodA(env, c, mid, vargs);
3218*795d594fSAndroid Build Coastguard Worker break;
3219*795d594fSAndroid Build Coastguard Worker default:
3220*795d594fSAndroid Build Coastguard Worker break;
3221*795d594fSAndroid Build Coastguard Worker }
3222*795d594fSAndroid Build Coastguard Worker break;
3223*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3224*795d594fSAndroid Build Coastguard Worker result_check = "I";
3225*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3226*795d594fSAndroid Build Coastguard Worker case kVirtual:
3227*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->CallIntMethodA(env, obj, mid, vargs);
3228*795d594fSAndroid Build Coastguard Worker break;
3229*795d594fSAndroid Build Coastguard Worker case kDirect:
3230*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->CallNonvirtualIntMethodA(env, obj, c, mid, vargs);
3231*795d594fSAndroid Build Coastguard Worker break;
3232*795d594fSAndroid Build Coastguard Worker case kStatic:
3233*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->CallStaticIntMethodA(env, c, mid, vargs);
3234*795d594fSAndroid Build Coastguard Worker break;
3235*795d594fSAndroid Build Coastguard Worker default:
3236*795d594fSAndroid Build Coastguard Worker break;
3237*795d594fSAndroid Build Coastguard Worker }
3238*795d594fSAndroid Build Coastguard Worker break;
3239*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3240*795d594fSAndroid Build Coastguard Worker result_check = "J";
3241*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3242*795d594fSAndroid Build Coastguard Worker case kVirtual:
3243*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->CallLongMethodA(env, obj, mid, vargs);
3244*795d594fSAndroid Build Coastguard Worker break;
3245*795d594fSAndroid Build Coastguard Worker case kDirect:
3246*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->CallNonvirtualLongMethodA(env, obj, c, mid, vargs);
3247*795d594fSAndroid Build Coastguard Worker break;
3248*795d594fSAndroid Build Coastguard Worker case kStatic:
3249*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->CallStaticLongMethodA(env, c, mid, vargs);
3250*795d594fSAndroid Build Coastguard Worker break;
3251*795d594fSAndroid Build Coastguard Worker default:
3252*795d594fSAndroid Build Coastguard Worker break;
3253*795d594fSAndroid Build Coastguard Worker }
3254*795d594fSAndroid Build Coastguard Worker break;
3255*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3256*795d594fSAndroid Build Coastguard Worker result_check = "F";
3257*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3258*795d594fSAndroid Build Coastguard Worker case kVirtual:
3259*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->CallFloatMethodA(env, obj, mid, vargs);
3260*795d594fSAndroid Build Coastguard Worker break;
3261*795d594fSAndroid Build Coastguard Worker case kDirect:
3262*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->CallNonvirtualFloatMethodA(env, obj, c, mid, vargs);
3263*795d594fSAndroid Build Coastguard Worker break;
3264*795d594fSAndroid Build Coastguard Worker case kStatic:
3265*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->CallStaticFloatMethodA(env, c, mid, vargs);
3266*795d594fSAndroid Build Coastguard Worker break;
3267*795d594fSAndroid Build Coastguard Worker default:
3268*795d594fSAndroid Build Coastguard Worker break;
3269*795d594fSAndroid Build Coastguard Worker }
3270*795d594fSAndroid Build Coastguard Worker break;
3271*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3272*795d594fSAndroid Build Coastguard Worker result_check = "D";
3273*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3274*795d594fSAndroid Build Coastguard Worker case kVirtual:
3275*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->CallDoubleMethodA(env, obj, mid, vargs);
3276*795d594fSAndroid Build Coastguard Worker break;
3277*795d594fSAndroid Build Coastguard Worker case kDirect:
3278*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->CallNonvirtualDoubleMethodA(env, obj, c, mid, vargs);
3279*795d594fSAndroid Build Coastguard Worker break;
3280*795d594fSAndroid Build Coastguard Worker case kStatic:
3281*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->CallStaticDoubleMethodA(env, c, mid, vargs);
3282*795d594fSAndroid Build Coastguard Worker break;
3283*795d594fSAndroid Build Coastguard Worker default:
3284*795d594fSAndroid Build Coastguard Worker break;
3285*795d594fSAndroid Build Coastguard Worker }
3286*795d594fSAndroid Build Coastguard Worker break;
3287*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimVoid:
3288*795d594fSAndroid Build Coastguard Worker result_check = "V";
3289*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
3290*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3291*795d594fSAndroid Build Coastguard Worker case kVirtual:
3292*795d594fSAndroid Build Coastguard Worker baseEnv(env)->CallVoidMethodA(env, obj, mid, vargs);
3293*795d594fSAndroid Build Coastguard Worker break;
3294*795d594fSAndroid Build Coastguard Worker case kDirect:
3295*795d594fSAndroid Build Coastguard Worker baseEnv(env)->CallNonvirtualVoidMethodA(env, obj, c, mid, vargs);
3296*795d594fSAndroid Build Coastguard Worker break;
3297*795d594fSAndroid Build Coastguard Worker case kStatic:
3298*795d594fSAndroid Build Coastguard Worker baseEnv(env)->CallStaticVoidMethodA(env, c, mid, vargs);
3299*795d594fSAndroid Build Coastguard Worker break;
3300*795d594fSAndroid Build Coastguard Worker default:
3301*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3302*795d594fSAndroid Build Coastguard Worker }
3303*795d594fSAndroid Build Coastguard Worker break;
3304*795d594fSAndroid Build Coastguard Worker }
3305*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, result_check, &result)) {
3306*795d594fSAndroid Build Coastguard Worker return result;
3307*795d594fSAndroid Build Coastguard Worker }
3308*795d594fSAndroid Build Coastguard Worker }
3309*795d594fSAndroid Build Coastguard Worker result.J = 0;
3310*795d594fSAndroid Build Coastguard Worker return result;
3311*795d594fSAndroid Build Coastguard Worker }
3312*795d594fSAndroid Build Coastguard Worker
3313*795d594fSAndroid Build Coastguard Worker NO_STACK_PROTECTOR
CallMethodV(const char * function_name,JNIEnv * env,jobject obj,jclass c,jmethodID mid,va_list vargs,Primitive::Type type,InvokeType invoke)3314*795d594fSAndroid Build Coastguard Worker static JniValueType CallMethodV(const char* function_name, JNIEnv* env, jobject obj, jclass c,
3315*795d594fSAndroid Build Coastguard Worker jmethodID mid, va_list vargs, Primitive::Type type,
3316*795d594fSAndroid Build Coastguard Worker InvokeType invoke) {
3317*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, JniValueType());
3318*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3319*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
3320*795d594fSAndroid Build Coastguard Worker JniValueType result;
3321*795d594fSAndroid Build Coastguard Worker VarArgs rest(mid, vargs);
3322*795d594fSAndroid Build Coastguard Worker if (CheckCallArgs(soa, sc, env, obj, c, mid, invoke, &rest) &&
3323*795d594fSAndroid Build Coastguard Worker sc.CheckMethodAndSig(soa, obj, c, mid, type, invoke)) {
3324*795d594fSAndroid Build Coastguard Worker const char* result_check;
3325*795d594fSAndroid Build Coastguard Worker switch (type) {
3326*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimNot:
3327*795d594fSAndroid Build Coastguard Worker result_check = "L";
3328*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3329*795d594fSAndroid Build Coastguard Worker case kVirtual:
3330*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->CallObjectMethodV(env, obj, mid, vargs);
3331*795d594fSAndroid Build Coastguard Worker break;
3332*795d594fSAndroid Build Coastguard Worker case kDirect:
3333*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->CallNonvirtualObjectMethodV(env, obj, c, mid, vargs);
3334*795d594fSAndroid Build Coastguard Worker break;
3335*795d594fSAndroid Build Coastguard Worker case kStatic:
3336*795d594fSAndroid Build Coastguard Worker result.L = baseEnv(env)->CallStaticObjectMethodV(env, c, mid, vargs);
3337*795d594fSAndroid Build Coastguard Worker break;
3338*795d594fSAndroid Build Coastguard Worker default:
3339*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3340*795d594fSAndroid Build Coastguard Worker }
3341*795d594fSAndroid Build Coastguard Worker break;
3342*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3343*795d594fSAndroid Build Coastguard Worker result_check = "Z";
3344*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3345*795d594fSAndroid Build Coastguard Worker case kVirtual:
3346*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->CallBooleanMethodV(env, obj, mid, vargs);
3347*795d594fSAndroid Build Coastguard Worker break;
3348*795d594fSAndroid Build Coastguard Worker case kDirect:
3349*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->CallNonvirtualBooleanMethodV(env, obj, c, mid, vargs);
3350*795d594fSAndroid Build Coastguard Worker break;
3351*795d594fSAndroid Build Coastguard Worker case kStatic:
3352*795d594fSAndroid Build Coastguard Worker result.Z = baseEnv(env)->CallStaticBooleanMethodV(env, c, mid, vargs);
3353*795d594fSAndroid Build Coastguard Worker break;
3354*795d594fSAndroid Build Coastguard Worker default:
3355*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3356*795d594fSAndroid Build Coastguard Worker }
3357*795d594fSAndroid Build Coastguard Worker break;
3358*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3359*795d594fSAndroid Build Coastguard Worker result_check = "B";
3360*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3361*795d594fSAndroid Build Coastguard Worker case kVirtual:
3362*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->CallByteMethodV(env, obj, mid, vargs);
3363*795d594fSAndroid Build Coastguard Worker break;
3364*795d594fSAndroid Build Coastguard Worker case kDirect:
3365*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->CallNonvirtualByteMethodV(env, obj, c, mid, vargs);
3366*795d594fSAndroid Build Coastguard Worker break;
3367*795d594fSAndroid Build Coastguard Worker case kStatic:
3368*795d594fSAndroid Build Coastguard Worker result.B = baseEnv(env)->CallStaticByteMethodV(env, c, mid, vargs);
3369*795d594fSAndroid Build Coastguard Worker break;
3370*795d594fSAndroid Build Coastguard Worker default:
3371*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3372*795d594fSAndroid Build Coastguard Worker }
3373*795d594fSAndroid Build Coastguard Worker break;
3374*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3375*795d594fSAndroid Build Coastguard Worker result_check = "C";
3376*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3377*795d594fSAndroid Build Coastguard Worker case kVirtual:
3378*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->CallCharMethodV(env, obj, mid, vargs);
3379*795d594fSAndroid Build Coastguard Worker break;
3380*795d594fSAndroid Build Coastguard Worker case kDirect:
3381*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->CallNonvirtualCharMethodV(env, obj, c, mid, vargs);
3382*795d594fSAndroid Build Coastguard Worker break;
3383*795d594fSAndroid Build Coastguard Worker case kStatic:
3384*795d594fSAndroid Build Coastguard Worker result.C = baseEnv(env)->CallStaticCharMethodV(env, c, mid, vargs);
3385*795d594fSAndroid Build Coastguard Worker break;
3386*795d594fSAndroid Build Coastguard Worker default:
3387*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3388*795d594fSAndroid Build Coastguard Worker }
3389*795d594fSAndroid Build Coastguard Worker break;
3390*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3391*795d594fSAndroid Build Coastguard Worker result_check = "S";
3392*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3393*795d594fSAndroid Build Coastguard Worker case kVirtual:
3394*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->CallShortMethodV(env, obj, mid, vargs);
3395*795d594fSAndroid Build Coastguard Worker break;
3396*795d594fSAndroid Build Coastguard Worker case kDirect:
3397*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->CallNonvirtualShortMethodV(env, obj, c, mid, vargs);
3398*795d594fSAndroid Build Coastguard Worker break;
3399*795d594fSAndroid Build Coastguard Worker case kStatic:
3400*795d594fSAndroid Build Coastguard Worker result.S = baseEnv(env)->CallStaticShortMethodV(env, c, mid, vargs);
3401*795d594fSAndroid Build Coastguard Worker break;
3402*795d594fSAndroid Build Coastguard Worker default:
3403*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3404*795d594fSAndroid Build Coastguard Worker }
3405*795d594fSAndroid Build Coastguard Worker break;
3406*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3407*795d594fSAndroid Build Coastguard Worker result_check = "I";
3408*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3409*795d594fSAndroid Build Coastguard Worker case kVirtual:
3410*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->CallIntMethodV(env, obj, mid, vargs);
3411*795d594fSAndroid Build Coastguard Worker break;
3412*795d594fSAndroid Build Coastguard Worker case kDirect:
3413*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->CallNonvirtualIntMethodV(env, obj, c, mid, vargs);
3414*795d594fSAndroid Build Coastguard Worker break;
3415*795d594fSAndroid Build Coastguard Worker case kStatic:
3416*795d594fSAndroid Build Coastguard Worker result.I = baseEnv(env)->CallStaticIntMethodV(env, c, mid, vargs);
3417*795d594fSAndroid Build Coastguard Worker break;
3418*795d594fSAndroid Build Coastguard Worker default:
3419*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3420*795d594fSAndroid Build Coastguard Worker }
3421*795d594fSAndroid Build Coastguard Worker break;
3422*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3423*795d594fSAndroid Build Coastguard Worker result_check = "J";
3424*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3425*795d594fSAndroid Build Coastguard Worker case kVirtual:
3426*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->CallLongMethodV(env, obj, mid, vargs);
3427*795d594fSAndroid Build Coastguard Worker break;
3428*795d594fSAndroid Build Coastguard Worker case kDirect:
3429*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->CallNonvirtualLongMethodV(env, obj, c, mid, vargs);
3430*795d594fSAndroid Build Coastguard Worker break;
3431*795d594fSAndroid Build Coastguard Worker case kStatic:
3432*795d594fSAndroid Build Coastguard Worker result.J = baseEnv(env)->CallStaticLongMethodV(env, c, mid, vargs);
3433*795d594fSAndroid Build Coastguard Worker break;
3434*795d594fSAndroid Build Coastguard Worker default:
3435*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3436*795d594fSAndroid Build Coastguard Worker }
3437*795d594fSAndroid Build Coastguard Worker break;
3438*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3439*795d594fSAndroid Build Coastguard Worker result_check = "F";
3440*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3441*795d594fSAndroid Build Coastguard Worker case kVirtual:
3442*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->CallFloatMethodV(env, obj, mid, vargs);
3443*795d594fSAndroid Build Coastguard Worker break;
3444*795d594fSAndroid Build Coastguard Worker case kDirect:
3445*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->CallNonvirtualFloatMethodV(env, obj, c, mid, vargs);
3446*795d594fSAndroid Build Coastguard Worker break;
3447*795d594fSAndroid Build Coastguard Worker case kStatic:
3448*795d594fSAndroid Build Coastguard Worker result.F = baseEnv(env)->CallStaticFloatMethodV(env, c, mid, vargs);
3449*795d594fSAndroid Build Coastguard Worker break;
3450*795d594fSAndroid Build Coastguard Worker default:
3451*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3452*795d594fSAndroid Build Coastguard Worker }
3453*795d594fSAndroid Build Coastguard Worker break;
3454*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3455*795d594fSAndroid Build Coastguard Worker result_check = "D";
3456*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3457*795d594fSAndroid Build Coastguard Worker case kVirtual:
3458*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->CallDoubleMethodV(env, obj, mid, vargs);
3459*795d594fSAndroid Build Coastguard Worker break;
3460*795d594fSAndroid Build Coastguard Worker case kDirect:
3461*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->CallNonvirtualDoubleMethodV(env, obj, c, mid, vargs);
3462*795d594fSAndroid Build Coastguard Worker break;
3463*795d594fSAndroid Build Coastguard Worker case kStatic:
3464*795d594fSAndroid Build Coastguard Worker result.D = baseEnv(env)->CallStaticDoubleMethodV(env, c, mid, vargs);
3465*795d594fSAndroid Build Coastguard Worker break;
3466*795d594fSAndroid Build Coastguard Worker default:
3467*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3468*795d594fSAndroid Build Coastguard Worker }
3469*795d594fSAndroid Build Coastguard Worker break;
3470*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimVoid:
3471*795d594fSAndroid Build Coastguard Worker result_check = "V";
3472*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
3473*795d594fSAndroid Build Coastguard Worker switch (invoke) {
3474*795d594fSAndroid Build Coastguard Worker case kVirtual:
3475*795d594fSAndroid Build Coastguard Worker baseEnv(env)->CallVoidMethodV(env, obj, mid, vargs);
3476*795d594fSAndroid Build Coastguard Worker break;
3477*795d594fSAndroid Build Coastguard Worker case kDirect:
3478*795d594fSAndroid Build Coastguard Worker baseEnv(env)->CallNonvirtualVoidMethodV(env, obj, c, mid, vargs);
3479*795d594fSAndroid Build Coastguard Worker break;
3480*795d594fSAndroid Build Coastguard Worker case kStatic:
3481*795d594fSAndroid Build Coastguard Worker baseEnv(env)->CallStaticVoidMethodV(env, c, mid, vargs);
3482*795d594fSAndroid Build Coastguard Worker break;
3483*795d594fSAndroid Build Coastguard Worker default:
3484*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected invoke: " << invoke;
3485*795d594fSAndroid Build Coastguard Worker }
3486*795d594fSAndroid Build Coastguard Worker break;
3487*795d594fSAndroid Build Coastguard Worker }
3488*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, result_check, &result)) {
3489*795d594fSAndroid Build Coastguard Worker return result;
3490*795d594fSAndroid Build Coastguard Worker }
3491*795d594fSAndroid Build Coastguard Worker }
3492*795d594fSAndroid Build Coastguard Worker result.J = 0;
3493*795d594fSAndroid Build Coastguard Worker return result;
3494*795d594fSAndroid Build Coastguard Worker }
3495*795d594fSAndroid Build Coastguard Worker
GetStringCharsInternal(const char * function_name,JNIEnv * env,jstring string,jboolean * is_copy,bool utf,bool critical)3496*795d594fSAndroid Build Coastguard Worker static const void* GetStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3497*795d594fSAndroid Build Coastguard Worker jboolean* is_copy, bool utf, bool critical) {
3498*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, nullptr);
3499*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3500*795d594fSAndroid Build Coastguard Worker int flags = critical ? kFlag_CritGet : kFlag_CritOkay;
3501*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(flags, function_name);
3502*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.s = string}, {.p = is_copy}};
3503*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Esp", args)) {
3504*795d594fSAndroid Build Coastguard Worker JniValueType result;
3505*795d594fSAndroid Build Coastguard Worker void* ptr;
3506*795d594fSAndroid Build Coastguard Worker if (utf) {
3507*795d594fSAndroid Build Coastguard Worker CHECK(!critical);
3508*795d594fSAndroid Build Coastguard Worker ptr = const_cast<char*>(baseEnv(env)->GetStringUTFChars(env, string, is_copy));
3509*795d594fSAndroid Build Coastguard Worker result.u = reinterpret_cast<char*>(ptr);
3510*795d594fSAndroid Build Coastguard Worker } else {
3511*795d594fSAndroid Build Coastguard Worker ptr = const_cast<jchar*>(critical ? baseEnv(env)->GetStringCritical(env, string, is_copy) :
3512*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetStringChars(env, string, is_copy));
3513*795d594fSAndroid Build Coastguard Worker result.p = ptr;
3514*795d594fSAndroid Build Coastguard Worker }
3515*795d594fSAndroid Build Coastguard Worker // TODO: could we be smarter about not copying when local_is_copy?
3516*795d594fSAndroid Build Coastguard Worker if (ptr != nullptr && soa.ForceCopy()) {
3517*795d594fSAndroid Build Coastguard Worker if (utf) {
3518*795d594fSAndroid Build Coastguard Worker size_t length_in_bytes = strlen(result.u) + 1;
3519*795d594fSAndroid Build Coastguard Worker result.u =
3520*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const char*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3521*795d594fSAndroid Build Coastguard Worker } else {
3522*795d594fSAndroid Build Coastguard Worker size_t length_in_bytes = baseEnv(env)->GetStringLength(env, string) * 2;
3523*795d594fSAndroid Build Coastguard Worker result.p =
3524*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jchar*>(GuardedCopy::Create(ptr, length_in_bytes, false));
3525*795d594fSAndroid Build Coastguard Worker }
3526*795d594fSAndroid Build Coastguard Worker if (is_copy != nullptr) {
3527*795d594fSAndroid Build Coastguard Worker *is_copy = JNI_TRUE;
3528*795d594fSAndroid Build Coastguard Worker }
3529*795d594fSAndroid Build Coastguard Worker }
3530*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, utf ? "u" : "p", &result)) {
3531*795d594fSAndroid Build Coastguard Worker return utf ? result.u : result.p;
3532*795d594fSAndroid Build Coastguard Worker }
3533*795d594fSAndroid Build Coastguard Worker }
3534*795d594fSAndroid Build Coastguard Worker return nullptr;
3535*795d594fSAndroid Build Coastguard Worker }
3536*795d594fSAndroid Build Coastguard Worker
ReleaseStringCharsInternal(const char * function_name,JNIEnv * env,jstring string,const void * chars,bool utf,bool critical)3537*795d594fSAndroid Build Coastguard Worker static void ReleaseStringCharsInternal(const char* function_name, JNIEnv* env, jstring string,
3538*795d594fSAndroid Build Coastguard Worker const void* chars, bool utf, bool critical) {
3539*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(function_name);
3540*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3541*795d594fSAndroid Build Coastguard Worker int flags = kFlag_ExcepOkay | kFlag_Release;
3542*795d594fSAndroid Build Coastguard Worker if (critical) {
3543*795d594fSAndroid Build Coastguard Worker flags |= kFlag_CritRelease;
3544*795d594fSAndroid Build Coastguard Worker }
3545*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(flags, function_name);
3546*795d594fSAndroid Build Coastguard Worker sc.CheckNonNull(chars);
3547*795d594fSAndroid Build Coastguard Worker bool force_copy_ok = !soa.ForceCopy() || GuardedCopy::Check(function_name, chars, false);
3548*795d594fSAndroid Build Coastguard Worker if (force_copy_ok && soa.ForceCopy()) {
3549*795d594fSAndroid Build Coastguard Worker chars = reinterpret_cast<const jchar*>(GuardedCopy::Destroy(const_cast<void*>(chars)));
3550*795d594fSAndroid Build Coastguard Worker }
3551*795d594fSAndroid Build Coastguard Worker if (force_copy_ok) {
3552*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.s = string}, {.p = chars}};
3553*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, utf ? "Esu" : "Esp", args)) {
3554*795d594fSAndroid Build Coastguard Worker if (utf) {
3555*795d594fSAndroid Build Coastguard Worker CHECK(!critical);
3556*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseStringUTFChars(env, string, reinterpret_cast<const char*>(chars));
3557*795d594fSAndroid Build Coastguard Worker } else {
3558*795d594fSAndroid Build Coastguard Worker if (critical) {
3559*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseStringCritical(env, string, reinterpret_cast<const jchar*>(chars));
3560*795d594fSAndroid Build Coastguard Worker } else {
3561*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseStringChars(env, string, reinterpret_cast<const jchar*>(chars));
3562*795d594fSAndroid Build Coastguard Worker }
3563*795d594fSAndroid Build Coastguard Worker }
3564*795d594fSAndroid Build Coastguard Worker JniValueType result;
3565*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
3566*795d594fSAndroid Build Coastguard Worker }
3567*795d594fSAndroid Build Coastguard Worker }
3568*795d594fSAndroid Build Coastguard Worker }
3569*795d594fSAndroid Build Coastguard Worker
NewPrimitiveArray(const char * function_name,JNIEnv * env,jsize length,Primitive::Type type)3570*795d594fSAndroid Build Coastguard Worker static jarray NewPrimitiveArray(const char* function_name, JNIEnv* env, jsize length,
3571*795d594fSAndroid Build Coastguard Worker Primitive::Type type) {
3572*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, nullptr);
3573*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3574*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
3575*795d594fSAndroid Build Coastguard Worker JniValueType args[2] = {{.E = env}, {.z = length}};
3576*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Ez", args)) {
3577*795d594fSAndroid Build Coastguard Worker JniValueType result;
3578*795d594fSAndroid Build Coastguard Worker switch (type) {
3579*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3580*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewBooleanArray(env, length);
3581*795d594fSAndroid Build Coastguard Worker break;
3582*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3583*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewByteArray(env, length);
3584*795d594fSAndroid Build Coastguard Worker break;
3585*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3586*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewCharArray(env, length);
3587*795d594fSAndroid Build Coastguard Worker break;
3588*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3589*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewShortArray(env, length);
3590*795d594fSAndroid Build Coastguard Worker break;
3591*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3592*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewIntArray(env, length);
3593*795d594fSAndroid Build Coastguard Worker break;
3594*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3595*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewLongArray(env, length);
3596*795d594fSAndroid Build Coastguard Worker break;
3597*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3598*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewFloatArray(env, length);
3599*795d594fSAndroid Build Coastguard Worker break;
3600*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3601*795d594fSAndroid Build Coastguard Worker result.a = baseEnv(env)->NewDoubleArray(env, length);
3602*795d594fSAndroid Build Coastguard Worker break;
3603*795d594fSAndroid Build Coastguard Worker default:
3604*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected primitive type: " << type;
3605*795d594fSAndroid Build Coastguard Worker }
3606*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "a", &result)) {
3607*795d594fSAndroid Build Coastguard Worker return result.a;
3608*795d594fSAndroid Build Coastguard Worker }
3609*795d594fSAndroid Build Coastguard Worker }
3610*795d594fSAndroid Build Coastguard Worker return nullptr;
3611*795d594fSAndroid Build Coastguard Worker }
3612*795d594fSAndroid Build Coastguard Worker
GetPrimitiveArrayElements(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,jboolean * is_copy)3613*795d594fSAndroid Build Coastguard Worker static void* GetPrimitiveArrayElements(const char* function_name, Primitive::Type type,
3614*795d594fSAndroid Build Coastguard Worker JNIEnv* env, jarray array, jboolean* is_copy) {
3615*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD(function_name, nullptr);
3616*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3617*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
3618*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.E = env}, {.a = array}, {.p = is_copy}};
3619*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eap", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3620*795d594fSAndroid Build Coastguard Worker JniValueType result;
3621*795d594fSAndroid Build Coastguard Worker void* ptr = nullptr;
3622*795d594fSAndroid Build Coastguard Worker switch (type) {
3623*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3624*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3625*795d594fSAndroid Build Coastguard Worker is_copy);
3626*795d594fSAndroid Build Coastguard Worker break;
3627*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3628*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetByteArrayElements(env, down_cast<jbyteArray>(array), is_copy);
3629*795d594fSAndroid Build Coastguard Worker break;
3630*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3631*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetCharArrayElements(env, down_cast<jcharArray>(array), is_copy);
3632*795d594fSAndroid Build Coastguard Worker break;
3633*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3634*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetShortArrayElements(env, down_cast<jshortArray>(array), is_copy);
3635*795d594fSAndroid Build Coastguard Worker break;
3636*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3637*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetIntArrayElements(env, down_cast<jintArray>(array), is_copy);
3638*795d594fSAndroid Build Coastguard Worker break;
3639*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3640*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetLongArrayElements(env, down_cast<jlongArray>(array), is_copy);
3641*795d594fSAndroid Build Coastguard Worker break;
3642*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3643*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetFloatArrayElements(env, down_cast<jfloatArray>(array), is_copy);
3644*795d594fSAndroid Build Coastguard Worker break;
3645*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3646*795d594fSAndroid Build Coastguard Worker ptr = baseEnv(env)->GetDoubleArrayElements(env, down_cast<jdoubleArray>(array), is_copy);
3647*795d594fSAndroid Build Coastguard Worker break;
3648*795d594fSAndroid Build Coastguard Worker default:
3649*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected primitive type: " << type;
3650*795d594fSAndroid Build Coastguard Worker }
3651*795d594fSAndroid Build Coastguard Worker if (ptr != nullptr && soa.ForceCopy()) {
3652*795d594fSAndroid Build Coastguard Worker ptr = GuardedCopy::CreateGuardedPACopy(env, array, is_copy, ptr);
3653*795d594fSAndroid Build Coastguard Worker if (is_copy != nullptr) {
3654*795d594fSAndroid Build Coastguard Worker *is_copy = JNI_TRUE;
3655*795d594fSAndroid Build Coastguard Worker }
3656*795d594fSAndroid Build Coastguard Worker }
3657*795d594fSAndroid Build Coastguard Worker result.p = ptr;
3658*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, false, "p", &result)) {
3659*795d594fSAndroid Build Coastguard Worker return const_cast<void*>(result.p);
3660*795d594fSAndroid Build Coastguard Worker }
3661*795d594fSAndroid Build Coastguard Worker }
3662*795d594fSAndroid Build Coastguard Worker return nullptr;
3663*795d594fSAndroid Build Coastguard Worker }
3664*795d594fSAndroid Build Coastguard Worker
ReleasePrimitiveArrayElements(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,void * elems,jint mode)3665*795d594fSAndroid Build Coastguard Worker static void ReleasePrimitiveArrayElements(const char* function_name, Primitive::Type type,
3666*795d594fSAndroid Build Coastguard Worker JNIEnv* env, jarray array, void* elems, jint mode) {
3667*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(function_name);
3668*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3669*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_ExcepOkay, function_name);
3670*795d594fSAndroid Build Coastguard Worker if (sc.CheckNonNull(elems) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3671*795d594fSAndroid Build Coastguard Worker if (soa.ForceCopy()) {
3672*795d594fSAndroid Build Coastguard Worker elems = GuardedCopy::ReleaseGuardedPACopy(function_name, env, array, elems, mode);
3673*795d594fSAndroid Build Coastguard Worker }
3674*795d594fSAndroid Build Coastguard Worker if (!soa.ForceCopy() || elems != nullptr) {
3675*795d594fSAndroid Build Coastguard Worker JniValueType args[4] = {{.E = env}, {.a = array}, {.p = elems}, {.r = mode}};
3676*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "Eapr", args)) {
3677*795d594fSAndroid Build Coastguard Worker switch (type) {
3678*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3679*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseBooleanArrayElements(env, down_cast<jbooleanArray>(array),
3680*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jboolean*>(elems), mode);
3681*795d594fSAndroid Build Coastguard Worker break;
3682*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3683*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseByteArrayElements(env, down_cast<jbyteArray>(array),
3684*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jbyte*>(elems), mode);
3685*795d594fSAndroid Build Coastguard Worker break;
3686*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3687*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseCharArrayElements(env, down_cast<jcharArray>(array),
3688*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jchar*>(elems), mode);
3689*795d594fSAndroid Build Coastguard Worker break;
3690*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3691*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseShortArrayElements(env, down_cast<jshortArray>(array),
3692*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jshort*>(elems), mode);
3693*795d594fSAndroid Build Coastguard Worker break;
3694*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3695*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseIntArrayElements(env, down_cast<jintArray>(array),
3696*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jint*>(elems), mode);
3697*795d594fSAndroid Build Coastguard Worker break;
3698*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3699*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseLongArrayElements(env, down_cast<jlongArray>(array),
3700*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jlong*>(elems), mode);
3701*795d594fSAndroid Build Coastguard Worker break;
3702*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3703*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseFloatArrayElements(env, down_cast<jfloatArray>(array),
3704*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jfloat*>(elems), mode);
3705*795d594fSAndroid Build Coastguard Worker break;
3706*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3707*795d594fSAndroid Build Coastguard Worker baseEnv(env)->ReleaseDoubleArrayElements(env, down_cast<jdoubleArray>(array),
3708*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jdouble*>(elems), mode);
3709*795d594fSAndroid Build Coastguard Worker break;
3710*795d594fSAndroid Build Coastguard Worker default:
3711*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected primitive type: " << type;
3712*795d594fSAndroid Build Coastguard Worker }
3713*795d594fSAndroid Build Coastguard Worker JniValueType result;
3714*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
3715*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
3716*795d594fSAndroid Build Coastguard Worker }
3717*795d594fSAndroid Build Coastguard Worker }
3718*795d594fSAndroid Build Coastguard Worker }
3719*795d594fSAndroid Build Coastguard Worker }
3720*795d594fSAndroid Build Coastguard Worker
GetPrimitiveArrayRegion(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,jsize start,jsize len,void * buf)3721*795d594fSAndroid Build Coastguard Worker static void GetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3722*795d594fSAndroid Build Coastguard Worker jarray array, jsize start, jsize len, void* buf) {
3723*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(function_name);
3724*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3725*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
3726*795d594fSAndroid Build Coastguard Worker JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3727*795d594fSAndroid Build Coastguard Worker // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3728*795d594fSAndroid Build Coastguard Worker // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3729*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3730*795d594fSAndroid Build Coastguard Worker switch (type) {
3731*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3732*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3733*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jboolean*>(buf));
3734*795d594fSAndroid Build Coastguard Worker break;
3735*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3736*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3737*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jbyte*>(buf));
3738*795d594fSAndroid Build Coastguard Worker break;
3739*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3740*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3741*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jchar*>(buf));
3742*795d594fSAndroid Build Coastguard Worker break;
3743*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3744*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3745*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jshort*>(buf));
3746*795d594fSAndroid Build Coastguard Worker break;
3747*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3748*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3749*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jint*>(buf));
3750*795d594fSAndroid Build Coastguard Worker break;
3751*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3752*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3753*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jlong*>(buf));
3754*795d594fSAndroid Build Coastguard Worker break;
3755*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3756*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3757*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jfloat*>(buf));
3758*795d594fSAndroid Build Coastguard Worker break;
3759*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3760*795d594fSAndroid Build Coastguard Worker baseEnv(env)->GetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3761*795d594fSAndroid Build Coastguard Worker reinterpret_cast<jdouble*>(buf));
3762*795d594fSAndroid Build Coastguard Worker break;
3763*795d594fSAndroid Build Coastguard Worker default:
3764*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected primitive type: " << type;
3765*795d594fSAndroid Build Coastguard Worker }
3766*795d594fSAndroid Build Coastguard Worker JniValueType result;
3767*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
3768*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
3769*795d594fSAndroid Build Coastguard Worker }
3770*795d594fSAndroid Build Coastguard Worker }
3771*795d594fSAndroid Build Coastguard Worker
SetPrimitiveArrayRegion(const char * function_name,Primitive::Type type,JNIEnv * env,jarray array,jsize start,jsize len,const void * buf)3772*795d594fSAndroid Build Coastguard Worker static void SetPrimitiveArrayRegion(const char* function_name, Primitive::Type type, JNIEnv* env,
3773*795d594fSAndroid Build Coastguard Worker jarray array, jsize start, jsize len, const void* buf) {
3774*795d594fSAndroid Build Coastguard Worker CHECK_ATTACHED_THREAD_VOID(function_name);
3775*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(env);
3776*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Default, function_name);
3777*795d594fSAndroid Build Coastguard Worker JniValueType args[5] = {{.E = env}, {.a = array}, {.z = start}, {.z = len}, {.p = buf}};
3778*795d594fSAndroid Build Coastguard Worker // Note: the start and len arguments are checked as 'I' rather than 'z' as invalid indices
3779*795d594fSAndroid Build Coastguard Worker // result in ArrayIndexOutOfBoundsExceptions in the base implementation.
3780*795d594fSAndroid Build Coastguard Worker if (sc.Check(soa, true, "EaIIp", args) && sc.CheckPrimitiveArrayType(soa, array, type)) {
3781*795d594fSAndroid Build Coastguard Worker switch (type) {
3782*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimBoolean:
3783*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetBooleanArrayRegion(env, down_cast<jbooleanArray>(array), start, len,
3784*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jboolean*>(buf));
3785*795d594fSAndroid Build Coastguard Worker break;
3786*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimByte:
3787*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetByteArrayRegion(env, down_cast<jbyteArray>(array), start, len,
3788*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jbyte*>(buf));
3789*795d594fSAndroid Build Coastguard Worker break;
3790*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimChar:
3791*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetCharArrayRegion(env, down_cast<jcharArray>(array), start, len,
3792*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jchar*>(buf));
3793*795d594fSAndroid Build Coastguard Worker break;
3794*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimShort:
3795*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetShortArrayRegion(env, down_cast<jshortArray>(array), start, len,
3796*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jshort*>(buf));
3797*795d594fSAndroid Build Coastguard Worker break;
3798*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimInt:
3799*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetIntArrayRegion(env, down_cast<jintArray>(array), start, len,
3800*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jint*>(buf));
3801*795d594fSAndroid Build Coastguard Worker break;
3802*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimLong:
3803*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetLongArrayRegion(env, down_cast<jlongArray>(array), start, len,
3804*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jlong*>(buf));
3805*795d594fSAndroid Build Coastguard Worker break;
3806*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimFloat:
3807*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetFloatArrayRegion(env, down_cast<jfloatArray>(array), start, len,
3808*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jfloat*>(buf));
3809*795d594fSAndroid Build Coastguard Worker break;
3810*795d594fSAndroid Build Coastguard Worker case Primitive::kPrimDouble:
3811*795d594fSAndroid Build Coastguard Worker baseEnv(env)->SetDoubleArrayRegion(env, down_cast<jdoubleArray>(array), start, len,
3812*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const jdouble*>(buf));
3813*795d594fSAndroid Build Coastguard Worker break;
3814*795d594fSAndroid Build Coastguard Worker default:
3815*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected primitive type: " << type;
3816*795d594fSAndroid Build Coastguard Worker }
3817*795d594fSAndroid Build Coastguard Worker JniValueType result;
3818*795d594fSAndroid Build Coastguard Worker result.V = nullptr;
3819*795d594fSAndroid Build Coastguard Worker sc.Check(soa, false, "V", &result);
3820*795d594fSAndroid Build Coastguard Worker }
3821*795d594fSAndroid Build Coastguard Worker }
3822*795d594fSAndroid Build Coastguard Worker };
3823*795d594fSAndroid Build Coastguard Worker
3824*795d594fSAndroid Build Coastguard Worker const JNINativeInterface gCheckNativeInterface = {
3825*795d594fSAndroid Build Coastguard Worker nullptr, // reserved0.
3826*795d594fSAndroid Build Coastguard Worker nullptr, // reserved1.
3827*795d594fSAndroid Build Coastguard Worker nullptr, // reserved2.
3828*795d594fSAndroid Build Coastguard Worker nullptr, // reserved3.
3829*795d594fSAndroid Build Coastguard Worker CheckJNI::GetVersion,
3830*795d594fSAndroid Build Coastguard Worker CheckJNI::DefineClass,
3831*795d594fSAndroid Build Coastguard Worker CheckJNI::FindClass,
3832*795d594fSAndroid Build Coastguard Worker CheckJNI::FromReflectedMethod,
3833*795d594fSAndroid Build Coastguard Worker CheckJNI::FromReflectedField,
3834*795d594fSAndroid Build Coastguard Worker CheckJNI::ToReflectedMethod,
3835*795d594fSAndroid Build Coastguard Worker CheckJNI::GetSuperclass,
3836*795d594fSAndroid Build Coastguard Worker CheckJNI::IsAssignableFrom,
3837*795d594fSAndroid Build Coastguard Worker CheckJNI::ToReflectedField,
3838*795d594fSAndroid Build Coastguard Worker CheckJNI::Throw,
3839*795d594fSAndroid Build Coastguard Worker CheckJNI::ThrowNew,
3840*795d594fSAndroid Build Coastguard Worker CheckJNI::ExceptionOccurred,
3841*795d594fSAndroid Build Coastguard Worker CheckJNI::ExceptionDescribe,
3842*795d594fSAndroid Build Coastguard Worker CheckJNI::ExceptionClear,
3843*795d594fSAndroid Build Coastguard Worker CheckJNI::FatalError,
3844*795d594fSAndroid Build Coastguard Worker CheckJNI::PushLocalFrame,
3845*795d594fSAndroid Build Coastguard Worker CheckJNI::PopLocalFrame,
3846*795d594fSAndroid Build Coastguard Worker CheckJNI::NewGlobalRef,
3847*795d594fSAndroid Build Coastguard Worker CheckJNI::DeleteGlobalRef,
3848*795d594fSAndroid Build Coastguard Worker CheckJNI::DeleteLocalRef,
3849*795d594fSAndroid Build Coastguard Worker CheckJNI::IsSameObject,
3850*795d594fSAndroid Build Coastguard Worker CheckJNI::NewLocalRef,
3851*795d594fSAndroid Build Coastguard Worker CheckJNI::EnsureLocalCapacity,
3852*795d594fSAndroid Build Coastguard Worker CheckJNI::AllocObject,
3853*795d594fSAndroid Build Coastguard Worker CheckJNI::NewObject,
3854*795d594fSAndroid Build Coastguard Worker CheckJNI::NewObjectV,
3855*795d594fSAndroid Build Coastguard Worker CheckJNI::NewObjectA,
3856*795d594fSAndroid Build Coastguard Worker CheckJNI::GetObjectClass,
3857*795d594fSAndroid Build Coastguard Worker CheckJNI::IsInstanceOf,
3858*795d594fSAndroid Build Coastguard Worker CheckJNI::GetMethodID,
3859*795d594fSAndroid Build Coastguard Worker CheckJNI::CallObjectMethod,
3860*795d594fSAndroid Build Coastguard Worker CheckJNI::CallObjectMethodV,
3861*795d594fSAndroid Build Coastguard Worker CheckJNI::CallObjectMethodA,
3862*795d594fSAndroid Build Coastguard Worker CheckJNI::CallBooleanMethod,
3863*795d594fSAndroid Build Coastguard Worker CheckJNI::CallBooleanMethodV,
3864*795d594fSAndroid Build Coastguard Worker CheckJNI::CallBooleanMethodA,
3865*795d594fSAndroid Build Coastguard Worker CheckJNI::CallByteMethod,
3866*795d594fSAndroid Build Coastguard Worker CheckJNI::CallByteMethodV,
3867*795d594fSAndroid Build Coastguard Worker CheckJNI::CallByteMethodA,
3868*795d594fSAndroid Build Coastguard Worker CheckJNI::CallCharMethod,
3869*795d594fSAndroid Build Coastguard Worker CheckJNI::CallCharMethodV,
3870*795d594fSAndroid Build Coastguard Worker CheckJNI::CallCharMethodA,
3871*795d594fSAndroid Build Coastguard Worker CheckJNI::CallShortMethod,
3872*795d594fSAndroid Build Coastguard Worker CheckJNI::CallShortMethodV,
3873*795d594fSAndroid Build Coastguard Worker CheckJNI::CallShortMethodA,
3874*795d594fSAndroid Build Coastguard Worker CheckJNI::CallIntMethod,
3875*795d594fSAndroid Build Coastguard Worker CheckJNI::CallIntMethodV,
3876*795d594fSAndroid Build Coastguard Worker CheckJNI::CallIntMethodA,
3877*795d594fSAndroid Build Coastguard Worker CheckJNI::CallLongMethod,
3878*795d594fSAndroid Build Coastguard Worker CheckJNI::CallLongMethodV,
3879*795d594fSAndroid Build Coastguard Worker CheckJNI::CallLongMethodA,
3880*795d594fSAndroid Build Coastguard Worker CheckJNI::CallFloatMethod,
3881*795d594fSAndroid Build Coastguard Worker CheckJNI::CallFloatMethodV,
3882*795d594fSAndroid Build Coastguard Worker CheckJNI::CallFloatMethodA,
3883*795d594fSAndroid Build Coastguard Worker CheckJNI::CallDoubleMethod,
3884*795d594fSAndroid Build Coastguard Worker CheckJNI::CallDoubleMethodV,
3885*795d594fSAndroid Build Coastguard Worker CheckJNI::CallDoubleMethodA,
3886*795d594fSAndroid Build Coastguard Worker CheckJNI::CallVoidMethod,
3887*795d594fSAndroid Build Coastguard Worker CheckJNI::CallVoidMethodV,
3888*795d594fSAndroid Build Coastguard Worker CheckJNI::CallVoidMethodA,
3889*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualObjectMethod,
3890*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualObjectMethodV,
3891*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualObjectMethodA,
3892*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualBooleanMethod,
3893*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualBooleanMethodV,
3894*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualBooleanMethodA,
3895*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualByteMethod,
3896*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualByteMethodV,
3897*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualByteMethodA,
3898*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualCharMethod,
3899*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualCharMethodV,
3900*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualCharMethodA,
3901*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualShortMethod,
3902*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualShortMethodV,
3903*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualShortMethodA,
3904*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualIntMethod,
3905*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualIntMethodV,
3906*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualIntMethodA,
3907*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualLongMethod,
3908*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualLongMethodV,
3909*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualLongMethodA,
3910*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualFloatMethod,
3911*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualFloatMethodV,
3912*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualFloatMethodA,
3913*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualDoubleMethod,
3914*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualDoubleMethodV,
3915*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualDoubleMethodA,
3916*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualVoidMethod,
3917*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualVoidMethodV,
3918*795d594fSAndroid Build Coastguard Worker CheckJNI::CallNonvirtualVoidMethodA,
3919*795d594fSAndroid Build Coastguard Worker CheckJNI::GetFieldID,
3920*795d594fSAndroid Build Coastguard Worker CheckJNI::GetObjectField,
3921*795d594fSAndroid Build Coastguard Worker CheckJNI::GetBooleanField,
3922*795d594fSAndroid Build Coastguard Worker CheckJNI::GetByteField,
3923*795d594fSAndroid Build Coastguard Worker CheckJNI::GetCharField,
3924*795d594fSAndroid Build Coastguard Worker CheckJNI::GetShortField,
3925*795d594fSAndroid Build Coastguard Worker CheckJNI::GetIntField,
3926*795d594fSAndroid Build Coastguard Worker CheckJNI::GetLongField,
3927*795d594fSAndroid Build Coastguard Worker CheckJNI::GetFloatField,
3928*795d594fSAndroid Build Coastguard Worker CheckJNI::GetDoubleField,
3929*795d594fSAndroid Build Coastguard Worker CheckJNI::SetObjectField,
3930*795d594fSAndroid Build Coastguard Worker CheckJNI::SetBooleanField,
3931*795d594fSAndroid Build Coastguard Worker CheckJNI::SetByteField,
3932*795d594fSAndroid Build Coastguard Worker CheckJNI::SetCharField,
3933*795d594fSAndroid Build Coastguard Worker CheckJNI::SetShortField,
3934*795d594fSAndroid Build Coastguard Worker CheckJNI::SetIntField,
3935*795d594fSAndroid Build Coastguard Worker CheckJNI::SetLongField,
3936*795d594fSAndroid Build Coastguard Worker CheckJNI::SetFloatField,
3937*795d594fSAndroid Build Coastguard Worker CheckJNI::SetDoubleField,
3938*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticMethodID,
3939*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticObjectMethod,
3940*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticObjectMethodV,
3941*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticObjectMethodA,
3942*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticBooleanMethod,
3943*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticBooleanMethodV,
3944*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticBooleanMethodA,
3945*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticByteMethod,
3946*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticByteMethodV,
3947*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticByteMethodA,
3948*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticCharMethod,
3949*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticCharMethodV,
3950*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticCharMethodA,
3951*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticShortMethod,
3952*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticShortMethodV,
3953*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticShortMethodA,
3954*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticIntMethod,
3955*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticIntMethodV,
3956*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticIntMethodA,
3957*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticLongMethod,
3958*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticLongMethodV,
3959*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticLongMethodA,
3960*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticFloatMethod,
3961*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticFloatMethodV,
3962*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticFloatMethodA,
3963*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticDoubleMethod,
3964*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticDoubleMethodV,
3965*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticDoubleMethodA,
3966*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticVoidMethod,
3967*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticVoidMethodV,
3968*795d594fSAndroid Build Coastguard Worker CheckJNI::CallStaticVoidMethodA,
3969*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticFieldID,
3970*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticObjectField,
3971*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticBooleanField,
3972*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticByteField,
3973*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticCharField,
3974*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticShortField,
3975*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticIntField,
3976*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticLongField,
3977*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticFloatField,
3978*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStaticDoubleField,
3979*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticObjectField,
3980*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticBooleanField,
3981*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticByteField,
3982*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticCharField,
3983*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticShortField,
3984*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticIntField,
3985*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticLongField,
3986*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticFloatField,
3987*795d594fSAndroid Build Coastguard Worker CheckJNI::SetStaticDoubleField,
3988*795d594fSAndroid Build Coastguard Worker CheckJNI::NewString,
3989*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStringLength,
3990*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStringChars,
3991*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseStringChars,
3992*795d594fSAndroid Build Coastguard Worker CheckJNI::NewStringUTF,
3993*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStringUTFLength,
3994*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStringUTFChars,
3995*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseStringUTFChars,
3996*795d594fSAndroid Build Coastguard Worker CheckJNI::GetArrayLength,
3997*795d594fSAndroid Build Coastguard Worker CheckJNI::NewObjectArray,
3998*795d594fSAndroid Build Coastguard Worker CheckJNI::GetObjectArrayElement,
3999*795d594fSAndroid Build Coastguard Worker CheckJNI::SetObjectArrayElement,
4000*795d594fSAndroid Build Coastguard Worker CheckJNI::NewBooleanArray,
4001*795d594fSAndroid Build Coastguard Worker CheckJNI::NewByteArray,
4002*795d594fSAndroid Build Coastguard Worker CheckJNI::NewCharArray,
4003*795d594fSAndroid Build Coastguard Worker CheckJNI::NewShortArray,
4004*795d594fSAndroid Build Coastguard Worker CheckJNI::NewIntArray,
4005*795d594fSAndroid Build Coastguard Worker CheckJNI::NewLongArray,
4006*795d594fSAndroid Build Coastguard Worker CheckJNI::NewFloatArray,
4007*795d594fSAndroid Build Coastguard Worker CheckJNI::NewDoubleArray,
4008*795d594fSAndroid Build Coastguard Worker CheckJNI::GetBooleanArrayElements,
4009*795d594fSAndroid Build Coastguard Worker CheckJNI::GetByteArrayElements,
4010*795d594fSAndroid Build Coastguard Worker CheckJNI::GetCharArrayElements,
4011*795d594fSAndroid Build Coastguard Worker CheckJNI::GetShortArrayElements,
4012*795d594fSAndroid Build Coastguard Worker CheckJNI::GetIntArrayElements,
4013*795d594fSAndroid Build Coastguard Worker CheckJNI::GetLongArrayElements,
4014*795d594fSAndroid Build Coastguard Worker CheckJNI::GetFloatArrayElements,
4015*795d594fSAndroid Build Coastguard Worker CheckJNI::GetDoubleArrayElements,
4016*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseBooleanArrayElements,
4017*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseByteArrayElements,
4018*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseCharArrayElements,
4019*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseShortArrayElements,
4020*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseIntArrayElements,
4021*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseLongArrayElements,
4022*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseFloatArrayElements,
4023*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseDoubleArrayElements,
4024*795d594fSAndroid Build Coastguard Worker CheckJNI::GetBooleanArrayRegion,
4025*795d594fSAndroid Build Coastguard Worker CheckJNI::GetByteArrayRegion,
4026*795d594fSAndroid Build Coastguard Worker CheckJNI::GetCharArrayRegion,
4027*795d594fSAndroid Build Coastguard Worker CheckJNI::GetShortArrayRegion,
4028*795d594fSAndroid Build Coastguard Worker CheckJNI::GetIntArrayRegion,
4029*795d594fSAndroid Build Coastguard Worker CheckJNI::GetLongArrayRegion,
4030*795d594fSAndroid Build Coastguard Worker CheckJNI::GetFloatArrayRegion,
4031*795d594fSAndroid Build Coastguard Worker CheckJNI::GetDoubleArrayRegion,
4032*795d594fSAndroid Build Coastguard Worker CheckJNI::SetBooleanArrayRegion,
4033*795d594fSAndroid Build Coastguard Worker CheckJNI::SetByteArrayRegion,
4034*795d594fSAndroid Build Coastguard Worker CheckJNI::SetCharArrayRegion,
4035*795d594fSAndroid Build Coastguard Worker CheckJNI::SetShortArrayRegion,
4036*795d594fSAndroid Build Coastguard Worker CheckJNI::SetIntArrayRegion,
4037*795d594fSAndroid Build Coastguard Worker CheckJNI::SetLongArrayRegion,
4038*795d594fSAndroid Build Coastguard Worker CheckJNI::SetFloatArrayRegion,
4039*795d594fSAndroid Build Coastguard Worker CheckJNI::SetDoubleArrayRegion,
4040*795d594fSAndroid Build Coastguard Worker CheckJNI::RegisterNatives,
4041*795d594fSAndroid Build Coastguard Worker CheckJNI::UnregisterNatives,
4042*795d594fSAndroid Build Coastguard Worker CheckJNI::MonitorEnter,
4043*795d594fSAndroid Build Coastguard Worker CheckJNI::MonitorExit,
4044*795d594fSAndroid Build Coastguard Worker CheckJNI::GetJavaVM,
4045*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStringRegion,
4046*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStringUTFRegion,
4047*795d594fSAndroid Build Coastguard Worker CheckJNI::GetPrimitiveArrayCritical,
4048*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleasePrimitiveArrayCritical,
4049*795d594fSAndroid Build Coastguard Worker CheckJNI::GetStringCritical,
4050*795d594fSAndroid Build Coastguard Worker CheckJNI::ReleaseStringCritical,
4051*795d594fSAndroid Build Coastguard Worker CheckJNI::NewWeakGlobalRef,
4052*795d594fSAndroid Build Coastguard Worker CheckJNI::DeleteWeakGlobalRef,
4053*795d594fSAndroid Build Coastguard Worker CheckJNI::ExceptionCheck,
4054*795d594fSAndroid Build Coastguard Worker CheckJNI::NewDirectByteBuffer,
4055*795d594fSAndroid Build Coastguard Worker CheckJNI::GetDirectBufferAddress,
4056*795d594fSAndroid Build Coastguard Worker CheckJNI::GetDirectBufferCapacity,
4057*795d594fSAndroid Build Coastguard Worker CheckJNI::GetObjectRefType,
4058*795d594fSAndroid Build Coastguard Worker };
4059*795d594fSAndroid Build Coastguard Worker
4060*795d594fSAndroid Build Coastguard Worker class CheckJII {
4061*795d594fSAndroid Build Coastguard Worker public:
DestroyJavaVM(JavaVM * vm)4062*795d594fSAndroid Build Coastguard Worker static jint DestroyJavaVM(JavaVM* vm) {
4063*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Invocation, __FUNCTION__, false);
4064*795d594fSAndroid Build Coastguard Worker JniValueType args[1] = {{.v = vm}};
4065*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4066*795d594fSAndroid Build Coastguard Worker JniValueType result;
4067*795d594fSAndroid Build Coastguard Worker result.i = BaseVm(vm)->DestroyJavaVM(vm);
4068*795d594fSAndroid Build Coastguard Worker // Use null to signal that the JavaVM isn't valid anymore. DestroyJavaVM deletes the runtime,
4069*795d594fSAndroid Build Coastguard Worker // which will delete the JavaVMExt.
4070*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(nullptr, false, "i", &result);
4071*795d594fSAndroid Build Coastguard Worker return result.i;
4072*795d594fSAndroid Build Coastguard Worker }
4073*795d594fSAndroid Build Coastguard Worker
AttachCurrentThread(JavaVM * vm,JNIEnv ** p_env,void * thr_args)4074*795d594fSAndroid Build Coastguard Worker static jint AttachCurrentThread(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
4075*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4076*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4077*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4078*795d594fSAndroid Build Coastguard Worker JniValueType result;
4079*795d594fSAndroid Build Coastguard Worker result.i = BaseVm(vm)->AttachCurrentThread(vm, p_env, thr_args);
4080*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4081*795d594fSAndroid Build Coastguard Worker return result.i;
4082*795d594fSAndroid Build Coastguard Worker }
4083*795d594fSAndroid Build Coastguard Worker
AttachCurrentThreadAsDaemon(JavaVM * vm,JNIEnv ** p_env,void * thr_args)4084*795d594fSAndroid Build Coastguard Worker static jint AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env, void* thr_args) {
4085*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4086*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.p = thr_args}};
4087*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpp", args);
4088*795d594fSAndroid Build Coastguard Worker JniValueType result;
4089*795d594fSAndroid Build Coastguard Worker result.i = BaseVm(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
4090*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4091*795d594fSAndroid Build Coastguard Worker return result.i;
4092*795d594fSAndroid Build Coastguard Worker }
4093*795d594fSAndroid Build Coastguard Worker
DetachCurrentThread(JavaVM * vm)4094*795d594fSAndroid Build Coastguard Worker static jint DetachCurrentThread(JavaVM* vm) {
4095*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4096*795d594fSAndroid Build Coastguard Worker JniValueType args[1] = {{.v = vm}};
4097*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "v", args);
4098*795d594fSAndroid Build Coastguard Worker JniValueType result;
4099*795d594fSAndroid Build Coastguard Worker result.i = BaseVm(vm)->DetachCurrentThread(vm);
4100*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4101*795d594fSAndroid Build Coastguard Worker return result.i;
4102*795d594fSAndroid Build Coastguard Worker }
4103*795d594fSAndroid Build Coastguard Worker
GetEnv(JavaVM * vm,void ** p_env,jint version)4104*795d594fSAndroid Build Coastguard Worker static jint GetEnv(JavaVM* vm, void** p_env, jint version) {
4105*795d594fSAndroid Build Coastguard Worker ScopedCheck sc(kFlag_Invocation, __FUNCTION__);
4106*795d594fSAndroid Build Coastguard Worker JniValueType args[3] = {{.v = vm}, {.p = p_env}, {.I = version}};
4107*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), true, "vpI", args);
4108*795d594fSAndroid Build Coastguard Worker JniValueType result;
4109*795d594fSAndroid Build Coastguard Worker result.i = BaseVm(vm)->GetEnv(vm, p_env, version);
4110*795d594fSAndroid Build Coastguard Worker sc.CheckNonHeap(reinterpret_cast<JavaVMExt*>(vm), false, "i", &result);
4111*795d594fSAndroid Build Coastguard Worker return result.i;
4112*795d594fSAndroid Build Coastguard Worker }
4113*795d594fSAndroid Build Coastguard Worker
4114*795d594fSAndroid Build Coastguard Worker private:
BaseVm(JavaVM * vm)4115*795d594fSAndroid Build Coastguard Worker static const JNIInvokeInterface* BaseVm(JavaVM* vm) {
4116*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<JavaVMExt*>(vm)->GetUncheckedFunctions();
4117*795d594fSAndroid Build Coastguard Worker }
4118*795d594fSAndroid Build Coastguard Worker };
4119*795d594fSAndroid Build Coastguard Worker
4120*795d594fSAndroid Build Coastguard Worker const JNIInvokeInterface gCheckInvokeInterface = {
4121*795d594fSAndroid Build Coastguard Worker nullptr, // reserved0
4122*795d594fSAndroid Build Coastguard Worker nullptr, // reserved1
4123*795d594fSAndroid Build Coastguard Worker nullptr, // reserved2
4124*795d594fSAndroid Build Coastguard Worker CheckJII::DestroyJavaVM,
4125*795d594fSAndroid Build Coastguard Worker CheckJII::AttachCurrentThread,
4126*795d594fSAndroid Build Coastguard Worker CheckJII::DetachCurrentThread,
4127*795d594fSAndroid Build Coastguard Worker CheckJII::GetEnv,
4128*795d594fSAndroid Build Coastguard Worker CheckJII::AttachCurrentThreadAsDaemon
4129*795d594fSAndroid Build Coastguard Worker };
4130*795d594fSAndroid Build Coastguard Worker
4131*795d594fSAndroid Build Coastguard Worker } // anonymous namespace
4132*795d594fSAndroid Build Coastguard Worker
GetCheckJniNativeInterface()4133*795d594fSAndroid Build Coastguard Worker const JNINativeInterface* GetCheckJniNativeInterface() {
4134*795d594fSAndroid Build Coastguard Worker return &gCheckNativeInterface;
4135*795d594fSAndroid Build Coastguard Worker }
4136*795d594fSAndroid Build Coastguard Worker
GetCheckJniInvokeInterface()4137*795d594fSAndroid Build Coastguard Worker const JNIInvokeInterface* GetCheckJniInvokeInterface() {
4138*795d594fSAndroid Build Coastguard Worker return &gCheckInvokeInterface;
4139*795d594fSAndroid Build Coastguard Worker }
4140*795d594fSAndroid Build Coastguard Worker
4141*795d594fSAndroid Build Coastguard Worker } // namespace art
4142