1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * Compile-time, zero-cost checking of JNI signatures against their C++ function type.
19  * This can trigger compile-time assertions if any of the input is invalid:
20  *     (a) The signature specified does not conform to the JNI function descriptor syntax.
21  *     (b) The C++ function is itself an invalid JNI function (e.g. missing JNIEnv*, etc).
22  *     (c) The descriptor does not match the C++ function (e.g. "()V" will not match jint(jint)).
23  *
24  * The fundamental macros are as following:
25  *   MAKE_JNI_[FAST_|CRITICAL_]NATIVE_METHOD - Create a checked JNINativeMethod{name, sig, func}.
26  *   MAKE_JNI_[FAST_|CRITICAL_]NATIVE_METHOD_AUTOSIG - Same as above, but infer the JNI signature.
27  *
28  * Usage examples:
29  *     // path/to/package/KlassName.java
30  *     class KlassName {
31  *         native jobject normal(int x);
32  *         @FastNative native jobject fast(int x);
33  *         @CriticalNative native int critical(long ptr);
34  *     }
35  *     // path_to_package_KlassName.cpp
36  *     jobject KlassName_normal(JNIEnv*,jobject,jint) {...}
37  *     jobject KlassName_fast(JNIEnv*,jobject,jint) {...}
38  *     jint KlassName_critical(jlong) {...}
39  *
40  *     // Manually specify each signature:
41  *     JNINativeMethod[] gMethods = {
42  *         MAKE_JNI_NATIVE_METHOD("normal", "(I)Ljava/lang/Object;", KlassName_normal),
43  *         MAKE_JNI_FAST_NATIVE_METHOD("fast", "(I)Ljava/lang/Object;", KlassName_fast),
44  *         MAKE_JNI_CRITICAL_NATIVE_METHOD("critical", "(Z)I", KlassName_critical),
45  *     };
46  *
47  *     // Automatically infer the signature:
48  *     JNINativeMethod[] gMethodsAutomaticSignature = {
49  *         MAKE_JNI_NATIVE_METHOD_AUTOSIG("normal", KlassName_normal),
50  *         MAKE_JNI_FAST_NATIVE_METHOD_AUTOSIG("fast", KlassName_fast),
51  *         MAKE_JNI_CRITICAL_NATIVE_METHOD_AUTOSIG("critical", KlassName_critical),
52  *     };
53  *
54  *     // and then call JNIEnv::RegisterNatives with gMethods as usual.
55  *
56  * For convenience the following macros are defined:
57  *   [FAST_|CRITICAL_]NATIVE_METHOD - Return JNINativeMethod for class, func name, and signature.
58  *   OVERLOADED_[FAST_|CRITICAL_]NATIVE_METHOD - Same as above but allows a separate func identifier.
59  *   [FAST_|CRITICAL_]NATIVE_METHOD_AUTOSIG - Return JNINativeMethod, sig inferred from function.
60  *
61  * The FAST_ prefix corresponds to functions annotated with @FastNative,
62  * and the CRITICAL_ prefix corresponds to functions annotated with @CriticalNative.
63  * See dalvik.annotation.optimization.CriticalNative for more details.
64  *
65  * =======================================
66  * Checking rules
67  * =======================================
68  *
69  * ---------------------------------------
70  * JNI descriptor syntax for functions
71  *
72  * Refer to "Chapter 3: JNI Types and Data Structures" of the JNI specification
73  * under the subsection "Type Signatures" table entry "method type".
74  *
75  * JNI signatures not conforming to the above syntax are rejected.
76  * ---------------------------------------
77  * C++ function types
78  *
79  * A normal or @FastNative JNI function type must be of the form
80  *
81  *     ReturnType (JNIEnv*, jclass|jobject, [ArgTypes...]) {}
82  *
83  * A @CriticalNative JNI function type:
84  *
85  *   must be of the form...  ReturnType ([ArgTypes...]){}
86  *   and must not contain any Reference Types.
87  *
88  * Refer to "Chapter 3: JNI Types and Data Structures" of the JNI specification
89  * under the subsection "Primitive Types" and "Reference Types" for the list
90  * of valid argument/return types.
91  *
92  * C++ function types not conforming to the above requirements are rejected.
93  * ---------------------------------------
94  * Matching of C++ function type against JNI function descriptor.
95  *
96  * Assuming all of the above conditions are met for signature and C++ type validity,
97  * then matching between the signature and the type validity can occur:
98  *
99  * Given a signature (Args...)Ret and the
100  *     C++ function type of the form "CRet fn(JNIEnv*, jclass|jobject, CArgs...)",
101  *     or for @CriticalNative of the form "CRet fn(CArgs...)"
102  *
103  * The number of Args... and the number of CArgs... must be equal.
104  *
105  * If so, attempt to match every component from the signature and function type
106  * against each other:
107  *
108  * ReturnType:
109  *     V <-> void
110  *     ArgumentType
111  *
112  * ArgumentType:
113  *     PrimitiveType
114  *     ReferenceType  [except for @CriticalNative]
115  *
116  * PrimitiveType:
117  *     Z <-> jboolean
118  *     B <-> jbyte
119  *     C <-> jchar
120  *     S <-> jshort
121  *     I <-> jint
122  *     J <-> jlong
123  *     F <-> jfloat
124  *     D <-> jdouble
125  *
126  * ReferenceType:
127  *     Ljava/lang/String;    <-> jstring
128  *     Ljava/lang/Class;     <-> jclass
129  *     L*;                   <-  jobject
130  *     Ljava/lang/Throwable;  -> jthrowable
131  *     L*;                   <-  jthrowable
132  *     [ PrimitiveType       <-> ${CPrimitiveType}Array
133  *     [ ReferenceType       <-> jobjectArray
134  *     [*                    <-  jarray
135  *
136  * Wherein <-> represents a strong match (if the left or right pattern occurs,
137  * then left must match right, otherwise matching fails). <- and -> represent
138  * weak matches (that is, other match rules can be still attempted).
139  *
140  * Sidenote: Whilst a jobject could also represent a jclass, jstring, etc,
141  * the stricter approach is taken: the most exact C++ type must be used.
142  */
143 
144 #ifndef NATIVEHELPER_JNI_MACROS_H
145 #define NATIVEHELPER_JNI_MACROS_H
146 
147 // The below basic macros do not perform automatic stringification,
148 // invoked e.g. as MAKE_JNI_NATIVE_METHOD("some_name", "()V", void_fn)
149 
150 // An expression that evaluates to JNINativeMethod { name, signature, function },
151 //   and applies the above compile-time checking for signature+function.
152 // The equivalent Java Language code must not be annotated with @FastNative/@CriticalNative.
153 #define MAKE_JNI_NATIVE_METHOD(name, signature, function)                      \
154   _NATIVEHELPER_JNI_MAKE_METHOD(kNormalNative, name, signature, function)
155 
156 // An expression that evaluates to JNINativeMethod { name, signature, function },
157 //   and applies the above compile-time checking for signature+function.
158 // The equivalent Java Language code must be annotated with @FastNative.
159 #define MAKE_JNI_FAST_NATIVE_METHOD(name, signature, function)                 \
160   _NATIVEHELPER_JNI_MAKE_METHOD(kFastNative, name, signature, function)
161 
162 // An expression that evaluates to JNINativeMethod { name, signature, function },
163 //   and applies the above compile-time checking for signature+function.
164 // The equivalent Java Language code must be annotated with @CriticalNative.
165 #define MAKE_JNI_CRITICAL_NATIVE_METHOD(name, signature, function)             \
166   _NATIVEHELPER_JNI_MAKE_METHOD(kCriticalNative, name, signature, function)
167 
168 // Automatically signature-inferencing macros are also available,
169 // which also checks the C++ function types for validity:
170 
171 // An expression that evalutes to JNINativeMethod { name, infersig(function), function) }
172 // by inferring the signature at compile-time. Only works when the C++ function type
173 // corresponds to one unambigous JNI parameter (e.g. 'jintArray' -> '[I' but 'jobject' -> ???).
174 //
175 // The equivalent Java Language code must not be annotated with @FastNative/@CriticalNative.
176 #define MAKE_JNI_NATIVE_METHOD_AUTOSIG(name, function)                         \
177   _NATIVEHELPER_JNI_MAKE_METHOD_AUTOSIG(kNormalNative, name, function)
178 
179 // An expression that evalutes to JNINativeMethod { name, infersig(function), function) }
180 // by inferring the signature at compile-time. Only works when the C++ function type
181 // corresponds to one unambigous JNI parameter (e.g. 'jintArray' -> '[I' but 'jobject' -> ???).
182 //
183 // The equivalent Java Language code must be annotated with @FastNative.
184 #define MAKE_JNI_FAST_NATIVE_METHOD_AUTOSIG(name, function)                    \
185   _NATIVEHELPER_JNI_MAKE_METHOD_AUTOSIG(kFastNative, name, function)
186 
187 // An expression that evalutes to JNINativeMethod { name, infersig(function), function) }
188 // by inferring the signature at compile-time.
189 //
190 // The equivalent Java Language code must be annotated with @CriticalNative.
191 #define MAKE_JNI_CRITICAL_NATIVE_METHOD_AUTOSIG(name, function)                 \
192   _NATIVEHELPER_JNI_MAKE_METHOD_AUTOSIG(kCriticalNative, name, function)
193 
194 // Convenience macros when the functions follow the naming convention:
195 //       .java file           .cpp file
196 //       JavaLanguageName <-> ${ClassName}_${JavaLanguageName}
197 //
198 // Stringification is done automatically, invoked as:
199 //   NATIVE_[FAST_|CRITICAL]_METHOD(ClassName, JavaLanguageName, Signature)
200 //
201 // Intended to construct a JNINativeMethod.
202 //   (Assumes the C name is the ClassName_JavaMethodName).
203 //
204 // The Java Language code must be annotated with one of (none,@FastNative,@CriticalNative)
205 // for the (none,FAST_,CRITICAL_) variants of these macros.
206 
207 #define NATIVE_METHOD(className, functionName, signature)                \
208   MAKE_JNI_NATIVE_METHOD(#functionName, signature, className ## _ ## functionName)
209 
210 #define OVERLOADED_NATIVE_METHOD(className, functionName, signature, identifier) \
211   MAKE_JNI_NATIVE_METHOD(#functionName, signature, className ## _ ## identifier)
212 
213 #define NATIVE_METHOD_AUTOSIG(className, functionName) \
214   MAKE_JNI_NATIVE_METHOD_AUTOSIG(#functionName, className ## _ ## functionName)
215 
216 #define FAST_NATIVE_METHOD(className, functionName, signature)           \
217   MAKE_JNI_FAST_NATIVE_METHOD(#functionName, signature, className ## _ ## functionName)
218 
219 #define OVERLOADED_FAST_NATIVE_METHOD(className, functionName, signature, identifier) \
220   MAKE_JNI_FAST_NATIVE_METHOD(#functionName, signature, className ## _ ## identifier)
221 
222 #define FAST_NATIVE_METHOD_AUTOSIG(className, functionName) \
223   MAKE_JNI_FAST_NATIVE_METHOD_AUTOSIG(#functionName, className ## _ ## functionName)
224 
225 #define CRITICAL_NATIVE_METHOD(className, functionName, signature)           \
226   MAKE_JNI_CRITICAL_NATIVE_METHOD(#functionName, signature, className ## _ ## functionName)
227 
228 #define OVERLOADED_CRITICAL_NATIVE_METHOD(className, functionName, signature, identifier) \
229   MAKE_JNI_CRITICAL_NATIVE_METHOD(#functionName, signature, className ## _ ## identifier)
230 
231 #define CRITICAL_NATIVE_METHOD_AUTOSIG(className, functionName) \
232   MAKE_JNI_CRITICAL_NATIVE_METHOD_AUTOSIG(#functionName, className ## _ ## functionName)
233 
234 ////////////////////////////////////////////////////////
235 //                IMPLEMENTATION ONLY.
236 //                DO NOT USE DIRECTLY.
237 ////////////////////////////////////////////////////////
238 
239 #if defined(__cplusplus) && __cplusplus >= 201402L
240 #include "nativehelper/detail/signature_checker.h"  // for MAKE_CHECKED_JNI_NATIVE_METHOD
241 #endif
242 
243 // Expands to an expression whose type is JNINativeMethod.
244 // This is for older versions of C++ or C, so it has no compile-time checking.
245 #define _NATIVEHELPER_JNI_MAKE_METHOD_OLD(kind, name, sig, fn)     \
246   (                                                                \
247     (JNINativeMethod) {                                            \
248         (name),                                                    \
249         (sig),                                                     \
250         _NATIVEHELPER_JNI_MACRO_CAST(reinterpret_cast, void *)(fn) \
251     }                                                              \
252   )
253 
254 // C++14 or better, use compile-time checking.
255 #if defined(__cplusplus) && __cplusplus >= 201402L
256 // Expands to a compound expression whose type is JNINativeMethod.
257 #define _NATIVEHELPER_JNI_MAKE_METHOD(kind, name, sig, fn) \
258   MAKE_CHECKED_JNI_NATIVE_METHOD(kind, name, sig, fn)
259 
260 // Expands to a compound expression whose type is JNINativeMethod.
261 #define _NATIVEHELPER_JNI_MAKE_METHOD_AUTOSIG(kind, name, function) \
262   MAKE_INFERRED_JNI_NATIVE_METHOD(kind, name, function)
263 
264 #else
265 // Older versions of C++ or C code get the regular macro that's unchecked.
266 // Expands to a compound expression whose type is JNINativeMethod.
267 #define _NATIVEHELPER_JNI_MAKE_METHOD(kind, name, sig, fn)         \
268   _NATIVEHELPER_JNI_MAKE_METHOD_OLD(kind, name, sig, fn)
269 
270 // Need C++14 or newer to use the AUTOSIG macros.
271 #define _NATIVEHELPER_JNI_MAKE_METHOD_AUTOSIG(kind, name, function) \
272   static_assert(false, "Cannot infer JNI signatures prior to C++14 for function " #function);
273 
274 #endif  // C++14 check
275 
276 // C-style cast for C, C++-style cast for C++ to avoid warnings/errors.
277 #if defined(__cplusplus)
278 #define _NATIVEHELPER_JNI_MACRO_CAST(which_cast, to) \
279     which_cast<to>
280 #else
281 #define _NATIVEHELPER_JNI_MACRO_CAST(which_cast, to) \
282     (to)
283 #endif
284 
285 #endif  // NATIVEHELPER_JNI_MACROS_H
286