Beispiel #1
0
/*ARGSUSED*/
void
la_activity(uintptr_t *cookie, uint_t flags)
{
    struct ps_prochandle *P;
    int err, ret;
    GElf_Sym sym;

    if (flags != LA_ACT_CONSISTENT)
        return;

    while (list != NULL) {
        obj_list_t *node = list;
        char *name = node->ol_name;

        list = node->ol_next;

        P = Pgrab(getpid(), PGRAB_RDONLY, &err);
        ret = Plookup_by_name(P, name, "___SUNW_dof", &sym);
        Prelease(P, 0);

        if (ret == 0) {
            dtrace_link_dof((void *)(uintptr_t)sym.st_value,
                            node->ol_lmid, node->ol_name, node->ol_addr);
        }

        free(node->ol_name);
        free(node);
    }
}
/*
 * Class:     sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal
 * Method:    attach0
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_attach0__I
  (JNIEnv *env, jobject this_obj, jint jpid) {

  struct ps_prochandle* ph;
  if ( (ph = Pgrab(jpid)) == NULL) {
    THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process");
  }
  (*env)->SetLongField(env, this_obj, p_ps_prochandle_ID, (jlong)(intptr_t)ph);
  fillThreadsAndLoadObjects(env, this_obj, ph);
}
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);
}
static struct ps_prochandle *
grab_zone_proc(zoneid_t zid)
{
	DIR *dirp;
	struct dirent *dentp;
	int pid, pid_self, tmp;
	psinfo_t psinfo;
	struct ps_prochandle *pr = NULL;

	pid_self = getpid();

	if ((dirp = opendir("/proc")) == NULL)
		return (NULL);

	while (dentp = readdir(dirp)) {
		pid = atoi(dentp->d_name);

		/* Skip self */
		if (pid == pid_self)
			continue;

		if (proc_get_psinfo(pid, &psinfo) != 0)
			continue;

		if (psinfo.pr_zoneid != zid)
			continue;

		/* attempt to grab process */
		if ((pr = Pgrab(pid, 0, &tmp)) != NULL) {
			if (Psetflags(pr, PR_RLC) != 0) {
				Prelease(pr, 0);
			}
			if (Pcreate_agent(pr) == 0) {
				if (pr_getzoneid(pr) != zid) {
					Prelease(pr, 0);
					continue;
				}

				(void) closedir(dirp);
				return (pr);
			} else {
				Prelease(pr, 0);
			}
		}
	}

	(void) closedir(dirp);
	return (NULL);
}
Beispiel #5
0
struct ps_prochandle *
dt_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags, int nomonitor)
{
	dt_proc_hash_t *dph = dtp->dt_procs;
	uint_t h = pid & (dph->dph_hashlen - 1);
	dt_proc_t *dpr, *opr;
	int err;

	/*
	 * Search the hash table for the pid.  If it is already grabbed or
	 * created, move the handle to the front of the lrulist, increment
	 * the reference count, and return the existing ps_prochandle.
	 */
	for (dpr = dph->dph_hash[h]; dpr != NULL; dpr = dpr->dpr_hash) {
		if (dpr->dpr_pid == pid && !dpr->dpr_stale) {
			/*
			 * If the cached handle was opened read-only and
			 * this request is for a writeable handle, mark
			 * the cached handle as stale and open a new handle.
			 * Since it's stale, unmark it as cacheable.
			 */
			if (dpr->dpr_rdonly && !(flags & PGRAB_RDONLY)) {
				dt_dprintf("upgrading pid %d\n", (int)pid);
				dpr->dpr_stale = B_TRUE;
				dpr->dpr_cacheable = B_FALSE;
				dph->dph_lrucnt--;
				break;
			}

			dt_dprintf("grabbed pid %d (cached)\n", (int)pid);
			dt_list_delete(&dph->dph_lrulist, dpr);
			dt_list_prepend(&dph->dph_lrulist, dpr);
			dpr->dpr_refs++;
			return (dpr->dpr_proc);
		}
	}

	if ((dpr = dt_zalloc(dtp, sizeof (dt_proc_t))) == NULL)
		return (NULL); /* errno is set for us */

	(void) pthread_mutex_init(&dpr->dpr_lock, NULL);
	(void) pthread_cond_init(&dpr->dpr_cv, NULL);

//printf("grabbing pid %d\n", pid);
	if ((dpr->dpr_proc = Pgrab(pid, flags, &err)) == NULL) {
		return (dt_proc_error(dtp, dpr,
		    "failed to grab pid %d: %s\n", (int)pid, Pgrab_error(err)));
	}

	dpr->dpr_hdl = dtp;
	dpr->dpr_pid = pid;

	(void) Punsetflags(dpr->dpr_proc, PR_KLC);
	(void) Psetflags(dpr->dpr_proc, PR_RLC);

	/*
	 * If we are attempting to grab the process without a monitor
	 * thread, then mark the process cacheable only if it's being
	 * grabbed read-only.  If we're currently caching more process
	 * handles than dph_lrulim permits, attempt to find the
	 * least-recently-used handle that is currently unreferenced and
	 * release it from the cache.  Otherwise we are grabbing the process
	 * for control: create a control thread for this process and store
	 * its ID in dpr->dpr_tid.
	 */
	if (nomonitor || (flags & PGRAB_RDONLY)) {
		if (dph->dph_lrucnt >= dph->dph_lrulim) {
			for (opr = dt_list_prev(&dph->dph_lrulist);
			    opr != NULL; opr = dt_list_prev(opr)) {
				if (opr->dpr_cacheable && opr->dpr_refs == 0) {
					dt_proc_destroy(dtp, opr->dpr_proc);
					break;
				}
			}
		}

		if (flags & PGRAB_RDONLY) {
			dpr->dpr_cacheable = B_TRUE;
			dpr->dpr_rdonly = B_TRUE;
			dph->dph_lrucnt++;
		}

	} else if (dt_proc_create_thread(dtp, dpr, DT_PROC_STOP_GRAB) != 0)
		return (NULL); /* dt_proc_error() has been called for us */

	dpr->dpr_hash = dph->dph_hash[h];
	dph->dph_hash[h] = dpr;
	dt_list_prepend(&dph->dph_lrulist, dpr);

	dt_dprintf("grabbed pid %d\n", (int)pid);
	dpr->dpr_refs++;

	return (dpr->dpr_proc);
}
Beispiel #6
0
/*
 * Force the parent process (ppid) to wait for its child process (pid).
 */
