Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <jvmti.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #ifdef HAVE_JVMTI_CMLR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <jvmticmlr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <limits.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include "jvmti_agent.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) static int has_line_numbers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) void *jvmti_agent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) static void print_error(jvmtiEnv *jvmti, const char *msg, jvmtiError ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	char *err_msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	jvmtiError err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	err = (*jvmti)->GetErrorName(jvmti, ret, &err_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	if (err == JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 		warnx("%s failed with %s", msg, err_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 		(*jvmti)->Deallocate(jvmti, (unsigned char *)err_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 		warnx("%s failed with an unknown error %d", msg, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #ifdef HAVE_JVMTI_CMLR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static jvmtiError
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) do_get_line_number(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 		   jvmti_line_info_t *tab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	jint i, nr_lines = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	jvmtiLineNumberEntry *loc_tab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	jvmtiError ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	jint src_line = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	if (ret == JVMTI_ERROR_ABSENT_INFORMATION || ret == JVMTI_ERROR_NATIVE_METHOD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		/* No debug information for this method */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	} else if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		print_error(jvmti, "GetLineNumberTable", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	for (i = 0; i < nr_lines && loc_tab[i].start_location <= bci; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 		src_line = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	if (src_line != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		tab->pc = (unsigned long)pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		tab->line_number = loc_tab[src_line].line_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 		tab->discrim = 0; /* not yet used */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		tab->methodID = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		ret = JVMTI_ERROR_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 		ret = JVMTI_ERROR_ABSENT_INFORMATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	(*jvmti)->Deallocate(jvmti, (unsigned char *)loc_tab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static jvmtiError
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **tab, int *nr_lines)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	const jvmtiCompiledMethodLoadRecordHeader *hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	jvmtiCompiledMethodLoadInlineRecord *rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	PCStackInfo *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	jint ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	int nr_total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	int i, lines_total = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if (!(tab && nr_lines))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		return JVMTI_ERROR_NULL_POINTER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	 * Phase 1 -- get the number of lines necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	for (hdr = compile_info; hdr != NULL; hdr = hdr->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		if (hdr->kind == JVMTI_CMLR_INLINE_INFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 			rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			nr_total += rec->numpcs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (nr_total == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		return JVMTI_ERROR_NOT_FOUND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	 * Phase 2 -- allocate big enough line table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	*tab = malloc(nr_total * sizeof(**tab));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	if (!*tab)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		return JVMTI_ERROR_OUT_OF_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	for (hdr = compile_info; hdr != NULL; hdr = hdr->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 		if (hdr->kind == JVMTI_CMLR_INLINE_INFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 			rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			for (i = 0; i < rec->numpcs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 				c = rec->pcinfo + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)                                 /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)                                  * c->methods is the stack of inlined method calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)                                  * at c->pc. [0] is the leaf method. Caller frames
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)                                  * are ignored at the moment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)                                  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 				ret = do_get_line_number(jvmti, c->pc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 							 c->methods[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 							 c->bcis[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 							 *tab + lines_total);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 				if (ret == JVMTI_ERROR_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 					lines_total++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	*nr_lines = lines_total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	return JVMTI_ERROR_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) #else /* HAVE_JVMTI_CMLR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static jvmtiError
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) get_line_numbers(jvmtiEnv *jvmti __maybe_unused, const void *compile_info __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		 jvmti_line_info_t **tab __maybe_unused, int *nr_lines __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return JVMTI_ERROR_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #endif /* HAVE_JVMTI_CMLR */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) copy_class_filename(const char * class_sign, const char * file_name, char * result, size_t max_length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	* Assume path name is class hierarchy, this is a common practice with Java programs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	if (*class_sign == 'L') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		int j, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		char *p = strrchr(class_sign, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		if (p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			/* drop the 'L' prefix and copy up to the final '/' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			for (i = 0; i < (p - class_sign); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 				result[i] = class_sign[i+1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		* append file name, we use loops and not string ops to avoid modifying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		* class_sign which is used later for the symbol name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		for (j = 0; i < (max_length - 1) && file_name && j < strlen(file_name); j++, i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			result[i] = file_name[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		result[i] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		/* fallback case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		strlcpy(result, file_name, max_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) static jvmtiError
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) get_source_filename(jvmtiEnv *jvmti, jmethodID methodID, char ** buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	jvmtiError ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	jclass decl_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	char *file_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	char *class_sign = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	char fn[PATH_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	ret = (*jvmti)->GetMethodDeclaringClass(jvmti, methodID, &decl_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		print_error(jvmti, "GetMethodDeclaringClass", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		print_error(jvmti, "GetSourceFileName", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		print_error(jvmti, "GetClassSignature", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		goto free_file_name_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	copy_class_filename(class_sign, file_name, fn, PATH_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	len = strlen(fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	*buffer = malloc((len + 1) * sizeof(char));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	if (!*buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		print_error(jvmti, "GetClassSignature", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		ret = JVMTI_ERROR_OUT_OF_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		goto free_class_sign_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	strcpy(*buffer, fn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	ret = JVMTI_ERROR_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) free_class_sign_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	(*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) free_file_name_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	(*jvmti)->Deallocate(jvmti, (unsigned char *)file_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static jvmtiError
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) fill_source_filenames(jvmtiEnv *jvmti, int nr_lines,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		      const jvmti_line_info_t * line_tab,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		      char ** file_names)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	jvmtiError ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	for (index = 0; index < nr_lines; ++index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		ret = get_source_filename(jvmti, line_tab[index].methodID, &(file_names[index]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		if (ret != JVMTI_ERROR_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	return JVMTI_ERROR_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static void JNICALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) compiled_method_load_cb(jvmtiEnv *jvmti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			jmethodID method,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 			jint code_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 			void const *code_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 			jint map_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 			jvmtiAddrLocationMap const *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 			const void *compile_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	jvmti_line_info_t *line_tab = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	char ** line_file_names = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	jclass decl_class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	char *class_sign = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	char *func_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	char *func_sign = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	uint64_t addr = (uint64_t)(uintptr_t)code_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	jvmtiError ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	int nr_lines = 0; /* in line_tab[] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	int output_debug_info = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 						&decl_class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		print_error(jvmti, "GetMethodDeclaringClass", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	if (has_line_numbers && map && map_length) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		ret = get_line_numbers(jvmti, compile_info, &line_tab, &nr_lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 			if (ret != JVMTI_ERROR_NOT_FOUND) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 				warnx("jvmti: cannot get line table for method");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			nr_lines = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		} else if (nr_lines > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 			line_file_names = malloc(sizeof(char*) * nr_lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			if (!line_file_names) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 				warnx("jvmti: cannot allocate space for line table method names");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 				memset(line_file_names, 0, sizeof(char*) * nr_lines);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 				ret = fill_source_filenames(jvmti, nr_lines, line_tab, line_file_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 				if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 					warnx("jvmti: fill_source_filenames failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 					output_debug_info = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	ret = (*jvmti)->GetClassSignature(jvmti, decl_class,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 					  &class_sign, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		print_error(jvmti, "GetClassSignature", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 	ret = (*jvmti)->GetMethodName(jvmti, method, &func_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 				      &func_sign, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		print_error(jvmti, "GetMethodName", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	 * write source line info record if we have it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	if (output_debug_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		if (jvmti_write_debug_info(jvmti_agent, addr, nr_lines, line_tab, (const char * const *) line_file_names))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 			warnx("jvmti: write_debug_info() failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		char str[len];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 		snprintf(str, len, "%s%s%s", class_sign, func_name, func_sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		if (jvmti_write_code(jvmti_agent, str, addr, code_addr, code_size))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			warnx("jvmti: write_code() failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	(*jvmti)->Deallocate(jvmti, (unsigned char *)func_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	(*jvmti)->Deallocate(jvmti, (unsigned char *)func_sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	(*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	free(line_tab);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	while (line_file_names && (nr_lines > 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	    if (line_file_names[nr_lines - 1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	        free(line_file_names[nr_lines - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	    nr_lines -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	free(line_file_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) static void JNICALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) code_generated_cb(jvmtiEnv *jvmti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 		  char const *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 		  void const *code_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 		  jint code_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	uint64_t addr = (uint64_t)(unsigned long)code_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	ret = jvmti_write_code(jvmti_agent, name, addr, code_addr, code_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		warnx("jvmti: write_code() failed for code_generated");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) JNIEXPORT jint JNICALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	jvmtiEventCallbacks cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	jvmtiCapabilities caps1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	jvmtiJlocationFormat format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	jvmtiEnv *jvmti = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	jint ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	jvmti_agent = jvmti_open();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	if (!jvmti_agent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		warnx("jvmti: open_agent failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	 * Request a JVMTI interface version 1 environment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	ret = (*jvm)->GetEnv(jvm, (void *)&jvmti, JVMTI_VERSION_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 	if (ret != JNI_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		warnx("jvmti: jvmti version 1 not supported");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 	 * acquire method_load capability, we require it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 	 * request line numbers (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	memset(&caps1, 0, sizeof(caps1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 	caps1.can_generate_compiled_method_load_events = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		print_error(jvmti, "AddCapabilities", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	ret = (*jvmti)->GetJLocationFormat(jvmti, &format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)         if (ret == JVMTI_ERROR_NONE && format == JVMTI_JLOCATION_JVMBCI) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)                 memset(&caps1, 0, sizeof(caps1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)                 caps1.can_get_line_numbers = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)                 caps1.can_get_source_file_name = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 		ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)                 if (ret == JVMTI_ERROR_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)                         has_line_numbers = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)         } else if (ret != JVMTI_ERROR_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		print_error(jvmti, "GetJLocationFormat", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	memset(&cb, 0, sizeof(cb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 	cb.CompiledMethodLoad   = compiled_method_load_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 	cb.DynamicCodeGenerated = code_generated_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 	ret = (*jvmti)->SetEventCallbacks(jvmti, &cb, sizeof(cb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 		print_error(jvmti, "SetEventCallbacks", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) 	ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) 			JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) 		print_error(jvmti, "SetEventNotificationMode(METHOD_LOAD)", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) 	ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) 			JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) 	if (ret != JVMTI_ERROR_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) 		print_error(jvmti, "SetEventNotificationMode(CODE_GENERATED)", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) JNIEXPORT void JNICALL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) Agent_OnUnload(JavaVM *jvm __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) 	ret = jvmti_close(jvmti_agent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) 		errx(1, "Error: op_close_agent()");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }