Пример #1
0
static int
dt_pid_mod_filt(void *arg, const prmap_t *pmp, const char *obj)
{
	char name[DTRACE_MODNAMELEN];
	dt_pid_probe_t *pp = arg;

	if (gmatch(obj, pp->dpp_mod))
		return (dt_pid_per_mod(pp, pmp, obj));

#if defined(sun)
	(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#else
	pp->dpp_lmid = 0;
#endif

	if ((pp->dpp_obj = strrchr(obj, '/')) == NULL)
		pp->dpp_obj = obj;
	else
		pp->dpp_obj++;

	if (gmatch(pp->dpp_obj, pp->dpp_mod))
		return (dt_pid_per_mod(pp, pmp, obj));

#if defined(sun)
	(void) Plmid(pp->dpp_pr, pmp->pr_vaddr, &pp->dpp_lmid);
#endif

	dt_pid_objname(name, sizeof (name), pp->dpp_lmid, pp->dpp_obj);

	if (gmatch(name, pp->dpp_mod))
		return (dt_pid_per_mod(pp, pmp, obj));

	return (0);
}
Пример #2
0
/*
* patMatch:  Return 1 if name matches any of the comma separated patterns
*	in pat.  Patterns are shell filename matching patterns (composed
*	of ?, [...], *, and literal characters).  If deselect is non-zero,
*	reverse the return value (0 becomes 1, 1 becomes 0).  A NULL pattern
*	list matches everything.
*/
int
patMatch(const char *pat,
	 const char *name,
	 int deselect)
{
    const char *pStart;
    const char *pEnd;
    int match;
    int flip;

    if (deselect) {
	flip = 1;		/* must be 1, not other non-zero */
    } else {
	flip = 0;
    }

    if (pat == NULL) {
	return 1 ^ flip;
    }

    pStart = pat;
    for (pEnd = pStart; *pEnd; ++pEnd) {
	if (*pEnd == ',') {
	    match = gmatch(name, pStart, pEnd);
	    if (match) {
		return 1 ^ flip;
	    }
	    pStart = pEnd + 1;
	}
    }

    match = gmatch(name, pStart, pStart + strlen(pStart));	/* returns 1 or 0 */

    return match ^ flip;
}
Пример #3
0
/* Check if name passes matching rules */
int
prof_name_matched(char *name, struct sdev_node *dir)
{
	int type, match = 0;
	char *expr;
	nvlist_t *nvl;
	nvpair_t *nvp = NULL;
	int rv;

	/* check against nvlist for leaf include/exclude */
	nvl = dir->sdev_prof.dev_name;
	while (nvp = nvlist_next_nvpair(nvl, nvp)) {
		expr = nvpair_name(nvp);
		rv = nvpair_value_int32(nvp, &type);
		if (rv != 0) {
			cmn_err(CE_WARN, sdev_nvp_val_err,
			    rv, nvpair_name(nvp));
			break;
		}

		if (type == PROFILE_TYPE_EXCLUDE) {
			if (gmatch(name, expr))
				return (0);	/* excluded */
		} else if (!match) {
			match = gmatch(name, expr);
		}
	}
	if (match) {
		sdcmn_err10(("prof_name_matched: %s\n", name));
		return (match);
	}

	/* check for match against directory globbing pattern */
	nvl = dir->sdev_prof.dev_glob_incdir;
	while (nvp = nvlist_next_nvpair(nvl, nvp)) {
		char *pathleft;
		expr = nvpair_name(nvp);
		if (gmatch(name, expr) == 0)
			continue;
		rv = nvpair_value_string(nvp, &pathleft);
		if (rv != 0) {
			cmn_err(CE_WARN, sdev_nvp_val_err,
			    rv, nvpair_name(nvp));
			break;
		}
		if (is_nonempty_dir(name, pathleft, dir)) {
			sdcmn_err10(("prof_name_matched: dir %s\n", name));
			return (1);
		}
	}

	return (0);
}
Пример #4
0
/*
 * Match a string against a shell glob or extended regular expression.
 */
static boolean_t
ks_match(ks_returner_t *ret, const char *str, ks_pattern_t *pattern)
{
	int	regcode;
	char	*regstr;
	char	*errbuf;
	size_t	bufsz;

	if (ret->ready == B_TRUE) {
		return B_FALSE;
	}

	if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) {
		/* All regex patterns are strdup'd copies */
		regstr = pattern->pstr + 1;
		*(strrchr(regstr, '/')) = '\0';

		regcode = regcomp(&pattern->preg, regstr,
		    REG_EXTENDED | REG_NOSUB);
		if (regcode != 0) {
			bufsz = regerror(regcode, NULL, NULL, 0);
			if (bufsz != 0) {
				errbuf = malloc(bufsz);
				if (errbuf == NULL) {
					ret->term = EKSTAT_ERROR("regex buffer malloc");
					ret->ready = B_TRUE;
					free(pattern->pstr);
					pattern->pstr = NULL;
					return B_FALSE;
				}
				(void) regerror(regcode, NULL, errbuf, bufsz);
				ret->term = EKSTAT_ERROR(errbuf);
				ret->ready = B_TRUE;
				free(errbuf);
			}
			free(pattern->pstr);
			pattern->pstr = NULL;
			return B_FALSE;
		}

		free(pattern->pstr);
		pattern->pstr = NULL;
	}

	if (pattern->pstr == NULL) {
		return (regexec(&pattern->preg, str, 0, NULL, 0) == 0);
	}

	return ((gmatch(str, pattern->pstr) != 0));
}
Пример #5
0
/* apply include/exclude pattern to existing directory content */
static void
apply_dir_pattern(struct sdev_node *dir, char *expr, char *pathleft, int type)
{
	struct sdev_node *dv;

	/* leaf pattern */
	if (pathleft == NULL) {
		if (type == PROFILE_TYPE_INCLUDE)
			return;	/* nothing to do for include */
		(void) sdev_cleandir(dir, expr, SDEV_ENFORCE);
		return;
	}

	/* directory pattern */
	rw_enter(&dir->sdev_contents, RW_WRITER);

	for (dv = SDEV_FIRST_ENTRY(dir); dv; dv = SDEV_NEXT_ENTRY(dir, dv)) {
		if (gmatch(dv->sdev_name, expr) == 0 ||
		    SDEVTOV(dv)->v_type != VDIR)
			continue;
		process_rule(dv, dv->sdev_origin,
		    pathleft, NULL, type);
	}
	rw_exit(&dir->sdev_contents);
}
Пример #6
0
/*
 * Check if exec name matches cfgname found in madv cfg file.
 */
static int
fnmatch(const char *execname, char *cfgname, char *cwd)
{
	const char	*ename;
	int		rc;

	/* cfgname should not have a '/' unless it begins with one */
	if (cfgname[0] == '/') {
		/*
		 * if execname does not begin with a '/', prepend the
		 * current directory.
		 */
		if (execname[0] != '/') {
			ename = (const char *)strcat(cwd, execname);
		} else
			ename = execname;
	} else {	/* simple cfg name */
		if (ename = strrchr(execname, '/'))
			/* execname is a path name - get the base name */
			ename++;
		else
			ename = execname;
	}
	rc = gmatch(ename, cfgname);
	MADVPRINT(2, (stderr, "gmatch: %s %s %s %d\n",
	    cfgname, ename, execname, rc));

	return (rc);
}
Пример #7
0
static void
apply_glob_pattern(struct sdev_node *pdir, struct sdev_node *cdir)
{
	char *name;
	nvpair_t *nvp = NULL;
	nvlist_t *nvl;
	struct vnode *vp = SDEVTOV(cdir);
	int rv = 0;

	if (vp->v_type != VDIR)
		return;
	name = cdir->sdev_name;
	nvl = pdir->sdev_prof.dev_glob_incdir;
	while (nvp = nvlist_next_nvpair(nvl, nvp)) {
		char *pathleft;
		char *expr = nvpair_name(nvp);
		if (!gmatch(name, expr))
			continue;
		rv = nvpair_value_string(nvp, &pathleft);
		if (rv != 0) {
			cmn_err(CE_WARN, sdev_nvp_val_err,
			    rv, nvpair_name(nvp));
			break;
		}
		process_rule(cdir, cdir->sdev_origin,
		    pathleft, NULL, PROFILE_TYPE_INCLUDE);
	}
}
Пример #8
0
static int
dt_pid_sym_filt(void *arg, const GElf_Sym *symp, const char *func)
{
	dt_pid_probe_t *pp = arg;

	if (symp->st_shndx == SHN_UNDEF)
		return (0);

	if (symp->st_size == 0) {
		dt_dprintf("st_size of %s is zero\n", func);
		return (0);
	}

	if (pp->dpp_last_taken == 0 ||
	    symp->st_value != pp->dpp_last.st_value ||
	    symp->st_size != pp->dpp_last.st_size) {
		/*
		 * Due to 4524008, _init and _fini may have a bloated st_size.
		 * While this bug has been fixed for a while, old binaries
		 * may exist that still exhibit this problem. As a result, we
		 * don't match _init and _fini though we allow users to
		 * specify them explicitly.
		 */
		if (strcmp(func, "_init") == 0 || strcmp(func, "_fini") == 0)
			return (0);

		if ((pp->dpp_last_taken = gmatch(func, pp->dpp_func)) != 0) {
			pp->dpp_last = *symp;
			return (dt_pid_per_sym(pp, symp, func));
		}
	}

	return (0);
}
Пример #9
0
bool pattern_match(const char *pat,const char *str)
{
#ifdef _SGI_SOURCE
  return (gmatch(str,pat) != 0);
#else
  return (fnmatch(pat,str,0) == 0);
#endif
}
Пример #10
0
static int
match_name(char *name, void *arg)
{
	struct match_arg *margp = (struct match_arg *)arg;

	if (gmatch(name, margp->expr)) {
		margp->match = 1;
		return (WALK_DIR_TERMINATE);
	}
	return (WALK_DIR_CONTINUE);
}
Пример #11
0
/*
 *  Apply pattern matching to a table: all table entries that match a pattern
 * are added to wp.
 */
