コード例 #1
0
ファイル: test.c プロジェクト: munraj/cherigc
int
test_procstat(struct tf_test *thiz)
{
	struct procstat *ps;
	struct kinfo_vmentry *kv;
	struct kinfo_proc *kp;
	unsigned cnt, i;

	ps = procstat_open_sysctl();
	thiz->t_assert(ps != NULL);
	cnt = 0;
	kp = procstat_getprocs(ps, KERN_PROC_PID, getpid(), &cnt);
	thiz->t_assert(kp != NULL);
	thiz->t_pf("getprocs retrieved %u procs\n", cnt);
	kv = procstat_getvmmap(ps, kp, &cnt);
	thiz->t_assert(kv != NULL);
	for (i = 0; i < cnt; i++) {
		thiz->t_pf("[%u] type: %d, "
		    "start: 0x%"PRIx64", end: 0x%"PRIx64" "
		    "(sz: %"PRIu64"%c), prot: 0x%x\n",
		    i, kv[i].kve_type, kv[i].kve_start, kv[i].kve_end,
		    SZFORMAT(kv[i].kve_end - kv[i].kve_start),
		    kv[i].kve_protection);
	}
	procstat_freevmmap(ps, kv);
	procstat_freeprocs(ps, kp);
	procstat_close(ps);

	return (TF_SUCC);
}
コード例 #2
0
const char *proc_maps(pid_t pid, size_t *start, size_t *end, int *exe_self)
{
    static struct kinfo_vmentry *freep = NULL;
    static unsigned int i, cnt;
    static char *exe_name;

    /* first, init */
    if (freep == NULL) {
        struct kinfo_proc *ki = kinfo_getproc(pid);
        if (ki == NULL) {
            perror("Error in get process info");
            exit(6);
        }
        freep = procstat_getvmmap(procstat_open_sysctl(), ki, &cnt);
        exe_name = ki->ki_comm;
    }

    while (i < cnt) {
        struct kinfo_vmentry *kve = &freep[i++];
        if ((kve->kve_protection & KVME_PROT_EXEC) && kve->kve_path[0] == '/') {
            *start = kve->kve_start;
            *end = kve->kve_end;

            if (exe_self != NULL) {
                *exe_self = (strcmp(exe_name, strrchr(kve->kve_path, '/') + 1) == 0);
            }
            return kve->kve_path;
        }
    }

    i = 0;
    free(freep);
    freep = NULL;
    return NULL;
}
コード例 #3
0
ファイル: gc_vm.c プロジェクト: munraj/cherigc
int
gc_vm_tbl_update(_gc_cap struct gc_vm_tbl *vt)
{
#ifdef GC_USE_LIBPROCSTAT
	struct procstat *ps;
	struct kinfo_vmentry *kv;
	struct kinfo_proc *kp;
	unsigned cnt, i;

	ps = procstat_open_sysctl();
	if (ps == NULL)
		return (GC_ERROR);
	cnt = 0;
	kp = procstat_getprocs(ps, KERN_PROC_PID, getpid(), &cnt);
	if (kp == NULL)
		return (GC_ERROR);
	gc_debug("getprocs retrieved %u procs", cnt);
	kv = procstat_getvmmap(ps, kp, &cnt);
	if (kv == NULL)
		return (GC_ERROR);
	gc_debug("getvmmap retrieved %u entries", cnt);
	if (vt->vt_sz < cnt)
		return (GC_TOO_SMALL);
	vt->vt_nent = cnt;
	for (i = 0; i < vt->vt_nent; i++) {
		vt->vt_ent[i].ve_start = kv[i].kve_start;
		vt->vt_ent[i].ve_end = kv[i].kve_end;
		vt->vt_ent[i].ve_prot = kv[i].kve_protection;
		vt->vt_ent[i].ve_type = kv[i].kve_type;
		vt->vt_ent[i].ve_gctype = 0;
		gc_vm_tbl_track(vt, &vt->vt_ent[i]);
	}
	procstat_freevmmap(ps, kv);
	procstat_freeprocs(ps, kp);
	procstat_close(ps);
	return (GC_SUCC);
#else /* !GC_USE_LIBPROCSTAT */
	return (GC_ERROR);
#endif /* GC_USE_LIBPROCSTAT */
}
コード例 #4
0
ファイル: vm_dump.c プロジェクト: rhenium/ruby
void
procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
{
	struct kinfo_vmentry *freep, *kve;
	int ptrwidth;
	unsigned int i, cnt;
	const char *str;
#ifdef __x86_64__
	ptrwidth = 14;
#else
	ptrwidth = 2*sizeof(void *) + 2;
#endif
	fprintf(stderr, "%*s %*s %3s %4s %4s %3s %3s %4s %-2s %-s\n",
		ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
		"PRES", "REF", "SHD", "FL", "TP", "PATH");

#ifdef HAVE_PROCSTAT_GETVMMAP
	freep = procstat_getvmmap(procstat, kipp, &cnt);
#else
	freep = kinfo_getvmmap(kipp->ki_pid, &cnt);
#endif
	if (freep == NULL)
		return;
	for (i = 0; i < cnt; i++) {
		kve = &freep[i];
		fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_start);
		fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_end);
		fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
		fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-");
		fprintf(stderr, "%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-");
		fprintf(stderr, "%4d ", kve->kve_resident);
		fprintf(stderr, "%4d ", kve->kve_private_resident);
		fprintf(stderr, "%3d ", kve->kve_ref_count);
		fprintf(stderr, "%3d ", kve->kve_shadow_count);
		fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-");
		fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" :
		    "-");
		fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_SUPER ? "S" : "-");
		fprintf(stderr, "%-1s ", kve->kve_flags & KVME_FLAG_GROWS_UP ? "U" :
		    kve->kve_flags & KVME_FLAG_GROWS_DOWN ? "D" : "-");
		switch (kve->kve_type) {
		case KVME_TYPE_NONE:
			str = "--";
			break;
		case KVME_TYPE_DEFAULT:
			str = "df";
			break;
		case KVME_TYPE_VNODE:
			str = "vn";
			break;
		case KVME_TYPE_SWAP:
			str = "sw";
			break;
		case KVME_TYPE_DEVICE:
			str = "dv";
			break;
		case KVME_TYPE_PHYS:
			str = "ph";
			break;
		case KVME_TYPE_DEAD:
			str = "dd";
			break;
		case KVME_TYPE_SG:
			str = "sg";
			break;
		case KVME_TYPE_MGTDEVICE:
			str = "md";
			break;
		case KVME_TYPE_UNKNOWN:
		default:
			str = "??";
			break;
		}
		fprintf(stderr, "%-2s ", str);
		fprintf(stderr, "%-s\n", kve->kve_path);
	}
	free(freep);
}
コード例 #5
0
ファイル: processes.cpp プロジェクト: tburgin/osquery
  files = procstat_getfiles(pstat, proc, 0);
  if (files != nullptr) {
    STAILQ_FOREACH(file, files, next) {
      if (file->fs_uflags & PS_FST_UFLAG_CDIR) {
        r["cwd"] = TEXT(file->fs_path);
      }
      else if (file->fs_uflags & PS_FST_UFLAG_RDIR) {
        r["root"] = TEXT(file->fs_path);
      }
    }

    procstat_freefiles(pstat, files);
  }

  vmentry = procstat_getvmmap(pstat, proc, &cnt);
  if (vmentry != nullptr) {
    // Add up all the resident pages for each vmmap entry.
    for (i = 0; i < cnt; i++) {
      pages += vmentry[i].kve_resident;
    }

    // The column is in bytes.
    r["resident_size"] += INTEGER(pages * getpagesize());

    procstat_freevmmap(pstat, vmentry);
  }

  // XXX: Not sure how to get these on FreeBSD yet.
  r["wired_size"] = INTEGER("0");
  r["phys_footprint"] = INTEGER("0");
