<commit_before>/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define USING_VMI

#include "instrument.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef HY_ZIP_API
#include <zipsup.h>
#else /* HY_ZIP_API */
#include <vmizip.h>
#endif /* HY_ZIP_API */
#include <jni.h>
#include <vmi.h>

/*
 * This file implements a JVMTI agent to init Instrument instance, and handle class define/redefine events
 */

AgentList *tail = &list;
int gsupport_redefine = 0;
static JNIEnv *jnienv;

//call back function for ClassLoad event
void JNICALL callbackClassFileLoadHook(jvmtiEnv *jvmti_env,
	JNIEnv* jni_env,
	jclass class_being_redefined,
	jobject loader,
	const char* name,
	jobject protection_domain,
	jint class_data_len,
	const unsigned char* class_data,
	jint* new_class_data_len,
	unsigned char** new_class_data){

	jclass inst_class = *(gdata->inst_class);
	jbyteArray jnew_bytes = NULL;
	jbyteArray jold_bytes = (*jni_env)->NewByteArray(jni_env, class_data_len);
	jmethodID transform_method = *(gdata->transform_method);
	int name_len = strlen(name);
	jbyteArray jname_bytes = (*jni_env)->NewByteArray(jni_env, name_len);
	
	//construct java byteArray for old class data and class name
	(*jni_env)->SetByteArrayRegion(jni_env, jold_bytes, 0, class_data_len, (jbyte *)class_data);
	(*jni_env)->SetByteArrayRegion(jni_env, jname_bytes, 0, name_len, (jbyte *)name);
	
	//invoke transform method
	jnew_bytes = (jbyteArray)(*jni_env)->CallObjectMethod(jni_env, *(gdata->inst), transform_method, loader, jname_bytes, class_being_redefined, protection_domain, jold_bytes);	

	//get transform result to native char array
	if(0 != jnew_bytes){
		*new_class_data_len = (*jni_env)->GetArrayLength(jni_env, jnew_bytes);
		(*jvmti_env)->Allocate(jvmti_env, *new_class_data_len, new_class_data);		
		*new_class_data = (*jni_env)->GetPrimitiveArrayCritical(jni_env, jnew_bytes, JNI_FALSE);
		(*jni_env)->ReleasePrimitiveArrayCritical(jni_env, jnew_bytes, *new_class_data, 0);
	}
	return;
}

//call back function for VM init event
void JNICALL callbackVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread){
	jmethodID constructor;
	static jmethodID transform_method;
	static jmethodID premain_method;
	static jobject inst_obj;
	static jclass inst_class;
	jvmtiError err;
	AgentList *elem;
	
	PORT_ACCESS_FROM_ENV (env);	
	inst_class = (*env)->FindClass(env, "org/apache/harmony/instrument/internal/InstrumentationImpl");
	if(NULL == inst_class){		
		(*env)->FatalError(env,"class cannot find: org/apache/harmony/instrument/internal/InstrumentationImpl");
		return;	
	}
	inst_class = (jclass)(*env)->NewGlobalRef(env, inst_class);
	gdata->inst_class = &inst_class;

	constructor = (*env)->GetMethodID(env, inst_class,"<init>", "(Z)V");
	if(NULL == constructor){
		(*env)->FatalError(env,"constructor cannot be found.");				
		return;
	}
	
	inst_obj = (*env)->NewObject(env, inst_class, constructor, gsupport_redefine?JNI_TRUE:JNI_FALSE);
	if(NULL == inst_obj){
		(*env)->FatalError(env,"object cannot be inited.");				
		return;		
	}
	
	inst_obj = (*env)->NewGlobalRef(env, inst_obj);
	gdata->inst = &inst_obj;

	transform_method = (*env)->GetMethodID(env, inst_class, "transform", "(Ljava/lang/ClassLoader;[BLjava/lang/Class;Ljava/security/ProtectionDomain;[B)[B");
	if(NULL == transform_method){
		(*env)->FatalError(env,"transform method cannot find.");
		return;
	}
	gdata->transform_method = &transform_method;

	premain_method = (*env)->GetMethodID(env, inst_class, "executePremain", "([B[B)V");
	if(NULL == premain_method){
		(*env)->FatalError(env,"executePremain method cannot find.");
		return;
	}
	gdata->premain_method = &premain_method;		
	err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);	
	check_jvmti_error(env, err, "Cannot set JVMTI ClassFileLoadHook event notification mode.");
	
	//parse command options and run premain class here	
	if(tail == &list){
		return;
	}
	for(elem = list.next; elem != NULL; elem = list.next){
		char *agent_options = elem->option;	
		char *class_name = elem->class_name;
		jbyteArray joptions=NULL, jclass_name;
		if(class_name){
			jclass_name = (*env)->NewByteArray(env, strlen(class_name));
			(*env)->SetByteArrayRegion(env, jclass_name, 0, strlen(class_name), (jbyte*)class_name);
		}else{
			goto DEALLOCATE;
		}
		if(agent_options){
			joptions = (*env)->NewByteArray(env, strlen(agent_options));
			(*env)->SetByteArrayRegion(env, joptions, 0, strlen(agent_options), (jbyte*)agent_options);
		}
		
		(*env)->CallObjectMethod(env, *(gdata->inst), *(gdata->premain_method), jclass_name, joptions);
DEALLOCATE:
		list.next = elem->next;
		hymem_free_memory(elem->class_name);
		hymem_free_memory(elem->option);
		hymem_free_memory(elem);
	}	
	tail = &list;	
}