static void
glob_table(const char *pat, XPtrV *wp, struct table *tp)
{
	struct tstate ts;
	struct tbl *te;

	for (ktwalk(&ts, tp); (te = ktnext(&ts)); ) {
		if (gmatch(te->name, pat, false))
			XPput(*wp, str_save(te->name, ATEMP));
	}
}
Пример #12
0
int
dt_pid_create_probes_module(dtrace_hdl_t *dtp, dt_proc_t *dpr)
{
	dtrace_prog_t *pgp;
	dt_stmt_t *stp;
	dtrace_probedesc_t *pdp, pd;
	pid_t pid;
	int ret = 0, found = B_FALSE;
	char provname[DTRACE_PROVNAMELEN];

	(void) snprintf(provname, sizeof (provname), "pid%d",
	    (int)dpr->dpr_pid);

	for (pgp = dt_list_next(&dtp->dt_programs); pgp != NULL;
	    pgp = dt_list_next(pgp)) {

		for (stp = dt_list_next(&pgp->dp_stmts); stp != NULL;
		    stp = dt_list_next(stp)) {

			pdp = &stp->ds_desc->dtsd_ecbdesc->dted_probe;
			pid = dt_pid_get_pid(pdp, dtp, NULL, dpr);
			if (pid != dpr->dpr_pid)
				continue;

			found = B_TRUE;

			pd = *pdp;

			if (gmatch(provname, pdp->dtpd_provider) != 0 &&
			    dt_pid_create_pid_probes(&pd, dtp, NULL, dpr) != 0)
				ret = 1;

			/*
			 * If it's not strictly a pid provider, we might match
			 * a USDT provider.
			 */
			if (strcmp(provname, pdp->dtpd_provider) != 0 &&
			    dt_pid_create_usdt_probes(&pd, dtp, NULL, dpr) != 0)
				ret = 1;
		}
	}

	if (found) {
		/*
		 * Give DTrace a shot to the ribs to get it to check
		 * out the newly created probes.
		 */
		(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
	}

	return (ret);
}
Пример #13
0
/*
* Match a string against a shell glob or extended regular expression.
*/
static boolean_t
ks_match(const char *str, ks_pattern_t *pattern)
{
int	regcode;
char	*regstr;
char	*errbuf;
size_t	bufsz;

if (pattern->pstr != NULL && gmatch(pattern->pstr, "/*/") != 0) {
	/* All regex patterns are strdup'd copies */
	regstr = pattern->pstr + 1;
	*(strrchr(regstr, '/')) = '\0';

	regcode = regcomp(&pattern->preg, regstr,
			REG_EXTENDED | REG_NOSUB);
	if (regcode != 0) {
		bufsz = regerror(regcode, NULL, NULL, 0);
		if (bufsz != 0) {
			errbuf = malloc(bufsz);
			if (errbuf == NULL) {
				perror("malloc");
				exit(3);
			}
			(void) regerror(regcode, NULL, errbuf, bufsz);
			(void) fprintf(stderr, "kstat: %s\n", errbuf);
		}
		usage();
		exit(2);
	}

	pattern->pstr = NULL;
}

if (pattern->pstr == NULL) {
	return (regexec(&pattern->preg, str, 0, NULL, 0) == 0);
}

return ((gmatch(str, pattern->pstr) != 0));
}
Пример #14
0
/*ARGSUSED*/
int
dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
{
	ulong_t i;

	ftp->ftps_type = DTFTP_OFFSETS;
	ftp->ftps_pc = (uintptr_t)symp->st_value;
	ftp->ftps_size = (size_t)symp->st_size;
	ftp->ftps_noffs = 0;

	/*
	 * If we're matching against everything, just iterate through each
	 * instruction in the function, otherwise look for matching offset
	 * names by constructing the string and comparing it against the
	 * pattern.
	 */
	if (strcmp("*", pattern) == 0) {
		for (i = 0; i < symp->st_size; i += 4) {
			ftp->ftps_offs[ftp->ftps_noffs++] = i;
		}
	} else {
		char name[sizeof (i) * 2 + 1];

		for (i = 0; i < symp->st_size; i += 4) {
			(void) snprintf(name, sizeof(name), "%lx", i);
			if (gmatch(name, pattern))
				ftp->ftps_offs[ftp->ftps_noffs++] = i;
		}
	}

	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
		dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
		    strerror(errno));
		return (dt_set_errno(dtp, errno));
	}

	return (ftp->ftps_noffs);
}
Пример #15
0
/*
 * Check if string matches any of exec arguments.
 */
