jlong DTraceJSDT::activate( jint version, jstring module_name, jint providers_count, JVM_DTraceProvider* providers, TRAPS) { size_t count = 0; RegisteredProbes* probes = NULL; if (!is_supported()) { return 0; } assert(module_name != NULL, "valid module name"); assert(providers != NULL, "valid provider array"); for (int i = 0; i < providers_count; ++i) { count += providers[i].probe_count; } probes = new RegisteredProbes(count); count = 0; for (int i = 0; i < providers_count; ++i) { assert(providers[i].name != NULL, "valid provider name"); assert(providers[i].probe_count == 0 || providers[i].probes != NULL, "valid probe count"); for (int j = 0; j < providers[i].probe_count; ++j) { JVM_DTraceProbe* probe = &(providers[i].probes[j]); assert(probe != NULL, "valid probe"); assert(probe->method != NULL, "valid method"); assert(probe->name != NULL, "valid probe name"); assert(probe->function != NULL, "valid probe function spec"); methodHandle h_method = methodHandle(THREAD, JNIHandles::resolve_jmethod_id(probe->method)); nmethod* nm = AdapterHandlerLibrary::create_dtrace_nmethod(h_method); if (nm == NULL) { delete probes; THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to register DTrace probes (CodeCache: no room for DTrace nmethods)."); } h_method()->set_not_compilable(CompLevel_highest_tier); h_method()->set_code(h_method, nm); probes->nmethod_at_put(count++, nm); } } int handle = pd_activate((void*)probes, module_name, providers_count, providers); if (handle <= 0) { delete probes; THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to register DTrace probes (internal error)."); } probes->set_helper_handle(handle); return RegisteredProbes::toOpaqueProbes(probes); }
// Unpacks one or more frames into user-supplied buffers. // Updates the end index, and returns the number of unpacked frames. // Always start with the existing vfst.method and bci. // Do not call vfst.next to advance over the last returned value. // In other words, do not leave any stale data in the vfst. // // Parameters: // mode Restrict which frames to be decoded. // BaseFrameStream stream of frames // max_nframes Maximum number of frames to be filled. // start_index Start index to the user-supplied buffers. // frames_array Buffer to store Class or StackFrame in, starting at start_index. // frames array is a Class<?>[] array when only getting caller // reference, and a StackFrameInfo[] array (or derivative) // otherwise. It should never be null. // end_index End index to the user-supplied buffers with unpacked frames. // // Returns the number of frames whose information was transferred into the buffers. // int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream, int max_nframes, int start_index, objArrayHandle frames_array, int& end_index, TRAPS) { log_debug(stackwalk)("fill_in_frames limit=%d start=%d frames length=%d", max_nframes, start_index, frames_array->length()); assert(max_nframes > 0, "invalid max_nframes"); assert(start_index + max_nframes <= frames_array->length(), "oob"); int frames_decoded = 0; for (; !stream.at_end(); stream.next()) { Method* method = stream.method(); if (method == NULL) continue; // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES // not set) and when StackWalker::getCallerClass is called if (!ShowHiddenFrames && (skip_hidden_frames(mode) || get_caller_class(mode))) { if (method->is_hidden()) { if (log_is_enabled(Debug, stackwalk)) { ResourceMark rm(THREAD); outputStream* st = Log(stackwalk)::debug_stream(); st->print(" hidden method: "); method->print_short_name(st); st->cr(); } continue; } } int index = end_index++; if (log_is_enabled(Debug, stackwalk)) { ResourceMark rm(THREAD); outputStream* st = Log(stackwalk)::debug_stream(); st->print(" %d: frame method: ", index); method->print_short_name(st); st->print_cr(" bci=%d", stream.bci()); } if (!need_method_info(mode) && get_caller_class(mode) && index == start_index && method->caller_sensitive()) { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method", method->name_and_sig_as_C_string())); } // fill in StackFrameInfo and initialize MemberName stream.fill_frame(index, frames_array, method, CHECK_0); if (++frames_decoded >= max_nframes) break; } return frames_decoded; }
address NativeLookup::lookup_base(methodHandle method, bool& in_base_library, TRAPS) { address entry = NULL; ResourceMark rm(THREAD); entry = lookup_entry(method, in_base_library, THREAD); if (entry != NULL) return entry; // standard native method resolution has failed. Check if there are any // JVM TI prefixes which have been applied to the native method name. entry = lookup_entry_prefixed(method, in_base_library, THREAD); if (entry != NULL) return entry; // Native function not found, throw UnsatisfiedLinkError THROW_MSG_0(vmSymbols::java_lang_UnsatisfiedLinkError(), method->name_and_sig_as_C_string()); }
symbolOop symbolKlass::allocate_symbol(u1* name, int len, TRAPS) { // Don't allow symbol oops to be created which cannot fit in a symbolOop. if (len > symbolOopDesc::max_length()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "name is too long to represent"); } int size = symbolOopDesc::object_size(len); symbolKlassHandle h_k(THREAD, as_klassOop()); symbolOop sym = (symbolOop) CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_0); assert(!sym->is_parsable(), "not expecting parsability yet."); sym->set_next(NULL); sym->set_utf8_length(len); for (int i = 0; i < len; i++) { sym->byte_at_put(i, name[i]); } // Let the first emptySymbol be created and // ensure only one is ever created. assert(sym->is_parsable() || Universe::emptySymbol() == NULL, "should be parsable here."); return sym; }
// return the name of the user that owns the process identified by vmid. // // This method uses a slow directory search algorithm to find the backing // store file for the specified vmid and returns the user name, as determined // by the user name suffix of the hsperfdata_<username> directory name. // // the caller is expected to free the allocated memory. // static char* get_user_name_slow(int vmid, TRAPS) { // short circuit the directory search if the process doesn't even exist. if (kill(vmid, 0) == OS_ERR) { if (errno == ESRCH) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "Process not found"); } else /* EPERM */ { THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); } } // directory search char* oldest_user = NULL; time_t oldest_ctime = 0; const char* tmpdirname = os::get_temp_directory(); DIR* tmpdirp = os::opendir(tmpdirname); if (tmpdirp == NULL) { return NULL; } // for each entry in the directory that matches the pattern hsperfdata_*, // open the directory and check if the file for the given vmid exists. // The file with the expected name and the latest creation date is used // to determine the user name for the process id. // struct dirent* dentry; char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal); errno = 0; while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) { // check if the directory entry is a hsperfdata file if (strncmp(dentry->d_name, PERFDATA_NAME, strlen(PERFDATA_NAME)) != 0) { continue; } char* usrdir_name = NEW_C_HEAP_ARRAY(char, strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal); strcpy(usrdir_name, tmpdirname); strcat(usrdir_name, "/"); strcat(usrdir_name, dentry->d_name); // Open the user directory. DIR* subdirp = open_directory_secure(usrdir_name); if (subdirp == NULL) { FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); continue; } // Since we don't create the backing store files in directories // pointed to by symbolic links, we also don't follow them when // looking for the files. We check for a symbolic link after the // call to opendir in order to eliminate a small window where the // symlink can be exploited. // if (!is_directory_secure(usrdir_name)) { FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); os::closedir(subdirp); continue; } struct dirent* udentry; char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal); errno = 0; while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) { if (filename_to_pid(udentry->d_name) == vmid) { struct stat statbuf; int result; char* filename = NEW_C_HEAP_ARRAY(char, strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal); strcpy(filename, usrdir_name); strcat(filename, "/"); strcat(filename, udentry->d_name); // don't follow symbolic links for the file RESTARTABLE(::lstat(filename, &statbuf), result); if (result == OS_ERR) { FREE_C_HEAP_ARRAY(char, filename, mtInternal); continue; } // skip over files that are not regular files. if (!S_ISREG(statbuf.st_mode)) { FREE_C_HEAP_ARRAY(char, filename, mtInternal); continue; } // compare and save filename with latest creation time if (statbuf.st_size > 0 && statbuf.st_ctime > oldest_ctime) { if (statbuf.st_ctime > oldest_ctime) { char* user = strchr(dentry->d_name, '_') + 1; if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user, mtInternal); oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal); strcpy(oldest_user, user); oldest_ctime = statbuf.st_ctime; } } FREE_C_HEAP_ARRAY(char, filename, mtInternal); } } os::closedir(subdirp); FREE_C_HEAP_ARRAY(char, udbuf, mtInternal); FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal); }