1 /*
2 * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/javaClasses.hpp"
27 #include "classfile/symbolTable.hpp"
28 #include "classfile/systemDictionary.hpp"
29 #include "classfile/vmSymbols.hpp"
30 #include "logging/log.hpp"
31 #include "logging/logTag.hpp"
32 #include "memory/oopFactory.hpp"
33 #include "memory/resourceArea.hpp"
34 #include "oops/instanceKlass.hpp"
35 #include "oops/method.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "oops/symbol.hpp"
38 #include "prims/jvm_misc.hpp"
39 #include "prims/nativeLookup.hpp"
40 #include "prims/unsafe.hpp"
41 #include "runtime/arguments.hpp"
42 #include "runtime/handles.inline.hpp"
43 #include "runtime/interfaceSupport.inline.hpp"
44 #include "runtime/javaCalls.hpp"
45 #include "runtime/os.inline.hpp"
46 #include "runtime/sharedRuntime.hpp"
47 #include "runtime/signature.hpp"
48 #include "utilities/macros.hpp"
49 #include "utilities/utf8.hpp"
50 #if INCLUDE_JFR
51 #include "jfr/jfr.hpp"
52 #endif
53
54 /*
55
56 The JNI specification defines the mapping from a Java native method name to
57 a C native library implementation function name as follows:
58
59 The mapping produces a native method name by concatenating the following components
60 derived from a `native` method declaration:
61
62 1. the prefix Java_
63 2. given the binary name, in internal form, of the class which declares the native method:
64 the result of escaping the name.
65 3. an underscore ("_")
66 4. the escaped method name
67 5. if the native method declaration is overloaded: two underscores ("__") followed by the
68 escaped parameter descriptor (JVMS 4.3.3) of the method declaration.
69
70 Escaping leaves every alphanumeric ASCII character (A-Za-z0-9) unchanged, and replaces each
71 UTF-16 code unit n the table below with the corresponding escape sequence. If the name to be
72 escaped contains a surrogate pair, then the high-surrogate code unit and the low-surrogate code
73 unit are escaped separately. The result of escaping is a string consisting only of the ASCII
74 characters A-Za-z0-9 and underscore.
75
76 ------------------------------ ------------------------------------
77 UTF-16 code unit Escape sequence
78 ------------------------------ ------------------------------------
79 Forward slash (/, U+002F) _
80 Underscore (_, U+005F) _1
81 Semicolon (;, U+003B) _2
82 Left square bracket ([, U+005B) _3
83 Any UTF-16 code unit \u_WXYZ_ that does not _0wxyz where w, x, y, and z are the lower-case
84 represent alphanumeric ASCII (A-Za-z0-9), forms of the hexadecimal digits W, X, Y, and Z.
85 forward slash, underscore, semicolon, (For example, U+ABCD becomes _0abcd.)
86 or left square bracket
87 ------------------------------ ------------------------------------
88
89 Note that escape sequences can safely begin _0, _1, etc, because class and method
90 names in Java source code never begin with a number. However, that is not the case in
91 class files that were not generated from Java source code.
92
93 To preserve the 1:1 mapping to a native method name, the VM checks the resulting name as
94 follows. If the process of escaping any precursor string from the native method declaration
95 (class or method name, or argument type) causes a "0", "1", "2", or "3" character
96 from the precursor string to appear unchanged in the result *either* immediately after an
97 underscore *or* at the beginning of the escaped string (where it will follow an underscore
98 in the fully assembled name), then the escaping process is said to have "failed".
99 In such cases, no native library search is performed, and the attempt to link the native
100 method invocation will throw UnsatisfiedLinkError.
101
102
103 For example:
104
105 package/my_class/method
106
107 and
108
109 package/my/1class/method
110
111 both map to
112
113 Java_package_my_1class_method
114
115 To address this potential conflict we need only check if the character after
116 / is a digit 0..3, or if the first character after an injected '_' seperator
117 is a digit 0..3. If we encounter an invalid identifier we reset the
118 stringStream and return false. Otherwise the stringStream contains the mapped
119 name and we return true.
120
121 To address legacy compatibility, the UseLegacyJNINameEscaping flag can be set
122 which skips the extra checks.
123
124 */
map_escaped_name_on(stringStream * st,Symbol * name,int begin,int end)125 static bool map_escaped_name_on(stringStream* st, Symbol* name, int begin, int end) {
126 char* bytes = (char*)name->bytes() + begin;
127 char* end_bytes = (char*)name->bytes() + end;
128 bool check_escape_char = true; // initially true as first character here follows '_'
129 while (bytes < end_bytes) {
130 jchar c;
131 bytes = UTF8::next(bytes, &c);
132 if (c <= 0x7f && isalnum(c)) {
133 if (check_escape_char && (c >= '0' && c <= '3') &&
134 !UseLegacyJNINameEscaping) {
135 // This is a non-Java identifier and we won't escape it to
136 // ensure no name collisions with a Java identifier.
137 if (log_is_enabled(Debug, jni, resolve)) {
138 ResourceMark rm;
139 log_debug(jni, resolve)("[Lookup of native method with non-Java identifier rejected: %s]",
140 name->as_C_string());
141 }
142 st->reset(); // restore to "" on error
143 return false;
144 }
145 st->put((char) c);
146 check_escape_char = false;
147 } else {
148 check_escape_char = false;
149 if (c == '_') st->print("_1");
150 else if (c == '/') {
151 st->print("_");
152 // Following a / we must have non-escape character
153 check_escape_char = true;
154 }
155 else if (c == ';') st->print("_2");
156 else if (c == '[') st->print("_3");
157 else st->print("_%.5x", c);
158 }
159 }
160 return true;
161 }
162
163
map_escaped_name_on(stringStream * st,Symbol * name)164 static bool map_escaped_name_on(stringStream* st, Symbol* name) {
165 return map_escaped_name_on(st, name, 0, name->utf8_length());
166 }
167
168
pure_jni_name(const methodHandle & method)169 char* NativeLookup::pure_jni_name(const methodHandle& method) {
170 stringStream st;
171 // Prefix
172 st.print("Java_");
173 // Klass name
174 if (!map_escaped_name_on(&st, method->klass_name())) {
175 return NULL;
176 }
177 st.print("_");
178 // Method name
179 if (!map_escaped_name_on(&st, method->name())) {
180 return NULL;
181 }
182 return st.as_string();
183 }
184
185
critical_jni_name(const methodHandle & method)186 char* NativeLookup::critical_jni_name(const methodHandle& method) {
187 stringStream st;
188 // Prefix
189 st.print("JavaCritical_");
190 // Klass name
191 if (!map_escaped_name_on(&st, method->klass_name())) {
192 return NULL;
193 }
194 st.print("_");
195 // Method name
196 if (!map_escaped_name_on(&st, method->name())) {
197 return NULL;
198 }
199 return st.as_string();
200 }
201
202
long_jni_name(const methodHandle & method)203 char* NativeLookup::long_jni_name(const methodHandle& method) {
204 // Signatures ignore the wrapping parentheses and the trailing return type
205 stringStream st;
206 Symbol* signature = method->signature();
207 st.print("__");
208 // find ')'
209 int end;
210 for (end = 0; end < signature->utf8_length() && signature->char_at(end) != JVM_SIGNATURE_ENDFUNC; end++);
211 // skip first '('
212 if (!map_escaped_name_on(&st, signature, 1, end)) {
213 return NULL;
214 }
215
216 return st.as_string();
217 }
218
219 extern "C" {
220 void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
221 void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
222 void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
223 #if INCLUDE_JVMCI
224 jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
225 void JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
226 #endif
227 }
228
229 #define CC (char*) /* cast a literal from (const char*) */
230 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
231
232 static JNINativeMethod lookup_special_native_methods[] = {
233 { CC"Java_jdk_internal_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterJDKInternalMiscUnsafeMethods) },
234 { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
235 { CC"Java_jdk_internal_perf_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) },
236 { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) },
237 #if INCLUDE_JVMCI
238 { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime", NULL, FN_PTR(JVM_GetJVMCIRuntime) },
239 { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives", NULL, FN_PTR(JVM_RegisterJVMCINatives) },
240 #endif
241 #if INCLUDE_JFR
242 { CC"Java_jdk_jfr_internal_JVM_registerNatives", NULL, FN_PTR(jfr_register_natives) },
243 #endif
244 };
245
lookup_special_native(const char * jni_name)246 static address lookup_special_native(const char* jni_name) {
247 int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod);
248 for (int i = 0; i < count; i++) {
249 // NB: To ignore the jni prefix and jni postfix strstr is used matching.
250 if (strstr(jni_name, lookup_special_native_methods[i].name) != NULL) {
251 return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr);
252 }
253 }
254 return NULL;
255 }
256
lookup_style(const methodHandle & method,char * pure_name,const char * long_name,int args_size,bool os_style,bool & in_base_library,TRAPS)257 address NativeLookup::lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS) {
258 address entry;
259 const char* jni_name = compute_complete_jni_name(pure_name, long_name, args_size, os_style);
260
261
262 // If the loader is null we have a system class, so we attempt a lookup in
263 // the native Java library. This takes care of any bootstrapping problems.
264 // Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_findNative
265 // gets found the first time around - otherwise an infinite loop can occure. This is
266 // another VM/library dependency
267 Handle loader(THREAD, method->method_holder()->class_loader());
268 if (loader.is_null()) {
269 entry = lookup_special_native(jni_name);
270 if (entry == NULL) {
271 entry = (address) os::dll_lookup(os::native_java_library(), jni_name);
272 }
273 if (entry != NULL) {
274 in_base_library = true;
275 return entry;
276 }
277 }
278
279 // Otherwise call static method findNative in ClassLoader
280 Klass* klass = SystemDictionary::ClassLoader_klass();
281 Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL);
282
283 JavaValue result(T_LONG);
284 JavaCalls::call_static(&result,
285 klass,
286 vmSymbols::findNative_name(),
287 vmSymbols::classloader_string_long_signature(),
288 // Arguments
289 loader,
290 name_arg,
291 CHECK_NULL);
292 entry = (address) (intptr_t) result.get_jlong();
293
294 if (entry == NULL) {
295 // findNative didn't find it, if there are any agent libraries look in them
296 AgentLibrary* agent;
297 for (agent = Arguments::agents(); agent != NULL; agent = agent->next()) {
298 entry = (address) os::dll_lookup(agent->os_lib(), jni_name);
299 if (entry != NULL) {
300 return entry;
301 }
302 }
303 }
304
305 return entry;
306 }
307
compute_complete_jni_name(const char * pure_name,const char * long_name,int args_size,bool os_style)308 const char* NativeLookup::compute_complete_jni_name(const char* pure_name, const char* long_name, int args_size, bool os_style) {
309 stringStream st;
310 if (os_style) {
311 os::print_jni_name_prefix_on(&st, args_size);
312 }
313
314 st.print_raw(pure_name);
315 st.print_raw(long_name);
316 if (os_style) {
317 os::print_jni_name_suffix_on(&st, args_size);
318 }
319
320 return st.as_string();
321 }
322
lookup_critical_style(void * dll,const char * pure_name,const char * long_name,int args_size,bool os_style)323 address NativeLookup::lookup_critical_style(void* dll, const char* pure_name, const char* long_name, int args_size, bool os_style) {
324 const char* jni_name = compute_complete_jni_name(pure_name, long_name, args_size, os_style);
325 assert(dll != NULL, "dll must be loaded");
326 return (address)os::dll_lookup(dll, jni_name);
327 }
328
329 // Check all the formats of native implementation name to see if there is one
330 // for the specified method.
lookup_entry(const methodHandle & method,bool & in_base_library,TRAPS)331 address NativeLookup::lookup_entry(const methodHandle& method, bool& in_base_library, TRAPS) {
332 address entry = NULL;
333 in_base_library = false;
334 // Compute pure name
335 char* pure_name = pure_jni_name(method);
336 if (pure_name == NULL) {
337 // JNI name mapping rejected this method so return
338 // NULL to indicate UnsatisfiedLinkError should be thrown.
339 return NULL;
340 }
341
342 // Compute argument size
343 int args_size = 1 // JNIEnv
344 + (method->is_static() ? 1 : 0) // class for static methods
345 + method->size_of_parameters(); // actual parameters
346
347 // 1) Try JNI short style
348 entry = lookup_style(method, pure_name, "", args_size, true, in_base_library, CHECK_NULL);
349 if (entry != NULL) return entry;
350
351 // Compute long name
352 char* long_name = long_jni_name(method);
353 if (long_name == NULL) {
354 // JNI name mapping rejected this method so return
355 // NULL to indicate UnsatisfiedLinkError should be thrown.
356 return NULL;
357 }
358
359 // 2) Try JNI long style
360 entry = lookup_style(method, pure_name, long_name, args_size, true, in_base_library, CHECK_NULL);
361 if (entry != NULL) return entry;
362
363 // 3) Try JNI short style without os prefix/suffix
364 entry = lookup_style(method, pure_name, "", args_size, false, in_base_library, CHECK_NULL);
365 if (entry != NULL) return entry;
366
367 // 4) Try JNI long style without os prefix/suffix
368 entry = lookup_style(method, pure_name, long_name, args_size, false, in_base_library, CHECK_NULL);
369
370 return entry; // NULL indicates not found
371 }
372
373 // Check all the formats of native implementation name to see if there is one
374 // for the specified method.
lookup_critical_entry(const methodHandle & method)375 address NativeLookup::lookup_critical_entry(const methodHandle& method) {
376 assert(CriticalJNINatives, "or should not be here");
377
378 if (method->is_synchronized() ||
379 !method->is_static()) {
380 // Only static non-synchronized methods are allowed
381 return NULL;
382 }
383
384 ResourceMark rm;
385
386 Symbol* signature = method->signature();
387 for (int end = 0; end < signature->utf8_length(); end++) {
388 if (signature->char_at(end) == 'L') {
389 // Don't allow object types
390 return NULL;
391 }
392 }
393
394 // Compute argument size
395 int args_size = method->size_of_parameters();
396 for (SignatureStream ss(signature); !ss.at_return_type(); ss.next()) {
397 if (ss.is_array()) {
398 args_size += T_INT_size; // array length parameter
399 }
400 }
401
402 // dll handling requires I/O. Don't do that while in _thread_in_vm (safepoint may get requested).
403 ThreadToNativeFromVM thread_in_native(JavaThread::current());
404
405 void* dll = dll_load(method);
406 address entry = NULL;
407
408 if (dll != NULL) {
409 entry = lookup_critical_style(dll, method, args_size);
410 // Close the handle to avoid keeping the library alive if the native method holder is unloaded.
411 // This is fine because the library is still kept alive by JNI (see JVM_LoadLibrary). As soon
412 // as the holder class and the library are unloaded (see JVM_UnloadLibrary), the native wrapper
413 // that calls 'critical_entry' becomes unreachable and is unloaded as well.
414 os::dll_unload(dll);
415 }
416
417 return entry; // NULL indicates not found
418 }
419
dll_load(const methodHandle & method)420 void* NativeLookup::dll_load(const methodHandle& method) {
421 if (method->has_native_function()) {
422
423 address current_entry = method->native_function();
424
425 char dll_name[JVM_MAXPATHLEN];
426 int offset;
427 if (os::dll_address_to_library_name(current_entry, dll_name, sizeof(dll_name), &offset)) {
428 char ebuf[32];
429 return os::dll_load(dll_name, ebuf, sizeof(ebuf));
430 }
431 }
432
433 return NULL;
434 }
435
lookup_critical_style(void * dll,const methodHandle & method,int args_size)436 address NativeLookup::lookup_critical_style(void* dll, const methodHandle& method, int args_size) {
437 address entry = NULL;
438 const char* critical_name = critical_jni_name(method);
439 if (critical_name == NULL) {
440 // JNI name mapping rejected this method so return
441 // NULL to indicate UnsatisfiedLinkError should be thrown.
442 return NULL;
443 }
444
445 // 1) Try JNI short style
446 entry = lookup_critical_style(dll, critical_name, "", args_size, true);
447 if (entry != NULL) {
448 return entry;
449 }
450
451 const char* long_name = long_jni_name(method);
452 if (long_name == NULL) {
453 // JNI name mapping rejected this method so return
454 // NULL to indicate UnsatisfiedLinkError should be thrown.
455 return NULL;
456 }
457
458 // 2) Try JNI long style
459 entry = lookup_critical_style(dll, critical_name, long_name, args_size, true);
460 if (entry != NULL) {
461 return entry;
462 }
463
464 // 3) Try JNI short style without os prefix/suffix
465 entry = lookup_critical_style(dll, critical_name, "", args_size, false);
466 if (entry != NULL) {
467 return entry;
468 }
469
470 // 4) Try JNI long style without os prefix/suffix
471 return lookup_critical_style(dll, critical_name, long_name, args_size, false);
472 }
473
474 // Check if there are any JVM TI prefixes which have been applied to the native method name.
475 // If any are found, remove them before attemping the look up of the
476 // native implementation again.
477 // See SetNativeMethodPrefix in the JVM TI Spec for more details.
lookup_entry_prefixed(const methodHandle & method,bool & in_base_library,TRAPS)478 address NativeLookup::lookup_entry_prefixed(const methodHandle& method, bool& in_base_library, TRAPS) {
479 #if INCLUDE_JVMTI
480 ResourceMark rm(THREAD);
481
482 int prefix_count;
483 char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);
484 char* in_name = method->name()->as_C_string();
485 char* wrapper_name = in_name;
486 // last applied prefix will be first -- go backwards
487 for (int i = prefix_count-1; i >= 0; i--) {
488 char* prefix = prefixes[i];
489 size_t prefix_len = strlen(prefix);
490 if (strncmp(prefix, wrapper_name, prefix_len) == 0) {
491 // has this prefix remove it
492 wrapper_name += prefix_len;
493 }
494 }
495 if (wrapper_name != in_name) {
496 // we have a name for a wrapping method
497 int wrapper_name_len = (int)strlen(wrapper_name);
498 TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len);
499 if (wrapper_symbol != NULL) {
500 Klass* k = method->method_holder();
501 Method* wrapper_method = k->lookup_method(wrapper_symbol, method->signature());
502 if (wrapper_method != NULL && !wrapper_method->is_native()) {
503 // we found a wrapper method, use its native entry
504 method->set_is_prefixed_native();
505 return lookup_entry(methodHandle(THREAD, wrapper_method), in_base_library, THREAD);
506 }
507 }
508 }
509 #endif // INCLUDE_JVMTI
510 return NULL;
511 }
512
lookup_base(const methodHandle & method,bool & in_base_library,TRAPS)513 address NativeLookup::lookup_base(const methodHandle& method, bool& in_base_library, TRAPS) {
514 address entry = NULL;
515 ResourceMark rm(THREAD);
516
517 entry = lookup_entry(method, in_base_library, THREAD);
518 if (entry != NULL) return entry;
519
520 // standard native method resolution has failed. Check if there are any
521 // JVM TI prefixes which have been applied to the native method name.
522 entry = lookup_entry_prefixed(method, in_base_library, THREAD);
523 if (entry != NULL) return entry;
524
525 // Native function not found, throw UnsatisfiedLinkError
526 stringStream ss;
527 ss.print("'");
528 method->print_external_name(&ss);
529 ss.print("'");
530 THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string());
531 }
532
533
lookup(const methodHandle & method,bool & in_base_library,TRAPS)534 address NativeLookup::lookup(const methodHandle& method, bool& in_base_library, TRAPS) {
535 if (!method->has_native_function()) {
536 address entry = lookup_base(method, in_base_library, CHECK_NULL);
537 method->set_native_function(entry,
538 Method::native_bind_event_is_interesting);
539 // -verbose:jni printing
540 if (log_is_enabled(Debug, jni, resolve)) {
541 ResourceMark rm(THREAD);
542 log_debug(jni, resolve)("[Dynamic-linking native method %s.%s ... JNI]",
543 method->method_holder()->external_name(),
544 method->name()->as_C_string());
545 }
546 }
547 return method->native_function();
548 }
549
base_library_lookup(const char * class_name,const char * method_name,const char * signature)550 address NativeLookup::base_library_lookup(const char* class_name, const char* method_name, const char* signature) {
551 EXCEPTION_MARK;
552 bool in_base_library = true; // SharedRuntime inits some math methods.
553 TempNewSymbol c_name = SymbolTable::new_symbol(class_name);
554 TempNewSymbol m_name = SymbolTable::new_symbol(method_name);
555 TempNewSymbol s_name = SymbolTable::new_symbol(signature);
556
557 // Find the class
558 Klass* k = SystemDictionary::resolve_or_fail(c_name, true, CATCH);
559 InstanceKlass* klass = InstanceKlass::cast(k);
560
561 // Find method and invoke standard lookup
562 methodHandle method (THREAD,
563 klass->uncached_lookup_method(m_name, s_name, Klass::find_overpass));
564 address result = lookup(method, in_base_library, CATCH);
565 assert(in_base_library, "must be in basic library");
566 guarantee(result != NULL, "must be non NULL");
567 return result;
568 }
569