Esempio n. 1
0
/*
  * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
  * Method:      lookupByName0
  * Signature:   (Ljava/lang/String;Ljava/lang/String;)J
  * Description: symbol lookup by name
*/
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookupByName0
   (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
   jlong p_ps_prochandle;
   p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);

   jboolean isCopy;
   const char* objectName_cstr = NULL;
   if (objectName != NULL) {
     objectName_cstr = env->GetStringUTFChars(objectName, &isCopy);
     CHECK_EXCEPTION_(0);
   } else {
     objectName_cstr = PR_OBJ_EVERY;
   }

   const char* symbolName_cstr = env->GetStringUTFChars(symbolName, &isCopy);
   CHECK_EXCEPTION_(0);

   psaddr_t symbol_addr = (psaddr_t) 0;
   ps_pglobal_lookup((struct ps_prochandle*) p_ps_prochandle,  objectName_cstr,
                    symbolName_cstr, &symbol_addr);

   if (symbol_addr == 0) {
      print_debug("lookup for %s in %s failed\n", symbolName_cstr, objectName_cstr);
   }

   if (objectName_cstr != PR_OBJ_EVERY) {
     env->ReleaseStringUTFChars(objectName, objectName_cstr);
   }
   env->ReleaseStringUTFChars(symbolName, symbolName_cstr);
   return (jlong) (uintptr_t) symbol_addr;
}
Esempio n. 2
0
ps_err_e
td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
{
    ps_err_e result;
    assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
    result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx],
                                sym_addr);

#ifdef HAVE_ASM_GLOBAL_DOT_NAME
    /* For PowerPC, 64-bit uses dot symbols but 32-bit does not.
       We could be a 64-bit libthread_db debugging a 32-bit libpthread.  */
    if (result == PS_NOSYM && symbol_list_arr[idx][0] == '.')
        result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, &symbol_list_arr[idx][1],
                                    sym_addr);
