1 /*
  2  * Copyright (c) 1997, 2023, 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/vmClasses.hpp"
 30 #include "classfile/vmSymbols.hpp"
 31 #include "logging/log.hpp"
 32 #include "logging/logTag.hpp"
 33 #include "memory/oopFactory.hpp"
 34 #include "memory/resourceArea.hpp"
 35 #include "oops/instanceKlass.hpp"
 36 #include "oops/klass.inline.hpp"
 37 #include "oops/method.hpp"
 38 #include "oops/oop.inline.hpp"
 39 #include "oops/symbol.hpp"
 40 #include "prims/jvmtiAgentList.hpp"
 41 #include "prims/jvm_misc.hpp"
 42 #include "prims/jvmtiExport.hpp"
 43 #include "prims/nativeLookup.hpp"
 44 #include "prims/unsafe.hpp"
 45 #include "prims/scopedMemoryAccess.hpp"
 46 #include "prims/shipilevMagic.hpp"
 47 #include "runtime/arguments.hpp"
 48 #include "runtime/handles.inline.hpp"
 49 #include "runtime/interfaceSupport.inline.hpp"
 50 #include "runtime/javaCalls.hpp"
 51 #include "runtime/os.hpp"
 52 #include "runtime/sharedRuntime.hpp"
 53 #include "runtime/signature.hpp"
 54 #include "utilities/macros.hpp"
 55 #include "utilities/utf8.hpp"
 56 #if INCLUDE_JFR
 57 #include "jfr/jfr.hpp"
 58 #endif
 59 
 60 /*
 61 
 62 The JNI specification defines the mapping from a Java native method name to
 63 a C native library implementation function name as follows:
 64 
 65   The mapping produces a native method name by concatenating the following components
 66   derived from a `native` method declaration:
 67 
 68   1. the prefix Java_
 69   2. given the binary name, in internal form, of the class which declares the native method:
 70      the result of escaping the name.
 71   3. an underscore ("_")
 72   4. the escaped method name
 73   5. if the native method declaration is overloaded: two underscores ("__") followed by the
 74    escaped parameter descriptor (JVMS 4.3.3) of the method declaration.
 75 
 76   Escaping leaves every alphanumeric ASCII character (A-Za-z0-9) unchanged, and replaces each
 77   UTF-16 code unit n the table below with the corresponding escape sequence. If the name to be
 78   escaped contains a surrogate pair, then the high-surrogate code unit and the low-surrogate code
 79   unit are escaped separately. The result of escaping is a string consisting only of the ASCII
 80   characters A-Za-z0-9 and underscore.
 81 
 82   ------------------------------                  ------------------------------------
 83   UTF-16 code unit                                Escape sequence
 84   ------------------------------                  ------------------------------------
 85   Forward slash (/, U+002F)                       _
 86   Underscore (_, U+005F)                          _1
 87   Semicolon (;, U+003B)                           _2
 88   Left square bracket ([, U+005B)                 _3
 89   Any UTF-16 code unit \u_WXYZ_ that does not     _0wxyz where w, x, y, and z are the lower-case
 90   represent alphanumeric ASCII (A-Za-z0-9),       forms of the hexadecimal digits W, X, Y, and Z.
 91   forward slash, underscore, semicolon,           (For example, U+ABCD becomes _0abcd.)
 92   or left square bracket
 93   ------------------------------                  ------------------------------------
 94 
 95   Note that escape sequences can safely begin _0, _1, etc, because class and method
 96   names in Java source code never begin with a number. However, that is not the case in
 97   class files that were not generated from Java source code.
 98 
 99   To preserve the 1:1 mapping to a native method name, the VM checks the resulting name as
100   follows. If the process of escaping any precursor string from the native  method declaration
101   (class or method name, or argument type) causes a "0", "1", "2", or "3" character
102   from the precursor string to appear unchanged in the result *either* immediately after an
103   underscore *or* at the beginning of the escaped string (where it will follow an underscore
104   in the fully assembled name), then the escaping process is said to have "failed".
105   In such cases, no native library search is performed, and the attempt to link the native
106   method invocation will throw UnsatisfiedLinkError.
107 
108 
109 For example:
110 
111   package/my_class/method
112 
113 and
114 
115   package/my/1class/method
116 
117 both map to
118 
119   Java_package_my_1class_method
120 
121 To address this potential conflict we need only check if the character after
122 / is a digit 0..3, or if the first character after an injected '_' separator
123 is a digit 0..3. If we encounter an invalid identifier we reset the
124 stringStream and return false. Otherwise the stringStream contains the mapped
125 name and we return true.
126 
127 */
128 static bool map_escaped_name_on(stringStream* st, Symbol* name, int begin, int end) {
129   char* bytes = (char*)name->bytes() + begin;
130   char* end_bytes = (char*)name->bytes() + end;
131   bool check_escape_char = true; // initially true as first character here follows '_'
132   while (bytes < end_bytes) {
133     jchar c;
134     bytes = UTF8::next(bytes, &c);
135     if (c <= 0x7f && isalnum(c)) {
136       if (check_escape_char && (c >= '0' && c <= '3')) {
137         // This is a non-Java identifier and we won't escape it to
138         // ensure no name collisions with a Java identifier.
139         if (log_is_enabled(Debug, jni, resolve)) {
140           ResourceMark rm;
141           log_debug(jni, resolve)("[Lookup of native method with non-Java identifier rejected: %s]",
142                                   name->as_C_string());
143         }
144         st->reset();  // restore to "" on error
145         return false;
146       }
147       st->put((char) c);
148       check_escape_char = false;
149     } else {
150       check_escape_char = false;
151       if (c == '_') st->print("_1");
152       else if (c == '/') {
153         st->print("_");
154         // Following a / we must have non-escape character
155         check_escape_char = true;
156       }
157       else if (c == ';') st->print("_2");
158       else if (c == '[') st->print("_3");
159       else               st->print("_%.5x", c);
160     }
161   }
162   return true;
163 }
164 
165 
166 static bool map_escaped_name_on(stringStream* st, Symbol* name) {
167   return map_escaped_name_on(st, name, 0, name->utf8_length());
168 }
169 
170 
171 char* NativeLookup::pure_jni_name(const methodHandle& method) {
172   stringStream st;
173   // Prefix
174   st.print("Java_");
175   // Klass name
176   if (!map_escaped_name_on(&st, method->klass_name())) {
177     return nullptr;
178   }
179   st.print("_");
180   // Method name
181   if (!map_escaped_name_on(&st, method->name())) {
182     return nullptr;
183   }
184   return st.as_string();
185 }
186 
187 char* NativeLookup::long_jni_name(const methodHandle& method) {
188   // Signatures ignore the wrapping parentheses and the trailing return type
189   stringStream st;
190   Symbol* signature = method->signature();
191   st.print("__");
192   // find ')'
193   int end;
194   for (end = 0; end < signature->utf8_length() && signature->char_at(end) != JVM_SIGNATURE_ENDFUNC; end++);
195   // skip first '('
196   if (!map_escaped_name_on(&st, signature, 1, end)) {
197     return nullptr;
198   }
199 
200   return st.as_string();
201 }
202 
203 extern "C" {
204   void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
205   void JNICALL JVM_RegisterReferencesMethods(JNIEnv *env, jclass unsafecls);
206   void JNICALL JVM_RegisterUpcallHandlerMethods(JNIEnv *env, jclass unsafecls);
207   void JNICALL JVM_RegisterUpcallLinkerMethods(JNIEnv *env, jclass unsafecls);
208   void JNICALL JVM_RegisterNativeEntryPointMethods(JNIEnv *env, jclass unsafecls);
209   void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
210   void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
211   void JNICALL JVM_RegisterVectorSupportMethods(JNIEnv *env, jclass vsclass);
212 #if INCLUDE_JVMCI
213   jobject  JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
214   jlong    JNICALL JVM_ReadSystemPropertiesInfo(JNIEnv *env, jclass c, jintArray offsets);
215   void     JNICALL JVM_RegisterJVMCINatives(JNIEnv *env, jclass compilerToVMClass);
216 #endif
217 }
218 
219 #define CC (char*)  /* cast a literal from (const char*) */
220 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
221 
222 static JNINativeMethod lookup_special_native_methods[] = {
223   { CC"Java_jdk_internal_misc_Unsafe_registerNatives",             nullptr, FN_PTR(JVM_RegisterJDKInternalMiscUnsafeMethods) },
224   { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", nullptr, FN_PTR(JVM_RegisterMethodHandleMethods) },
225   { CC"Java_jdk_internal_foreign_abi_UpcallStubs_registerNatives",      nullptr, FN_PTR(JVM_RegisterUpcallHandlerMethods) },
226   { CC"Java_jdk_internal_foreign_abi_UpcallLinker_registerNatives",      nullptr, FN_PTR(JVM_RegisterUpcallLinkerMethods) },
227   { CC"Java_jdk_internal_foreign_abi_NativeEntryPoint_registerNatives",      nullptr, FN_PTR(JVM_RegisterNativeEntryPointMethods) },
228   { CC"Java_jdk_internal_perf_Perf_registerNatives",               nullptr, FN_PTR(JVM_RegisterPerfMethods)         },
229   { CC"Java_sun_hotspot_WhiteBox_registerNatives",                 nullptr, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
230   { CC"Java_jdk_test_whitebox_WhiteBox_registerNatives",           nullptr, FN_PTR(JVM_RegisterWhiteBoxMethods)     },
231   { CC"Java_jdk_internal_vm_vector_VectorSupport_registerNatives", nullptr, FN_PTR(JVM_RegisterVectorSupportMethods)},
232 #if INCLUDE_JVMCI
233   { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime",            nullptr, FN_PTR(JVM_GetJVMCIRuntime)             },
234   { CC"Java_jdk_vm_ci_services_Services_readSystemPropertiesInfo", nullptr, FN_PTR(JVM_ReadSystemPropertiesInfo)    },
235   { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives",       nullptr, FN_PTR(JVM_RegisterJVMCINatives)        },
236 #endif
237 #if INCLUDE_JFR
238   { CC"Java_jdk_jfr_internal_JVM_registerNatives",                 nullptr, FN_PTR(jfr_register_natives)            },
239 #endif
240   { CC"Java_jdk_internal_misc_ScopedMemoryAccess_registerNatives", nullptr, FN_PTR(JVM_RegisterJDKInternalMiscScopedMemoryAccessMethods) },
241   { CC"Java_net_shipilev_Magic_registerNatives",                   nullptr, FN_PTR(JVM_RegisterNetShipilevMagicMethods) },
242 };
243 
244 static address lookup_special_native(const char* jni_name) {
245   int count = sizeof(lookup_special_native_methods) / sizeof(JNINativeMethod);
246   for (int i = 0; i < count; i++) {
247     // NB: To ignore the jni prefix and jni postfix strstr is used matching.
248     if (strstr(jni_name, lookup_special_native_methods[i].name) != nullptr) {
249       return CAST_FROM_FN_PTR(address, lookup_special_native_methods[i].fnPtr);
250     }
251   }
252   return nullptr;
253 }
254 
255 address NativeLookup::lookup_style(const methodHandle& method, char* pure_name, const char* long_name, int args_size, bool os_style, TRAPS) {
256   address entry;
257   const char* jni_name = compute_complete_jni_name(pure_name, long_name, args_size, os_style);
258 
259 
260   // If the loader is null we have a system class, so we attempt a lookup in
261   // the native Java library. This takes care of any bootstrapping problems.
262   // Note: It is critical for bootstrapping that Java_java_lang_ClassLoader_findNative
263   // gets found the first time around - otherwise an infinite loop can occur. This is
264   // another VM/library dependency
265   Handle loader(THREAD, method->method_holder()->class_loader());
266   if (loader.is_null()) {
267     entry = lookup_special_native(jni_name);
268     if (entry == nullptr) {
269        entry = (address) os::dll_lookup(os::native_java_library(), jni_name);
270     }
271     if (entry != nullptr) {
272       return entry;
273     }
274   }
275 
276   // Otherwise call static method findNative in ClassLoader
277   Klass*   klass = vmClasses::ClassLoader_klass();
278   Handle name_arg = java_lang_String::create_from_str(jni_name, CHECK_NULL);
279 
280   JavaValue result(T_LONG);
281   JavaCalls::call_static(&result,
282                          klass,
283                          vmSymbols::findNative_name(),
284                          vmSymbols::classloader_string_long_signature(),
285                          // Arguments
286                          loader,
287                          name_arg,
288                          CHECK_NULL);
289   entry = (address) (intptr_t) result.get_jlong();
290 
291   if (entry == nullptr) {
292     // findNative didn't find it, if there are any agent libraries look in them
293     JvmtiAgentList::Iterator it = JvmtiAgentList::agents();
294     while (it.has_next()) {
295       entry = (address)os::dll_lookup(it.next()->os_lib(), jni_name);
296       if (entry != nullptr) {
297         return entry;
298       }
299     }
300   }
301 
302   return entry;
303 }
304 
305 const char* NativeLookup::compute_complete_jni_name(const char* pure_name, const char* long_name, int args_size, bool os_style) {
306   stringStream st;
307   if (os_style) {
308     os::print_jni_name_prefix_on(&st, args_size);
309   }
310 
311   st.print_raw(pure_name);
312   st.print_raw(long_name);
313   if (os_style) {
314     os::print_jni_name_suffix_on(&st, args_size);
315   }
316 
317   return st.as_string();
318 }
319 
320 // Check all the formats of native implementation name to see if there is one
321 // for the specified method.
322 address NativeLookup::lookup_entry(const methodHandle& method, TRAPS) {
323   address entry = nullptr;
324   // Compute pure name
325   char* pure_name = pure_jni_name(method);
326   if (pure_name == nullptr) {
327     // JNI name mapping rejected this method so return
328     // null to indicate UnsatisfiedLinkError should be thrown.
329     return nullptr;
330   }
331 
332   // Compute argument size
333   int args_size = 1                             // JNIEnv
334                 + (method->is_static() ? 1 : 0) // class for static methods
335                 + method->size_of_parameters(); // actual parameters
336 
337   // 1) Try JNI short style
338   entry = lookup_style(method, pure_name, "",        args_size, true,  CHECK_NULL);
339   if (entry != nullptr) return entry;
340 
341   // Compute long name
342   char* long_name = long_jni_name(method);
343   if (long_name == nullptr) {
344     // JNI name mapping rejected this method so return
345     // null to indicate UnsatisfiedLinkError should be thrown.
346     return nullptr;
347   }
348 
349   // 2) Try JNI long style
350   entry = lookup_style(method, pure_name, long_name, args_size, true,  CHECK_NULL);
351   if (entry != nullptr) return entry;
352 
353   // 3) Try JNI short style without os prefix/suffix
354   entry = lookup_style(method, pure_name, "",        args_size, false, CHECK_NULL);
355   if (entry != nullptr) return entry;
356 
357   // 4) Try JNI long style without os prefix/suffix
358   entry = lookup_style(method, pure_name, long_name, args_size, false, CHECK_NULL);
359 
360   return entry; // null indicates not found
361 }
362 
363 // Check if there are any JVM TI prefixes which have been applied to the native method name.
364 // If any are found, remove them before attempting the look up of the
365 // native implementation again.
366 // See SetNativeMethodPrefix in the JVM TI Spec for more details.
367 address NativeLookup::lookup_entry_prefixed(const methodHandle& method, TRAPS) {
368 #if INCLUDE_JVMTI
369   ResourceMark rm(THREAD);
370 
371   int prefix_count;
372   char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);
373   char* in_name = method->name()->as_C_string();
374   char* wrapper_name = in_name;
375   // last applied prefix will be first -- go backwards
376   for (int i = prefix_count-1; i >= 0; i--) {
377     char* prefix = prefixes[i];
378     size_t prefix_len = strlen(prefix);
379     if (strncmp(prefix, wrapper_name, prefix_len) == 0) {
380       // has this prefix remove it
381       wrapper_name += prefix_len;
382     }
383   }
384   if (wrapper_name != in_name) {
385     // we have a name for a wrapping method
386     int wrapper_name_len = (int)strlen(wrapper_name);
387     TempNewSymbol wrapper_symbol = SymbolTable::probe(wrapper_name, wrapper_name_len);
388     if (wrapper_symbol != nullptr) {
389       Klass* k = method->method_holder();
390       Method* wrapper_method = k->lookup_method(wrapper_symbol, method->signature());
391       if (wrapper_method != nullptr && !wrapper_method->is_native()) {
392         // we found a wrapper method, use its native entry
393         method->set_is_prefixed_native();
394         return lookup_entry(methodHandle(THREAD, wrapper_method), THREAD);
395       }
396     }
397   }
398 #endif // INCLUDE_JVMTI
399   return nullptr;
400 }
401 
402 address NativeLookup::lookup_base(const methodHandle& method, TRAPS) {
403   address entry = nullptr;
404   ResourceMark rm(THREAD);
405 
406   entry = lookup_entry(method, CHECK_NULL);
407   if (entry != nullptr) return entry;
408 
409   // standard native method resolution has failed.  Check if there are any
410   // JVM TI prefixes which have been applied to the native method name.
411   entry = lookup_entry_prefixed(method, CHECK_NULL);
412   if (entry != nullptr) return entry;
413 
414   // Native function not found, throw UnsatisfiedLinkError
415   stringStream ss;
416   ss.print("'");
417   method->print_external_name(&ss);
418   ss.print("'");
419   THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), ss.as_string());
420 }
421 
422 
423 address NativeLookup::lookup(const methodHandle& method, TRAPS) {
424   if (!method->has_native_function()) {
425     address entry = lookup_base(method, CHECK_NULL);
426     method->set_native_function(entry,
427       Method::native_bind_event_is_interesting);
428     // -verbose:jni printing
429     if (log_is_enabled(Debug, jni, resolve)) {
430       ResourceMark rm(THREAD);
431       log_debug(jni, resolve)("[Dynamic-linking native method %s.%s ... JNI]",
432                               method->method_holder()->external_name(),
433                               method->name()->as_C_string());
434     }
435   }
436   return method->native_function();
437 }