Exemple #1
0
struct ps_prochandle *
dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv)
{
	dt_proc_hash_t *dph = dtp->dt_procs;
	dt_proc_t *dpr;
	int err;

	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);
	if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0, dtp->dt_arch)) == NULL) {
		return (dt_proc_error(dtp, dpr,
		    "failed to execute %s: %s\n", file, Pcreate_error(err)));
	}

	dpr->dpr_hdl = dtp;
	dpr->dpr_pid = Pstatus(dpr->dpr_proc)->pr_pid;

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

	if (dt_proc_create_thread(dtp, dpr, dtp->dt_prcmode) != 0)
		return (NULL); /* dt_proc_error() has been called for us */

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

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

	return (dpr->dpr_proc);
}
/*
 * Unload all the loaded modules and then refresh the module cache with the
 * latest list of loaded modules and their address ranges.
 */
void
dtrace_update(dtrace_hdl_t *dtp)
{
	dt_module_t *dmp;
	DIR *dirp;

	for (dmp = dt_list_next(&dtp->dt_modlist);
	    dmp != NULL; dmp = dt_list_next(dmp))
		dt_module_unload(dtp, dmp);

	if (!(dtp->dt_oflags & DTRACE_O_NOSYS)) {
		dt_module_update(dtp, "mach_kernel");
	}

	/*
	 * Look up all the macro identifiers and set di_id to the latest value.
	 * This code collaborates with dt_lex.l on the use of di_id.  We will
	 * need to implement something fancier if we need to support non-ints.
	 */
	dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid();
	dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid();
	dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid();
	dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
	dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
	dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
	dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
	dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
	dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
	dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();

	/*
	 * Cache the pointers to the modules representing the base executable
	 * and the run-time linker in the dtrace client handle. Note that on
	 * x86 krtld is folded into unix, so if we don't find it, use unix
	 * instead.
	 */
	dtp->dt_exec = dt_module_lookup_by_name(dtp, "mach_kernel");
	dtp->dt_rtld = dt_module_lookup_by_name(dtp, "dyld"); /* XXX to what purpose? */

	/*
	 * If this is the first time we are initializing the module list,
	 * remove the module for genunix from the module list and then move it
	 * to the front of the module list.  We do this so that type and symbol
	 * queries encounter genunix and thereby optimize for the common case
	 * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below.
	 */
	if (dtp->dt_exec != NULL &&
	    dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) {
		dt_list_delete(&dtp->dt_modlist, dtp->dt_exec);
		dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec);
	}
}
Exemple #3
0
/*----------------------------------------------------------------------------.
 | DB_PACKAGES_GET_BY_CUSTOM_FILTER                                           |
 '----------------------------------------------------------------------------*/
bool
db_packages_get_by_custom_filter (const char* location, const char* filter,
			       dt_list** packages)
{
  if (packages == NULL) return false;

  /* Allocate memory for a database connection handler, a result object and 
   * an integer for the status. */
  sqlite3* db;
  sqlite3_stmt *result;
  int status;

  /* Open the database connection. */
  status = sqlite3_open (location, &db);
  if (status != SQLITE_OK) return false;

  size_t query_len = 225 + strlen (filter);
  char* query = calloc (1, query_len + 1);
  strcpy (query,
    "SELECT p.id, r.domain, p.name, description, license, category, "
    "location, p.checksum, p.created_at, p.is_local, r.is_enabled FROM "
    "packages p INNER JOIN repositories r ON r.id = p.repository_id ");
  strcat (query, filter);
  strcat (query, " ORDER BY p.id DESC");

  status = sqlite3_prepare_v2 (db, query, -1, &result, NULL);

  if (status == SQLITE_OK)
    while (sqlite3_step (result) == SQLITE_ROW)
      {
	dt_package* item = db_packages_handle_step (result);
	if (item != NULL)
	  *packages = dt_list_prepend (*packages, item);
      }

  sqlite3_finalize (result);
  sqlite3_close (db);

  free (query);
  return true;  
}
Exemple #4
0
/*----------------------------------------------------------------------------.
 | DB_REPOSITORIES_GET_BY_CUSTOM_FILTER                                       |
 '----------------------------------------------------------------------------*/
