Example #1
0
/*
 * Class:       sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal
 * Method:      fillLoadObjectList0
 * Signature:   (Ljava/util/List;)V
 * Description: fills shared objects of the debuggee process/core
 */
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_proc_ProcDebuggerLocal_fillLoadObjectList0
  (JNIEnv *env, jobject this_obj, jobject list) {
  DebuggerWithObject dbgo;
  dbgo.env = env;
  dbgo.this_obj = this_obj;
  dbgo.obj = list;

  jlong p_ps_prochandle = env->GetLongField(this_obj, p_ps_prochandle_ID);
  Pobject_iter((struct ps_prochandle*) p_ps_prochandle, fill_load_object_list, &dbgo);
}
Example #2
0
lx_handle_dlsym_t
lx_call_init(void)
{
	struct ps_prochandle	*ph;
	lookup_cb_arg_t		lca;
	extern int 		__libc_threaded;
	int			err;

	lx_debug("lx_call_init(): looking up Linux dlsym");

	/*
	 * The handle is really the address of the Linux "dlsym" function.
	 * Once we have this address we can call into the Linux "dlsym"
	 * function to lookup other functions.  It's the initial lookup
	 * of "dlsym" that's difficult.  To do this we'll leverage the
	 * brand support that we added to librtld_db.  We're going
	 * to fire up a seperate native solaris process that will
	 * attach to us via libproc/librtld_db and lookup the symbol
	 * for us.
	 */

	/* Make sure we're single threaded. */
	if (__libc_threaded) {
		lx_debug("lx_call_init() fail: "
		    "process must be single threaded");
		return (NULL);
	}

	/* Tell libproc.so where the real procfs is mounted. */
	Pset_procfs_path("/native/proc");

	/* Tell librtld_db.so where the real /native is */
	(void) rd_ctl(RD_CTL_SET_HELPPATH, "/native");

	/* Grab ourselves but don't stop ourselves. */
	if ((ph = Pgrab(getpid(),
	    PGRAB_FORCE | PGRAB_RDONLY | PGRAB_NOSTOP, &err)) == NULL) {
		lx_debug("lx_call_init() fail: Pgrab failed: %s",
		    Pgrab_error(err));
		return (NULL);
	}

	lca.lca_ph = ph;
	lca.lca_ptr = NULL;
	if (Pobject_iter(ph, lookup_cb, &lca) == -1) {
		lx_debug("lx_call_init() fail: couldn't find Linux dlsym");
		return (NULL);
	}

	lx_debug("lx_call_init(): Linux dlsym = 0x%p", lca.lca_ptr);
	return ((lx_handle_dlsym_t)lca.lca_ptr);
}
Example #3
0
static int
python_db_init(void)
{
	struct ps_prochandle *Ph;

	if (mdb_get_xdata("pshandle", &Ph, sizeof (Ph)) == -1) {
		mdb_warn("couldn't read pshandle xdata\n");
		dlclose(pydb_dlhdl);
		pydb_dlhdl = NULL;
		return (-1);
	}

	(void) Pobject_iter(Ph, python_object_iter, Ph);

	pydb_agent_create = (pydb_agent_create_f)
	    dlsym(pydb_dlhdl, "pydb_agent_create");
	pydb_agent_destroy = (pydb_agent_destroy_f)
	    dlsym(pydb_dlhdl, "pydb_agent_destroy");
	pydb_get_frameinfo = (pydb_get_frameinfo_f)
	    dlsym(pydb_dlhdl, "pydb_get_frameinfo");

	pydb_frame_iter_init = (pydb_iter_init_f)
	    dlsym(pydb_dlhdl, "pydb_frame_iter_init");
	pydb_interp_iter_init = (pydb_iter_init_f)
	    dlsym(pydb_dlhdl, "pydb_interp_iter_init");
	pydb_thread_iter_init = (pydb_iter_init_f)
	    dlsym(pydb_dlhdl, "pydb_thread_iter_init");
	pydb_iter_next = (pydb_iter_next_f)dlsym(pydb_dlhdl, "pydb_iter_next");
	pydb_iter_fini = (pydb_iter_fini_f)dlsym(pydb_dlhdl, "pydb_iter_fini");


	if (pydb_agent_create == NULL || pydb_agent_destroy == NULL ||
	    pydb_get_frameinfo == NULL || pydb_frame_iter_init == NULL ||
	    pydb_interp_iter_init == NULL || pydb_thread_iter_init == NULL ||
	    pydb_iter_next == NULL || pydb_iter_fini == NULL) {
		mdb_warn("couldn't load pydb functions");
		dlclose(pydb_dlhdl);
		pydb_dlhdl = NULL;
		return (-1);
	}

	pydb_hdl = pydb_agent_create(Ph, PYDB_VERSION);
	if (pydb_hdl == NULL) {
		mdb_warn("unable to create pydb_agent");
		dlclose(pydb_dlhdl);
		pydb_dlhdl = NULL;
		return (-1);
	}

	return (0);
}
Example #4
0
static int
dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
    dt_pcb_t *pcb, dt_proc_t *dpr)
{
	struct ps_prochandle *P = dpr->dpr_proc;
	int ret = 0;

	assert(DT_MUTEX_HELD(&dpr->dpr_lock));
#if defined(sun)
	(void) Pupdate_maps(P);
	if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {
		ret = -1;
		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,
		    "failed to instantiate probes for pid %d: %s",
#if defined(sun)
		    (int)Pstatus(P)->pr_pid, strerror(errno));
#else
		    (int)proc_getpid(P), strerror(errno));
