1 /*
   2  * Copyright (c) 2003, 2010, 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 "prims/jvmtiExport.hpp"
  27 #include "prims/jvmtiExtensions.hpp"
  28 
  29 // the list of extension functions
  30 GrowableArray<jvmtiExtensionFunctionInfo*>* JvmtiExtensions::_ext_functions;
  31 
  32 // the list of extension events
  33 GrowableArray<jvmtiExtensionEventInfo*>* JvmtiExtensions::_ext_events;
  34 
  35 
  36 // extension function
  37 static jvmtiError JNICALL IsClassUnloadingEnabled(const jvmtiEnv* env, jboolean* enabled, ...) {
  38   if (enabled == NULL) {
  39     return JVMTI_ERROR_NULL_POINTER;
  40   }
  41   *enabled = (jboolean)ClassUnloading;
  42   return JVMTI_ERROR_NONE;
  43 }
  44 
  45 // register extension functions and events. In this implementation we
  46 // have a single extension function (to prove the API) that tests if class
  47 // unloading is enabled or disabled. We also have a single extension event
  48 // EXT_EVENT_CLASS_UNLOAD which is used to provide the JVMDI_EVENT_CLASS_UNLOAD
  49 // event. The function and the event are registered here.
  50 //
  51 void JvmtiExtensions::register_extensions() {
  52   _ext_functions = new (ResourceObj::C_HEAP) GrowableArray<jvmtiExtensionFunctionInfo*>(1,true);
  53   _ext_events = new (ResourceObj::C_HEAP) GrowableArray<jvmtiExtensionEventInfo*>(1,true);
  54 
  55   // register our extension function
  56   static jvmtiParamInfo func_params[] = {
  57     { (char*)"IsClassUnloadingEnabled", JVMTI_KIND_OUT,  JVMTI_TYPE_JBOOLEAN, JNI_FALSE }
  58   };
  59   static jvmtiExtensionFunctionInfo ext_func = {
  60     (jvmtiExtensionFunction)IsClassUnloadingEnabled,
  61     (char*)"com.sun.hotspot.functions.IsClassUnloadingEnabled",
  62     (char*)"Tell if class unloading is enabled (-noclassgc)",
  63     sizeof(func_params)/sizeof(func_params[0]),
  64     func_params,
  65     0,              // no non-universal errors
  66     NULL
  67   };
  68   _ext_functions->append(&ext_func);
  69 
  70   // register our extension event
  71 
  72   static jvmtiParamInfo event_params[] = {
  73     { (char*)"JNI Environment", JVMTI_KIND_IN, JVMTI_TYPE_JNIENV, JNI_FALSE },
  74     { (char*)"Thread", JVMTI_KIND_IN, JVMTI_TYPE_JTHREAD, JNI_FALSE },
  75     { (char*)"Class", JVMTI_KIND_IN, JVMTI_TYPE_JCLASS, JNI_FALSE }
  76   };
  77   static jvmtiExtensionEventInfo ext_event = {
  78     EXT_EVENT_CLASS_UNLOAD,
  79     (char*)"com.sun.hotspot.events.ClassUnload",
  80     (char*)"CLASS_UNLOAD event",
  81     sizeof(event_params)/sizeof(event_params[0]),
  82     event_params
  83   };
  84   _ext_events->append(&ext_event);
  85 }
  86 
  87 
  88 // return the list of extension functions
  89 
  90 jvmtiError JvmtiExtensions::get_functions(JvmtiEnv* env,
  91                                           jint* extension_count_ptr,
  92                                           jvmtiExtensionFunctionInfo** extensions)
  93 {
  94   guarantee(_ext_functions != NULL, "registration not done");
  95 
  96   ResourceTracker rt(env);
  97 
  98   jvmtiExtensionFunctionInfo* ext_funcs;
  99   jvmtiError err = rt.allocate(_ext_functions->length() *
 100                                sizeof(jvmtiExtensionFunctionInfo),
 101                                (unsigned char**)&ext_funcs);
 102   if (err != JVMTI_ERROR_NONE) {
 103     return err;
 104   }
 105 
 106   for (int i=0; i<_ext_functions->length(); i++ ) {
 107     ext_funcs[i].func = _ext_functions->at(i)->func;
 108 
 109     char *id = _ext_functions->at(i)->id;
 110     err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_funcs[i].id));
 111     if (err != JVMTI_ERROR_NONE) {
 112       return err;
 113     }
 114     strcpy(ext_funcs[i].id, id);
 115 
 116     char *desc = _ext_functions->at(i)->short_description;
 117     err = rt.allocate(strlen(desc)+1,
 118                       (unsigned char**)&(ext_funcs[i].short_description));
 119     if (err != JVMTI_ERROR_NONE) {
 120       return err;
 121     }
 122     strcpy(ext_funcs[i].short_description, desc);
 123 
 124     // params
 125 
 126     jint param_count = _ext_functions->at(i)->param_count;
 127 
 128     ext_funcs[i].param_count = param_count;
 129     if (param_count == 0) {
 130       ext_funcs[i].params = NULL;
 131     } else {
 132       err = rt.allocate(param_count*sizeof(jvmtiParamInfo),
 133                         (unsigned char**)&(ext_funcs[i].params));
 134       if (err != JVMTI_ERROR_NONE) {
 135         return err;
 136       }
 137       jvmtiParamInfo* src_params = _ext_functions->at(i)->params;
 138       jvmtiParamInfo* dst_params = ext_funcs[i].params;
 139 
 140       for (int j=0; j<param_count; j++) {
 141         err = rt.allocate(strlen(src_params[j].name)+1,
 142                           (unsigned char**)&(dst_params[j].name));
 143         if (err != JVMTI_ERROR_NONE) {
 144           return err;
 145         }
 146         strcpy(dst_params[j].name, src_params[j].name);
 147 
 148         dst_params[j].kind = src_params[j].kind;
 149         dst_params[j].base_type = src_params[j].base_type;
 150         dst_params[j].null_ok = src_params[j].null_ok;
 151       }
 152     }
 153 
 154     // errors
 155 
 156     jint error_count = _ext_functions->at(i)->error_count;
 157     ext_funcs[i].error_count = error_count;
 158     if (error_count == 0) {
 159       ext_funcs[i].errors = NULL;
 160     } else {
 161       err = rt.allocate(error_count*sizeof(jvmtiError),
 162                         (unsigned char**)&(ext_funcs[i].errors));
 163       if (err != JVMTI_ERROR_NONE) {
 164         return err;
 165       }
 166       memcpy(ext_funcs[i].errors, _ext_functions->at(i)->errors,
 167              error_count*sizeof(jvmtiError));
 168     }
 169   }
 170 
 171   *extension_count_ptr = _ext_functions->length();
 172   *extensions = ext_funcs;
 173   return JVMTI_ERROR_NONE;
 174 }
 175 
 176 
 177 // return the list of extension events
 178 
 179 jvmtiError JvmtiExtensions::get_events(JvmtiEnv* env,
 180                                        jint* extension_count_ptr,
 181                                        jvmtiExtensionEventInfo** extensions)
 182 {
 183   guarantee(_ext_events != NULL, "registration not done");
 184 
 185   ResourceTracker rt(env);
 186 
 187   jvmtiExtensionEventInfo* ext_events;
 188   jvmtiError err = rt.allocate(_ext_events->length() * sizeof(jvmtiExtensionEventInfo),
 189                                (unsigned char**)&ext_events);
 190   if (err != JVMTI_ERROR_NONE) {
 191     return err;
 192   }
 193 
 194   for (int i=0; i<_ext_events->length(); i++ ) {
 195     ext_events[i].extension_event_index = _ext_events->at(i)->extension_event_index;
 196 
 197     char *id = _ext_events->at(i)->id;
 198     err = rt.allocate(strlen(id)+1, (unsigned char**)&(ext_events[i].id));
 199     if (err != JVMTI_ERROR_NONE) {
 200       return err;
 201     }
 202     strcpy(ext_events[i].id, id);
 203 
 204     char *desc = _ext_events->at(i)->short_description;
 205     err = rt.allocate(strlen(desc)+1,
 206                       (unsigned char**)&(ext_events[i].short_description));
 207     if (err != JVMTI_ERROR_NONE) {
 208       return err;
 209     }
 210     strcpy(ext_events[i].short_description, desc);
 211 
 212     // params
 213 
 214     jint param_count = _ext_events->at(i)->param_count;
 215 
 216     ext_events[i].param_count = param_count;
 217     if (param_count == 0) {
 218       ext_events[i].params = NULL;
 219     } else {
 220       err = rt.allocate(param_count*sizeof(jvmtiParamInfo),
 221                         (unsigned char**)&(ext_events[i].params));
 222       if (err != JVMTI_ERROR_NONE) {
 223         return err;
 224       }
 225       jvmtiParamInfo* src_params = _ext_events->at(i)->params;
 226       jvmtiParamInfo* dst_params = ext_events[i].params;
 227 
 228       for (int j=0; j<param_count; j++) {
 229         err = rt.allocate(strlen(src_params[j].name)+1,
 230                           (unsigned char**)&(dst_params[j].name));
 231         if (err != JVMTI_ERROR_NONE) {
 232           return err;
 233         }
 234         strcpy(dst_params[j].name, src_params[j].name);
 235 
 236         dst_params[j].kind = src_params[j].kind;
 237         dst_params[j].base_type = src_params[j].base_type;
 238         dst_params[j].null_ok = src_params[j].null_ok;
 239       }
 240     }
 241   }
 242 
 243   *extension_count_ptr = _ext_events->length();
 244   *extensions = ext_events;
 245   return JVMTI_ERROR_NONE;
 246 }
 247 
 248 // set callback for an extension event and enable/disable it.
 249 
 250 jvmtiError JvmtiExtensions::set_event_callback(JvmtiEnv* env,
 251                                                jint extension_event_index,
 252                                                jvmtiExtensionEvent callback)
 253 {
 254   guarantee(_ext_events != NULL, "registration not done");
 255 
 256   jvmtiExtensionEventInfo* event = NULL;
 257 
 258   // if there are extension events registered then validate that the
 259   // extension_event_index matches one of the registered events.
 260   if (_ext_events != NULL) {
 261     for (int i=0; i<_ext_events->length(); i++ ) {
 262       if (_ext_events->at(i)->extension_event_index == extension_event_index) {
 263          event = _ext_events->at(i);
 264          break;
 265       }
 266     }
 267   }
 268 
 269   // invalid event index
 270   if (event == NULL) {
 271     return JVMTI_ERROR_ILLEGAL_ARGUMENT;
 272   }
 273 
 274   JvmtiEventController::set_extension_event_callback(env, extension_event_index,
 275                                                      callback);
 276 
 277   return JVMTI_ERROR_NONE;
 278 }