示例#1
0
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);
}
示例#2
0
// 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;
}
示例#3
0
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);
  }