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