char* Read_Manifest(JavaVM *vm, JNIEnv *env,const char *jar_name){
	I_32 retval;
#ifndef HY_ZIP_API
	HyZipFile zipFile;
	HyZipEntry zipEntry;
#else
	VMIZipFile zipFile;
	VMIZipEntry zipEntry;
#endif
	char *result;
	int size = 0;
	char errorMessage[1024];

	/* Reach for the VM interface */	
	VMI_ACCESS_FROM_JAVAVM(vm);
	PORT_ACCESS_FROM_JAVAVM(vm);

#ifdef HY_ZIP_API
	VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI);

#endif /* HY_ZIP_API */
	/* open zip file */
#ifndef HY_ZIP_API
	retval = zip_openZipFile(privatePortLibrary, (char *)jar_name, &zipFile, NULL);
#else /* HY_ZIP_API */
	retval = zipFuncs->zip_openZipFile(VMI, (char *)jar_name, &zipFile, 0);
#endif /* HY_ZIP_API */
	if(retval){
		sprintf(errorMessage,"failed to open file:%s, %d\n", jar_name, retval);
		(*env)->FatalError(env, errorMessage);
		return NULL;
	}

	/* get manifest entry */
#ifndef HY_ZIP_API
	zip_initZipEntry(privatePortLibrary, &zipEntry);
	retval = zip_getZipEntry(privatePortLibrary, &zipFile, &zipEntry, "META-INF/MANIFEST.MF", TRUE);
#else /* HY_ZIP_API */
	zipFuncs->zip_initZipEntry(VMI, &zipEntry);
	retval = zipFuncs->zip_getZipEntry(VMI, &zipFile, &zipEntry, "META-INF/MANIFEST.MF", TRUE);
#endif /* HY_ZIP_API */
	if (retval) {
#ifndef HY_ZIP_API
		zip_freeZipEntry(PORTLIB, &zipEntry);
#else /* HY_ZIP_API */
		zipFuncs->zip_freeZipEntry(VMI, &zipEntry);
#endif /* HY_ZIP_API */
		sprintf(errorMessage,"failed to get entry: %d\n", retval);
		(*env)->FatalError(env, errorMessage);
		return NULL;
	}<commit_msg>r834882 should be also apply to trunk<commit_after>/* 
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define USING_VMI

#include "instrument.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef HY_ZIP_API
#include <zipsup.h>
#else /* HY_ZIP_API */
#include <vmizip.h>
#endif /* HY_ZIP_API */
#include <jni.h>
#include <vmi.h>

