Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/agent_util/agent_util.c
38827 views
/*1* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940#include <agent_util.h>4142/* ------------------------------------------------------------------- */43/* Generic C utility functions */4445/* Send message to stdout or whatever the data output location is */46void47stdout_message(const char * format, ...)48{49va_list ap;5051va_start(ap, format);52(void)vfprintf(stdout, format, ap);53va_end(ap);54}5556/* Send message to stderr or whatever the error output location is and exit */57void58fatal_error(const char * format, ...)59{60va_list ap;6162va_start(ap, format);63(void)vfprintf(stderr, format, ap);64(void)fflush(stderr);65va_end(ap);66exit(3);67}6869/* Get a token from a string (strtok is not MT-safe)70* str String to scan71* seps Separation characters72* buf Place to put results73* max Size of buf74* Returns NULL if no token available or can't do the scan.75*/76char *77get_token(char *str, char *seps, char *buf, int max)78{79int len;8081buf[0] = 0;82if ( str==NULL || str[0]==0 ) {83return NULL;84}85str += strspn(str, seps);86if ( str[0]==0 ) {87return NULL;88}89len = (int)strcspn(str, seps);90if ( len >= max ) {91return NULL;92}93(void)strncpy(buf, str, len);94buf[len] = 0;95return str+len;96}9798/* Determines if a class/method is specified by a list item99* item String that represents a pattern to match100* If it starts with a '*', then any class is allowed101* If it ends with a '*', then any method is allowed102* cname Class name, e.g. "java.lang.Object"103* mname Method name, e.g. "<init>"104* Returns 1(true) or 0(false).105*/106static int107covered_by_list_item(char *item, char *cname, char *mname)108{109int len;110111len = (int)strlen(item);112if ( item[0]=='*' ) {113if ( strncmp(mname, item+1, len-1)==0 ) {114return 1;115}116} else if ( item[len-1]=='*' ) {117if ( strncmp(cname, item, len-1)==0 ) {118return 1;119}120} else {121int cname_len;122123cname_len = (int)strlen(cname);124if ( strncmp(cname, item, (len>cname_len?cname_len:len))==0 ) {125if ( cname_len >= len ) {126/* No method name supplied in item, we must have matched */127return 1;128} else {129int mname_len;130131mname_len = (int)strlen(mname);132item += cname_len+1;133len -= cname_len+1;134if ( strncmp(mname, item, (len>mname_len?mname_len:len))==0 ) {135return 1;136}137}138}139}140return 0;141}142143/* Determines if a class/method is specified by this list144* list String of comma separated pattern items145* cname Class name, e.g. "java.lang.Object"146* mname Method name, e.g. "<init>"147* Returns 1(true) or 0(false).148*/149static int150covered_by_list(char *list, char *cname, char *mname)151{152char token[1024];153char *next;154155if ( list[0] == 0 ) {156return 0;157}158159next = get_token(list, ",", token, sizeof(token));160while ( next != NULL ) {161if ( covered_by_list_item(token, cname, mname) ) {162return 1;163}164next = get_token(next, ",", token, sizeof(token));165}166return 0;167}168169/* Determines which class and methods we are interested in170* cname Class name, e.g. "java.lang.Object"171* mname Method name, e.g. "<init>"172* include_list Empty or an explicit list for inclusion173* exclude_list Empty or an explicit list for exclusion174* Returns 1(true) or 0(false).175*/176int177interested(char *cname, char *mname, char *include_list, char *exclude_list)178{179if ( exclude_list!=NULL && exclude_list[0]!=0 &&180covered_by_list(exclude_list, cname, mname) ) {181return 0;182}183if ( include_list!=NULL && include_list[0]!=0 &&184!covered_by_list(include_list, cname, mname) ) {185return 0;186}187return 1;188}189190/* ------------------------------------------------------------------- */191/* Generic JVMTI utility functions */192193/* Every JVMTI interface returns an error code, which should be checked194* to avoid any cascading errors down the line.195* The interface GetErrorName() returns the actual enumeration constant196* name, making the error messages much easier to understand.197*/198void199check_jvmti_error(jvmtiEnv *jvmti, jvmtiError errnum, const char *str)200{201if ( errnum != JVMTI_ERROR_NONE ) {202char *errnum_str;203204errnum_str = NULL;205(void)(*jvmti)->GetErrorName(jvmti, errnum, &errnum_str);206207fatal_error("ERROR: JVMTI: %d(%s): %s\n", errnum,208(errnum_str==NULL?"Unknown":errnum_str),209(str==NULL?"":str));210}211}212213/* All memory allocated by JVMTI must be freed by the JVMTI Deallocate214* interface.215*/216void217deallocate(jvmtiEnv *jvmti, void *ptr)218{219jvmtiError error;220221error = (*jvmti)->Deallocate(jvmti, ptr);222check_jvmti_error(jvmti, error, "Cannot deallocate memory");223}224225/* Allocation of JVMTI managed memory */226void *227allocate(jvmtiEnv *jvmti, jint len)228{229jvmtiError error;230void *ptr;231232error = (*jvmti)->Allocate(jvmti, len, (unsigned char **)&ptr);233check_jvmti_error(jvmti, error, "Cannot allocate memory");234return ptr;235}236237/* Add demo jar file to boot class path (the BCI Tracker class must be238* in the boot classpath)239*240* WARNING: This code assumes that the jar file can be found at one of:241* ${JAVA_HOME}/demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar242* ${JAVA_HOME}/../demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar243* where JAVA_HOME may refer to the jre directory.244* Both these values are added to the boot classpath.245* These locations are only true for these demos, installed246* in the JDK area. Platform specific code could be used to247* find the location of the DLL or .so library, and construct a248* path name to the jar file, relative to the library location.249*/250void251add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name)252{253jvmtiError error;254char *file_sep;255int max_len;256char *java_home;257char jar_path[FILENAME_MAX+1];258259java_home = NULL;260error = (*jvmti)->GetSystemProperty(jvmti, "java.home", &java_home);261check_jvmti_error(jvmti, error, "Cannot get java.home property value");262if ( java_home == NULL || java_home[0] == 0 ) {263fatal_error("ERROR: Java home not found\n");264}265266#ifdef WIN32267file_sep = "\\";268#else269file_sep = "/";270#endif271272max_len = (int)(strlen(java_home) + strlen(demo_name)*2 +273strlen(file_sep)*5 +27416 /* ".." "demo" "jvmti" ".jar" NULL */ );275if ( max_len > (int)sizeof(jar_path) ) {276fatal_error("ERROR: Path to jar file too long\n");277}278(void)strcpy(jar_path, java_home);279(void)strcat(jar_path, file_sep);280(void)strcat(jar_path, "demo");281(void)strcat(jar_path, file_sep);282(void)strcat(jar_path, "jvmti");283(void)strcat(jar_path, file_sep);284(void)strcat(jar_path, demo_name);285(void)strcat(jar_path, file_sep);286(void)strcat(jar_path, demo_name);287(void)strcat(jar_path, ".jar");288error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path);289check_jvmti_error(jvmti, error, "Cannot add to boot classpath");290291(void)strcpy(jar_path, java_home);292(void)strcat(jar_path, file_sep);293(void)strcat(jar_path, "..");294(void)strcat(jar_path, file_sep);295(void)strcat(jar_path, "demo");296(void)strcat(jar_path, file_sep);297(void)strcat(jar_path, "jvmti");298(void)strcat(jar_path, file_sep);299(void)strcat(jar_path, demo_name);300(void)strcat(jar_path, file_sep);301(void)strcat(jar_path, demo_name);302(void)strcat(jar_path, ".jar");303304error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path);305check_jvmti_error(jvmti, error, "Cannot add to boot classpath");306}307308/* ------------------------------------------------------------------- */309310311