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); } }
/*----------------------------------------------------------------------------. | 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; }
/*----------------------------------------------------------------------------. | 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; }
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); }
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; }
/* * 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); } }