static int
argmatch(char *str)
{
	int fd;
	psinfo_t pi;
	int rc = 0;
	int arg;
	char **argv;

	fd = open("/proc/self/psinfo", O_RDONLY);

	if (fd >= 0) {
		if (read(fd, &pi, sizeof (pi)) == sizeof (pi)) {
			argv = (char **)pi.pr_argv;
			argv++;
			MADVPRINT(2, (stderr, "argmatch: %s ", str));
			for (arg = 1; arg < pi.pr_argc; arg++, argv++) {
				if (rc = gmatch(*argv, str)) {
					MADVPRINT(2, (stderr, "%s ", *argv));
					break;
				}
			}
			MADVPRINT(2, (stderr, "%d\n", rc));
		} else {
			madverr(errfp, dgettext(TEXT_DOMAIN,
			    "%s: /proc/self/psinfo read failed [%s]\n"),
			    madvident, strerror(errno));
		}
		(void) close(fd);
	} else {
		madverr(errfp, dgettext(TEXT_DOMAIN,
		    "%s: /proc/self/psinfo open failed [%s]\n"),
		    madvident, strerror(errno));
	}
	return (rc);
}
Пример #16
0
int 
expand(unsigned char *as, int rcnt)
{
	int	count;
	DIR	*dirf;
	BOOL	dir = 0;
	unsigned char	*rescan = 0;
	unsigned char 	*slashsav = 0;
	register unsigned char	*s, *cs;
	unsigned char *s2 = 0;
	struct argnod	*schain = gchain;
	BOOL	slash;
	int	len;
	wchar_t	wc;

	if (trapnote & SIGSET)
		return (0);
	s = cs = as;
	/*
	 * check for meta chars
	 */
	{
		register BOOL open;

		slash = 0;
		open = 0;
		do
		{
			if ((len = nextc(&wc, (char *)cs)) <= 0) {
				len = 1;
				wc = (unsigned char)*cs;
			}

			cs += len;
			switch (wc) {
			case 0:
				if (rcnt && slash)
					break;
				else
					return (0);

			case '/':
				slash++;
				open = 0;
				continue;

			case '[':
				open++;
				continue;

			case ']':
				if (open == 0)
					continue;

			case '?':
			case '*':
				if (rcnt > slash)
					continue;
				else
					cs--;
				break;

			case '\\':
				cs++;
			default:
				continue;
			}
			break;
		} while (TRUE);
	}

	for (;;)
	{
		if (cs == s)
		{
			s = (unsigned char *)nullstr;
			break;
		} else if (*--cs == '/')
		{
			*cs = 0;
			if (s == cs)
				s = (unsigned char *)"/";
			else {
				/*
				 * push trimmed copy of directory prefix
				 * onto stack
				 */
				s2 = cpystak(s);
				trim(s2);
				s = s2;
			}
			break;
		}
	}

	if ((dirf = opendir(*s ? (char *)s : (char *)".")) != 0)
		dir++;

	/* Let s point to original string because it will be trimmed later */
	if (s2)
		s = as;
	count = 0;
	if (*cs == 0)
		slashsav = cs++; /* remember where first slash in as is */

	/* check for rescan */
	if (dir)
	{
		register unsigned char *rs;
		struct dirent *e;

		rs = cs;
		do /* find next / in as */
		{
			if (*rs == '/')
			{
				rescan = rs;
				*rs = 0;
				gchain = 0;
			}
		} while (*rs++);

		while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0)
		{
			if (e->d_name[0] == '.' && *cs != '.')
				continue;

			if (gmatch(e->d_name, cs))
			{
				addg(s, e->d_name, rescan, slashsav);
				count++;
			}
		}
		closedir(dirf);

		if (rescan)
		{
			register struct argnod	*rchain;

			rchain = gchain;
			gchain = schain;
			if (count)
			{
				count = 0;
				while (rchain)
				{
					count += expand(rchain->argval,
							slash + 1);
					rchain = rchain->argnxt;
				}
			}
			*rescan = '/';
		}
	}

	if (slashsav)
		*slashsav = '/';
	return (count);
}
Пример #17
0
int
test_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
    int do_eval)
{
	int res;
	int not;
	struct stat b1, b2;

	if (!do_eval)
		return 0;

	switch ((int) op) {
	/*
	 * Unary Operators
	 */
	case TO_STNZE: /* -n */
		return *opnd1 != '\0';
	case TO_STZER: /* -z */
		return *opnd1 == '\0';
	case TO_OPTION: /* -o */
		if ((not = *opnd1 == '!'))
			opnd1++;
		if ((res = option(opnd1)) < 0)
			res = 0;
		else {
			res = Flag(res);
			if (not)
				res = !res;
		}
		return res;
	case TO_FILRD: /* -r */
		return test_eaccess(opnd1, R_OK) == 0;
	case TO_FILWR: /* -w */
		return test_eaccess(opnd1, W_OK) == 0;
	case TO_FILEX: /* -x */
		return test_eaccess(opnd1, X_OK) == 0;
	case TO_FILAXST: /* -a */
		return test_stat(opnd1, &b1) == 0;
	case TO_FILEXST: /* -e */
		/* at&t ksh does not appear to do the /dev/fd/ thing for
		 * this (unless the os itself handles it)
		 */
		return stat(opnd1, &b1) == 0;
	case TO_FILREG: /* -r */
		return test_stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode);
	case TO_FILID: /* -d */
		return test_stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode);
	case TO_FILCDEV: /* -c */
		return test_stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode);
	case TO_FILBDEV: /* -b */
		return test_stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode);
	case TO_FILFIFO: /* -p */
		return test_stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode);
	case TO_FILSYM: /* -h -L */
		return lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode);
	case TO_FILSOCK: /* -S */
		return test_stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode);
	case TO_FILCDF:/* -H HP context dependent files (directories) */
		return 0;
	case TO_FILSETU: /* -u */
		return test_stat(opnd1, &b1) == 0 &&
		    (b1.st_mode & S_ISUID) == S_ISUID;
	case TO_FILSETG: /* -g */
		return test_stat(opnd1, &b1) == 0 &&
		    (b1.st_mode & S_ISGID) == S_ISGID;
	case TO_FILSTCK: /* -k */
		return test_stat(opnd1, &b1) == 0 &&
		    (b1.st_mode & S_ISVTX) == S_ISVTX;
	case TO_FILGZ: /* -s */
		return test_stat(opnd1, &b1) == 0 && b1.st_size > 0L;
	case TO_FILTT: /* -t */
		if (opnd1 && !bi_getn(opnd1, &res)) {
			te->flags |= TEF_ERROR;
			res = 0;
		} else {
			/* generate error if in FPOSIX mode? */
			res = isatty(opnd1 ? res : 0);
		}
		return res;
	case TO_FILUID: /* -O */
		return test_stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid;
	case TO_FILGID: /* -G */
		return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid();
	/*
	 * Binary Operators
	 */
	case TO_STEQL: /* = */
		if (te->flags & TEF_DBRACKET)
			return gmatch(opnd1, opnd2, false);
		return strcmp(opnd1, opnd2) == 0;
	case TO_STNEQ: /* != */
		if (te->flags & TEF_DBRACKET)
			return !gmatch(opnd1, opnd2, false);
		return strcmp(opnd1, opnd2) != 0;
	case TO_STLT: /* < */
		return strcmp(opnd1, opnd2) < 0;
	case TO_STGT: /* > */
		return strcmp(opnd1, opnd2) > 0;
	case TO_INTEQ: /* -eq */
	case TO_INTNE: /* -ne */
	case TO_INTGE: /* -ge */
	case TO_INTGT: /* -gt */
	case TO_INTLE: /* -le */
	case TO_INTLT: /* -lt */
		{
			long v1, v2;

			if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR, false) ||
			    !evaluate(opnd2, &v2, KSH_RETURN_ERROR, false)) {
				/* error already printed.. */
				te->flags |= TEF_ERROR;
				return 1;
			}
			switch ((int) op) {
			case TO_INTEQ:
				return v1 == v2;
			case TO_INTNE:
				return v1 != v2;
			case TO_INTGE:
				return v1 >= v2;
			case TO_INTGT:
				return v1 > v2;
			case TO_INTLE:
				return v1 <= v2;
			case TO_INTLT:
				return v1 < v2;
			}
		}
	case TO_FILNT: /* -nt */
		{
			int s2;
			/* ksh88/ksh93 succeed if file2 can't be stated
			 * (subtly different from `does not exist').
			 */
			return stat(opnd1, &b1) == 0 &&
			    (((s2 = stat(opnd2, &b2)) == 0 &&
			    b1.st_mtime > b2.st_mtime) || s2 < 0);
		}
	case TO_FILOT: /* -ot */
		{
			int s1;
			/* ksh88/ksh93 succeed if file1 can't be stated
			 * (subtly different from `does not exist').
			 */
			return stat(opnd2, &b2) == 0 &&
			    (((s1 = stat(opnd1, &b1)) == 0 &&
			    b1.st_mtime < b2.st_mtime) || s1 < 0);
		}
	case TO_FILEQ: /* -ef */
		return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0 &&
		    b1.st_dev == b2.st_dev && b1.st_ino == b2.st_ino;
	}
	(*te->error)(te, 0, "internal error: unknown op");
	return 1;
}
Пример #18
0
static int
dt_pid_per_sym(dt_pid_probe_t *pp, const GElf_Sym *symp, const char *func)
{
	dtrace_hdl_t *dtp = pp->dpp_dtp;
	dt_pcb_t *pcb = pp->dpp_pcb;
	dt_proc_t *dpr = pp->dpp_dpr;
	fasttrap_probe_spec_t *ftp;
	uint64_t off;
	char *end;
	uint_t nmatches = 0;
	ulong_t sz;
	int glob, err;
	int isdash = strcmp("-", func) == 0;
	pid_t pid;

#if defined(sun)
	pid = Pstatus(pp->dpp_pr)->pr_pid;
#else
	pid = proc_getpid(pp->dpp_pr);
#endif

	dt_dprintf("creating probe pid%d:%s:%s:%s\n", (int)pid, pp->dpp_obj,
	    func, pp->dpp_name);

	sz = sizeof (fasttrap_probe_spec_t) + (isdash ? 4 :
	    (symp->st_size - 1) * sizeof (ftp->ftps_offs[0]));

	if ((ftp = dt_alloc(dtp, sz)) == NULL) {
		dt_dprintf("proc_per_sym: dt_alloc(%lu) failed\n", sz);
		return (1); /* errno is set for us */
	}

	ftp->ftps_pid = pid;
	(void) strncpy(ftp->ftps_func, func, sizeof (ftp->ftps_func));

	dt_pid_objname(ftp->ftps_mod, sizeof (ftp->ftps_mod), pp->dpp_lmid,
	    pp->dpp_obj);

	if (!isdash && gmatch("return", pp->dpp_name)) {
		if (dt_pid_create_return_probe(pp->dpp_pr, dtp, ftp, symp,
		    pp->dpp_stret) < 0) {
			return (dt_pid_error(dtp, pcb, dpr, ftp,
			    D_PROC_CREATEFAIL, "failed to create return probe "
			    "for '%s': %s", func,
			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
		}

		nmatches++;
	}

	if (!isdash && gmatch("entry", pp->dpp_name)) {
		if (dt_pid_create_entry_probe(pp->dpp_pr, dtp, ftp, symp) < 0) {
			return (dt_pid_error(dtp, pcb, dpr, ftp,
			    D_PROC_CREATEFAIL, "failed to create entry probe "
			    "for '%s': %s", func,
			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
		}

		nmatches++;
	}

	glob = strisglob(pp->dpp_name);
	if (!glob && nmatches == 0) {
		off = strtoull(pp->dpp_name, &end, 16);
		if (*end != '\0') {
			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_NAME,
			    "'%s' is an invalid probe name", pp->dpp_name));
		}

		if (off >= symp->st_size) {
			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_OFF,
			    "offset 0x%llx outside of function '%s'",
			    (u_longlong_t)off, func));
		}

		err = dt_pid_create_offset_probe(pp->dpp_pr, pp->dpp_dtp, ftp,
		    symp, off);

		if (err == DT_PROC_ERR) {
			return (dt_pid_error(dtp, pcb, dpr, ftp,
			    D_PROC_CREATEFAIL, "failed to create probe at "
			    "'%s+0x%llx': %s", func, (u_longlong_t)off,
			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
		}

		if (err == DT_PROC_ALIGN) {
			return (dt_pid_error(dtp, pcb, dpr, ftp, D_PROC_ALIGN,
			    "offset 0x%llx is not aligned on an instruction",
			    (u_longlong_t)off));
		}

		nmatches++;

	} else if (glob && !isdash) {
		if (dt_pid_create_glob_offset_probes(pp->dpp_pr,
		    pp->dpp_dtp, ftp, symp, pp->dpp_name) < 0) {
			return (dt_pid_error(dtp, pcb, dpr, ftp,
			    D_PROC_CREATEFAIL,
			    "failed to create offset probes in '%s': %s", func,
			    dtrace_errmsg(dtp, dtrace_errno(dtp))));
		}

		nmatches++;
	}

	pp->dpp_nmatches += nmatches;

	dt_free(dtp, ftp);

	return (0);
}
Пример #19
0
/*ARGSUSED*/
int
dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
{
	uint8_t *text;
	ulong_t i, end;
	int size;
	pid_t pid = Pstatus(P)->pr_pid;
	char dmodel = Pstatus(P)->pr_dmodel;

	if ((text = malloc(symp->st_size)) == NULL) {
		dt_dprintf("mr sparkle: malloc() failed\n");
		return (DT_PROC_ERR);
	}

	if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
		dt_dprintf("mr sparkle: Pread() failed\n");
		free(text);
		return (DT_PROC_ERR);
	}

	/*
	 * We can't instrument offsets in functions with jump tables as
	 * we might interpret a jump table offset as an instruction.
	 */
	if (dt_pid_has_jump_table(P, dtp, text, ftp, symp)) {
		free(text);
		return (0);
	}

	ftp->ftps_probe_type = DTFTP_OFFSETS;
	ftp->ftps_pc = symp->st_value;
	ftp->ftps_size = (size_t)symp->st_size;
	ftp->ftps_noffs = 0;

	end = ftp->ftps_size;

	if (strcmp("*", pattern) == 0) {
		for (i = 0; i < end; i += size) {
			ftp->ftps_offs[ftp->ftps_noffs++] = i;

			size = dt_instr_size(&text[i], dtp, pid,
			    symp->st_value + i, dmodel);

			/* bail if we hit an invalid opcode */
			if (size <= 0)
				break;
		}
	} else {
		char name[sizeof (i) * 2 + 1];

		for (i = 0; i < end; i += size) {
			(void) snprintf(name, sizeof (name), "%lx", i);
			if (gmatch(name, pattern))
				ftp->ftps_offs[ftp->ftps_noffs++] = i;

			size = dt_instr_size(&text[i], dtp, pid,
			    symp->st_value + i, dmodel);

			/* bail if we hit an invalid opcode */
			if (size <= 0)
				break;
		}
	}

	free(text);
	if (ftp->ftps_noffs > 0) {
		if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
			dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
			    strerror(errno));
			return (dt_set_errno(dtp, errno));
		}
	}

	return (ftp->ftps_noffs);
}
Пример #20
0
int execute(TREPTR argt, int execflg, int *pf1, int *pf2)
{
	/* `stakbot' is preserved by this routine */
	register TREPTR t;
	STKPTR sav = savstak();

	sigchk();

	if ((t = argt) && execbrk == 0) {
		register int treeflgs;
		int oldexit, type;
		register char **com;

		treeflgs = t->tretyp;
		type = treeflgs & COMMSK;
		oldexit = exitval;
		exitval = 0;

		switch (type) {

		case TCOM:
			{
				STRING a1;
				int argn, internal;
				ARGPTR schain = gchain;
				IOPTR io = t->treio;
				gchain = 0;
				argn = getarg((void *)t);/*FIXME*/
				com = scan(argn);
				a1 = com[1];
				gchain = schain;

				if ((internal = syslook(com[0], commands)) || argn == 0)
					setlist(((COMPTR) t)->comset, 0);

				if (argn && (flags & noexec) == 0) {	/* print command if execpr */
					if (flags & execpr) {
						argn = 0;
						prs(execpmsg);
						while (com[argn] != ENDARGS) {
							prs(com[argn++]);
							blank();
						}
						newline();
					}

					switch (internal) {

					case SYSDOT:
						if (a1) {
							register int f;

							if ((f = pathopen(getpath(a1), a1)) < 0)
								failed(a1, notfound);
							else
								execexp(0, f);
						}
						break;

					case SYSTIMES:
					{
						struct tms t;
						times(&t);
						prt(t.tms_cutime);
						blank();
						prt(t.tms_cstime);
						newline();
					}
					break;

					case SYSEXIT:
						exitsh(a1 ? stoi(a1) : oldexit);

					case SYSNULL:
						io = 0;
						break;

					case SYSCONT:
						execbrk = -loopcnt;
						break;

					case SYSBREAK:
						if ((execbrk = loopcnt) && a1)
							breakcnt = stoi(a1);
						break;

					case SYSTRAP:
						if (a1) {
							BOOL clear;
							if ((clear = digit(*a1)) == 0)
								++com;
							while (*++com) {
								int i;
								if ((i = stoi(*com)) >= MAXTRAP || i < MINTRAP)
									failed(*com, badtrap);
								else if (clear)
									clrsig(i);
								else {
									replace(&trapcom[i], a1);
									if (*a1)
										getsig(i);
									else
										ignsig(i);
								}
							}
						} else {	/* print out current traps */
							int i;

							for (i = 0; i < MAXTRAP; i++) {
								if (trapcom[i]) {
									prn(i);
									prs(colon);
									prs(trapcom[i]);
									newline();
								}
							}
						}
						break;

					case SYSEXEC:
						com++;
						initio(io);
						ioset = 0;
						io = 0;
						if (a1 == 0)
							break;

					case SYSLOGIN:
						flags |= forked;
						oldsigs();
						execa((const char **)com);
						done();

					case SYSCD:
						if (flags & rshflg)
							failed(com[0], restricted);
						else if ((a1 == 0 && (a1 = (char *)homenod.namval) == 0) || chdir(a1) < 0) /* FIXME */
							failed(a1, baddir);
						break;

					case SYSSHFT:
						if (dolc < 1)
							error(badshift);
						else {
							dolv++;
							dolc--;
						}
						assnum(&dolladr, dolc);
						break;

					case SYSWAIT:
						await(-1);
						break;

					case SYSREAD:
						exitval = readvar(&com[1]);
						break;

/*
				case SYSTST:
					exitval=testcmd(com);
					break;
*/

					case SYSSET:
						if (a1) {
							int argc;
							argc = options(argn, (const char **)com);
							if (argc > 1)
								setargs((const char **)com + argn - argc);
						} else if (((COMPTR) t)->comset == 0)
						        /* Scan name chain and print */
							namscan(printnam);
						break;

					case SYSRDONLY:
						exitval = N_RDONLY;
					case SYSXPORT:
						if (exitval == 0)
							exitval = N_EXPORT;;

						if (a1) {
							while (*++com)
								attrib(lookup(*com), exitval);
						} else {
							namscan(printflg);
						}
						exitval = 0;
						break;

					case SYSEVAL:
						if (a1)
							execexp(a1, (UFD)&com[2]);	/* FIXME */
						break;

					case SYSUMASK:
						if (a1) {
							int c, i;
							i = 0;
							while ((c = *a1++) >= '0' && c <= '7')
								i = (i << 3) + c - '0';
							umask(i);
						} else {
							int i, j;
							umask(i = umask(0));
							prc('0');
							for (j = 6; j >= 0; j -= 3)
								prc(((i >> j) & 07) + '0');
							newline();
						}
						break;

					default:
						internal = builtin(argn, com);

					}

					if (internal) {
						if (io)
							error(illegal);
						chktrap();
						break;
					}
				} else if (t->treio == 0)
					break;
			}

		case TFORK:
			if (execflg && (treeflgs & (FAMP | FPOU)) == 0)
				parent = 0;
			else {
				while ((parent = fork()) == -1) {
					sigchk();
					alarm(10);
					pause();
				}
			}

			if (parent) {	/* This is the parent branch of fork;    */
				/* it may or may not wait for the child. */
				if (treeflgs & FPRS && flags & ttyflg) {
					prn(parent);
					newline();
				}
				if (treeflgs & FPCL)
					closepipe(pf1);
				if ((treeflgs & (FAMP | FPOU)) == 0)
					await(parent);
				else if ((treeflgs & FAMP) == 0)
					post(parent);
				else
					assnum(&pcsadr, parent);

				chktrap();
				break;
			} else {	/* this is the forked branch (child) of execute */
				flags |= forked;
				iotemp = 0;
				postclr();
				settmp();

				/* Turn off INTR and QUIT if `FINT'  */
				/* Reset ramaining signals to parent */
				/* except for those `lost' by trap   */
				oldsigs();
				if (treeflgs & FINT) {
					signal(INTR, SIG_IGN);
					signal(QUIT, SIG_IGN);
				}

				/* pipe in or out */
				if (treeflgs & FPIN) {
					sh_rename(pf1[INPIPE], 0);
					close(pf1[OTPIPE]);
				}
				if (treeflgs & FPOU) {
					sh_rename(pf2[OTPIPE], 1);
					close(pf2[INPIPE]);
				}

				/* default std input for & */
				if (treeflgs & FINT && ioset == 0)
					sh_rename(chkopen(devnull), 0);

				/* io redirection */
				initio(t->treio);
				if (type != TCOM)
					execute(((FORKPTR) t)->forktre, 1, NULL, NULL);
				else if (com[0] != ENDARGS) {
					setlist(((COMPTR) t)->comset, N_EXPORT);
					execa((const char **)com);
				}
				done();
			}

		case TPAR:
			sh_rename(dup(2), output);
			execute(((PARPTR) t)->partre, execflg, NULL, NULL);
			done();

		case TFIL:
		{
			int pv[2];
			chkpipe(pv);
			if (execute(((LSTPTR) t)->lstlef, 0, pf1, pv) == 0)
				execute(((LSTPTR) t)->lstrit, execflg, pv, pf2);
			else
				closepipe(pv);
			break;
                }
		case TLST:
			execute(((LSTPTR) t)->lstlef, 0, NULL, NULL);
			execute(((LSTPTR) t)->lstrit, execflg, NULL, NULL);
			break;

		case TAND:
			if (execute(((LSTPTR) t)->lstlef, 0, NULL, NULL) == 0)
				execute(((LSTPTR) t)->lstrit, execflg, NULL, NULL);
			break;

		case TORF:
			if (execute(((LSTPTR) t)->lstlef, 0, NULL, NULL) != 0)
				execute(((LSTPTR) t)->lstrit, execflg, NULL, NULL);
			break;

		case TFOR:
		{
			NAMPTR n = lookup(((FORPTR) t)->fornam);
			char **args;
			DOLPTR argsav = 0;

			if (((FORPTR) t)->forlst == 0) {
				args = (char **)dolv + 1;
				argsav = useargs();
			} else {
				ARGPTR schain = gchain;
				gchain = 0;
				trim((args = scan(getarg(((FORPTR) t)->forlst)))[0]);
				gchain = schain;
			}
			loopcnt++;
			while (*args != ENDARGS && execbrk == 0) {
				assign(n, *args++);
				execute(((FORPTR) t)->fortre, 0, NULL, NULL);
				if (execbrk < 0) {
					execbrk = 0;
				}
			}
			if (breakcnt)
				breakcnt--;
			execbrk = breakcnt;
			loopcnt--;
			argfor = freeargs(argsav);
        		break;
		}

		case TWH:
		case TUN:
		{
			int i = 0;

			loopcnt++;
			while (execbrk == 0 && (execute(((WHPTR) t)->whtre, 0, NULL, NULL) == 0) == (type == TWH)) {
				i = execute(((WHPTR) t)->dotre, 0, NULL, NULL);
				if (execbrk < 0)
					execbrk = 0;
			}
			if (breakcnt)
				breakcnt--;

			execbrk = breakcnt;
			loopcnt--;
			exitval = i;
			break;
		}

		case TIF:
			if (execute(((IFPTR) t)->iftre, 0, NULL, NULL) == 0)
				execute(((IFPTR) t)->thtre, execflg, NULL, NULL);
			else
				execute(((IFPTR) t)->eltre, execflg, NULL, NULL);
			break;

		case TSW:
		{
			register char *r = mactrim(((SWPTR) t)->swarg);
			t = (TREPTR) ((SWPTR) t)->swlst;
			while (t) {
				ARGPTR rex = ((REGPTR) t)->regptr;
				while (rex) {
					register char *s;
					if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s))) {
						execute(((REGPTR)t)->regcom, 0, NULL, NULL);
						t = 0;
						break;
					} else
						rex = ((ARGPTR)rex)->argnxt;
				}
				if (t)
					t = (TREPTR) ((REGPTR) t)->regnxt;
			}
		}
		break;

		}
		exitset();
	}
