18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <linux/compiler.h> 38c2ecf20Sopenharmony_ci#include <linux/string.h> 48c2ecf20Sopenharmony_ci#include <sys/types.h> 58c2ecf20Sopenharmony_ci#include <stdio.h> 68c2ecf20Sopenharmony_ci#include <string.h> 78c2ecf20Sopenharmony_ci#include <stdlib.h> 88c2ecf20Sopenharmony_ci#include <err.h> 98c2ecf20Sopenharmony_ci#include <jvmti.h> 108c2ecf20Sopenharmony_ci#ifdef HAVE_JVMTI_CMLR 118c2ecf20Sopenharmony_ci#include <jvmticmlr.h> 128c2ecf20Sopenharmony_ci#endif 138c2ecf20Sopenharmony_ci#include <limits.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include "jvmti_agent.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic int has_line_numbers; 188c2ecf20Sopenharmony_civoid *jvmti_agent; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic void print_error(jvmtiEnv *jvmti, const char *msg, jvmtiError ret) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci char *err_msg = NULL; 238c2ecf20Sopenharmony_ci jvmtiError err; 248c2ecf20Sopenharmony_ci err = (*jvmti)->GetErrorName(jvmti, ret, &err_msg); 258c2ecf20Sopenharmony_ci if (err == JVMTI_ERROR_NONE) { 268c2ecf20Sopenharmony_ci warnx("%s failed with %s", msg, err_msg); 278c2ecf20Sopenharmony_ci (*jvmti)->Deallocate(jvmti, (unsigned char *)err_msg); 288c2ecf20Sopenharmony_ci } else { 298c2ecf20Sopenharmony_ci warnx("%s failed with an unknown error %d", msg, ret); 308c2ecf20Sopenharmony_ci } 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#ifdef HAVE_JVMTI_CMLR 348c2ecf20Sopenharmony_cistatic jvmtiError 358c2ecf20Sopenharmony_cido_get_line_number(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, 368c2ecf20Sopenharmony_ci jvmti_line_info_t *tab) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci jint i, nr_lines = 0; 398c2ecf20Sopenharmony_ci jvmtiLineNumberEntry *loc_tab = NULL; 408c2ecf20Sopenharmony_ci jvmtiError ret; 418c2ecf20Sopenharmony_ci jint src_line = -1; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab); 448c2ecf20Sopenharmony_ci if (ret == JVMTI_ERROR_ABSENT_INFORMATION || ret == JVMTI_ERROR_NATIVE_METHOD) { 458c2ecf20Sopenharmony_ci /* No debug information for this method */ 468c2ecf20Sopenharmony_ci return ret; 478c2ecf20Sopenharmony_ci } else if (ret != JVMTI_ERROR_NONE) { 488c2ecf20Sopenharmony_ci print_error(jvmti, "GetLineNumberTable", ret); 498c2ecf20Sopenharmony_ci return ret; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci for (i = 0; i < nr_lines && loc_tab[i].start_location <= bci; i++) { 538c2ecf20Sopenharmony_ci src_line = i; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (src_line != -1) { 578c2ecf20Sopenharmony_ci tab->pc = (unsigned long)pc; 588c2ecf20Sopenharmony_ci tab->line_number = loc_tab[src_line].line_number; 598c2ecf20Sopenharmony_ci tab->discrim = 0; /* not yet used */ 608c2ecf20Sopenharmony_ci tab->methodID = m; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci ret = JVMTI_ERROR_NONE; 638c2ecf20Sopenharmony_ci } else { 648c2ecf20Sopenharmony_ci ret = JVMTI_ERROR_ABSENT_INFORMATION; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci (*jvmti)->Deallocate(jvmti, (unsigned char *)loc_tab); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci return ret; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic jvmtiError 738c2ecf20Sopenharmony_ciget_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **tab, int *nr_lines) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci const jvmtiCompiledMethodLoadRecordHeader *hdr; 768c2ecf20Sopenharmony_ci jvmtiCompiledMethodLoadInlineRecord *rec; 778c2ecf20Sopenharmony_ci PCStackInfo *c; 788c2ecf20Sopenharmony_ci jint ret; 798c2ecf20Sopenharmony_ci int nr_total = 0; 808c2ecf20Sopenharmony_ci int i, lines_total = 0; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (!(tab && nr_lines)) 838c2ecf20Sopenharmony_ci return JVMTI_ERROR_NULL_POINTER; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* 868c2ecf20Sopenharmony_ci * Phase 1 -- get the number of lines necessary 878c2ecf20Sopenharmony_ci */ 888c2ecf20Sopenharmony_ci for (hdr = compile_info; hdr != NULL; hdr = hdr->next) { 898c2ecf20Sopenharmony_ci if (hdr->kind == JVMTI_CMLR_INLINE_INFO) { 908c2ecf20Sopenharmony_ci rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr; 918c2ecf20Sopenharmony_ci nr_total += rec->numpcs; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (nr_total == 0) 968c2ecf20Sopenharmony_ci return JVMTI_ERROR_NOT_FOUND; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* 998c2ecf20Sopenharmony_ci * Phase 2 -- allocate big enough line table 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_ci *tab = malloc(nr_total * sizeof(**tab)); 1028c2ecf20Sopenharmony_ci if (!*tab) 1038c2ecf20Sopenharmony_ci return JVMTI_ERROR_OUT_OF_MEMORY; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci for (hdr = compile_info; hdr != NULL; hdr = hdr->next) { 1068c2ecf20Sopenharmony_ci if (hdr->kind == JVMTI_CMLR_INLINE_INFO) { 1078c2ecf20Sopenharmony_ci rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr; 1088c2ecf20Sopenharmony_ci for (i = 0; i < rec->numpcs; i++) { 1098c2ecf20Sopenharmony_ci c = rec->pcinfo + i; 1108c2ecf20Sopenharmony_ci /* 1118c2ecf20Sopenharmony_ci * c->methods is the stack of inlined method calls 1128c2ecf20Sopenharmony_ci * at c->pc. [0] is the leaf method. Caller frames 1138c2ecf20Sopenharmony_ci * are ignored at the moment. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci ret = do_get_line_number(jvmti, c->pc, 1168c2ecf20Sopenharmony_ci c->methods[0], 1178c2ecf20Sopenharmony_ci c->bcis[0], 1188c2ecf20Sopenharmony_ci *tab + lines_total); 1198c2ecf20Sopenharmony_ci if (ret == JVMTI_ERROR_NONE) 1208c2ecf20Sopenharmony_ci lines_total++; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci } 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci *nr_lines = lines_total; 1258c2ecf20Sopenharmony_ci return JVMTI_ERROR_NONE; 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci#else /* HAVE_JVMTI_CMLR */ 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic jvmtiError 1308c2ecf20Sopenharmony_ciget_line_numbers(jvmtiEnv *jvmti __maybe_unused, const void *compile_info __maybe_unused, 1318c2ecf20Sopenharmony_ci jvmti_line_info_t **tab __maybe_unused, int *nr_lines __maybe_unused) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci return JVMTI_ERROR_NONE; 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci#endif /* HAVE_JVMTI_CMLR */ 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic void 1388c2ecf20Sopenharmony_cicopy_class_filename(const char * class_sign, const char * file_name, char * result, size_t max_length) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci /* 1418c2ecf20Sopenharmony_ci * Assume path name is class hierarchy, this is a common practice with Java programs 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_ci if (*class_sign == 'L') { 1448c2ecf20Sopenharmony_ci int j, i = 0; 1458c2ecf20Sopenharmony_ci char *p = strrchr(class_sign, '/'); 1468c2ecf20Sopenharmony_ci if (p) { 1478c2ecf20Sopenharmony_ci /* drop the 'L' prefix and copy up to the final '/' */ 1488c2ecf20Sopenharmony_ci for (i = 0; i < (p - class_sign); i++) 1498c2ecf20Sopenharmony_ci result[i] = class_sign[i+1]; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci /* 1528c2ecf20Sopenharmony_ci * append file name, we use loops and not string ops to avoid modifying 1538c2ecf20Sopenharmony_ci * class_sign which is used later for the symbol name 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ci for (j = 0; i < (max_length - 1) && file_name && j < strlen(file_name); j++, i++) 1568c2ecf20Sopenharmony_ci result[i] = file_name[j]; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci result[i] = '\0'; 1598c2ecf20Sopenharmony_ci } else { 1608c2ecf20Sopenharmony_ci /* fallback case */ 1618c2ecf20Sopenharmony_ci strlcpy(result, file_name, max_length); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic jvmtiError 1668c2ecf20Sopenharmony_ciget_source_filename(jvmtiEnv *jvmti, jmethodID methodID, char ** buffer) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci jvmtiError ret; 1698c2ecf20Sopenharmony_ci jclass decl_class; 1708c2ecf20Sopenharmony_ci char *file_name = NULL; 1718c2ecf20Sopenharmony_ci char *class_sign = NULL; 1728c2ecf20Sopenharmony_ci char fn[PATH_MAX]; 1738c2ecf20Sopenharmony_ci size_t len; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci ret = (*jvmti)->GetMethodDeclaringClass(jvmti, methodID, &decl_class); 1768c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 1778c2ecf20Sopenharmony_ci print_error(jvmti, "GetMethodDeclaringClass", ret); 1788c2ecf20Sopenharmony_ci return ret; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name); 1828c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 1838c2ecf20Sopenharmony_ci print_error(jvmti, "GetSourceFileName", ret); 1848c2ecf20Sopenharmony_ci return ret; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL); 1888c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 1898c2ecf20Sopenharmony_ci print_error(jvmti, "GetClassSignature", ret); 1908c2ecf20Sopenharmony_ci goto free_file_name_error; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci copy_class_filename(class_sign, file_name, fn, PATH_MAX); 1948c2ecf20Sopenharmony_ci len = strlen(fn); 1958c2ecf20Sopenharmony_ci *buffer = malloc((len + 1) * sizeof(char)); 1968c2ecf20Sopenharmony_ci if (!*buffer) { 1978c2ecf20Sopenharmony_ci print_error(jvmti, "GetClassSignature", ret); 1988c2ecf20Sopenharmony_ci ret = JVMTI_ERROR_OUT_OF_MEMORY; 1998c2ecf20Sopenharmony_ci goto free_class_sign_error; 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci strcpy(*buffer, fn); 2028c2ecf20Sopenharmony_ci ret = JVMTI_ERROR_NONE; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_cifree_class_sign_error: 2058c2ecf20Sopenharmony_ci (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); 2068c2ecf20Sopenharmony_cifree_file_name_error: 2078c2ecf20Sopenharmony_ci (*jvmti)->Deallocate(jvmti, (unsigned char *)file_name); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return ret; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic jvmtiError 2138c2ecf20Sopenharmony_cifill_source_filenames(jvmtiEnv *jvmti, int nr_lines, 2148c2ecf20Sopenharmony_ci const jvmti_line_info_t * line_tab, 2158c2ecf20Sopenharmony_ci char ** file_names) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci int index; 2188c2ecf20Sopenharmony_ci jvmtiError ret; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci for (index = 0; index < nr_lines; ++index) { 2218c2ecf20Sopenharmony_ci ret = get_source_filename(jvmti, line_tab[index].methodID, &(file_names[index])); 2228c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) 2238c2ecf20Sopenharmony_ci return ret; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return JVMTI_ERROR_NONE; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic void JNICALL 2308c2ecf20Sopenharmony_cicompiled_method_load_cb(jvmtiEnv *jvmti, 2318c2ecf20Sopenharmony_ci jmethodID method, 2328c2ecf20Sopenharmony_ci jint code_size, 2338c2ecf20Sopenharmony_ci void const *code_addr, 2348c2ecf20Sopenharmony_ci jint map_length, 2358c2ecf20Sopenharmony_ci jvmtiAddrLocationMap const *map, 2368c2ecf20Sopenharmony_ci const void *compile_info) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci jvmti_line_info_t *line_tab = NULL; 2398c2ecf20Sopenharmony_ci char ** line_file_names = NULL; 2408c2ecf20Sopenharmony_ci jclass decl_class; 2418c2ecf20Sopenharmony_ci char *class_sign = NULL; 2428c2ecf20Sopenharmony_ci char *func_name = NULL; 2438c2ecf20Sopenharmony_ci char *func_sign = NULL; 2448c2ecf20Sopenharmony_ci uint64_t addr = (uint64_t)(uintptr_t)code_addr; 2458c2ecf20Sopenharmony_ci jvmtiError ret; 2468c2ecf20Sopenharmony_ci int nr_lines = 0; /* in line_tab[] */ 2478c2ecf20Sopenharmony_ci size_t len; 2488c2ecf20Sopenharmony_ci int output_debug_info = 0; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method, 2518c2ecf20Sopenharmony_ci &decl_class); 2528c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 2538c2ecf20Sopenharmony_ci print_error(jvmti, "GetMethodDeclaringClass", ret); 2548c2ecf20Sopenharmony_ci return; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (has_line_numbers && map && map_length) { 2588c2ecf20Sopenharmony_ci ret = get_line_numbers(jvmti, compile_info, &line_tab, &nr_lines); 2598c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 2608c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NOT_FOUND) { 2618c2ecf20Sopenharmony_ci warnx("jvmti: cannot get line table for method"); 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci nr_lines = 0; 2648c2ecf20Sopenharmony_ci } else if (nr_lines > 0) { 2658c2ecf20Sopenharmony_ci line_file_names = malloc(sizeof(char*) * nr_lines); 2668c2ecf20Sopenharmony_ci if (!line_file_names) { 2678c2ecf20Sopenharmony_ci warnx("jvmti: cannot allocate space for line table method names"); 2688c2ecf20Sopenharmony_ci } else { 2698c2ecf20Sopenharmony_ci memset(line_file_names, 0, sizeof(char*) * nr_lines); 2708c2ecf20Sopenharmony_ci ret = fill_source_filenames(jvmti, nr_lines, line_tab, line_file_names); 2718c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 2728c2ecf20Sopenharmony_ci warnx("jvmti: fill_source_filenames failed"); 2738c2ecf20Sopenharmony_ci } else { 2748c2ecf20Sopenharmony_ci output_debug_info = 1; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci ret = (*jvmti)->GetClassSignature(jvmti, decl_class, 2818c2ecf20Sopenharmony_ci &class_sign, NULL); 2828c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 2838c2ecf20Sopenharmony_ci print_error(jvmti, "GetClassSignature", ret); 2848c2ecf20Sopenharmony_ci goto error; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci ret = (*jvmti)->GetMethodName(jvmti, method, &func_name, 2888c2ecf20Sopenharmony_ci &func_sign, NULL); 2898c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 2908c2ecf20Sopenharmony_ci print_error(jvmti, "GetMethodName", ret); 2918c2ecf20Sopenharmony_ci goto error; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* 2958c2ecf20Sopenharmony_ci * write source line info record if we have it 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_ci if (output_debug_info) 2988c2ecf20Sopenharmony_ci if (jvmti_write_debug_info(jvmti_agent, addr, nr_lines, line_tab, (const char * const *) line_file_names)) 2998c2ecf20Sopenharmony_ci warnx("jvmti: write_debug_info() failed"); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2; 3028c2ecf20Sopenharmony_ci { 3038c2ecf20Sopenharmony_ci char str[len]; 3048c2ecf20Sopenharmony_ci snprintf(str, len, "%s%s%s", class_sign, func_name, func_sign); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci if (jvmti_write_code(jvmti_agent, str, addr, code_addr, code_size)) 3078c2ecf20Sopenharmony_ci warnx("jvmti: write_code() failed"); 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_cierror: 3108c2ecf20Sopenharmony_ci (*jvmti)->Deallocate(jvmti, (unsigned char *)func_name); 3118c2ecf20Sopenharmony_ci (*jvmti)->Deallocate(jvmti, (unsigned char *)func_sign); 3128c2ecf20Sopenharmony_ci (*jvmti)->Deallocate(jvmti, (unsigned char *)class_sign); 3138c2ecf20Sopenharmony_ci free(line_tab); 3148c2ecf20Sopenharmony_ci while (line_file_names && (nr_lines > 0)) { 3158c2ecf20Sopenharmony_ci if (line_file_names[nr_lines - 1]) { 3168c2ecf20Sopenharmony_ci free(line_file_names[nr_lines - 1]); 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci nr_lines -= 1; 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci free(line_file_names); 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_cistatic void JNICALL 3248c2ecf20Sopenharmony_cicode_generated_cb(jvmtiEnv *jvmti, 3258c2ecf20Sopenharmony_ci char const *name, 3268c2ecf20Sopenharmony_ci void const *code_addr, 3278c2ecf20Sopenharmony_ci jint code_size) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci uint64_t addr = (uint64_t)(unsigned long)code_addr; 3308c2ecf20Sopenharmony_ci int ret; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci ret = jvmti_write_code(jvmti_agent, name, addr, code_addr, code_size); 3338c2ecf20Sopenharmony_ci if (ret) 3348c2ecf20Sopenharmony_ci warnx("jvmti: write_code() failed for code_generated"); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ciJNIEXPORT jint JNICALL 3388c2ecf20Sopenharmony_ciAgent_OnLoad(JavaVM *jvm, char *options, void *reserved __maybe_unused) 3398c2ecf20Sopenharmony_ci{ 3408c2ecf20Sopenharmony_ci jvmtiEventCallbacks cb; 3418c2ecf20Sopenharmony_ci jvmtiCapabilities caps1; 3428c2ecf20Sopenharmony_ci jvmtiJlocationFormat format; 3438c2ecf20Sopenharmony_ci jvmtiEnv *jvmti = NULL; 3448c2ecf20Sopenharmony_ci jint ret; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci jvmti_agent = jvmti_open(); 3478c2ecf20Sopenharmony_ci if (!jvmti_agent) { 3488c2ecf20Sopenharmony_ci warnx("jvmti: open_agent failed"); 3498c2ecf20Sopenharmony_ci return -1; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci /* 3538c2ecf20Sopenharmony_ci * Request a JVMTI interface version 1 environment 3548c2ecf20Sopenharmony_ci */ 3558c2ecf20Sopenharmony_ci ret = (*jvm)->GetEnv(jvm, (void *)&jvmti, JVMTI_VERSION_1); 3568c2ecf20Sopenharmony_ci if (ret != JNI_OK) { 3578c2ecf20Sopenharmony_ci warnx("jvmti: jvmti version 1 not supported"); 3588c2ecf20Sopenharmony_ci return -1; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* 3628c2ecf20Sopenharmony_ci * acquire method_load capability, we require it 3638c2ecf20Sopenharmony_ci * request line numbers (optional) 3648c2ecf20Sopenharmony_ci */ 3658c2ecf20Sopenharmony_ci memset(&caps1, 0, sizeof(caps1)); 3668c2ecf20Sopenharmony_ci caps1.can_generate_compiled_method_load_events = 1; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci ret = (*jvmti)->AddCapabilities(jvmti, &caps1); 3698c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 3708c2ecf20Sopenharmony_ci print_error(jvmti, "AddCapabilities", ret); 3718c2ecf20Sopenharmony_ci return -1; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci ret = (*jvmti)->GetJLocationFormat(jvmti, &format); 3748c2ecf20Sopenharmony_ci if (ret == JVMTI_ERROR_NONE && format == JVMTI_JLOCATION_JVMBCI) { 3758c2ecf20Sopenharmony_ci memset(&caps1, 0, sizeof(caps1)); 3768c2ecf20Sopenharmony_ci caps1.can_get_line_numbers = 1; 3778c2ecf20Sopenharmony_ci caps1.can_get_source_file_name = 1; 3788c2ecf20Sopenharmony_ci ret = (*jvmti)->AddCapabilities(jvmti, &caps1); 3798c2ecf20Sopenharmony_ci if (ret == JVMTI_ERROR_NONE) 3808c2ecf20Sopenharmony_ci has_line_numbers = 1; 3818c2ecf20Sopenharmony_ci } else if (ret != JVMTI_ERROR_NONE) 3828c2ecf20Sopenharmony_ci print_error(jvmti, "GetJLocationFormat", ret); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci memset(&cb, 0, sizeof(cb)); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci cb.CompiledMethodLoad = compiled_method_load_cb; 3888c2ecf20Sopenharmony_ci cb.DynamicCodeGenerated = code_generated_cb; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci ret = (*jvmti)->SetEventCallbacks(jvmti, &cb, sizeof(cb)); 3918c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 3928c2ecf20Sopenharmony_ci print_error(jvmti, "SetEventCallbacks", ret); 3938c2ecf20Sopenharmony_ci return -1; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 3978c2ecf20Sopenharmony_ci JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL); 3988c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 3998c2ecf20Sopenharmony_ci print_error(jvmti, "SetEventNotificationMode(METHOD_LOAD)", ret); 4008c2ecf20Sopenharmony_ci return -1; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, 4048c2ecf20Sopenharmony_ci JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL); 4058c2ecf20Sopenharmony_ci if (ret != JVMTI_ERROR_NONE) { 4068c2ecf20Sopenharmony_ci print_error(jvmti, "SetEventNotificationMode(CODE_GENERATED)", ret); 4078c2ecf20Sopenharmony_ci return -1; 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci return 0; 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ciJNIEXPORT void JNICALL 4138c2ecf20Sopenharmony_ciAgent_OnUnload(JavaVM *jvm __maybe_unused) 4148c2ecf20Sopenharmony_ci{ 4158c2ecf20Sopenharmony_ci int ret; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci ret = jvmti_close(jvmti_agent); 4188c2ecf20Sopenharmony_ci if (ret) 4198c2ecf20Sopenharmony_ci errx(1, "Error: op_close_agent()"); 4208c2ecf20Sopenharmony_ci} 421