#endif
	}
Example #5
0
static int
dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
    dt_pcb_t *pcb, dt_proc_t *dpr)
{
	struct ps_prochandle *P = dpr->dpr_proc;
	int ret = 0;

	assert(MUTEX_HELD(&dpr->dpr_lock));

	(void) Pupdate_maps(P);
	if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) {
		ret = -1;
		(void) dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_USDT,
		    "failed to instantiate probes for pid %d: %s",
		    (int)Pstatus(P)->pr_pid, strerror(errno));
	}

	/*
	 * Put the module name in its canonical form.
	 */
	(void) dt_pid_fix_mod(pdp, P);

	return (ret);
}
Example #6
0
static int
dt_pid_create_pid_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp,
    dt_pcb_t *pcb, dt_proc_t *dpr)
{
	dt_pid_probe_t pp;
	int ret = 0;

	pp.dpp_dtp = dtp;
	pp.dpp_dpr = dpr;
	pp.dpp_pr = dpr->dpr_proc;
	pp.dpp_pcb = pcb;

#ifdef DOODAD
	/*
	 * We can only trace dynamically-linked executables (since we've
	 * hidden some magic in ld.so.1 as well as libc.so.1).
	 */
	if (Pname_to_map(pp.dpp_pr, PR_OBJ_LDSO) == NULL) {
		return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_DYN,
		    "process %s is not a dynamically-linked executable",
		    &pdp->dtpd_provider[3]));
	}
