1 /*
  2  * Copyright (c) 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 
 27 #include "runtime/globals_extension.hpp"
 28 #include "runtime/interfaceSupport.inline.hpp"
 29 #include "runtime/runtimeUpcallNop.hpp"
 30 #include "runtime/runtimeUpcalls.hpp"
 31 
 32 bool RuntimeUpcallNop::_method_filter_result = false;
 33 
 34 bool runtimeUpcallNop_register_upcalls()
 35 {
 36   return RuntimeUpcallNop::register_upcalls();
 37 }
 38 
 39 bool RuntimeUpcallNop::register_upcalls()
 40 {
 41   if(AddRuntimeUpcallsNOP == nullptr || FLAG_IS_DEFAULT(AddRuntimeUpcallsNOP)) return true;
 42 
 43   const char* method_entry = "onMethodEntry:";
 44   const size_t method_entry_len = strlen(method_entry);
 45   const char* method_exit = "onMethodExit:";
 46   const size_t method_exit_len = strlen(method_exit);
 47 
 48   const char* filter_all = "all";
 49   const size_t filter_all_len = strlen(filter_all);
 50   const char* filter_none = "none";
 51   const size_t filter_none_len = strlen(filter_none);
 52 
 53   const char* filter_option = nullptr;
 54   RuntimeUpcallType upcall_type = RuntimeUpcallType::onMethodEntry;
 55   const char* command = AddRuntimeUpcallsNOP == nullptr ? "" : AddRuntimeUpcallsNOP;
 56 
 57   if (strncmp(command, method_entry, method_entry_len) == 0) {
 58     filter_option = command + method_entry_len;
 59     upcall_type = RuntimeUpcallType::onMethodEntry;
 60   } else if (strncmp(command, method_exit, method_exit_len) == 0) {
 61     filter_option = command + method_exit_len;
 62     upcall_type = RuntimeUpcallType::onMethodExit;
 63   } else {
 64     ttyLocker ttyl;
 65     tty->print_cr("An error occurred during parsing AddRuntimeUpcallsNOP");
 66     tty->print_cr("Error! Expected 'onMethodEntry:' or 'onMethodExit:'");
 67     return false;
 68   }
 69 
 70   assert(filter_option != nullptr, "sanity");
 71   if (strncmp(filter_option, filter_all, filter_all_len) == 0) {
 72     _method_filter_result = true;
 73   } else if (strncmp(filter_option, filter_none, filter_none_len) == 0) {
 74     _method_filter_result = false;
 75   } else {
 76     ttyLocker ttyl;
 77     tty->print_cr("An error occurred during parsing AddRuntimeUpcallsNOP");
 78     tty->print_cr("Error! Expected 'all' or 'none'");
 79     return false;
 80   }
 81 
 82   if (RuntimeUpcalls::register_upcall(
 83         upcall_type,
 84         "nop_method",
 85         RuntimeUpcallNop::nop_method,
 86         RuntimeUpcallNop::filter_method_callback)) {
 87     return true;
 88   }
 89   return false;
 90 }
 91 
 92 bool RuntimeUpcallNop::filter_method_callback(MethodDetails& method_details)
 93 {
 94   return _method_filter_result;
 95 }
 96 
 97 JRT_ENTRY(void, RuntimeUpcallNop::nop_method(JavaThread* current))
 98 {
 99 }
100 JRT_END