/*
 * This file implements a JVMTI agent to init Instrument instance, and handle class define/redefine events
 */

AgentList *tail = &list;
int gsupport_redefine = 0;
static JNIEnv *jnienv;

//call back function for ClassLoad event
void JNICALL callbackClassFileLoadHook(jvmtiEnv *jvmti_env,
	JNIEnv* jni_env,
	jclass class_being_redefined,
	jobject loader,
	const char* name,
	jobject protection_domain,
	jint class_data_len,
	const unsigned char* class_data,
	jint* new_class_data_len,
	unsigned char** new_class_data){

	jclass inst_class = *(gdata->inst_class);
	jbyteArray jnew_bytes = NULL;
	jbyteArray jold_bytes = (*jni_env)->NewByteArray(jni_env, class_data_len);
	jmethodID transform_method = *(gdata->transform_method);
	int name_len = strlen(name);
	jbyteArray jname_bytes = (*jni_env)->NewByteArray(jni_env, name_len);
	
	//construct java byteArray for old class data and class name
	(*jni_env)->SetByteArrayRegion(jni_env, jold_bytes, 0, class_data_len, (jbyte *)class_data);
	(*jni_env)->SetByteArrayRegion(jni_env, jname_bytes, 0, name_len, (jbyte *)name);
	
	//invoke transform method
	jnew_bytes = (jbyteArray)(*jni_env)->CallObjectMethod(jni_env, *(gdata->inst), transform_method, loader, jname_bytes, class_being_redefined, protection_domain, jold_bytes);	

	//get transform result to native char array
	if(0 != jnew_bytes){
		*new_class_data_len = (*jni_env)->GetArrayLength(jni_env, jnew_bytes);
		(*jvmti_env)->Allocate(jvmti_env, *new_class_data_len, new_class_data);		
		*new_class_data = (*jni_env)->GetPrimitiveArrayCritical(jni_env, jnew_bytes, JNI_FALSE);
		(*jni_env)->ReleasePrimitiveArrayCritical(jni_env, jnew_bytes, *new_class_data, 0);
	}
	return;
}

//call back function for VM init event
void JNICALL callbackVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread){
	jmethodID constructor;
	static jmethodID transform_method;
	static jmethodID premain_method;
	static jobject inst_obj;
	static jclass inst_class;
	jvmtiError err;
	AgentList *elem;
	
	PORT_ACCESS_FROM_ENV (env);	
	inst_class = (*env)->FindClass(env, "org/apache/harmony/instrument/internal/InstrumentationImpl");
	if(NULL == inst_class){		
		(*env)->FatalError(env,"class cannot find: org/apache/harmony/instrument/internal/InstrumentationImpl");
		return;	
	}
	inst_class = (jclass)(*env)->NewGlobalRef(env, inst_class);
	gdata->inst_class = &inst_class;

	constructor = (*env)->GetMethodID(env, inst_class,"<init>", "(Z)V");
	if(NULL == constructor){
		(*env)->FatalError(env,"constructor cannot be found.");				
		return;
	}
	
	inst_obj = (*env)->NewObject(env, inst_class, constructor, gsupport_redefine?JNI_TRUE:JNI_FALSE);
	if(NULL == inst_obj){
		(*env)->FatalError(env,"object cannot be inited.");				
		return;		
	}
	
	inst_obj = (*env)->NewGlobalRef(env, inst_obj);
	gdata->inst = &inst_obj;

	transform_method = (*env)->GetMethodID(env, inst_class, "transform", "(Ljava/lang/ClassLoader;[BLjava/lang/Class;Ljava/security/ProtectionDomain;[B)[B");
	if(NULL == transform_method){
		(*env)->FatalError(env,"transform method cannot find.");
		return;
	}
	gdata->transform_method = &transform_method;

	premain_method = (*env)->GetMethodID(env, inst_class, "executePremain", "([B[B)V");
	if(NULL == premain_method){
		(*env)->FatalError(env,"executePremain method cannot find.");
		return;
	}
	gdata->premain_method = &premain_method;		
	err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);	
	check_jvmti_error(env, err, "Cannot set JVMTI ClassFileLoadHook event notification mode.");
	
	//parse command options and run premain class here	
	if(tail == &list){
		return;
	}
	for(elem = list.next; elem != NULL; elem = list.next){
		char *agent_options = elem->option;	
		char *class_name = elem->class_name;
		jbyteArray joptions=NULL, jclass_name;
		if(class_name){
			jclass_name = (*env)->NewByteArray(env, strlen(class_name));
			(*env)->SetByteArrayRegion(env, jclass_name, 0, strlen(class_name), (jbyte*)class_name);
		}else{
			goto DEALLOCATE;
		}
		if(agent_options){
			joptions = (*env)->NewByteArray(env, strlen(agent_options));
			(*env)->SetByteArrayRegion(env, joptions, 0, strlen(agent_options), (jbyte*)agent_options);
		}
		
		(*env)->CallObjectMethod(env, *(gdata->inst), *(gdata->premain_method), jclass_name, joptions);
DEALLOCATE:
		list.next = elem->next;
		hymem_free_memory(elem->class_name);
		hymem_free_memory(elem->option);
		hymem_free_memory(elem);
	}	
	tail = &list;	
}