コード例 #6
0
/**
 * \todo This function contains many cases that do not allow for a
 *       recovery. Currently, xbt_abort() is called but we should
 *       much rather die with the specific reason so that it's easier
 *       to find out what's going on.
 */
XBT_PRIVATE std::vector<VmMap> get_memory_map(pid_t pid)
{
  std::vector<VmMap> ret;
#ifdef __linux__
  /* Open the actual process's proc maps file and create the memory_map_t */
  /* to be returned. */
  char* path = bprintf("/proc/%i/maps", (int) pid);
  FILE *fp = std::fopen(path, "r");
  if (fp == nullptr) {
    std::perror("fopen failed");
    xbt_die("Cannot open %s to investigate the memory map of the process.", path);
  }
  free(path);
  setbuf(fp, nullptr);

  /* Read one line at the time, parse it and add it to the memory map to be returned */
  ssize_t read; /* Number of bytes readed */
  char* line = nullptr;
  std::size_t n = 0; /* Amount of bytes to read by xbt_getline */
  while ((read = xbt_getline(&line, &n, fp)) != -1) {
    /**
     * The lines that we read have this format: (This is just an example)
     * 00602000-00603000 rw-p 00002000 00:28 1837264                            <complete-path-to-file>
     */

    //fprintf(stderr,"%s", line);

    /* Wipeout the new line character */
    line[read - 1] = '\0';

    /* Tokenize the line using spaces as delimiters and store each token in lfields array. We expect 5 tokens for 6 fields */
    char* lfields[6];
    lfields[0] = strtok(line, " ");

    int i;
    for (i = 1; i < 6 && lfields[i - 1] != nullptr; i++) {
      lfields[i] = std::strtok(nullptr, " ");
    }

    /* Check to see if we got the expected amount of columns */
    if (i < 6)
      xbt_die("The memory map apparently only supplied less than 6 columns. Recovery impossible.");

    /* Ok we are good enough to try to get the info we need */
    /* First get the start and the end address of the map   */
    char *tok = std::strtok(lfields[0], "-");
    if (tok == nullptr)
      xbt_die("Start and end address of the map are not concatenated by a hyphen (-). Recovery impossible.");

    VmMap memreg;
    char *endptr;
    memreg.start_addr = std::strtoull(tok, &endptr, 16);
    /* Make sure that the entire string was an hex number */
    if (*endptr != '\0')
      xbt_abort();

    tok = std::strtok(nullptr, "-");
    if (tok == nullptr)
      xbt_abort();

    memreg.end_addr = std::strtoull(tok, &endptr, 16);
    /* Make sure that the entire string was an hex number */
    if (*endptr != '\0')
      xbt_abort();

    /* Get the permissions flags */
    if (std::strlen(lfields[1]) < 4)
      xbt_abort();

    memreg.prot = 0;

    for (i = 0; i < 3; i++){
      switch(lfields[1][i]){
        case 'r':
          memreg.prot |= PROT_READ;
          break;
        case 'w':
          memreg.prot |= PROT_WRITE;
          break;
        case 'x':
          memreg.prot |= PROT_EXEC;
          break;
        default:
          break;
      }
    }
    if (memreg.prot == 0)
      memreg.prot |= PROT_NONE;

    if (lfields[1][3] == 'p') {
      memreg.flags |= MAP_PRIVATE;
    } else {
      memreg.flags |= MAP_SHARED;
      if (lfields[1][3] != 's')
	XBT_WARN("The protection is neither 'p' (private) nor 's' (shared) but '%s'. Let's assume shared, as on b0rken win-ubuntu systems.\nFull line: %s\n",
		 lfields[1], line);
    }

    /* Get the offset value */
    memreg.offset = std::strtoull(lfields[2], &endptr, 16);
    /* Make sure that the entire string was an hex number */
    if (*endptr != '\0')
      xbt_abort();

    /* Get the device major:minor bytes */
    tok = std::strtok(lfields[3], ":");
    if (tok == nullptr)
      xbt_abort();

    memreg.dev_major = (char) strtoul(tok, &endptr, 16);
    /* Make sure that the entire string was an hex number */
    if (*endptr != '\0')
      xbt_abort();

    tok = std::strtok(nullptr, ":");
    if (tok == nullptr)
      xbt_abort();

    memreg.dev_minor = (char) std::strtoul(tok, &endptr, 16);
    /* Make sure that the entire string was an hex number */
    if (*endptr != '\0')
      xbt_abort();

    /* Get the inode number and make sure that the entire string was a long int */
    memreg.inode = strtoul(lfields[4], &endptr, 10);
    if (*endptr != '\0')
      xbt_abort();

    /* And finally get the pathname */
    if (lfields[5])
      memreg.pathname = lfields[5];

    /* Create space for a new map region in the region's array and copy the */
    /* parsed stuff from the temporal memreg variable */
    XBT_DEBUG("Found region for %s", !memreg.pathname.empty() ? memreg.pathname.c_str() : "(null)");

    ret.push_back(std::move(memreg));
  }

  std::free(line);
  std::fclose(fp);
#elif defined __FreeBSD__
  struct procstat *prstat;
  struct kinfo_proc *proc;
  struct kinfo_vmentry *vmentries;
  unsigned int cnt;

  if ((prstat = procstat_open_sysctl()) == NULL) {
    std::perror("procstat_open_sysctl failed");
    xbt_die("Cannot access kernel state information");
  }
  if ((proc = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt)) == NULL) {
    std::perror("procstat_open_sysctl failed");
    xbt_die("Cannot access process information");
  }
  if ((vmentries = procstat_getvmmap(prstat, proc, &cnt)) == NULL) {
    std::perror("procstat_getvmmap failed");
    xbt_die("Cannot access process memory mappings");
  }
  for (unsigned int i = 0; i < cnt; i++) {
    VmMap memreg;

    /* Addresses */
    memreg.start_addr = vmentries[i].kve_start;
    memreg.end_addr = vmentries[i].kve_end;

    /* Permissions */
    memreg.prot = PROT_NONE;
    if (vmentries[i].kve_protection & KVME_PROT_READ)
      memreg.prot |= PROT_READ;
    if (vmentries[i].kve_protection & KVME_PROT_WRITE)
      memreg.prot |= PROT_WRITE;
    if (vmentries[i].kve_protection & KVME_PROT_EXEC)
      memreg.prot |= PROT_EXEC;

    /* Private (copy-on-write) or shared? */
    if (vmentries[i].kve_flags & KVME_FLAG_COW)
      memreg.flags |= MAP_PRIVATE;
    else
      memreg.flags |= MAP_SHARED;

    /* Offset */
    memreg.offset = vmentries[i].kve_offset;

    /* Device : not sure this can be mapped to something outside of Linux? */
    memreg.dev_major = 0;
    memreg.dev_minor = 0;

    /* Inode */
    memreg.inode = vmentries[i].kve_vn_fileid;

     /*
      * Path. Linuxize result by giving an anonymous mapping a path from
      * the previous mapping, provided previous is vnode and has a path,
      * and mark the stack.
      */
    if (vmentries[i].kve_path[0] != '\0')
      memreg.pathname = vmentries[i].kve_path;
    else if (vmentries[i].kve_type == KVME_TYPE_DEFAULT
	    && vmentries[i-1].kve_type == KVME_TYPE_VNODE
        && vmentries[i-1].kve_path[0] != '\0')
      memreg.pathname = vmentries[i-1].kve_path;
    else if (vmentries[i].kve_type == KVME_TYPE_DEFAULT
        && vmentries[i].kve_flags & KVME_FLAG_GROWS_DOWN)
      memreg.pathname = "[stack]";

    /*
     * One last dirty modification: remove write permission from shared
     * libraries private clean pages. This is necessary because simgrid
     * later identifies mappings based on the permissions that are expected
     * when running the Linux kernel.
     */
    if (vmentries[i].kve_type == KVME_TYPE_VNODE
        && ! (vmentries[i].kve_flags & KVME_FLAG_NEEDS_COPY))
      memreg.prot &= ~PROT_WRITE;

    ret.push_back(std::move(memreg));
  }
  procstat_freevmmap(prstat, vmentries);
  procstat_freeprocs(prstat, proc);
  procstat_close(prstat);
#else
  xbt_die("Could not get memory map from process %lli", (long long int) pid);
#endif
  return ret;
}