/* * static final native String mapLibraryName(String) */ _jc_object * _JC_JCNI_ATTR JCNI_java_lang_VMRuntime_mapLibraryName(_jc_env *env, _jc_object *string) { size_t name_len; char *fname; char *name; /* Check for null */ if (string == NULL) { _jc_post_exception(env, _JC_NullPointerException); _jc_throw_exception(env); } /* Decode string */ name_len = _jc_decode_string_utf8(env, string, NULL); if ((name = _JC_STACK_ALLOC(env, name_len + 1)) == NULL) { _jc_post_exception_info(env); _jc_throw_exception(env); } _jc_decode_string_utf8(env, string, name); /* Format filename */ if ((fname = _JC_FORMAT_STRING(env, _JC_LIBRARY_FMT, name)) == NULL) { _jc_post_exception_info(env); _jc_throw_exception(env); } /* Create new String object */ if ((string = _jc_new_string(env, fname, strlen(fname))) == NULL) _jc_throw_exception(env); /* Done */ return string; }
/* * public static final native boolean compileClasses(String) */ jboolean _JC_JCNI_ATTR JCNI_java_lang_VMCompiler_compileClasses(_jc_env *env, _jc_object *string) { _jc_jvm *const vm = env->vm; size_t slen; char *name; /* Decode string */ slen = _jc_decode_string_utf8(env, string, NULL); if ((name = _JC_STACK_ALLOC(env, slen + 1)) == NULL) { _jc_post_exception_info(env); _jc_throw_exception(env); } _jc_decode_string_utf8(env, string, name); /* XXX we are supposed to do some kind of pattern matching... */ /* Generate ELF object */ if (_jc_generate_object(env, vm->boot.loader, name) != JNI_OK) _jc_throw_exception(env); return JNI_TRUE; }
/* * static final native int nativeLoad(String, ClassLoader) */ jint _JC_JCNI_ATTR JCNI_java_lang_VMRuntime_nativeLoad(_jc_env *env, _jc_object *string, _jc_object *clobj) { _jc_jvm *const vm = env->vm; _jc_class_loader *loader; char *filename; size_t len; /* Check for null */ if (string == NULL) { _jc_post_exception(env, _JC_NullPointerException); _jc_throw_exception(env); } /* Convert String to UTF-8 */ len = _jc_decode_string_utf8(env, string, NULL); if ((filename = _JC_STACK_ALLOC(env, len + 1)) == NULL) { _jc_post_exception_info(env); _jc_throw_exception(env); } _jc_decode_string_utf8(env, string, filename); /* Get class loader */ if (clobj == NULL) loader = vm->boot.loader; else if ((loader = _jc_get_loader(env, clobj)) == NULL) _jc_throw_exception(env); /* Open native library */ if (_jc_load_native_library(env, loader, filename) != JNI_OK) { _jc_post_exception_info(env); _jc_throw_exception(env); } /* OK */ return 1; }
/* * Process DWARF2 line number information. * * If unsuccessful an exception is stored. */ jint _jc_debug_line_dwarf2(_jc_env *env, _jc_elf *elf, _jc_splay_tree *tree) { _jc_elf_info *const info = elf->info; const Elf_Shdr *const shdr = info->debug_lines.loadable.shdr; const u_char *ptr = (const u_char *)info->map_base + shdr->sh_offset; const u_char *const section_end = ptr + shdr->sh_size; jboolean using64bit = JNI_FALSE; _jc_dwarf2_line_hdr *hdr; _jc_method_node **nodes; _jc_map_state state; _jc_method *method; unsigned long totlen; union _jc_value jvalue; int node_index; const u_char *ptr_end; const u_char *pc; int num_nodes; int cline; int i; /* Put nodes in a list and elide methods with no line number table */ if ((nodes = _JC_STACK_ALLOC(env, tree->size * sizeof(*nodes))) == NULL) goto fail; _jc_splay_list(tree, (void **)nodes); for (i = num_nodes = 0; i < tree->size; i++) { _jc_method_node *const node = nodes[i]; _jc_method *const method = node->method; _JC_ASSERT(method != NULL); _JC_ASSERT(method->function != NULL); _JC_ASSERT(!_JC_ACC_TEST(method, INTERP)); _JC_ASSERT(method->u.exec.function_end != NULL); if (method->u.exec.u.linenum.len > 0) nodes[num_nodes++] = nodes[i]; } /* Anything to do? */ if (num_nodes == 0) return JNI_OK; /* Sort methods by starting address */ qsort(nodes, num_nodes, sizeof(*nodes), _jc_method_addr_cmp); /* Initialize map state */ memset(&state, 0, sizeof(state)); node_index = 0; method = NULL; again: /* Read prologue header */ memcpy(&jvalue, ptr, sizeof(jint)); ptr += sizeof(jint); totlen = jvalue.i; if (totlen == 0xffffffff) { memcpy(&jvalue, ptr, sizeof(jlong)); ptr += sizeof(jlong); totlen = jvalue.j; using64bit = JNI_TRUE; } else if (totlen == 0) { memcpy(&jvalue, ptr, sizeof(jint)); ptr += sizeof(jint); totlen = jvalue.i; using64bit = JNI_TRUE; } ptr_end = ptr + totlen; ptr += 2; /* skip version */ ptr += 4; /* skip header len */ if (using64bit) ptr += 4; hdr = (_jc_dwarf2_line_hdr *)ptr; ptr += sizeof(*hdr) + hdr->opcode_base - 1; /* Skip over directory table */ while (*ptr++ != '\0') ptr += strlen((const char *)ptr) + 1; /* Skip over file name table */ while (*ptr++ != '\0') { ptr += strlen((const char *)ptr) + 1; (void)_jc_read_leb128(&ptr, JNI_FALSE); (void)_jc_read_leb128(&ptr, JNI_FALSE); (void)_jc_read_leb128(&ptr, JNI_FALSE); } /* Initialize statement program state */ pc = NULL; cline = 1; /* Process statement program */ while (ptr < ptr_end) { jboolean writeout = JNI_FALSE; jboolean reset = JNI_FALSE; u_char opcode; if ((opcode = *ptr++) >= hdr->opcode_base) { /* special */ opcode -= hdr->opcode_base; pc += (opcode / hdr->line_range) * hdr->minimum_instruction_length; cline += hdr->line_base + opcode % hdr->line_range; writeout = JNI_TRUE; } else if (opcode == 0) { /* extended */ unsigned int oplen; u_char exop; oplen = _jc_read_leb128(&ptr, JNI_FALSE); exop = *ptr++; switch (exop) { case DW_LNE_end_sequence: reset = JNI_TRUE; writeout = JNI_TRUE; break; case DW_LNE_set_address: { const u_char *new_pc; /* Get new PC */ memcpy(&new_pc, ptr, sizeof(new_pc)); /* We don't support out-of-spec reversals */ if (new_pc < pc) { _JC_EX_STORE(env, LinkageError, "address reversals in .debug_line" " section are not supported"); goto fail; } /* OK */ pc = new_pc; break; } default: break; } ptr += oplen - 1; } else { /* standard */ switch (opcode) { case DW_LNS_copy: writeout = JNI_TRUE; break; case DW_LNS_advance_pc: pc += _jc_read_leb128(&ptr, JNI_FALSE) * hdr->minimum_instruction_length; break; case DW_LNS_advance_line: cline += _jc_read_leb128(&ptr, JNI_TRUE); break; case DW_LNS_const_add_pc: pc += ((255 - hdr->opcode_base) / hdr->line_range) * hdr->minimum_instruction_length; break; case DW_LNS_fixed_advance_pc: { uint16_t advance; memcpy(&advance, ptr, 2); pc += advance; ptr += 2; break; } default: for (i = 0; i < hdr->standard_opcode_lengths[ opcode - 1]; i++) _jc_read_leb128(&ptr, JNI_FALSE); break; } } /* Have we reached the next method? */ if (method == NULL && (const void *)pc >= nodes[node_index]->method->function) { /* Initialize state for this method */ _JC_ASSERT(state.pc_map.len == 0); _JC_ASSERT(state.last_linenum == 0); _JC_ASSERT(state.last_map == 0); method = nodes[node_index]->method; _JC_ASSERT(!_JC_ACC_TEST(method, INTERP)); state.linenum = method->u.exec.u.linenum; memset(&method->u.exec.u, 0, sizeof(method->u.exec.u)); } /* Finished with the current method? */ if (method != NULL && (const void *)pc >= method->u.exec.function_end) { /* Finalize map for current method */ if (_jc_debug_line_finish(env, method, elf->loader, &state) != JNI_OK) goto fail; method = NULL; /* Look for next method */ if (++node_index == num_nodes) goto done; } /* Write matrix row */ if (writeout && method != NULL) { if (_jc_debug_line_add(env, &state, pc, cline) != JNI_OK) goto fail; } /* Reset after DW_LNE_end_sequence */ if (reset) { pc = NULL; cline = 1; } } if (ptr < section_end) goto again; done: /* Sanity check */ _JC_ASSERT(method == NULL); #ifndef NDEBUG for (i = 0; i < num_nodes; i++) { _jc_method_node *const node = nodes[i]; _jc_method *const method = node->method; _JC_ASSERT(!_JC_ACC_TEST(method, INTERP)); _JC_ASSERT(method->u.exec.u.pc_map.map != NULL); } #endif /* Done */ return JNI_OK; fail: /* Failed */ return JNI_ERR; }