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