char* Read_Manifest(JavaVM *vm, JNIEnv *env,const char *jar_name){
	I_32 retval;
#ifndef HY_ZIP_API
	HyZipFile zipFile;
	HyZipEntry zipEntry;
#else
	VMIZipFile zipFile;
	VMIZipEntry zipEntry;
#endif
	char *result;
	int size = 0;
	char errorMessage[1024];

	/* Reach for the VM interface */	
	VMI_ACCESS_FROM_JAVAVM(vm);
	PORT_ACCESS_FROM_JAVAVM(vm);

#ifdef HY_ZIP_API
	VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI);

#endif /* HY_ZIP_API */
	/* open zip file */
#ifndef HY_ZIP_API
	retval = zip_openZipFile(privatePortLibrary, (char *)jar_name, &zipFile, NULL);
#else /* HY_ZIP_API */
	retval = zipFuncs->zip_openZipFile(VMI, (char *)jar_name, &zipFile, 0);
#endif /* HY_ZIP_API */
	if(retval){
		sprintf(errorMessage,"failed to open file:%s, %d\n", jar_name, retval);
		(*env)->FatalError(env, errorMessage);
		return NULL;
	}

	/* get manifest entry */
#ifndef HY_ZIP_API
	zip_initZipEntry(privatePortLibrary, &zipEntry);
	retval = zip_getZipEntry(privatePortLibrary, &zipFile, &zipEntry, "META-INF/MANIFEST.MF", TRUE);
#else /* HY_ZIP_API */
	zipFuncs->zip_initZipEntry(VMI, &zipEntry);
	retval = zipFuncs->zip_getZipEntry(VMI, &zipFile, &zipEntry, "META-INF/MANIFEST.MF", ZIP_FLAG_READ_DATA_POINTER);
#endif /* HY_ZIP_API */
	if (retval) {
#ifndef HY_ZIP_API
		zip_freeZipEntry(PORTLIB, &zipEntry);
#else /* HY_ZIP_API */
		zipFuncs->zip_freeZipEntry(VMI, &zipEntry);
#endif /* HY_ZIP_API */
		sprintf(errorMessage,"failed to get entry: %d\n", retval);
		(*env)->FatalError(env, errorMessage);
		return NULL;
	}
{'fraction_non_alphanumeric': 0.13244658270836282, 'fraction_numerical': 0.0031130607046837414, 'mean_word_length': 5.577477896696138, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 115, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2281421', 'n_tokens_mistral': 5311, 'n_tokens_neox': 5024, 'n_words': 1164}