bool
db_repositories_get_by_custom_filter (const char* location, const char* filter,
			       dt_list** repos)
{
  if (repos == NULL) return false;

  /* Allocate memory for a database connection handler, a result object and 
   * an integer for the status. */
  sqlite3* db;
  sqlite3_stmt *result;
  int status;

  /* Open the database connection. */
  status = sqlite3_open (location, &db);
  if (status != SQLITE_OK) return false;

  size_t query_len = 83 + strlen (filter);
  char* query = calloc (1, query_len + 1);
  strcpy (query, "SELECT id, name, domain, created_at, is_enabled FROM repositories ");
  if (strlen (filter) > 0) strcat (query, filter);
  strcat (query, " ORDER BY id DESC");

  status = sqlite3_prepare_v2 (db, query, -1, &result, NULL);

  if (status == SQLITE_OK)
    while (sqlite3_step (result) == SQLITE_ROW)
      {
	dt_repository* item = db_repositories_handle_step (result);
	if (item != NULL)
	  *repos = dt_list_prepend (*repos, item);
      }

  sqlite3_finalize (result);
  sqlite3_close (db);

  free (query);
  return true;  
}
Exemple #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);
}
Exemple #6
0
int
p_packages_from_buffer (dt_list** packages, const char* input)
{
  /* Allocate memory for a line buffer. */
  char line[LINE_LENGTH];

  /* Allocate memory to store package information. */
  dt_package* pkg = calloc (1, sizeof (dt_package));
  if (pkg == NULL) return 0;

  /* Read through the file line by line. */
  int count = 0;
  char* buffer = (char *)&line;
  while (m_buffer_fgets (&buffer, LINE_LENGTH, input, &count) > 0)
    {
      /* Skip the line whenever it starts with a #. */
      if (line[0] == '#') continue;

      /* Figure out the useful data. */
      char* location;
      if ((location = strstr ((char *)&line, "Package")) != NULL)
	{
	  /* When there's a previous package, process it first. */
          if (pkg->name != NULL)
	    {
	      *packages = dt_list_prepend (*packages, pkg);
	      pkg = calloc (1, sizeof (dt_package));
	      if (pkg == NULL) break;
	    }

          p_prepare (&location, 7),
	  pkg->name = calloc (1, strlen (location) + 1),
	  pkg->name = strncpy (pkg->name, location, strlen (location));
        }
      else if ((location = strstr ((char *)&line, "Description")) != NULL)
	p_prepare (&location, 11),
	pkg->description = calloc (1, strlen (location) + 1),
	pkg->description = strncpy (pkg->description, location, strlen (location));

      else if ((location = strstr ((char *)&line, "License")) != NULL)
	p_prepare (&location, 7),
	pkg->license = calloc (1, strlen (location) + 1),
	pkg->license = strncpy (pkg->license, location, strlen (location));

      else if ((location = strstr ((char *)&line, "Category")) != NULL)
	p_prepare (&location, 8),
	pkg->category = calloc (1, strlen (location) + 1),
	pkg->category = strncpy (pkg->category, location, strlen (location));

      else if ((location = strstr ((char *)&line, "Location")) != NULL)
	p_prepare (&location, 8),
	pkg->location = calloc (1, strlen (location) + 1),
	pkg->location = strncpy (pkg->location, location, strlen (location));

      else if ((location = strstr ((char *)&line, "Checksum")) != NULL)
	p_prepare (&location, 8),
	pkg->checksum = calloc (1, strlen (location) + 1),
	pkg->checksum = strncpy (pkg->checksum, location, strlen (location));

      else if ((location = strstr ((char *)&line, "Timestamp")) != NULL)
	p_prepare (&location, 9),
	pkg->created_at = calloc (1, strlen (location) + 1),
	pkg->created_at = strncpy (pkg->created_at, location, strlen (location));
    }
  
  /* Add the last package to the list. */
  if (pkg != NULL) *packages = dt_list_prepend (*packages, pkg);

  return 1;
}
Exemple #7
0
/*
 * Unload all the loaded modules and then refresh the module cache with the
 * latest list of loaded modules and their address ranges.
 */
void
dtrace_update(dtrace_hdl_t *dtp)
{
	dt_module_t *dmp;
	DIR *dirp;
#if defined(__FreeBSD__)
	int fileid;
#endif

	for (dmp = dt_list_next(&dtp->dt_modlist);
	    dmp != NULL; dmp = dt_list_next(dmp))
		dt_module_unload(dtp, dmp);

#if defined(sun)
	/*
	 * Open /system/object and attempt to create a libdtrace module for
	 * each kernel module that is loaded on the current system.
	 */
	if (!(dtp->dt_oflags & DTRACE_O_NOSYS) &&
	    (dirp = opendir(OBJFS_ROOT)) != NULL) {
		struct dirent *dp;

		while ((dp = readdir(dirp)) != NULL) {
			if (dp->d_name[0] != '.')
				dt_module_update(dtp, dp->d_name);
		}

		(void) closedir(dirp);
	}
#elif defined(__FreeBSD__)
	/*
	 * Use FreeBSD's kernel loader interface to discover what kernel
	 * modules are loaded and create a libdtrace module for each one.
	 */
	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
		struct kld_file_stat k_stat;
		k_stat.version = sizeof(k_stat);
		if (kldstat(fileid, &k_stat) == 0)
			dt_module_update(dtp, &k_stat);
	}
#endif

	/*
	 * Look up all the macro identifiers and set di_id to the latest value.
	 * This code collaborates with dt_lex.l on the use of di_id.  We will
	 * need to implement something fancier if we need to support non-ints.
	 */
	dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid();
	dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid();
	dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid();
	dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
	dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
	dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
#if defined(sun)
	dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
#endif
	dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
#if defined(sun)
	dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
#endif
	dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();

	/*
	 * Cache the pointers to the modules representing the base executable
	 * and the run-time linker in the dtrace client handle. Note that on
	 * x86 krtld is folded into unix, so if we don't find it, use unix
	 * instead.
	 */
	dtp->dt_exec = dt_module_lookup_by_name(dtp, "genunix");
	dtp->dt_rtld = dt_module_lookup_by_name(dtp, "krtld");
	if (dtp->dt_rtld == NULL)
		dtp->dt_rtld = dt_module_lookup_by_name(dtp, "unix");

	/*
	 * If this is the first time we are initializing the module list,
	 * remove the module for genunix from the module list and then move it
	 * to the front of the module list.  We do this so that type and symbol
	 * queries encounter genunix and thereby optimize for the common case
	 * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below.
	 */
	if (dtp->dt_exec != NULL &&
	    dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) {
		dt_list_delete(&dtp->dt_modlist, dtp->dt_exec);
		dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec);
	}
}