#endif

	pp.dpp_mod = pdp->dtpd_mod[0] != '\0' ? pdp->dtpd_mod : "*";
	pp.dpp_func = pdp->dtpd_func[0] != '\0' ? pdp->dtpd_func : "*";
	pp.dpp_name = pdp->dtpd_name[0] != '\0' ? pdp->dtpd_name : "*";
	pp.dpp_last_taken = 0;

	if (strcmp(pp.dpp_func, "-") == 0) {
		const prmap_t *aout, *pmp;

		if (pdp->dtpd_mod[0] == '\0') {
			pp.dpp_mod = pdp->dtpd_mod;
			(void) strcpy(pdp->dtpd_mod, "a.out");
		} else if (strisglob(pp.dpp_mod) ||
		    (aout = Pname_to_map(pp.dpp_pr, "a.out")) == NULL ||
		    (pmp = Pname_to_map(pp.dpp_pr, pp.dpp_mod)) == NULL ||
		    aout->pr_vaddr != pmp->pr_vaddr) {
			return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_LIB,
			    "only the a.out module is valid with the "
			    "'-' function"));
		}

		if (strisglob(pp.dpp_name)) {
			return (dt_pid_error(dtp, pcb, dpr, NULL, D_PROC_NAME,
			    "only individual addresses may be specified "
			    "with the '-' function"));
		}
	}

	/*
	 * If pp.dpp_mod contains any globbing meta-characters, we need
	 * to iterate over each module and compare its name against the
	 * pattern. An empty module name is treated as '*'.
	 */
	if (strisglob(pp.dpp_mod)) {
		ret = Pobject_iter(pp.dpp_pr, dt_pid_mod_filt, &pp);
	} else {
		const prmap_t *pmp;
		char *obj;

		/*
		 * If we can't find a matching module, don't sweat it -- either
		 * we'll fail the enabling because the probes don't exist or
		 * we'll wait for that module to come along.
		 */
		if ((pmp = dt_pid_fix_mod(pdp, pp.dpp_pr)) != NULL) {
			if ((obj = strchr(pdp->dtpd_mod, '`')) == NULL)
				obj = pdp->dtpd_mod;
			else
				obj++;

			ret = dt_pid_per_mod(&pp, pmp, obj);
		}
	}

	return (ret);
}
Example #7
0
static void attach_internal(JNIEnv* env, jobject this_obj, jstring cmdLine, jboolean isProcess) {
  jboolean isCopy;
  int gcode;
  const char* cmdLine_cstr = env->GetStringUTFChars(cmdLine, &isCopy);
  CHECK_EXCEPTION;

  // some older versions of libproc.so crash when trying to attach 32 bit
  // debugger to 64 bit core file. check and throw error.
#ifndef _LP64
  atoi(cmdLine_cstr);
  if (errno) {
     // core file
     int core_fd;
     if ((core_fd = open64(cmdLine_cstr, O_RDONLY)) >= 0) {
        Elf32_Ehdr e32;
        if (pread64(core_fd, &e32, sizeof (e32), 0) == sizeof (e32) &&
            memcmp(&e32.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0 &&
            e32.e_type == ET_CORE && e32.e_ident[EI_CLASS] == ELFCLASS64) {
              close(core_fd);
              THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 64 bit, use java -d64 for debugger");
        }
        close(core_fd);
     }
     // all other conditions are handled by libproc.so.
  }
#endif

  // connect to process/core
  ps_prochandle_t* ph = proc_arg_grab(cmdLine_cstr, (isProcess? PR_ARG_PIDS : PR_ARG_CORES), PGRAB_FORCE, &gcode, NULL);

  env->ReleaseStringUTFChars(cmdLine, cmdLine_cstr);
  if (! ph) {
     if (gcode > 0 && gcode < sizeof(proc_arg_grab_errmsgs)/sizeof(const char*)) {
        char errMsg[ERR_MSG_SIZE];
        sprintf(errMsg, "Attach failed : %s", proc_arg_grab_errmsgs[gcode]);
        THROW_NEW_DEBUGGER_EXCEPTION(errMsg);
    } else {
        if (_libsaproc_debug && gcode == G_STRANGE) {
           perror("libsaproc DEBUG: ");
        }
        if (isProcess) {
           THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to process!");
        } else {
           THROW_NEW_DEBUGGER_EXCEPTION("Not able to attach to core file!");
        }
     }
  }

  // even though libproc.so supports 64 bit debugger and 32 bit debuggee, we don't
  // support such cross-bit-debugging. check for that combination and throw error.
#ifdef _LP64
  int data_model;
  if (ps_pdmodel(ph, &data_model) != PS_OK) {
     Prelease(ph, PRELEASE_CLEAR);
     THROW_NEW_DEBUGGER_EXCEPTION("can't determine debuggee data model (ILP32? or LP64?)");
  }
  if (data_model == PR_MODEL_ILP32) {
     Prelease(ph, PRELEASE_CLEAR);
     THROW_NEW_DEBUGGER_EXCEPTION("debuggee is 32 bit, use 32 bit java for debugger");
  }
#endif

  env->SetLongField(this_obj, p_ps_prochandle_ID, (jlong)(uintptr_t)ph);

  Debugger dbg;
  dbg.env = env;
  dbg.this_obj = this_obj;
  jthrowable exception = 0;
  if (! isProcess) {
    /*
     * With class sharing, shared perm. gen heap is allocated in with MAP_SHARED|PROT_READ.
     * These pages are mapped from the file "classes.jsa". MAP_SHARED pages are not dumped
     * in Solaris core.To read shared heap pages, we have to read classes.jsa file.
     */
    Pobject_iter(ph, init_classsharing_workaround, &dbg);
    exception = env->ExceptionOccurred();
    if (exception) {
      env->ExceptionClear();
      detach_internal(env, this_obj);
      env->Throw(exception);
      return;
    }
  }

  /*
   * Iterate over the process mappings looking
   * for libthread and then dlopen the appropriate
   * libthread_db and get function pointers.
   */
  Pobject_iter(ph, init_libthread_db_ptrs, &dbg);
  exception = env->ExceptionOccurred();
  if (exception) {
    env->ExceptionClear();
    if (!sa_ignore_threaddb) {
      detach_internal(env, this_obj);
      env->Throw(exception);
    }
    return;
  }

  // init libthread_db and create thread_db agent
  p_td_init_t p_td_init = (p_td_init_t) env->GetLongField(this_obj, p_td_init_ID);
  if (p_td_init == 0) {
    if (!sa_ignore_threaddb) {
      detach_internal(env, this_obj);
    }
    HANDLE_THREADDB_FAILURE("Did not find libthread in target process/core!");
  }

  if (p_td_init() != TD_OK) {
    if (!sa_ignore_threaddb) {
      detach_internal(env, this_obj);
    }
    HANDLE_THREADDB_FAILURE("Can't initialize thread_db!");
  }

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

  td_thragent_t *p_td_thragent_t = 0;
  if (p_td_ta_new(ph, &p_td_thragent_t) != TD_OK) {
    if (!sa_ignore_threaddb) {
      detach_internal(env, this_obj);
    }
    HANDLE_THREADDB_FAILURE("Can't create thread_db agent!");
  }
  env->SetLongField(this_obj, p_td_thragent_t_ID, (jlong)(uintptr_t) p_td_thragent_t);

}
Example #8
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));
}