2 #include <linux/compiler.h> 17 static void print_error(jvmtiEnv *jvmti,
const char *msg, jvmtiError ret)
21 err = (*jvmti)->GetErrorName(jvmti, ret, &err_msg);
22 if (err == JVMTI_ERROR_NONE) {
23 warnx(
"%s failed with %s", msg, err_msg);
24 (*jvmti)->Deallocate(jvmti, (
unsigned char *)err_msg);
26 warnx(
"%s failed with an unknown error %d", msg, ret);
36 jvmtiLineNumberEntry *loc_tab = NULL;
39 ret = (*jvmti)->GetLineNumberTable(jvmti, m, &nr_lines, &loc_tab);
40 if (ret != JVMTI_ERROR_NONE) {
45 for (i = 0; i < nr_lines; i++) {
46 if (loc_tab[i].start_location < bci) {
47 tab[
lines].
pc = (
unsigned long)pc;
56 (*jvmti)->Deallocate(jvmti, (
unsigned char *)loc_tab);
58 return JVMTI_ERROR_NONE;
64 const jvmtiCompiledMethodLoadRecordHeader *hdr;
65 jvmtiCompiledMethodLoadInlineRecord *rec;
66 jvmtiLineNumberEntry *lne = NULL;
70 int i, lines_total = 0;
72 if (!(tab && nr_lines))
73 return JVMTI_ERROR_NULL_POINTER;
78 for (hdr = compile_info; hdr != NULL; hdr = hdr->next) {
79 if (hdr->kind == JVMTI_CMLR_INLINE_INFO) {
80 rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr;
81 for (i = 0; i < rec->numpcs; i++) {
87 ret = (*jvmti)->GetLineNumberTable(jvmti, c->methods[0], &nr, &lne);
88 if (ret == JVMTI_ERROR_NONE) {
90 (*jvmti)->Deallocate(jvmti, (
unsigned char *)lne);
100 return JVMTI_ERROR_NOT_FOUND;
105 *tab =
malloc(nr_total *
sizeof(**tab));
107 return JVMTI_ERROR_OUT_OF_MEMORY;
109 for (hdr = compile_info; hdr != NULL; hdr = hdr->next) {
110 if (hdr->kind == JVMTI_CMLR_INLINE_INFO) {
111 rec = (jvmtiCompiledMethodLoadInlineRecord *)hdr;
112 for (i = 0; i < rec->numpcs; i++) {
120 if (ret == JVMTI_ERROR_NONE)
125 *nr_lines = lines_total;
126 return JVMTI_ERROR_NONE;
135 if (*class_sign ==
'L') {
137 char *p = strrchr(class_sign,
'/');
140 for (i = 0; i < (p - class_sign); i++)
141 result[i] = class_sign[i+1];
147 for (j = 0; i < (max_length - 1) && file_name && j < strlen(file_name); j++, i++)
148 result[i] = file_name[j];
153 size_t file_name_len = strlen(file_name);
154 strncpy(result, file_name, file_name_len < max_length ? file_name_len : max_length);
163 char *file_name = NULL;
164 char *class_sign = NULL;
168 ret = (*jvmti)->GetMethodDeclaringClass(jvmti, methodID, &decl_class);
169 if (ret != JVMTI_ERROR_NONE) {
170 print_error(jvmti,
"GetMethodDeclaringClass", ret);
174 ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
175 if (ret != JVMTI_ERROR_NONE) {
180 ret = (*jvmti)->GetClassSignature(jvmti, decl_class, &class_sign, NULL);
181 if (ret != JVMTI_ERROR_NONE) {
183 goto free_file_name_error;
188 *buffer =
malloc((len + 1) *
sizeof(
char));
191 ret = JVMTI_ERROR_OUT_OF_MEMORY;
192 goto free_class_sign_error;
195 ret = JVMTI_ERROR_NONE;
197 free_class_sign_error:
198 (*jvmti)->Deallocate(jvmti, (
unsigned char *)class_sign);
199 free_file_name_error:
200 (*jvmti)->Deallocate(jvmti, (
unsigned char *)file_name);
213 for (index = 0; index < nr_lines; ++index) {
215 if (ret != JVMTI_ERROR_NONE)
219 return JVMTI_ERROR_NONE;
226 void const *code_addr,
228 jvmtiAddrLocationMap
const *
map,
229 const void *compile_info)
232 char ** line_file_names = NULL;
234 char *class_sign = NULL;
235 char *func_name = NULL;
236 char *func_sign = NULL;
237 char *file_name = NULL;
239 uint64_t addr = (uint64_t)(uintptr_t)code_addr;
243 int output_debug_info = 0;
245 ret = (*jvmti)->GetMethodDeclaringClass(jvmti, method,
247 if (ret != JVMTI_ERROR_NONE) {
248 print_error(jvmti,
"GetMethodDeclaringClass", ret);
254 if (ret != JVMTI_ERROR_NONE) {
255 warnx(
"jvmti: cannot get line table for method");
257 }
else if (nr_lines > 0) {
258 line_file_names =
malloc(
sizeof(
char*) * nr_lines);
259 if (!line_file_names) {
260 warnx(
"jvmti: cannot allocate space for line table method names");
262 memset(line_file_names, 0,
sizeof(
char*) * nr_lines);
264 if (ret != JVMTI_ERROR_NONE) {
265 warnx(
"jvmti: fill_source_filenames failed");
267 output_debug_info = 1;
273 ret = (*jvmti)->GetSourceFileName(jvmti, decl_class, &file_name);
274 if (ret != JVMTI_ERROR_NONE) {
279 ret = (*jvmti)->GetClassSignature(jvmti, decl_class,
281 if (ret != JVMTI_ERROR_NONE) {
286 ret = (*jvmti)->GetMethodName(jvmti, method, &func_name,
288 if (ret != JVMTI_ERROR_NONE) {
298 if (output_debug_info)
300 warnx(
"jvmti: write_debug_info() failed");
302 len = strlen(func_name) + strlen(class_sign) + strlen(func_sign) + 2;
305 snprintf(str, len,
"%s%s%s", class_sign, func_name, func_sign);
308 warnx(
"jvmti: write_code() failed");
311 (*jvmti)->Deallocate(jvmti, (
unsigned char *)func_name);
312 (*jvmti)->Deallocate(jvmti, (
unsigned char *)func_sign);
313 (*jvmti)->Deallocate(jvmti, (
unsigned char *)class_sign);
314 (*jvmti)->Deallocate(jvmti, (
unsigned char *)file_name);
316 while (line_file_names && (nr_lines > 0)) {
317 if (line_file_names[nr_lines - 1]) {
318 free(line_file_names[nr_lines - 1]);
322 free(line_file_names);
328 void const *code_addr,
331 uint64_t addr = (uint64_t)(
unsigned long)code_addr;
336 warnx(
"jvmti: write_code() failed for code_generated");
339 JNIEXPORT jint JNICALL
342 jvmtiEventCallbacks cb;
343 jvmtiCapabilities caps1;
344 jvmtiJlocationFormat format;
345 jvmtiEnv *jvmti = NULL;
350 warnx(
"jvmti: open_agent failed");
357 ret = (*jvm)->GetEnv(jvm, (
void *)&jvmti, JVMTI_VERSION_1);
359 warnx(
"jvmti: jvmti version 1 not supported");
367 memset(&caps1, 0,
sizeof(caps1));
368 caps1.can_generate_compiled_method_load_events = 1;
370 ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
371 if (ret != JVMTI_ERROR_NONE) {
375 ret = (*jvmti)->GetJLocationFormat(jvmti, &format);
376 if (ret == JVMTI_ERROR_NONE && format == JVMTI_JLOCATION_JVMBCI) {
377 memset(&caps1, 0,
sizeof(caps1));
378 caps1.can_get_line_numbers = 1;
379 caps1.can_get_source_file_name = 1;
380 ret = (*jvmti)->AddCapabilities(jvmti, &caps1);
381 if (ret == JVMTI_ERROR_NONE)
383 }
else if (ret != JVMTI_ERROR_NONE)
387 memset(&cb, 0,
sizeof(cb));
392 ret = (*jvmti)->SetEventCallbacks(jvmti, &cb,
sizeof(cb));
393 if (ret != JVMTI_ERROR_NONE) {
398 ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
399 JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
400 if (ret != JVMTI_ERROR_NONE) {
401 print_error(jvmti,
"SetEventNotificationMode(METHOD_LOAD)", ret);
405 ret = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
406 JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL);
407 if (ret != JVMTI_ERROR_NONE) {
408 print_error(jvmti,
"SetEventNotificationMode(CODE_GENERATED)", ret);
414 JNIEXPORT
void JNICALL
421 errx(1,
"Error: op_close_agent()");
static void JNICALL code_generated_cb(jvmtiEnv *jvmti, char const *name, void const *code_addr, jint code_size)
static void print_error(jvmtiEnv *jvmti, const char *msg, jvmtiError ret)
static int has_line_numbers
static jvmtiError fill_source_filenames(jvmtiEnv *jvmti, int nr_lines, const jvmti_line_info_t *line_tab, char **file_names)
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
static jvmtiError get_source_filename(jvmtiEnv *jvmti, jmethodID methodID, char **buffer)
static void JNICALL compiled_method_load_cb(jvmtiEnv *jvmti, jmethodID method, jint code_size, void const *code_addr, jint map_length, jvmtiAddrLocationMap const *map, const void *compile_info)
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *jvm __maybe_unused)
int jvmti_write_debug_info(void *agent, uint64_t code, int nr_lines, jvmti_line_info_t *li, const char *const *file_names)
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved __maybe_unused)
static int str(yyscan_t scanner, int token)
int jvmti_close(void *agent)
static jvmtiError get_line_numbers(jvmtiEnv *jvmti, const void *compile_info, jvmti_line_info_t **tab, int *nr_lines)
static jvmtiError do_get_line_numbers(jvmtiEnv *jvmti, void *pc, jmethodID m, jint bci, jvmti_line_info_t *tab, jint *nr)
static void copy_class_filename(const char *class_sign, const char *file_name, char *result, size_t max_length)
int jvmti_write_code(void *agent, char const *sym, uint64_t vma, void const *code, unsigned int const size)