static int
reap(char *arg, pid_t *reap_pid, int *exit_status)
{
	struct ps_prochandle *Pr;
	siginfo_t siginfo;
	psinfo_t psinfo;
	prusage_t usage;
	pid_t pid, ppid;
	time_t elapsed;
	int gret;

	/*
	 * get the specified pid and the psinfo struct
	 */
	if ((pid = proc_arg_psinfo(arg, PR_ARG_PIDS, &psinfo, &gret)) == -1) {
		(void) fprintf(stderr, "%s: cannot examine %s: %s\n",
		    command, arg, Pgrab_error(gret));
		return (1);
	}

	if (psinfo.pr_nlwp != 0) {
		(void) fprintf(stderr, "%s: process not defunct: %d\n",
		    command, (int)pid);
		return (1);
	}

	*exit_status = psinfo.pr_wstat;
	*reap_pid = psinfo.pr_pid;
	ppid = psinfo.pr_ppid;

	if (ppid == 1) {
		(void) fprintf(stderr, "%s: Failed to reap %d: the only "
		    "non-defunct ancestor is 'init'\n", command,
		    (int)pid);
		return (1);
	}

	if (proc_usage(pid, &usage, &gret) == 0) {
		elapsed = usage.pr_tstamp.tv_sec - usage.pr_term.tv_sec;
	} else {
		(void) fprintf(stderr, "%s: cannot examine %d: %s\n",
		    command, (int)pid, Pgrab_error(gret));
		return (1);
	}

	if ((Fflag == 0) && (elapsed < NOREAP_TIME)) {
		(void) fprintf(stderr, "%s: unsafe to reap %d; it has been "
		    "defunct less than %d seconds\n", command, (int)pid,
		    NOREAP_TIME);
		return (1);
	}

	if ((Pr = Pgrab(ppid, Fflag | PGRAB_NOSTOP, &gret)) == NULL) {
		(void) fprintf(stderr, "%s: cannot examine %d: %s\n", command,
		    (int)ppid, Pgrab_error(gret));
		return (1);
	}

	if ((Fflag == 0) && (Pstate(Pr) == PS_STOP)) {
		Prelease(Pr, 0);
		(void) fprintf(stderr, "%s: unsafe to reap %d; parent is "
		    "stopped and may reap status upon restart\n", command,
		    (int)pid);
		return (1);
	}

	/*
	 * Pstop() will fail if the process to be stopped has become a zombie.
	 * This means that we can say with certainty that the child of this
	 * process has not changed parents (i.e. been reparented to init) once
	 * the Pstop() succeeds.
	 */
	if (Pstop(Pr, 1000) != 0) {
		Prelease(Pr, 0);
		(void) fprintf(stderr, "%s: failed to stop %d: %s", command,
		    (int)ppid, strerror(errno));
		return (1);
	}

	if (pr_waitid(Pr, P_PID, pid, &siginfo, WEXITED|WNOHANG) != 0) {
		Prelease(Pr, 0);
		(void) fprintf(stderr, "%s: waitid() in process %d failed: %s",
		    command, (int)ppid, strerror(errno));
		return (1);
	}

	Prelease(Pr, 0);
	return (0);
}
Beispiel #7
0
/* ARGSUSED1 */
uint_t
la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie)
{
	uint_t		flags;
	static int	first = 1;
	int		perr;

	/*
	 * If this is the first time in, then l_name is the app
	 * and unless the user gave an explict from list
	 * we will trace calls from it.
	 */
	if (first && bindfrom_list == NULL) {
		flags = LA_FLG_BINDFROM | LA_FLG_BINDTO;
		first = 0;
		goto work;
	}

	/*
	 * If we have no bindto_list, then we assume that we
	 * bindto everything (apptrace -T \*)
	 *
	 * Otherwise we make sure that l_name is on the list.
	 */
	flags = 0;
	if (bindto_list == NULL) {
		flags = LA_FLG_BINDTO;
	} else if (check_list(bindto_list, lmp->l_name) != NULL) {
		flags |= LA_FLG_BINDTO;
	}

	/*
	 * If l_name is on the exclusion list, zero the bit.
	 */
	if ((bindto_excl != NULL) &&
	    check_list(bindto_excl, lmp->l_name) != NULL) {
		flags &= ~LA_FLG_BINDTO;
	}

	/*
	 * If l_name is on the bindfrom list then trace
	 */
	if (check_list(bindfrom_list, lmp->l_name) != NULL) {
		flags |= LA_FLG_BINDFROM;
	}

	/*
	 * If l_name is on the exclusion list, zero the bit
	 * else trace, (this allows "-F !foo" to imply
	 * "-F '*' -F !foo")
	 */
	if (check_list(bindfrom_excl, lmp->l_name) != NULL) {
		flags &= ~LA_FLG_BINDFROM;
	} else if (bindfrom_excl != NULL && bindfrom_list == NULL) {
		flags |= LA_FLG_BINDFROM;
	}

work:
	if (flags) {
		*cookie = (uintptr_t)abibasename(lmp->l_name);

		/*
		 * only call Pgrab() once to get the ps_prochandle
		 */
		if (proc_hdl == NULL)
			proc_hdl = Pgrab(getpid(), PGRAB_RDONLY, &perr);
	}

	return (flags);
}