#endif

    return result;
}
Esempio n. 3
0
ps_err_e
td_mod_lookup (struct ps_prochandle *ps, const char *mod,
	       int idx, psaddr_t *sym_addr)
{
  ps_err_e result;
  assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
  result = ps_pglobal_lookup (ps, mod, symbol_list_arr[idx], sym_addr);

  return result;
}
Esempio n. 4
0
static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
  psaddr_t sym_addr;
  int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
  if (err == PS_OK) {
    err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
    return err;
  }
  *valuep = -1;
  return -1;
}
Esempio n. 5
0
static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
  psaddr_t sym_addr;
  int err;

  err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
  if (err != PS_OK) goto fail;
  *valuep = sym_addr;
  return PS_OK;

 fail:
  return err;
}
Esempio n. 6
0
static int parse_vmstructs(jvm_agent_t* J) {
  VMStructEntry  vmVar;
  VMStructEntry* vmp = &vmVar;
  uint64_t gHotSpotVMStructs;
  psaddr_t sym_addr;
  uint64_t base;
  int err;

  /* Clear *vmp now in case we jump to fail: */
  memset(vmp, 0, sizeof(VMStructEntry));

  err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
  CHECK_FAIL(err);
  err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
  CHECK_FAIL(err);
  base = gHotSpotVMStructs;

  err = PS_OK;
  while (err == PS_OK) {
    memset(vmp, 0, sizeof(VMStructEntry));
    err = parse_vmstruct_entry(J, base, vmp);
    if (err != PS_OK || vmp->typeName == NULL) {
      break;
    }

    if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
      /* Read _heaps field of type GrowableArray<CodeHeaps*>*      */
      if (strcmp("_heaps", vmp->fieldName) == 0) {
        err = read_pointer(J, vmp->address, &J->CodeCache_heaps_address);
      }
    } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
      if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
        J->Universe_narrow_oop_base_address = vmp->address;
      }
      if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
        J->Universe_narrow_oop_shift_address = vmp->address;
      }
    }
    CHECK_FAIL(err);

    base += SIZE_VMStructEntry;
    if (vmp->typeName != NULL) free((void*)vmp->typeName);
    if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
  }

  return PS_OK;

 fail:
  if (vmp->typeName != NULL) free((void*)vmp->typeName);
  if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
  return -1;
}
Esempio n. 7
0
/*
 * Class:     sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
 * Method:    lookup0
 * Signature: (Ljava/lang/String;Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_lookup0
  (JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) {
  jlong ps_prochandle_ptr;
  ps_prochandle_ptr = env->GetLongField(this_obj, ps_prochandle_ptr_ID);

  jboolean isCopy;
  const char* objectName_cstr = env->GetStringUTFChars(objectName, &isCopy);
  CHECK_EXCEPTION_(0);
  const char* symbolName_cstr = env->GetStringUTFChars(symbolName, &isCopy);
  CHECK_EXCEPTION_(0);

  psaddr_t symbol_addr = (psaddr_t) 0;
  ps_pglobal_lookup((struct ps_prochandle*) ps_prochandle_ptr, objectName_cstr,
                   symbolName_cstr, &symbol_addr); 

  env->ReleaseStringUTFChars(objectName, objectName_cstr);
  env->ReleaseStringUTFChars(symbolName, symbolName_cstr);
  return (jlong) symbol_addr;
}
td_err_e
td_ta_event_addr(td_thragent_t const * agent, td_event_e event, td_notify_t * notify_out)
{
    int32_t err;

    /*
     * This is nasty, ps_pglobal_lookup is implemented in gdbserver and looks up
     * the symbol from it's cache, which is populated at start time with the
     * symbols returned from td_symbol_list via calls back to the host.
     */

    switch (event) {
        case TD_CREATE:
            err = ps_pglobal_lookup(NULL, NULL, gSymbols[SYM_TD_CREATE], &notify_out->u.bptaddr);
            if (err) {
                return TD_NOEVENT;
            }
            return TD_OK;
    }
    return TD_NOEVENT;
}
td_err_e
td_ta_event_getmsg(td_thragent_t const * agent, td_event_msg_t * event)
{
    td_err_e err;
    void * bkpt_addr;

    err = ps_pglobal_lookup(NULL, NULL, gSymbols[SYM_TD_CREATE], &bkpt_addr);
    if (err) {
        return err;
    }

    err = td_ta_thr_iter(agent, _event_getmsg_helper, bkpt_addr, 0, 0, NULL, 0);
    if (err != 0x42) {
        return TD_NOMSG;
    }

    event->event = TD_CREATE;
    event->th_p = &gEventMsgHandle; // Nasty hack, but it's the only way!

    return TD_OK;
}
Esempio n. 10
0
static int
init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name) {
  Debugger* dbg = (Debugger*) cd;
  JNIEnv*   env = dbg->env;
  jobject this_obj = dbg->this_obj;
  const char* jvm_name = 0;
  if ((jvm_name = strstr(obj_name, "libjvm.so")) != NULL) {
    jvm_name = obj_name;
  } else {
    return 0;
  }

  struct ps_prochandle* ph = (struct ps_prochandle*) env->GetLongField(this_obj, p_ps_prochandle_ID);

  // initialize classes.jsa file descriptor field.
  dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, -1);

  // check whether class sharing is on by reading variable "UseSharedSpaces"
  psaddr_t useSharedSpacesAddr = 0;
  ps_pglobal_lookup(ph, jvm_name, USE_SHARED_SPACES_SYM, &useSharedSpacesAddr);
  if (useSharedSpacesAddr == 0) {
    THROW_NEW_DEBUGGER_EXCEPTION_("can't find 'UseSharedSpaces' flag\n", 1);
  }

  // read the value of the flag "UseSharedSpaces"
  // Since hotspot types are not available to build this library. So
  // equivalent type "jboolean" is used to read the value of "UseSharedSpaces"
  // which is same as hotspot type "bool".
  jboolean value = 0;
  if (read_jboolean(ph, useSharedSpacesAddr, &value) != true) {
    THROW_NEW_DEBUGGER_EXCEPTION_("can't read 'UseSharedSpaces' flag", 1);
  } else if ((int)value == 0) {
    print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n");
    return 1;
  }

  char classes_jsa[PATH_MAX];
  psaddr_t sharedArchivePathAddrAddr = 0;
  ps_pglobal_lookup(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM, &sharedArchivePathAddrAddr);
  if (sharedArchivePathAddrAddr == 0) {
    print_debug("can't find symbol 'Arguments::SharedArchivePath'\n");
    THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1);
  }

  uintptr_t sharedArchivePathAddr = 0;
  if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) {
    print_debug("can't find read pointer 'Arguments::SharedArchivePath'\n");
    THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1);
  }

  if (read_string(ph, (psaddr_t)sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) {
    print_debug("can't find read 'Arguments::SharedArchivePath' value\n");
    THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1);
  }

  print_debug("looking for %s\n", classes_jsa);

  // open the classes.jsa
  int fd = libsaproc_open(classes_jsa, O_RDONLY);
  if (fd < 0) {
    char errMsg[ERR_MSG_SIZE];
    sprintf(errMsg, "can't open shared archive file %s", classes_jsa);
    THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
  } else {
    print_debug("opened shared archive file %s\n", classes_jsa);
  }

  // parse classes.jsa
  struct FileMapHeader* pheader = (struct FileMapHeader*) malloc(sizeof(struct FileMapHeader));
  if (pheader == NULL) {
    close(fd);
    THROW_NEW_DEBUGGER_EXCEPTION_("can't allocate memory for shared file map header", 1);
  }

  memset(pheader, 0, sizeof(struct FileMapHeader));
  // read FileMapHeader
  size_t n = read(fd, pheader, sizeof(struct FileMapHeader));
  if (n != sizeof(struct FileMapHeader)) {
    char errMsg[ERR_MSG_SIZE];
    sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa);
    close(fd);
    free(pheader);
    THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
  }

  // check file magic
  if (pheader->_magic != 0xf00baba2) {
    char errMsg[ERR_MSG_SIZE];
    sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2",
                   classes_jsa, pheader->_magic);
    close(fd);
    free(pheader);
    THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
  }

  // check version
  if (pheader->_version != CURRENT_ARCHIVE_VERSION) {
    char errMsg[ERR_MSG_SIZE];
    sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d",
                   classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION);
    close(fd);
    free(pheader);
    THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1);
  }

  if (_libsaproc_debug) {
    for (int m = 0; m < NUM_SHARED_MAPS; m++) {
       print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
          pheader->_space[m]._file_offset, pheader->_space[m]._base,
          pheader->_space[m]._used, pheader->_space[m]._read_only);
    }
  }

  // FIXME: For now, omitting other checks such as VM version etc.

  // store class archive file fd and map header in debugger object fields
  dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, fd);
  dbg->env->SetLongField(this_obj, p_file_map_header_ID, (jlong)(uintptr_t) pheader);
  return 1;
}
Esempio n. 11
0
int
td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr)
{
  assert (idx >= 0 && idx < NUM_MESSAGES);
  return ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], sym_addr);
}
Esempio n. 12
0
/*
 * Class:     sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
 * Method:    attach0
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_attach0
  (JNIEnv *env, jobject this_obj, jstring cmdLine) {
  jboolean isCopy;
  int gcode;
  const char* cmdLine_cstr = env->GetStringUTFChars(cmdLine, &isCopy);
  CHECK_EXCEPTION;

  struct ps_prochandle* Pr = proc_arg_grab(cmdLine_cstr, PR_ARG_ANY, PGRAB_FORCE, &gcode);
  env->ReleaseStringUTFChars(cmdLine, cmdLine_cstr);
  if(! Pr) 
    THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to process/core file!");

  env->SetLongField(this_obj, ps_prochandle_ptr_ID, (jlong) Pr);

  // initialize libthread_db pointers
  
  /*
   * Iterate over the process mappings looking
   * for libthread and then dlopen the appropriate
   * libthread_db and get pointers to functions.
   */

  Debugger dbg;
  dbg.env = env;
  dbg.obj = this_obj;
  (void) Pobject_iter(Pr, object_iter, &dbg);
  CHECK_EXCEPTION;
  
  // get the user level threads info
  td_thragent_t *Tap = 0;
  p_td_init_t p_td_init = (p_td_init_t) env->GetLongField(this_obj, p_td_init_ID);

  if (p_td_init == 0)
     return;

  p_td_ta_new_t p_td_ta_new = (p_td_ta_new_t) env->GetLongField(this_obj, p_td_ta_new_ID);

  if (p_td_init() != TD_OK) 
     THROW_NEW_DEBUGGER_EXCEPTION("Can't initialize thread_db!");

  if (p_td_ta_new(Pr, &Tap) != TD_OK)
     THROW_NEW_DEBUGGER_EXCEPTION("Can't create thread_db agent!");
 
  /*
   * Iterate over all threads, calling:
   *   thr_stack(td_thrhandle_t *Thp, NULL);
   * for each one to generate the list of threads.
   */

  p_td_ta_thr_iter_t p_td_ta_thr_iter = (p_td_ta_thr_iter_t)
                                     env->GetLongField(this_obj, p_td_ta_thr_iter_ID);

  (void) p_td_ta_thr_iter(Tap, thr_stack, &dbg,
                          TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
                           TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
  CHECK_EXCEPTION;

  p_td_ta_delete_t p_td_ta_delete = (p_td_ta_delete_t)
                                     env->GetLongField(this_obj, p_td_ta_delete_ID);
  (void) p_td_ta_delete(Tap);
  
  // Part of workaround for 4705086.

  /* 
   * iterate over maps of the process/core to get first
   * libjvm[_g].so mapping.
   */

  Pmapping_iter(Pr, iterate_map, &dbg);
  CHECK_EXCEPTION;

  /*
   * Get libjvm[_g].so text size. First location after the end of text segment
   * is marked by the global reserved symbol '_etext' in any ELF file.
   * Please refer to page 53 of "Linkers and Libraries Guide - 816-0559".
   */

  psaddr_t etext_addr;
  if (ps_pglobal_lookup(Pr, "libjvm.so", "_etext", &etext_addr) != PS_OK) {
      // try the debug version
      if (ps_pglobal_lookup(Pr, "libjvm_g.so", "_etext", &etext_addr) != PS_OK) 
         THROW_NEW_DEBUGGER_EXCEPTION("Can't get end of text address of libjvm!");
  }

  // now calculate and set libjvm text size.
  jlong libjvm_text_start = env->GetLongField(this_obj, libjvm_text_start_ID);
  env->SetLongField(this_obj, libjvm_text_size_ID, (jlong) (etext_addr - libjvm_text_start));
}