Пример #21
0
int
gmatch(const char *s, const char *p)
{
	const char	*bs = s;
	int	mb_cur_max = MB_CUR_MAX;
	wint_t	c, scc;
	int	n;

	if (fetch(scc, s, n) == WEOF)
		return (0);
	switch (fetch(c, p, n)) {

	case '[':	{
		int	ok = 0, excl;
		unsigned long	lc = ULONG_MAX;
		const char	*bp;

		if (*p == '!') {
			p++;
			excl = 1;
		} else
			excl = 0;
		fetch(c, p, n);
		bp = p;
		while (c != '\0') {
			if (c == ']' && p > bp)
				return (ok ^ excl ? gmatch(s, p) : 0);
			else if (c == '-' && p > bp && *p != ']') {
				if (*p == '\\')
					p++;
				if (fetch(c, p, n) == '\0')
					break;
				if (lc <= scc && scc <= c)
					ok = 1;
			} else {
				if (c == '\\') {
					if (fetch(c, p, n) == '\0')
						break;
				}
				if (scc == (lc = c))
					ok = 1;
			}
			fetch(c, p, n);
		}
		return (0);
	}

	case '\\':
		fetch(c, p, n);
		if (c == '\0')
			return (0);
		/*FALLTHRU*/

	default:
		if (c != scc)
			return (0);
		/*FALLTHRU*/

	case '?':
		return (scc ? gmatch(s, p) : 0);

	case '*':
		if (*p == '\0')
			return (1);
		s = bs;
		while (*s) {
			if (gmatch(s, p))
				return (1);
			fetch(scc, s, n);
		}
		return (0);

	case '\0':
		return (scc == '\0');

	case WEOF:
		return (0);

	}
}
Пример #22
0
int
gmatch(const char *s, const char *p)
{
	const char	*olds;
	wchar_t		scc, c;
	int 		n;
	wchar_t		cl;

	olds = s;
	n = mbtowc(&cl, s, MB_LEN_MAX);
	if (n <= 0) {
		s++;
		scc = n;
	} else {
		scc = cl;
		s += n;
	}
	n = mbtowc(&cl, p, MB_LEN_MAX);
	if (n < 0)
		return (0);
	if (n == 0)
		return (scc == 0);
	p += n;
	c = cl;

	switch (c) {
	case '[':
		if (scc <= 0)
			return (0);
	{
			int ok;
			wchar_t lc = 0;
			int notflag = 0;

			ok = 0;
			if (*p == '!') {
				notflag = 1;
				p++;
			}
			Popwchar(p, c);
			do
			{
				if (c == '-' && lc && *p != ']') {
					Popwchar(p, c);
					if (c == '\\') {
						Popwchar(p, c);
					}
					if (notflag) {
						if (!multibyte ||
						    valid_range(lc, c)) {
							if (scc < lc || scc > c)
								ok++;
							else
								return (0);
						}
					} else {
						if (!multibyte ||
						    valid_range(lc, c))
							if (lc <= scc &&
							    scc <= c)
								ok++;
					}
				} else if (c == '\\') {
					/* skip to quoted character */
					Popwchar(p, c);
				}
				lc = c;
				if (notflag) {
					if (scc != lc)
						ok++;
					else
						return (0);
				}
				else
				{
					if (scc == lc)
						ok++;
				}
				Popwchar(p, c);
			} while (c != ']');
			return (ok ? gmatch(s, p) : 0);
		}

	case '\\':
		/* skip to quoted character and see if it matches */
		Popwchar(p, c);

	default:
		if (c != scc)
			return (0);
			/*FALLTHRU*/

	case '?':
		return (scc > 0 ? gmatch(s, p) : 0);

	case '*':
		while (*p == '*')
			p++;

		if (*p == 0)
			return (1);
		s = olds;
		while (*s) {
			if (gmatch(s, p))
				return (1);
			n = mbtowc(&cl, s, MB_LEN_MAX);
			if (n < 0)
				/* skip past illegal byte sequence */
				s++;
			else
				s += n;
		}
		return (0);
	}
}
Пример #23
0
int
dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb)
{
	char provname[DTRACE_PROVNAMELEN];
	struct ps_prochandle *P;
	dt_proc_t *dpr;
	pid_t pid;
	int err = 0;

	assert(pcb != NULL);

	if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1)
		return (-1);

	if (dtp->dt_ftfd == -1) {
		if (dtp->dt_fterr == ENOENT) {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
			    "pid provider is not installed on this system");
		} else {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV,
			    "pid provider is not available: %s",
			    strerror(dtp->dt_fterr));
		}

		return (-1);
	}

	(void) snprintf(provname, sizeof (provname), "pid%d", (int)pid);

	if (gmatch(provname, pdp->dtpd_provider) != 0) {
		if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE,
		    0)) == NULL) {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
			    "failed to grab process %d", (int)pid);
			return (-1);
		}

		dpr = dt_proc_lookup(dtp, P, 0);
		assert(dpr != NULL);
		(void) pthread_mutex_lock(&dpr->dpr_lock);

		if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) {
			/*
			 * Alert other retained enablings which may match
			 * against the newly created probes.
			 */
			(void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
		}

		(void) pthread_mutex_unlock(&dpr->dpr_lock);
		dt_proc_release(dtp, P);
	}

	/*
	 * If it's not strictly a pid provider, we might match a USDT provider.
	 */
	if (strcmp(provname, pdp->dtpd_provider) != 0) {
		if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) {
			(void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB,
			    "failed to grab process %d", (int)pid);
			return (-1);
		}

		dpr = dt_proc_lookup(dtp, P, 0);
		assert(dpr != NULL);
		(void) pthread_mutex_lock(&dpr->dpr_lock);

		if (!dpr->dpr_usdt) {
			err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr);
			dpr->dpr_usdt = B_TRUE;
		}

		(void) pthread_mutex_unlock(&dpr->dpr_lock);
		dt_proc_release(dtp, P);
	}

	return (err ? -1 : 0);
}