Exemple #1
0
static uint32_t
_getms()
{
        uint32_t ms;
#ifdef __macosx__
        struct task_thread_times_info info;
        mach_msg_type_number_t count = TASK_THREAD_TIMES_INFO_COUNT;
        kern_return_t kr = task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, 
                        (task_info_t)&info, &count);
        if (kr != KERN_SUCCESS)
                return 0;

        ms = info.user_time.seconds * 1000;
        ms += info.user_time.microseconds / 1000;
        ms += info.system_time.seconds * 1000;
        ms += info.system_time.microseconds / 1000;
#else
        struct timespec tp;
        clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp);
        ms = tp.tv_sec * 1000;
        ms += tp.tv_nsec / 1000000;
#endif
        return ms;
}
Exemple #2
0
MemoryUtils::MemoryUtils()
{
#if defined(__APPLE__)
	Gestalt(gestaltSystemVersionMajor, &m_OSXMajor);
	Gestalt(gestaltSystemVersionMinor, &m_OSXMinor);

	/* Get pointer to struct that describes all loaded mach-o images in process */
	if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
	{
		task_dyld_info_data_t dyld_info;
		mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
		task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
		m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
	}
	else
	{
		struct nlist list[2];
		memset(list, 0, sizeof(list));
		list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
		nlist("/usr/lib/dyld", list);
		m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
	}
#endif
}
Exemple #3
0
/**
 * Returns the current resident set size (physical memory use) measured
 * in bytes, or zero if the value cannot be determined on this OS.
 */
size_t getCurrentRSS( )
{
#if defined(_WIN32)
  /* Windows -------------------------------------------------- */
  PROCESS_MEMORY_COUNTERS info;
  GetProcessMemoryInfo( GetCurrentProcess( ), &info, sizeof(info) );
  return (size_t)info.WorkingSetSize;

#elif defined(__APPLE__) && defined(__MACH__)
  /* OSX ------------------------------------------------------ */
  struct mach_task_basic_info info;
  mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
  if ( task_info( mach_task_self( ), MACH_TASK_BASIC_INFO,
    (task_info_t)&info, &infoCount ) != KERN_SUCCESS )
    return (size_t)0L;    /* Can't access? */
  return (size_t)info.resident_size;

#elif defined(__linux__) || defined(__linux) || defined(linux) || defined(__gnu_linux__)
  /* Linux ---------------------------------------------------- */
  long rss = 0L;
  FILE* fp = NULL;
  if ( (fp = fopen( "/proc/self/statm", "r" )) == NULL )
    return (size_t)0L;    /* Can't open? */
  if ( fscanf( fp, "%*s%ld", &rss ) != 1 )
  {
    fclose( fp );
    return (size_t)0L;    /* Can't read? */
  }
  fclose( fp );
  return (size_t)rss * (size_t)sysconf( _SC_PAGESIZE);

#else
  /* AIX, BSD, Solaris, and Unknown OS ------------------------ */
  return (size_t)0L;      /* Unsupported. */
#endif
}
Exemple #4
0
static gint64
get_process_stat_item (int pid, int pos, int sum, MonoProcessError *error)
{
#if defined(__APPLE__) 
	double process_user_time = 0, process_system_time = 0;//, process_percent = 0;
	task_t task;
	struct task_basic_info t_info;
	mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT, th_count;
	thread_array_t th_array;
	size_t i;

	if (task_for_pid(mach_task_self(), pid, &task) != KERN_SUCCESS)
		RET_ERROR (MONO_PROCESS_ERROR_NOT_FOUND);

	if (task_info(task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count) != KERN_SUCCESS) {
		mach_port_deallocate (mach_task_self (), task);
		RET_ERROR (MONO_PROCESS_ERROR_OTHER);
	}
	
	if (task_threads(task, &th_array, &th_count) != KERN_SUCCESS) {
		mach_port_deallocate (mach_task_self (), task);
		RET_ERROR (MONO_PROCESS_ERROR_OTHER);
	}
		
	for (i = 0; i < th_count; i++) {
		double thread_user_time, thread_system_time;//, thread_percent;
		
		struct thread_basic_info th_info;
		mach_msg_type_number_t th_info_count = THREAD_BASIC_INFO_COUNT;
		if (thread_info(th_array[i], THREAD_BASIC_INFO, (thread_info_t)&th_info, &th_info_count) == KERN_SUCCESS) {
			thread_user_time = th_info.user_time.seconds + th_info.user_time.microseconds / 1e6;
			thread_system_time = th_info.system_time.seconds + th_info.system_time.microseconds / 1e6;
			//thread_percent = (double)th_info.cpu_usage / TH_USAGE_SCALE;
			
			process_user_time += thread_user_time;
			process_system_time += thread_system_time;
			//process_percent += th_percent;
		}
	}
	
	for (i = 0; i < th_count; i++)
		mach_port_deallocate(task, th_array[i]);

	mach_port_deallocate (mach_task_self (), task);

	process_user_time += t_info.user_time.seconds + t_info.user_time.microseconds / 1e6;
	process_system_time += t_info.system_time.seconds + t_info.system_time.microseconds / 1e6;
    
	if (pos == 10 && sum == TRUE)
		return (gint64)((process_user_time + process_system_time) * 10000000);
	else if (pos == 10)
		return (gint64)(process_user_time * 10000000);
	else if (pos == 11)
		return (gint64)(process_system_time * 10000000);
		
	return 0;
#else
	char buf [512];
	char *s, *end;
	FILE *f;
	int len, i;
	gint64 value;

	g_snprintf (buf, sizeof (buf), "/proc/%d/stat", pid);
	f = fopen (buf, "r");
	if (!f)
		RET_ERROR (MONO_PROCESS_ERROR_NOT_FOUND);
	len = fread (buf, 1, sizeof (buf), f);
	fclose (f);
	if (len <= 0)
		RET_ERROR (MONO_PROCESS_ERROR_OTHER);
	s = strchr (buf, ')');
	if (!s)
		RET_ERROR (MONO_PROCESS_ERROR_OTHER);
	s++;
	while (g_ascii_isspace (*s)) s++;
	if (!*s)
		RET_ERROR (MONO_PROCESS_ERROR_OTHER);
	/* skip the status char */
	while (*s && !g_ascii_isspace (*s)) s++;
	if (!*s)
		RET_ERROR (MONO_PROCESS_ERROR_OTHER);
	for (i = 0; i < pos; ++i) {
		while (g_ascii_isspace (*s)) s++;
		if (!*s)
			RET_ERROR (MONO_PROCESS_ERROR_OTHER);
		while (*s && !g_ascii_isspace (*s)) s++;
		if (!*s)
			RET_ERROR (MONO_PROCESS_ERROR_OTHER);
	}
	/* we are finally at the needed item */
	value = strtoul (s, &end, 0);
	/* add also the following value */
	if (sum) {
		while (g_ascii_isspace (*s)) s++;
		if (!*s)
			RET_ERROR (MONO_PROCESS_ERROR_OTHER);
		value += strtoul (s, &end, 0);
	}
	if (error)
		*error = MONO_PROCESS_ERROR_NONE;
	return value;
#endif
}
Exemple #5
0
unsigned long long darwin_virtual_size()
{
    kern_return_t error;
    task_t task;
    struct task_basic_info_64 taskinfo;
    cpu_type_t cputype;
    mach_msg_type_number_t count;
    mach_vm_size_t size;
    mach_vm_address_t address;
    mach_port_t object_name;
    vm_region_top_info_data_t info;
    mach_vm_size_t	vsize;
    mach_vm_size_t	empty;
    int has_shared_regions;

    empty = 0;

    count = TASK_BASIC_INFO_64_COUNT;
    task = mach_task_self();
    error = task_info(task, TASK_BASIC_INFO_64, (task_info_t)&taskinfo, &count);

    if (error != KERN_SUCCESS) {
        return 0;
    }

    vsize = taskinfo.virtual_size;

    cputype = cpu_type();

    // Go through all the vm regions and check to see if we should count them in the vsize or not
    for (address = 0, has_shared_regions = 0; ; address += size) {
        count = VM_REGION_TOP_INFO_COUNT;
        if (mach_vm_region(task, &address, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count, &object_name) != KERN_SUCCESS) {
            // There are no more vm regions to look at.
            break;
        }

        if (in_shared_region(cputype, address)) {
            // Check if this process has the globally shared text and data regions mapped in.
            // If so, set has_shared_regions to 1 and so we only check once.
            if (has_shared_regions == 0 && info.share_mode == SM_EMPTY) {
                vm_region_basic_info_data_64_t basic_info;

                count = VM_REGION_BASIC_INFO_COUNT_64;
                if (mach_vm_region(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&basic_info, &count, &object_name) != KERN_SUCCESS) {
                    break;
                }

                if (basic_info.reserved) {
                    has_shared_regions = 1;
                }
            }

            // Skip the vm region if it is not a shared private region.
            if (info.share_mode != SM_PRIVATE) {
                continue;
            }
        }

        if (info.share_mode == SM_EMPTY) {
            empty += size;
        }
    }

    // Subtract out the globally shared text and data region.
    if (has_shared_regions == 1) {
        vsize -= shared_region_size(cputype);
    }

    // Subtract out the empty pages (pagezero, stack guard, etc)
    vsize -= empty;

    return vsize;
}
int
main (int argc, char **argv)
{
  kern_return_t kr;
  task_t task;
  pid_t pid = 0;
  char *procname = NULL;
  int arg_is_procname = 0;
  int do_loop = 0;
  int verbose = 0;
  int resume_when_done = 0;
  mach_port_t mytask = mach_task_self ();

  if (argc != 2 && argc != 3 && argc != 4 && argc != 5)
    {
      printf ("Usage: tdump [-l] [-v] [-r] pid/procname\n");
      exit (1);
    }
  
  if (argc == 3 || argc == 4)
    {
      int i = 1;
      while (i < argc - 1)
        {
          if (strcmp (argv[i], "-l") == 0)
            do_loop = 1;
          if (strcmp (argv[i], "-v") == 0)
            verbose = 1;
          if (strcmp (argv[i], "-r") == 0)
            resume_when_done++;
          i++;
        }
    }

  char *c = argv[argc - 1];
  if (*c == '\0')
    {
      printf ("Usage: tdump [-l] [-v] pid/procname\n");
      exit (1);
    }
  while (*c != '\0')
    {
      if (!isdigit (*c))
        {
          arg_is_procname = 1;
          procname = argv[argc - 1];
          break;
        }
      c++;
    }

  if (arg_is_procname && procname)
    {
      pid = get_pid_for_process_name (procname);
    }
  else
    {
      errno = 0;
      pid = (pid_t) strtol (argv[argc - 1], NULL, 10);
      if (pid == 0 && errno == EINVAL)
        {
          printf ("Usage: tdump [-l] [-v] pid/procname\n");
          exit (1);
        }
    }

  const char *process_name = get_process_name_for_pid (pid);

  // At this point "pid" is the process id and "process_name" is the process name
  // Now we have to get the process list from the kernel (which only has the truncated
  // 16 char names)

  struct kinfo_proc *kinfo = get_kinfo_proc_for_pid (pid, process_name);

  printf ("pid %d (%s) is currently ", pid, process_name);
  switch (kinfo->kp_proc.p_stat) {
    case SIDL: printf ("being created by fork"); break;
    case SRUN: printf ("runnable"); break;
    case SSLEEP: printf ("sleeping on an address"); break;
    case SSTOP: printf ("suspended"); break;
    case SZOMB: printf ("zombie state - awaiting collection by parent"); break;
    default: printf ("unknown");
  }
  if (kinfo->kp_proc.p_flag & P_TRACED)
    printf (" and is being debugged.");
  free ((void *) kinfo);

  printf ("\n");

  kr = task_for_pid (mach_task_self (), pid, &task);
  if (kr != KERN_SUCCESS)
    {
      printf ("Error - unable to task_for_pid()\n");
      exit (1);
    }

  struct task_basic_info info;
  unsigned int info_count = TASK_BASIC_INFO_COUNT;

  kr = task_info (task, TASK_BASIC_INFO, (task_info_t) &info, &info_count);
  if (kr != KERN_SUCCESS)
    {
      printf ("Error - unable to call task_info.\n");
      exit (1);
    }
  printf ("Task suspend count: %d.\n", info.suspend_count);

  struct timespec *rqtp = (struct timespec *) malloc (sizeof (struct timespec));
  rqtp->tv_sec = 0;
  rqtp->tv_nsec = 150000000;

  int loop_cnt = 1;
  do
    {
      int i;
      if (do_loop)
        printf ("Iteration %d:\n", loop_cnt++);
      thread_array_t thread_list;
      mach_msg_type_number_t thread_count;

      kr = task_threads (task, &thread_list, &thread_count);
      if (kr != KERN_SUCCESS)
        {
          printf ("Error - unable to get thread list\n");
          exit (1);
        }
      printf ("pid %d has %d threads\n", pid, thread_count);
      if (verbose)
        printf ("\n");

      for (i = 0; i < thread_count; i++)
        {
          thread_basic_info_t basic_info = get_thread_basic_info (thread_list[i]);

          thread_identifier_info_data_t identifier_info = get_thread_identifier_info (thread_list[i]);
          
          int wordsize;
          uint64_t pc = get_current_pc (thread_list[i], &wordsize);

          printf ("thread #%d, system-wide-unique-tid %lld, suspend count is %d, ", i,
                  identifier_info.thread_id,
                  basic_info->suspend_count);
          if (wordsize == 8)
            printf ("pc 0x%016llx, ", pc);
          else
            printf ("pc 0x%08llx, ", pc);
          printf ("run state is ");
          switch (basic_info->run_state) {
            case TH_STATE_RUNNING: puts ("running"); break;
            case TH_STATE_STOPPED: puts ("stopped"); break;
            case TH_STATE_WAITING: puts ("waiting"); break;
            case TH_STATE_UNINTERRUPTIBLE: puts ("uninterruptible"); break;
            case TH_STATE_HALTED: puts ("halted"); break;
            default: puts ("");
          }

          printf ("           pthread handle id 0x%llx (not the same value as pthread_self() returns)\n", (uint64_t) identifier_info.thread_handle);

          struct proc_threadinfo pth;
          int proc_threadinfo_succeeded = get_proc_threadinfo (pid, identifier_info.thread_handle, &pth);

          if (proc_threadinfo_succeeded && pth.pth_name[0] != '\0')
            printf ("           thread name '%s'\n", pth.pth_name);

          printf ("           libdispatch qaddr 0x%llx (not the same as the dispatch_queue_t token)\n", (uint64_t) identifier_info.dispatch_qaddr);

          if (verbose)
            {
              printf ("           (examine-threads port namespace) mach port # 0x%4.4x\n", (int) thread_list[i]);
              thread_t mach_port_inferior_namespace;
              if (inferior_namespace_mach_port_num (task, thread_list[i], &mach_port_inferior_namespace))
                  printf ("           (inferior port namepsace) mach port # 0x%4.4x\n", (int) mach_port_inferior_namespace);
              printf ("           user %d.%06ds, system %d.%06ds", 
                              basic_info->user_time.seconds, basic_info->user_time.microseconds, 
                              basic_info->system_time.seconds, basic_info->system_time.microseconds);
              if (basic_info->cpu_usage > 0)
                {
                  float cpu_percentage = basic_info->cpu_usage / 10.0;
                  printf (", using %.1f%% cpu currently", cpu_percentage);
                }
              if (basic_info->sleep_time > 0)
                printf (", this thread has slept for %d seconds", basic_info->sleep_time);

              printf ("\n           ");
              printf ("scheduling policy %d", basic_info->policy);

              if (basic_info->flags != 0)
                {
                  printf (", flags %d", basic_info->flags);
                  if ((basic_info->flags | TH_FLAGS_SWAPPED) == TH_FLAGS_SWAPPED)
                    printf (" (thread is swapped out)");
                  if ((basic_info->flags | TH_FLAGS_IDLE) == TH_FLAGS_IDLE)
                    printf (" (thread is idle)");
                }
               if (proc_threadinfo_succeeded)
                 printf (", current pri %d, max pri %d", pth.pth_curpri, pth.pth_maxpriority);

              printf ("\n\n");
            }

          free ((void *) basic_info);
        }
      if (do_loop)
        printf ("\n");
      vm_deallocate (mytask, (vm_address_t) thread_list, 
                         thread_count * sizeof (thread_act_t));
      nanosleep (rqtp, NULL);
    } while (do_loop);
  
    while (resume_when_done > 0)
    {
        kern_return_t err = task_resume (task);
        if (err != KERN_SUCCESS)
          printf ("Error resuming task: %d.", err);
        resume_when_done--;
    }

    vm_deallocate (mytask, (vm_address_t) task, sizeof (task_t));
    free ((void *) process_name);

  return 0;
}
int
machine_get_procs(LinkedList * procs)
{
	struct kinfo_proc *kprocs;

	procinfo_type *p;
	int nproc, i;
	int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};

	size_t size = 0;

	/* Call sysctl with a NULL buffer as a dry run. */
	if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0) {
		perror("Failure calling sysctl");
		return FALSE;
	}
	/* Allocate a buffer based on previous results of sysctl. */
	kprocs = (struct kinfo_proc *)alloca(size);
	if (kprocs == NULL) {
		perror("mem_alloca");
		return FALSE;
	}
	/* Call sysctl again with the new buffer. */
	if (sysctl(mib, 4, kprocs, &size, NULL, 0) < 0) {
		perror("Failure calling sysctl");
		return FALSE;
	}

	nproc = size / sizeof(struct kinfo_proc);

	for (i = 0; i < nproc; i++, kprocs++) {
		mach_port_t task;
		unsigned int status = kprocs->kp_proc.p_stat;

		if (status == SIDL || status == SZOMB)
			continue;

		p = malloc(sizeof(procinfo_type));
		if (!p) {
			perror("mem_malloc");
			continue;
		}
		strncpy(p->name, kprocs->kp_proc.p_comm, 15);
		p->name[15] = '\0';

		p->number = kprocs->kp_proc.p_pid;

		LL_Push(procs, (void *)p);

		/* Normal user can't get tasks for processes owned by root. */
		if (kprocs->kp_eproc.e_pcred.p_ruid == 0)
			continue;

		/* Get the memory data for each pid from Mach. */
		if (task_for_pid(mach_task_self(), kprocs->kp_proc.p_pid, &task) == KERN_SUCCESS) {
			task_basic_info_data_t info;
			mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;

			if (task_info(task, TASK_BASIC_INFO, (task_info_t) & info, &count) == KERN_SUCCESS) {
				p->totl = (unsigned long)( /* info.virtual_size */ info.resident_size / 1024);
			}
		}
		else {
			/*
			 * This error pops up very often because of Mac OS X
			 * security fixes. It might pop up all of the time on
			 * an intel Mac. Basically, we cannot get many tasks
			 * unless we are root.
			 */
			/* perror("task_for_pid"); */
			p->totl = 0;
		}
	}

	kprocs -= i;

	return (TRUE);
}
/*
 * Return a Python tuple (user_time, kernel_time)
 */
static PyObject*
get_cpu_times(PyObject* self, PyObject* args)
{
    long pid;
    int err;
    unsigned int info_count = TASK_BASIC_INFO_COUNT;
    task_port_t task;  // = (task_port_t)NULL;
    time_value_t user_time, system_time;
    struct task_basic_info tasks_info;
    struct task_thread_times_info task_times;

    if (! PyArg_ParseTuple(args, "l", &pid)) {
        return NULL;
    }

    /*  task_for_pid() requires special privileges
     * "This function can be called only if the process is owned by the
     * procmod group or if the caller is root."
     * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html  */
    err = task_for_pid(mach_task_self(), pid, &task);
    if ( err == KERN_SUCCESS) {
        info_count = TASK_BASIC_INFO_COUNT;
        err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
        if (err != KERN_SUCCESS) {
                // errcode 4 is "invalid argument" (access denied)
                if (err == 4) {
                    return AccessDenied();
                }

                // otherwise throw a runtime error with appropriate error code
                return PyErr_Format(PyExc_RuntimeError,
                                   "task_info(TASK_BASIC_INFO) failed");
        }

        info_count = TASK_THREAD_TIMES_INFO_COUNT;
        err = task_info(task, TASK_THREAD_TIMES_INFO,
                        (task_info_t)&task_times, &info_count);
        if (err != KERN_SUCCESS) {
                // errcode 4 is "invalid argument" (access denied)
                if (err == 4) {
                    return AccessDenied();
                }
                return PyErr_Format(PyExc_RuntimeError,
                                   "task_info(TASK_BASIC_INFO) failed");
        }
    }

    else { // task_for_pid failed
        if (! pid_exists(pid) ) {
            return NoSuchProcess();
        }
        // pid exists, so return AccessDenied error since task_for_pid() failed
        return AccessDenied();
    }

    float user_t = -1.0;
    float sys_t = -1.0;
    user_time = tasks_info.user_time;
    system_time = tasks_info.system_time;

    time_value_add(&user_time, &task_times.user_time);
    time_value_add(&system_time, &task_times.system_time);

    user_t = (float)user_time.seconds + ((float)user_time.microseconds / 1000000.0);
    sys_t = (float)system_time.seconds + ((float)system_time.microseconds / 1000000.0);
    return Py_BuildValue("(dd)", user_t, sys_t);
}
/*
 * Return process threads
 */
static PyObject*
get_process_threads(PyObject* self, PyObject* args)
{
    long pid;
    int err, j, ret;
    kern_return_t kr;
    unsigned int info_count = TASK_BASIC_INFO_COUNT;
    mach_port_t task;
    struct task_basic_info tasks_info;
    thread_act_port_array_t thread_list;
    thread_info_data_t thinfo;
    thread_basic_info_t basic_info_th;
    mach_msg_type_number_t thread_count, thread_info_count;

    PyObject* retList = PyList_New(0);
    PyObject* pyTuple = NULL;

    // the argument passed should be a process id
    if (! PyArg_ParseTuple(args, "l", &pid)) {
        return NULL;
    }

    // task_for_pid() requires special privileges
    err = task_for_pid(mach_task_self(), pid, &task);
    if (err != KERN_SUCCESS) {
        if (! pid_exists(pid) ) {
            return NoSuchProcess();
        }
        return AccessDenied();
    }

    info_count = TASK_BASIC_INFO_COUNT;
    err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
    if (err != KERN_SUCCESS) {
        // errcode 4 is "invalid argument" (access denied)
        if (err == 4) {
            return AccessDenied();
        }
        // otherwise throw a runtime error with appropriate error code
        return PyErr_Format(PyExc_RuntimeError,
                            "task_info(TASK_BASIC_INFO) failed");
    }

    err = task_threads(task, &thread_list, &thread_count);
    if (err != KERN_SUCCESS) {
        return PyErr_Format(PyExc_RuntimeError, "task_threads() failed");
    }

    for (j = 0; j < thread_count; j++) {
        thread_info_count = THREAD_INFO_MAX;
        kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
                         (thread_info_t)thinfo, &thread_info_count);
        if (kr != KERN_SUCCESS) {
            return PyErr_Format(PyExc_RuntimeError, "thread_info() failed");
        }
        basic_info_th = (thread_basic_info_t)thinfo;
        // XXX - thread_info structure does not provide any process id;
        // the best we can do is assigning an incremental bogus value
        pyTuple = Py_BuildValue("Iff", j + 1,
                    (float)basic_info_th->user_time.microseconds / 1000000.0,
                    (float)basic_info_th->system_time.microseconds / 1000000.0
                  );
        PyList_Append(retList, pyTuple);
        Py_XDECREF(pyTuple);
    }

    ret = vm_deallocate(task, (vm_address_t)thread_list,
                        thread_count * sizeof(int));
    if (ret != KERN_SUCCESS) {
        printf("vm_deallocate() failed\n");
    }

    return retList;
}
Exemple #10
0
static kern_return_t it_stuff(task_t task, cpu_type_t* cputype, it_addr_bundle_t* addrs)
{
    // make the optimizer happy
    *cputype = 0; 

    // init the task info
    task_dyld_info_data_t   info = {0};
    mach_msg_type_number_t  count = TASK_DYLD_INFO_COUNT;
    if (task_info(task, TASK_DYLD_INFO, (task_info_t) &info, &count)) return tb_false;

    // read all image info
    union 
    {
        it_dyld_all_image_infos_t       data;
        it_dyld_all_image_infos_64_t    data64;

    } u;
    mach_vm_size_t data_size = sizeof(u);
    if (info.all_image_info_size < data_size) data_size = info.all_image_info_size;
    if (mach_vm_read_overwrite(task, info.all_image_info_addr, data_size, it_address_cast(&u), &data_size)) return tb_false;
    if (u.data.version <= 1) return tb_false;

    // read mach header
#if defined(TB_ARCH_x86) || defined(TB_ARCH_x64) || defined(TB_ARCH_ARM64)
    tb_bool_t proc64 = u.data64.dyldImageLoadAddress > 0? tb_true : tb_false;
#else
    tb_bool_t proc64 = tb_false;
#endif 
    tb_trace_d("proc64: %p", proc64);   
    struct mach_header  mach_hdr = {0};
    mach_vm_address_t   dyldImageLoadAddress = proc64? u.data64.dyldImageLoadAddress : u.data.dyldImageLoadAddress;
    if (mach_vm_read_overwrite(task, dyldImageLoadAddress, (mach_vm_size_t)sizeof(mach_hdr), it_address_cast(&mach_hdr), &data_size)) return tb_false;

    // swap?
    tb_bool_t               swap = (mach_hdr.magic == MH_CIGAM || mach_hdr.magic == MH_CIGAM_64)? tb_true : tb_false;
    tb_trace_d("swap: %u", swap);

    // save sputype
    *cputype = it_swap_u32(mach_hdr.cputype);

    // read cmds
    mach_vm_size_t          sizeofcmds = it_swap_u32(mach_hdr.sizeofcmds);
    struct load_command*    cmds = malloc(sizeofcmds);
    tb_bool_t               mh64 = (mach_hdr.magic == MH_MAGIC_64 || mach_hdr.magic == MH_CIGAM_64)? tb_true : tb_false;
    tb_trace_d("mh64: %u", mh64);   
    if (mach_vm_read_overwrite(task, dyldImageLoadAddress + (mh64 ? sizeof(struct mach_header_64) : sizeof(struct mach_header)), (mach_vm_size_t)sizeofcmds, it_address_cast(cmds), &sizeofcmds)) return tb_false;

    // read symtab
    mach_vm_address_t       slide;
    it_symtab_bundle_t      symtab;
    tb_size_t               nlist_size = mh64 ? sizeof(struct nlist_64) : sizeof(struct nlist);
    if (!it_find_symtab_addrs(dyldImageLoadAddress, mach_hdr.ncmds, sizeofcmds, cmds, swap, nlist_size, &symtab, &slide)) return tb_false;

    // read strs & syms
    tb_char_t*      strs = malloc(symtab.strsize);
    tb_pointer_t    syms = malloc(symtab.nsyms * nlist_size);
    if (mach_vm_read_overwrite(task, symtab.straddr, (mach_vm_size_t)(symtab.strsize), it_address_cast(strs), &data_size)) return tb_false;
    if (mach_vm_read_overwrite(task, symtab.symaddr, (mach_vm_size_t)(symtab.nsyms * nlist_size), it_address_cast(syms), &data_size)) return tb_false;

    // read address
    memset(addrs, 0, sizeof(*addrs));
    if (mh64) 
    {
        struct nlist_64 const* nl = syms;
        while (symtab.nsyms--) 
        {
            tb_uint32_t strx = (tb_uint32_t) it_swap_u32(nl->n_un.n_strx);
            tb_assert(strx < symtab.strsize);
            it_handle_sym(strs + strx, symtab.strsize - strx, (mach_vm_address_t) it_swap_u64(nl->n_value) + slide, addrs);
            nl++;
        }
    } 
    else 
    {
        struct nlist const* nl = syms;
        while (symtab.nsyms--)
        {
            tb_uint32_t strx = it_swap_u32(nl->n_un.n_strx);
            tb_assert(strx < symtab.strsize);
            it_handle_sym(strs + strx, symtab.strsize - strx, (mach_vm_address_t) it_swap_u32(nl->n_value) + slide, addrs);
            nl++;
        }
    }
    tb_assert(addrs->dlopen);
    tb_assert(addrs->syscall);

    // free
    if (cmds) free(cmds);
    if (strs) free(strs);
    if (syms) free(syms);

    // ok
    return tb_true;
}
Exemple #11
0
static void encode(struct rvce_encoder *enc)
{
	int i;
	unsigned luma_offset, chroma_offset;

	task_info(enc, 0x00000003);

	RVCE_BEGIN(0x05000001); // context buffer
	RVCE_READWRITE(enc->cpb.res->cs_buf, enc->cpb.res->domains); // encodeContextAddressHi
	RVCE_CS(0x00000000); // encodeContextAddressLo
	RVCE_END();

	RVCE_BEGIN(0x05000004); // video bitstream buffer
	RVCE_WRITE(enc->bs_handle, RADEON_DOMAIN_GTT); // videoBitstreamRingAddressHi
	RVCE_CS(0x00000000); // videoBitstreamRingAddressLo
	RVCE_CS(enc->bs_size); // videoBitstreamRingSize
	RVCE_END();

	RVCE_BEGIN(0x03000001); // encode
	RVCE_CS(0x00000000); // insertHeaders
	RVCE_CS(0x00000000); // pictureStructure
	RVCE_CS(enc->bs_size); // allowedMaxBitstreamSize
	RVCE_CS(0x00000000); // forceRefreshMap
	RVCE_CS(0x00000000); // insertAUD
	RVCE_CS(0x00000000); // endOfSequence
	RVCE_CS(0x00000000); // endOfStream
	RVCE_READ(enc->handle, RADEON_DOMAIN_VRAM); // inputPictureLumaAddressHi
	RVCE_CS(enc->luma->level[0].offset); // inputPictureLumaAddressLo
	RVCE_READ(enc->handle, RADEON_DOMAIN_VRAM); // inputPictureChromaAddressHi
	RVCE_CS(enc->chroma->level[0].offset); // inputPictureChromaAddressLo
	RVCE_CS(align(enc->luma->npix_y, 16)); // encInputFrameYPitch
	RVCE_CS(enc->luma->level[0].pitch_bytes); // encInputPicLumaPitch
	RVCE_CS(enc->chroma->level[0].pitch_bytes); // encInputPicChromaPitch
	RVCE_CS(0x00000000); // encInputPic(Addr|Array)Mode
	RVCE_CS(0x00000000); // encInputPicTileConfig
	RVCE_CS(enc->pic.picture_type); // encPicType
	RVCE_CS(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR); // encIdrFlag
	RVCE_CS(0x00000000); // encIdrPicId
	RVCE_CS(0x00000000); // encMGSKeyPic
	RVCE_CS(!enc->pic.not_referenced); // encReferenceFlag
	RVCE_CS(0x00000000); // encTemporalLayerIndex
	RVCE_CS(0x00000000); // num_ref_idx_active_override_flag
	RVCE_CS(0x00000000); // num_ref_idx_l0_active_minus1
	RVCE_CS(0x00000000); // num_ref_idx_l1_active_minus1

	i = enc->pic.frame_num - enc->pic.ref_idx_l0;
	if (i > 1 && enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P) {
		RVCE_CS(0x00000001); // encRefListModificationOp
		RVCE_CS(i - 1);      // encRefListModificationNum
	} else {
		RVCE_CS(0x00000000); // encRefListModificationOp
		RVCE_CS(0x00000000); // encRefListModificationNum
	}

	for (i = 0; i < 3; ++i) {
		RVCE_CS(0x00000000); // encRefListModificationOp
		RVCE_CS(0x00000000); // encRefListModificationNum
	}
	for (i = 0; i < 4; ++i) {
		RVCE_CS(0x00000000); // encDecodedPictureMarkingOp
		RVCE_CS(0x00000000); // encDecodedPictureMarkingNum
		RVCE_CS(0x00000000); // encDecodedPictureMarkingIdx
		RVCE_CS(0x00000000); // encDecodedRefBasePictureMarkingOp
		RVCE_CS(0x00000000); // encDecodedRefBasePictureMarkingNum
	}

	// encReferencePictureL0[0]
	RVCE_CS(0x00000000); // pictureStructure
	if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P ||
	   enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) {
		struct rvce_cpb_slot *l0 = l0_slot(enc);
		rvce_frame_offset(enc, l0, &luma_offset, &chroma_offset);
		RVCE_CS(l0->picture_type); // encPicType
		RVCE_CS(l0->frame_num); // frameNumber
		RVCE_CS(l0->pic_order_cnt); // pictureOrderCount
		RVCE_CS(luma_offset); // lumaOffset
		RVCE_CS(chroma_offset); // chromaOffset
	} else {
		RVCE_CS(0x00000000); // encPicType
		RVCE_CS(0x00000000); // frameNumber
		RVCE_CS(0x00000000); // pictureOrderCount
		RVCE_CS(0xffffffff); // lumaOffset
		RVCE_CS(0xffffffff); // chromaOffset
	}

	// encReferencePictureL0[1]
	RVCE_CS(0x00000000); // pictureStructure
	RVCE_CS(0x00000000); // encPicType
	RVCE_CS(0x00000000); // frameNumber
	RVCE_CS(0x00000000); // pictureOrderCount
	RVCE_CS(0xffffffff); // lumaOffset
	RVCE_CS(0xffffffff); // chromaOffset

	// encReferencePictureL1[0]
	RVCE_CS(0x00000000); // pictureStructure
	if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) {
		struct rvce_cpb_slot *l1 = l1_slot(enc);
		rvce_frame_offset(enc, l1, &luma_offset, &chroma_offset);
		RVCE_CS(l1->picture_type); // encPicType
		RVCE_CS(l1->frame_num); // frameNumber
		RVCE_CS(l1->pic_order_cnt); // pictureOrderCount
		RVCE_CS(luma_offset); // lumaOffset
		RVCE_CS(chroma_offset); // chromaOffset
	} else {
		RVCE_CS(0x00000000); // encPicType
		RVCE_CS(0x00000000); // frameNumber
		RVCE_CS(0x00000000); // pictureOrderCount
		RVCE_CS(0xffffffff); // lumaOffset
		RVCE_CS(0xffffffff); // chromaOffset
	}

	rvce_frame_offset(enc, current_slot(enc), &luma_offset, &chroma_offset);
	RVCE_CS(luma_offset); // encReconstructedLumaOffset
	RVCE_CS(chroma_offset); // encReconstructedChromaOffset
	RVCE_CS(0x00000000); // encColocBufferOffset
	RVCE_CS(0x00000000); // encReconstructedRefBasePictureLumaOffset
	RVCE_CS(0x00000000); // encReconstructedRefBasePictureChromaOffset
	RVCE_CS(0x00000000); // encReferenceRefBasePictureLumaOffset
	RVCE_CS(0x00000000); // encReferenceRefBasePictureChromaOffset
	RVCE_CS(0x00000000); // pictureCount
	RVCE_CS(enc->pic.frame_num); // frameNumber
	RVCE_CS(enc->pic.pic_order_cnt); // pictureOrderCount
	RVCE_CS(0x00000000); // numIPicRemainInRCGOP
	RVCE_CS(0x00000000); // numPPicRemainInRCGOP
	RVCE_CS(0x00000000); // numBPicRemainInRCGOP
	RVCE_CS(0x00000000); // numIRPicRemainInRCGOP
	RVCE_CS(0x00000000); // enableIntraRefresh
	RVCE_END();
}
Exemple #12
0
static void encode(struct rvce_encoder *enc)
{
	int i;
	unsigned pitch = align(enc->luma->level[0].pitch_bytes, 128);
	unsigned vpitch = align(enc->luma->npix_y, 16);
	unsigned fsize = pitch * (vpitch + vpitch / 2);
	unsigned chroma_offset = pitch * vpitch;
	unsigned luma_offset;

	task_info(enc, 0x00000003);

	RVCE_BEGIN(0x05000001); // context buffer
	RVCE_READWRITE(enc->cpb.cs_handle, enc->cpb.domain); // encodeContextAddressHi
	RVCE_CS(0x00000000); // encodeContextAddressLo
	RVCE_END();

	RVCE_BEGIN(0x05000004); // video bitstream buffer
	RVCE_WRITE(enc->bs_handle, RADEON_DOMAIN_GTT); // videoBitstreamRingAddressHi
	RVCE_CS(0x00000000); // videoBitstreamRingAddressLo
	RVCE_CS(enc->bs_size); // videoBitstreamRingSize
	RVCE_END();

	RVCE_BEGIN(0x03000001); // encode
	RVCE_CS(0x00000000); // insertHeaders
	RVCE_CS(0x00000000); // pictureStructure
	RVCE_CS(enc->bs_size); // allowedMaxBitstreamSize
	RVCE_CS(0x00000000); // forceRefreshMap
	RVCE_CS(0x00000000); // insertAUD
	RVCE_CS(0x00000000); // endOfSequence
	RVCE_CS(0x00000000); // endOfStream
	RVCE_READ(enc->handle, RADEON_DOMAIN_VRAM); // inputPictureLumaAddressHi
	RVCE_CS(enc->luma->level[0].offset); // inputPictureLumaAddressLo
	RVCE_READ(enc->handle, RADEON_DOMAIN_VRAM); // inputPictureChromaAddressHi
	RVCE_CS(enc->chroma->level[0].offset); // inputPictureChromaAddressLo
	RVCE_CS(align(enc->luma->npix_y, 16)); // encInputFrameYPitch
	RVCE_CS(enc->luma->level[0].pitch_bytes); // encInputPicLumaPitch
	RVCE_CS(enc->chroma->level[0].pitch_bytes); // encInputPicChromaPitch
	RVCE_CS(0x00000000); // encInputPic(Addr|Array)Mode
	RVCE_CS(0x00000000); // encInputPicTileConfig
	RVCE_CS(enc->pic.picture_type); // encPicType
	RVCE_CS(enc->pic.picture_type == 3); // encIdrFlag
	RVCE_CS(0x00000000); // encIdrPicId
	RVCE_CS(0x00000000); // encMGSKeyPic
	RVCE_CS(0x00000001); // encReferenceFlag
	RVCE_CS(0x00000000); // encTemporalLayerIndex
	RVCE_CS(0x00000000); // num_ref_idx_active_override_flag
	RVCE_CS(0x00000000); // num_ref_idx_l0_active_minus1
	RVCE_CS(0x00000000); // num_ref_idx_l1_active_minus1
	for (i = 0; i < 4; ++i) {
		RVCE_CS(0x00000000); // encRefListModificationOp
		RVCE_CS(0x00000000); // encRefListModificationNum
	}
	for (i = 0; i < 4; ++i) {
		RVCE_CS(0x00000000); // encDecodedPictureMarkingOp
		RVCE_CS(0x00000000); // encDecodedPictureMarkingNum
		RVCE_CS(0x00000000); // encDecodedPictureMarkingIdx
	}
	for (i = 0; i < 4; ++i) {
		RVCE_CS(0x00000000); // encDecodedRefBasePictureMarkingOp
		RVCE_CS(0x00000000); // encDecodedRefBasePictureMarkingNum
	}

	RVCE_CS(0x00000000); // pictureStructure

	luma_offset = (2 * ((enc->pic.frame_num - 1) % 2) * fsize + 2 * fsize); 
	if (enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_IDR) { 
		RVCE_CS(0x00000000); // encPicType
		RVCE_CS(0x00000000); // frameNumber
		RVCE_CS(0x00000000); // pictureOrderCount
		RVCE_CS(0xffffffff); // lumaOffset
		RVCE_CS(0xffffffff); // chromaOffset
	}
	else if(enc->pic.picture_type == PIPE_H264_ENC_PICTURE_TYPE_P) {
		RVCE_CS(0x00000000); // encPicType
		RVCE_CS(enc->pic.frame_num - 1); // frameNumber
		RVCE_CS(enc->pic.frame_num - 1); // pictureOrderCount
		RVCE_CS(luma_offset); // lumaOffset
		RVCE_CS(chroma_offset + luma_offset); // chromaOffset
	}
	for (i = 0; i < 2; ++i) {
		RVCE_CS(0x00000000); // pictureStructure
		RVCE_CS(0x00000000); // encPicType
		RVCE_CS(0x00000000); // frameNumber
		RVCE_CS(0x00000000); // pictureOrderCount
		RVCE_CS(0xffffffff); // lumaOffset
		RVCE_CS(0xffffffff); // chromaOffset
	}
	
	luma_offset = (2 * (enc->pic.frame_num % 2) * fsize + 2 * fsize);
	RVCE_CS(luma_offset); // encReconstructedLumaOffset
	RVCE_CS(chroma_offset + luma_offset); // encReconstructedChromaOffset
	RVCE_CS(0x00000000); // encColocBufferOffset
	RVCE_CS(0x00000000); // encReconstructedRefBasePictureLumaOffset
	RVCE_CS(0x00000000); // encReconstructedRefBasePictureChromaOffset
	RVCE_CS(0x00000000); // encReferenceRefBasePictureLumaOffset
	RVCE_CS(0x00000000); // encReferenceRefBasePictureChromaOffset
	RVCE_CS(0x00000000); // pictureCount
	RVCE_CS(0x00000000); // frameNumber
	RVCE_CS(0x00000000); // pictureOrderCount
	RVCE_CS(0x00000000); // numIPicRemainInRCGOP
	RVCE_CS(0x00000000); // numPPicRemainInRCGOP
	RVCE_CS(0x00000000); // numBPicRemainInRCGOP
	RVCE_CS(0x00000000); // numIRPicRemainInRCGOP
	RVCE_CS(0x00000000); // enableIntraRefresh
	RVCE_END();
}
Exemple #13
0
void get_memusage(uint64_t * rss, uint64_t * vsz) {

#ifdef UNBIT
	*vsz = syscall(356);
#elif defined(__linux__)
	FILE *procfile;
	int i;
	procfile = fopen("/proc/self/stat", "r");
	if (procfile) {
		i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
		if (i != 2) {
			uwsgi_log("warning: invalid record in /proc/self/stat\n");
		}
		fclose(procfile);
	}
	*rss = *rss * uwsgi.page_size;
#elif defined (__sun__)
	psinfo_t info;
	int procfd;

	procfd = open("/proc/self/psinfo", O_RDONLY);
	if (procfd >= 0) {
		if (read(procfd, (char *) &info, sizeof(info)) > 0) {
			*rss = (uint64_t) info.pr_rssize * 1024;
			*vsz = (uint64_t) info.pr_size * 1024;
		}
		close(procfd);
	}

#elif defined(__APPLE__)
	/* darwin documentation says that the value are in pages, but they are bytes !!! */
	struct task_basic_info t_info;
	mach_msg_type_number_t t_size = sizeof(struct task_basic_info);

	if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
		*rss = t_info.resident_size;
		*vsz = t_info.virtual_size;
	}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
	kvm_t *kv;
	int cnt;

#if defined(__FreeBSD__)
	kv = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, NULL);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
	kv = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
#else
	kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
#endif
	if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)

		struct kinfo_proc *kproc;
		kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
		if (kproc && cnt > 0) {
			*vsz = kproc->ki_size;
			*rss = kproc->ki_rssize * uwsgi.page_size;
		}
#elif defined(UWSGI_NEW_OPENBSD)
		struct kinfo_proc *kproc; 
		kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc), &cnt);
		if (kproc && cnt > 0) { 
			*vsz = (kproc->p_vm_dsize + kproc->p_vm_ssize + kproc->p_vm_tsize) * uwsgi.page_size;
			*rss = kproc->p_vm_rssize * uwsgi.page_size;
		}
#elif defined(__NetBSD__) || defined(__OpenBSD__)
		struct kinfo_proc2 *kproc2;

		kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
		if (kproc2 && cnt > 0) {
#ifdef __OpenBSD__
			*vsz = (kproc2->p_vm_dsize + kproc2->p_vm_ssize + kproc2->p_vm_tsize) * uwsgi.page_size;
#else
			*vsz = kproc2->p_vm_msize * uwsgi.page_size;
#endif
			*rss = kproc2->p_vm_rssize * uwsgi.page_size;
		}
#endif

		kvm_close(kv);
	}
#elif defined(__HAIKU__)
	area_info ai;
	int32 cookie;

	*vsz = 0;
	*rss = 0;
	while (get_next_area_info(0, &cookie, &ai) == B_OK) {
		*vsz += ai.ram_size;
		if ((ai.protection & B_WRITE_AREA) != 0) {
			*rss += ai.ram_size;
		}
	}
#endif

}
TRI_process_info_t TRI_ProcessInfoSelf () {
  TRI_process_info_t result;
  struct rusage used;
  int res;

  memset(&result, 0, sizeof(result));
  result._scClkTck = 1000000;

  res = getrusage(RUSAGE_SELF, &used);

  if (res == 0) {
    result._minorPageFaults = used.ru_minflt;
    result._majorPageFaults = used.ru_majflt;

    result._systemTime = TRI_MicrosecondsTv(&used.ru_stime);
    result._userTime = TRI_MicrosecondsTv(&used.ru_utime);

    // ru_maxrss is the resident set size in kilobytes. need to multiply with 1024 to get the number of bytes
    result._residentSize = used.ru_maxrss * TRI_GETRUSAGE_MAXRSS_UNIT;
  }

#ifdef TRI_HAVE_MACH
  {
    kern_return_t rc;
    thread_array_t array;
    mach_msg_type_number_t count;

    rc = task_threads(mach_task_self(), &array, &count);

    if (rc == KERN_SUCCESS) {
      unsigned int i;

      result._numberThreads = count;

      for (i = 0;  i < count;  ++i) {
        mach_port_deallocate(mach_task_self(), array[i]);
      }

      vm_deallocate(mach_task_self(), (vm_address_t)array, sizeof(thread_t) * count);
    }
  }

  {
    kern_return_t rc;
    struct task_basic_info t_info;
    mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;

    rc = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
    if (rc == KERN_SUCCESS) {
      result._virtualSize = t_info.virtual_size;
      result._residentSize = t_info.resident_size;
    }
    else {
      result._virtualSize = 0;
      result._residentSize = 0;
    }


  }
#endif

  return result;
}
Exemple #15
0
void genProcessLibraries(const mach_port_t &task,
                         std::map<vm_address_t, std::string> &libraries) {
  struct task_dyld_info dyld_info;
  mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
  auto status =
      task_info(task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
  if (status != KERN_SUCCESS) {
    // Cannot request dyld information for pid (permissions, invalid).
    return;
  }

  // The info struct is a pointer to another process's virtual space.
  auto all_info = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
  uint64_t image_offset = (uint64_t)all_info;
  if (dyld_info.all_image_info_format != TASK_DYLD_ALL_IMAGE_INFO_64) {
    // Only support 64bit process images.
    return;
  }

  // Skip the 32-bit integer version field.
  image_offset += sizeof(uint32_t);
  uint32_t info_array_count = 0;
  // Read the process's 32-bit integer infoArrayCount (number of libraries).
  if (!readProcessMemory(task,
                         image_offset,
                         sizeof(uint32_t),
                         (vm_address_t)&info_array_count)) {
    return;
  }

  image_offset += sizeof(uint32_t);
  vm_address_t info_array = 0;
  // Read the process's infoArray address field.
  if (!readProcessMemory(task,
                         image_offset,
                         sizeof(vm_address_t),
                         (vm_address_t)&info_array)) {
    return;
  }

  // Loop over the array of dyld_image_info structures.
  // Read the process-mapped address and pointer to the library path.
  for (uint32_t i = 0; i < info_array_count; i++) {
    dyld_image_info image;
    if (!readProcessMemory(task,
                           info_array + (i * sizeof(struct dyld_image_info)),
                           sizeof(dyld_image_info),
                           (vm_address_t)&image)) {
      return;
    }

    // It's possible to optimize for smaller reads by chucking the memory reads.
    char path[PATH_MAX] = {0};
    if (!readProcessMemory(task,
                           (vm_address_t)image.imageFilePath,
                           PATH_MAX,
                           (vm_address_t)&path)) {
      continue;
    }

    // Keep the process-mapped address as the library index.
    libraries[(vm_address_t)image.imageLoadAddress] = path;
  }
}
Exemple #16
0
// rsize and dirty_size is not adjusted for dyld shared cache and multiple __LINKEDIT segment, as in vmmap. In practice, dirty_size doesn't differ much but rsize may. There is performance penalty for the adjustment. Right now, only use the dirty_size.
void 
MachVMMemory::GetRegionSizes(task_t task, mach_vm_size_t &rsize, mach_vm_size_t &dirty_size)
{
#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22
    
    task_vm_info_data_t vm_info;
    mach_msg_type_number_t info_count;
    kern_return_t kr;
    
    info_count = TASK_VM_INFO_COUNT;
#ifdef TASK_VM_INFO_PURGEABLE
    kr = task_info(task, TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &info_count);
#else
    kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count);
#endif
    if (kr == KERN_SUCCESS)
        dirty_size = vm_info.internal;
    
#else
    mach_vm_address_t address = 0;
    mach_vm_size_t size;
    kern_return_t err = 0;
    unsigned nestingDepth = 0;
    mach_vm_size_t pages_resident = 0;
    mach_vm_size_t pages_dirtied = 0;
    
    while (1)
    {
        mach_msg_type_number_t count;
        struct vm_region_submap_info_64 info;
        
        count = VM_REGION_SUBMAP_INFO_COUNT_64;
        err = mach_vm_region_recurse(task, &address, &size, &nestingDepth, (vm_region_info_t)&info, &count);
        if (err == KERN_INVALID_ADDRESS)
        {
            // It seems like this is a good break too.
            break;
        }
        else if (err)
        {
            mach_error("vm_region",err);
            break; // reached last region
        }
        
        bool should_count = true;
        if (info.is_submap)
        { // is it a submap?
            nestingDepth++;
            should_count = false;
        }
        else
        {
            // Don't count malloc stack logging data in the TOTAL VM usage lines.
            if (info.user_tag == VM_MEMORY_ANALYSIS_TOOL)
                should_count = false;
            
            address = address+size;
        }
        
        if (should_count)
        {
            pages_resident += info.pages_resident;
            pages_dirtied += info.pages_dirtied;
        }
    }
    
    vm_size_t pagesize = PageSize (task);
    rsize = pages_resident * pagesize;
    dirty_size = pages_dirtied * pagesize;
    
#endif
}
JNIEXPORT jlong JNICALL
Java_com_sun_management_UnixOperatingSystem_getCommittedVirtualMemorySize
  (JNIEnv *env, jobject mbean)
{
#ifdef __solaris__
    psinfo_t psinfo;
    ssize_t result;
    size_t remaining;
    char* addr;
    int fd;

    fd = JVM_Open("/proc/self/psinfo", O_RDONLY, 0);
    if (fd < 0) {
        throw_internal_error(env, "Unable to open /proc/self/psinfo");
        return -1;
    }

    addr = (char *)&psinfo;
    for (remaining = sizeof(psinfo_t); remaining > 0;) {
        result = JVM_Read(fd, addr, remaining);
        if (result < 0) {
            JVM_Close(fd);
            throw_internal_error(env, "Unable to read /proc/self/psinfo");
            return -1;
        }
        remaining -= result;
        addr += result;
    }

    JVM_Close(fd);
    return (jlong) psinfo.pr_size * 1024;
#elif defined(__linux__)
    FILE *fp;
    unsigned long vsize = 0;

    if ((fp = fopen("/proc/self/stat", "r")) == NULL) {
        throw_internal_error(env, "Unable to open /proc/self/stat");
        return -1;
    }

    // Ignore everything except the vsize entry
    if (fscanf(fp, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %lu %*[^\n]\n", &vsize) == EOF) {
        throw_internal_error(env, "Unable to get virtual memory usage");
        fclose(fp);
        return -1;
    }

    fclose(fp);
    return (jlong)vsize;
#elif defined(__APPLE__)
    struct task_basic_info t_info;
    mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;

    kern_return_t res = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
    if (res != KERN_SUCCESS) {
        throw_internal_error(env, "task_info failed");
    }
    return t_info.virtual_size;
#else /* _ALLBSD_SOURCE */
    /*
     * XXXBSD: there's no way available to do it in FreeBSD, AFAIK.
     */
    // throw_internal_error(env, "Unimplemented in FreeBSD");
    return (64 * MB);
#endif
}
caddr_t get_process_info(struct system_info *si,
		struct process_select *sel, int x)

{
	register int 				i;
	register int 				total_procs;
	register int 				active_procs;
	register struct macos_proc 		**prefp;
	register struct macos_proc 		*pp;
	register struct kinfo_proc		*pp2;
	register struct kinfo_proc		**prefp2;
	register struct thread_basic_info 	*thread;

	/*
	 * these are copied out of sel for speed
	 */

	int show_idle;
	int show_system;
	int show_uid;
	int show_command;

	kproc_list = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nproc);

	if(nproc > onproc)
		{
		proc_list = (struct macos_proc*)realloc(proc_list, sizeof(struct macos_proc) * nproc);
		proc_ref = (struct macos_proc **)realloc(proc_ref, sizeof(struct macos_proc *) * (onproc = nproc));
		}

	if(proc_ref == NULL || proc_list == NULL || kproc_list == NULL)
		{
		puke("error:  out of memory (%s)", strerror(errno));
		return(NULL);
		}

	/*
	 * now, our task is to build the array of information we
	 * need to function correctly.  This involves setting a pointer
	 * to each real kinfo_proc structure returned by kvm_getprocs()
	 * in addition to getting the mach information for each of
	 * those processes.
	 */

	for(pp2 = kproc_list, i = 0; i < nproc; pp2++, i++)
		{
		kern_return_t	rc;
		u_int		info_count = TASK_BASIC_INFO_COUNT;

		/*
		 * first, we set the pointer to the reference in
		 * the kproc list.
		 */
		
		proc_list[i].kproc = pp2;

		/*
		 * then, we load all of the task info for the process
		 */

		if(PP(pp2, p_stat) != SZOMB)
			{
			rc = task_for_pid(mach_task_self(), 
				PP(pp2, p_pid), 
				&(proc_list[i].the_task));

			if(rc != KERN_SUCCESS)
				{
				puke("error:  get task info for pid %d failed with rc = %d", PP(pp2, p_pid), rc);
				}

			/*
			 * load the task information
			 */

			rc = task_info(proc_list[i].the_task, TASK_BASIC_INFO, 
				(task_info_t)&(proc_list[i].task_info),
				&info_count);

			if(rc != KERN_SUCCESS)
				{
				puke("error:  couldn't get task info (%s); rc = %d", strerror(errno), rc);
				}

			/*
			 * load the thread summary information
			 */

			load_thread_info(&proc_list[i]);
			}
		}

	/* get a pointer to the states summary array */
	si->procstates = process_states;

	/* set up flags which define what we are going to select */
	show_idle = sel->idle;
	show_system = sel->system;
	show_uid = sel->uid != -1;
	show_command = sel->command != NULL;

	/* count up process states and get pointers to interesting procs */
	total_procs = 0;
	active_procs = 0;
	memset((char *)process_states, 0, sizeof(process_states));
	prefp = proc_ref;
	for(pp = proc_list, i = 0; i < nproc; pp++, i++)
		{
		/*
		 *  Place pointers to each valid proc structure in 
		 * proc_ref[].  Process slots that are actually in use 
		 * have a non-zero status field.  Processes with
		 * P_SYSTEM set are system processes---these get 
		 * ignored unless show_sysprocs is set.
		 */
		if(MPP(pp, p_stat) != 0 && 
				(show_system || ((MPP(pp, p_flag) & P_SYSTEM) == 0)))
			{
			total_procs++;
			process_states[(unsigned char) MPP(pp, p_stat)]++;
			if((MPP(pp, p_stat) != SZOMB) &&
					(show_idle || (MPP(pp, p_pctcpu) != 0) || 
			 		(MPP(pp, p_stat) == SRUN)) &&
					(!show_uid || MEP(pp, e_pcred.p_ruid) == (uid_t)sel->uid))
				{
				*prefp++ = pp;
				active_procs++;
				}
			}
		}
	
	/* 
	 * if requested, sort the "interesting" processes
	 */

	qsort((char *)proc_ref, active_procs, sizeof(struct macos_proc *), proc_compare);

	/* remember active and total counts */
	si->p_total = total_procs;
	si->p_active = pref_len = active_procs;

	/* pass back a handle */
	handle.next_proc = proc_ref;
	handle.remaining = active_procs;
	return((caddr_t)&handle);
}
 void MergeDispatcher::start_buffer()
 {
     LOG_DEBUG("[start_buffer]");
     dispatch_io_svc().post(MergeTask(task_info(), 
         boost::bind(&MergeDispatcher::handle_buffer, this, _1), merger_));
 }
Exemple #20
0
bool SysInfo::GetProcessInfo(task_t a_task)
{
	boolean_t		retval = FALSE;
	kern_return_t		error;
	struct kinfo_proc	kinfo;
	size_t			kinfosize;
	int			pid, mib[4];
	mach_msg_type_number_t	count;
	struct task_basic_info_64	ti;
	unsigned int vsize;
	
	mach_vm_address_t	address;
	mach_port_t		object_name;
	vm_region_top_info_data_t info;
	mach_vm_size_t		size;
	boolean_t split;
	char userName[9];
	std::vector<ProcessInfo>::iterator pInfoItem;

	error = pid_for_task(a_task, &pid);
	if (error != KERN_SUCCESS) return FALSE;
	
	kinfosize = sizeof(struct kinfo_proc);
	mib[0] = CTL_KERN;
	mib[1] = KERN_PROC;
	mib[2] = KERN_PROC_PID;
	mib[3] = pid;
	
	if (sysctl(mib, 4, &kinfo, &kinfosize, NULL, 0) == -1) {
		printf("%s(): Error in sysctl()", __FUNCTION__);
		retval = TRUE;
		goto RETURN;
	}
	
	if (kinfo.kp_proc.p_stat == 0) {
		retval = FALSE;
		goto RETURN;
	}
	
	count = TASK_BASIC_INFO_64_COUNT;
	error = task_info(a_task, TASK_BASIC_INFO_64, (task_info_t)&ti, &count);
	if (error != KERN_SUCCESS) {
		return FALSE;
	}
	
	vsize = ti.virtual_size;
	
	{
		struct passwd *pwd;
		
		setpwent();
		pwd = getpwuid(kinfo.kp_eproc.e_ucred.cr_uid);
		memset(userName, 0, 9);
		if (pwd != NULL) 
			snprintf(userName, 9, "%s", pwd->pw_name);
		endpwent();
	}

	{
		ProcessInfo temp;
		temp.pid = kinfo.kp_proc.p_pid;
		pInfoItem=std::find(m_pInfoList.begin(), m_pInfoList.end(), temp); 
		if(pInfoItem != m_pInfoList.end())
		{
			pInfoItem->prevTime = pInfoItem->curTime;
			pInfoItem->curTime += ti.user_time.seconds*1000+ti.user_time.microseconds;
			pInfoItem->curTime += ti.system_time.seconds*1000+ti.system_time.microseconds;
			pInfoItem->runTime = pInfoItem->curTime - pInfoItem->prevTime;
			m_nTotalTime += pInfoItem->runTime;
			pInfoItem->rSize = ti.resident_size;
			pInfoItem->vSize = vsize;
			pInfoItem->isDel = false;
		}
		else
		{
			ProcessInfo procInfo;
			procInfo.prevTime = 0;
			procInfo.curTime += ti.user_time.seconds*1000+ti.user_time.microseconds;
			procInfo.curTime += ti.system_time.seconds*1000+ti.system_time.microseconds;
			procInfo.runTime = procInfo.curTime;
			m_nTotalTime += procInfo.runTime;
			procInfo.pid = kinfo.kp_proc.p_pid;
			snprintf(procInfo.pName, 9, "%s", kinfo.kp_proc.p_comm);
			snprintf(procInfo.userName, 9, "%s", userName);
			procInfo.rSize = ti.resident_size;
			procInfo.vSize = vsize;
			procInfo.isDel = false;
			procInfo.isSys = false;
			m_pInfoList.push_back(procInfo);
		}
	}
	
RETURN:
	return retval;
}
Exemple #21
0
/*
 * Return a tuple of RSS and VMS memory usage.
 */
static PyObject*
get_memory_info(PyObject* self, PyObject* args)
{
    long pid;
    int err;
    unsigned int info_count = TASK_BASIC_INFO_COUNT;
    mach_port_t task;
    struct task_basic_info tasks_info;
    vm_region_basic_info_data_64_t  b_info;
    vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT;
    vm_size_t size;
    mach_port_t object_name;

    // the argument passed should be a process id
    if (! PyArg_ParseTuple(args, "l", &pid)) {
        return NULL;
    }

    /* task_for_pid() requires special privileges
     * "This function can be called only if the process is owned by the
     * procmod group or if the caller is root."
     * - http://developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_tips/chapter_5_section_19.html */
    err = task_for_pid(mach_task_self(), pid, &task);
    if ( err == KERN_SUCCESS) {
        info_count = TASK_BASIC_INFO_COUNT;
        err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, &info_count);
        if (err != KERN_SUCCESS) {
                if (err == 4) {
                    // errcode 4 is "invalid argument" (access denied)
                    return AccessDenied();
                }
                // otherwise throw a runtime error with appropriate error code
                return PyErr_Format(PyExc_RuntimeError,
                                    "task_info(TASK_BASIC_INFO) failed");
        }

        /* Issue #73 http://code.google.com/p/psutil/issues/detail?id=73
         * adjust the virtual memory size down to account for
         * shared memory that task_info.virtual_size includes w/every process
         */
        info_count = VM_REGION_BASIC_INFO_COUNT_64;
        err = vm_region_64(task, &address, &size, VM_REGION_BASIC_INFO,
            (vm_region_info_t)&b_info, &info_count, &object_name);
        if (err == KERN_SUCCESS) {
            if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) &&
                tasks_info.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE))
            {
                tasks_info.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
            }
        }
    }

    else {
        if (! pid_exists(pid) ) {
            return NoSuchProcess();
        }

        // pid exists, so return AccessDenied error since task_for_pid() failed
        return AccessDenied();
    }

    return Py_BuildValue("(ll)", tasks_info.resident_size, tasks_info.virtual_size);
}
Exemple #22
0
static RList *xnu_dbg_modules(RDebug *dbg) {
	struct task_dyld_info info;
	mach_msg_type_number_t count;
	kern_return_t kr;
	int size, info_array_count, info_array_size, i;
	ut64 info_array_address;
	void *info_array = NULL;
	void *header_data = NULL;
	char file_path[MAXPATHLEN];
	count = TASK_DYLD_INFO_COUNT;
	task_t task = pid_to_task (dbg->tid);
	ut64 addr, file_path_address;
	RDebugMap *mr = NULL;
	RList *list = NULL;

	kr = task_info (task, TASK_DYLD_INFO, (task_info_t) &info, &count);
	if (kr != KERN_SUCCESS)
		return NULL;

	if (info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_64) {
		DyldAllImageInfos64 all_infos;
		dbg->iob.read_at (dbg->iob.io, info.all_image_info_addr,
			(ut8*)&all_infos, sizeof (DyldAllImageInfos64));
		info_array_count = all_infos.info_array_count;
		info_array_size = info_array_count * DYLD_IMAGE_INFO_64_SIZE;
		info_array_address = all_infos.info_array;
	} else {
		DyldAllImageInfos32 all_info;
		dbg->iob.read_at (dbg->iob.io, info.all_image_info_addr,
			(ut8*)&all_info, sizeof (DyldAllImageInfos32));
		info_array_count = all_info.info_array_count;
		info_array_size = info_array_count * DYLD_IMAGE_INFO_32_SIZE;
		info_array_address = all_info.info_array;
	}

	if (info_array_address == 0) {
		return NULL;
	}

	info_array = malloc (info_array_size);
	if (!info_array) {
		eprintf ("Cannot allocate info_array_size %d\n", info_array_size);
		return NULL;
	}
	
	dbg->iob.read_at (dbg->iob.io, info_array_address,
			info_array, info_array_size);

	list = r_list_new ();
	for (i=0; i < info_array_count; i++) {
		if (info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_64) {
			DyldImageInfo64 * info = info_array + (i * DYLD_IMAGE_INFO_64_SIZE);
			addr = info->image_load_address;
			file_path_address = info->image_file_path;
		} else {
			DyldImageInfo32 * info = info_array + (i * DYLD_IMAGE_INFO_32_SIZE);
			addr = info->image_load_address;
			file_path_address = info->image_file_path;
		}
		dbg->iob.read_at (dbg->iob.io, file_path_address,
				(ut8*)file_path, MAXPATHLEN);
		//eprintf ("--> %d 0x%08"PFMT64x" %s\n", i, addr, file_path);
		size = mach0_size (dbg, addr);
		mr = r_debug_map_new (file_path, addr, addr+size, 7, 0);
		if (mr == NULL) {
			eprintf ("Cannot create r_debug_map_new\n");
			break;
		}
		mr->file = strdup (file_path);
		r_list_append (list, mr);
	}
	free (info_array);
	return list;
}
Exemple #23
0
void get_memusage() {

#ifdef UNBIT
	uwsgi.workers[uwsgi.mywid].vsz_size = syscall(356);
#elif defined(__linux__)
	FILE *procfile;
	int i;
	procfile = fopen("/proc/self/stat", "r");
	if (procfile) {
		i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", &uwsgi.workers[uwsgi.mywid].vsz_size, &uwsgi.workers[uwsgi.mywid].rss_size);
		if (i != 2) {
			fprintf(stderr, "warning: invalid record in /proc/self/stat\n");
		}
		fclose(procfile);
	}
	uwsgi.workers[uwsgi.mywid].rss_size = uwsgi.workers[uwsgi.mywid].rss_size * uwsgi.page_size;
#elif defined (__sun__)
	psinfo_t info;
	int procfd ;

	procfd = open("/proc/self/psinfo", O_RDONLY);
	if (procfd >= 0) {
		if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
			uwsgi.workers[uwsgi.mywid].rss_size = (uint64_t) info.pr_rssize * 1024 ;
			uwsgi.workers[uwsgi.mywid].vsz_size = (uint64_t) info.pr_size * 1024 ;
		}
		close(procfd);
	}
	
#elif defined( __APPLE__)
	/* darwin documentation says that the value are in pages, but they are bytes !!! */
	struct task_basic_info t_info;
	mach_msg_type_number_t t_size = sizeof(struct task_basic_info);

	if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t) & t_info, &t_size) == KERN_SUCCESS) {
		uwsgi.workers[uwsgi.mywid].rss_size = t_info.resident_size;
		uwsgi.workers[uwsgi.mywid].vsz_size = t_info.virtual_size;
	}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
	kvm_t *kv;
	int cnt;

	kv = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
	if (kv) {
#if defined(__FreeBSD__) || defined(__DragonFly__)

		struct kinfo_proc *kproc;
		kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
		if (kproc && cnt > 0) {
			uwsgi.workers[uwsgi.mywid].vsz_size = kproc->ki_size;
			uwsgi.workers[uwsgi.mywid].rss_size = kproc->ki_rssize * uwsgi.page_size;
		}
#elif defined(__NetBSD__)
		struct kinfo_proc2 *kproc2;
		
		kproc2 = kvm_getproc2(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc2), &cnt);
		if (kproc2 && cnt > 0) {
			uwsgi.workers[uwsgi.mywid].vsz_size = kproc2->p_vm_msize * uwsgi.page_size;
			uwsgi.workers[uwsgi.mywid].rss_size = kproc2->p_vm_rssize * uwsgi.page_size;
		}
#endif

		kvm_close(kv);
	}

#endif
}
JNIEXPORT jdouble JNICALL
Java_com_sun_management_UnixOperatingSystem_getProcessCpuLoad
(JNIEnv *env, jobject dummy)
{
    // This code is influenced by the darwin top source

    struct task_basic_info_64 task_info_data;
    struct task_thread_times_info thread_info_data;
    struct timeval user_timeval, system_timeval, task_timeval;
    struct timeval now;
    mach_port_t task = mach_task_self();
    kern_return_t kr;

    static jlong last_task_time = 0;
    static jlong last_time      = 0;

    mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT;
    kr = task_info(task,
            TASK_THREAD_TIMES_INFO,
            (task_info_t)&thread_info_data,
            &thread_info_count);
    if (kr != KERN_SUCCESS) {
        // Most likely cause: |task| is a zombie.
        return -1;
    }

    mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
    kr = task_info(task,
            TASK_BASIC_INFO_64,
            (task_info_t)&task_info_data,
            &count);
    if (kr != KERN_SUCCESS) {
        // Most likely cause: |task| is a zombie.
        return -1;
    }

    /* Set total_time. */
    // thread info contains live time...
    TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval);
    TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval);
    timeradd(&user_timeval, &system_timeval, &task_timeval);

    // ... task info contains terminated time.
    TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval);
    TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval);
    timeradd(&user_timeval, &task_timeval, &task_timeval);
    timeradd(&system_timeval, &task_timeval, &task_timeval);

    if (gettimeofday(&now, NULL) < 0) {
       return -1;
    }
    jint ncpus      = JVM_ActiveProcessorCount();
    jlong time      = TIME_VALUE_TO_MICROSECONDS(now) * ncpus;
    jlong task_time = TIME_VALUE_TO_MICROSECONDS(task_timeval);

    if ((last_task_time == 0) || (last_time == 0)) {
        // First call, just set the last values.
        last_task_time = task_time;
        last_time      = time;
        // return 0 since we have no data, not -1 which indicates error
        return 0;
    }

    jlong task_time_delta = task_time - last_task_time;
    jlong time_delta      = time - last_time;
    if (time_delta == 0) {
        return -1;
    }

    jdouble cpu = (jdouble) task_time_delta / time_delta;

    last_task_time = task_time;
    last_time      = time;

    return cpu;
 }
/* On Mac OS X, the only way to get enough information is to become root. Pretty frustrating!*/
int run_get_dynamic_proc_info(pid_t pid, RunProcDyn *rpd)
{
	task_t task;
	kern_return_t error;
	mach_msg_type_number_t count;
	thread_array_t thread_table;
	thread_basic_info_t thi;
	thread_basic_info_data_t thi_data;
	unsigned table_size;
	struct task_basic_info ti;

	error = task_for_pid(mach_task_self(), pid, &task);
	if (error != KERN_SUCCESS) {
		/* fprintf(stderr, "++ Probably you have to set suid or become root.\n"); */
		rpd->rss = rpd->vsize = 0;
		rpd->utime = rpd->stime = 0;
		return 0;
	}
	count = TASK_BASIC_INFO_COUNT;
	error = task_info(task, TASK_BASIC_INFO, (task_info_t)&ti, &count);
	assert(error == KERN_SUCCESS);
	{ /* adapted from ps/tasks.c */
		vm_region_basic_info_data_64_t b_info;
        vm_address_t address = GLOBAL_SHARED_TEXT_SEGMENT;
        vm_size_t size;
        mach_port_t object_name;
        count = VM_REGION_BASIC_INFO_COUNT_64;
        error = vm_region_64(task, &address, &size, VM_REGION_BASIC_INFO,
							 (vm_region_info_t)&b_info, &count, &object_name);
		if (error == KERN_SUCCESS) {
			if (b_info.reserved && size == (SHARED_TEXT_REGION_SIZE) &&
                ti.virtual_size > (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE))
			{
				ti.virtual_size -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
			}
		}
		rpd->rss = ti.resident_size;
		rpd->vsize = ti.virtual_size;
	}
	{ /* calculate CPU times, adapted from top/libtop.c */
		unsigned i;
		rpd->utime = ti.user_time.seconds + ti.user_time.microseconds * 1e-6;
		rpd->stime = ti.system_time.seconds + ti.system_time.microseconds * 1e-6;
		error = task_threads(task, &thread_table, &table_size);
		assert(error == KERN_SUCCESS);
		thi = &thi_data;
		for (i = 0; i != table_size; ++i) {
			count = THREAD_BASIC_INFO_COUNT;
			error = thread_info(thread_table[i], THREAD_BASIC_INFO, (thread_info_t)thi, &count);
			assert(error == KERN_SUCCESS);
			if ((thi->flags & TH_FLAGS_IDLE) == 0) {
				rpd->utime += thi->user_time.seconds + thi->user_time.microseconds * 1e-6;
				rpd->stime += thi->system_time.seconds + thi->system_time.microseconds * 1e-6;
			}
			if (task != mach_task_self()) {
				error = mach_port_deallocate(mach_task_self(), thread_table[i]);
				assert(error == KERN_SUCCESS);
			}
		}
		error = vm_deallocate(mach_task_self(), (vm_offset_t)thread_table, table_size * sizeof(thread_array_t));
		assert(error == KERN_SUCCESS);
	}
	mach_port_deallocate(mach_task_self(), task);
	return 0;
}
// This method should be incorporated into NSPR
static PRBool GetMemUsage(MemUsage *result)
{
  PRBool setResult = PR_FALSE;
#if defined(__linux)
  // Read /proc/<pid>/statm, and look at the first and second fields, which
  // report the program size and the number of resident pages for this process,
  // respectively.
 
  char buf[256];
  if (!sProcFP) {
    pid_t pid = getpid();
    snprintf(buf, sizeof(buf), "/proc/%d/statm", pid);
    sProcFP = fopen(buf, "rb");
  }
  if (sProcFP) {
    int vmsize, vmrss;

    int count = fscanf(sProcFP, "%d %d", &vmsize, &vmrss);
    rewind(sProcFP);

    if (count == 2) {
      static int ps = getpagesize();
      result->total = PRInt64(vmsize) * ps;
      result->resident = PRInt64(vmrss) * ps;
      setResult = PR_TRUE;
    }
  }
#elif defined(XP_WIN)
  // Use GetProcessMemoryInfo, which only works on WinNT and later.

  if (!sGetMemInfo) {
    sPSModule = LoadLibrary("psapi.dll");
    if (sPSModule) {
      sGetMemInfo = (GETPROCESSMEMORYINFO_FUNC)
          GetProcAddress(sPSModule, "GetProcessMemoryInfo");
      if (sGetMemInfo)
        sProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                               FALSE, GetCurrentProcessId());
      // Don't leave ourselves partially initialized.
      if (!sProcess)
        GetMemUsage_Shutdown();
    }
  }
  if (sGetMemInfo) {
    PROCESS_MEMORY_COUNTERS pmc;
    if (sGetMemInfo(sProcess, &pmc, sizeof(pmc))) {
      result->total = PRInt64(pmc.PagefileUsage);
      result->resident = PRInt64(pmc.WorkingSetSize);
      setResult = PR_TRUE;
    }
  }
#elif defined(XP_MACOSX)
  // Use task_info

  task_basic_info_data_t ti;
  mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
  kern_return_t error = task_info(mach_task_self(), TASK_BASIC_INFO,
                                  (task_info_t) &ti, &count);
  if (error == KERN_SUCCESS) {
    result->total = PRInt64(ti.virtual_size);
    result->resident = PRInt64(ti.resident_size);
    setResult = PR_TRUE;
  }
#endif
  return setResult;
}
Exemple #27
0
void
gum_darwin_enumerate_modules (mach_port_t task,
                              GumFoundModuleFunc func,
                              gpointer user_data)
{
  struct task_dyld_info info;
  mach_msg_type_number_t count;
  kern_return_t kr;
  gsize info_array_count, info_array_size, i;
  GumAddress info_array_address;
  gpointer info_array = NULL;
  gpointer header_data = NULL;
  gchar * file_path = NULL;
  gboolean carry_on = TRUE;

#if defined (HAVE_ARM) || defined (HAVE_ARM64)
  DyldInfo info_raw;
  count = DYLD_INFO_COUNT;
  kr = task_info (task, TASK_DYLD_INFO, (task_info_t) &info_raw, &count);
  if (kr != KERN_SUCCESS)
    goto beach;
  switch (count)
  {
    case DYLD_INFO_LEGACY_COUNT:
      info.all_image_info_addr = info_raw.info_legacy.all_image_info_addr;
      info.all_image_info_size = 0;
      info.all_image_info_format = TASK_DYLD_ALL_IMAGE_INFO_32;
      break;
    case DYLD_INFO_32_COUNT:
      info.all_image_info_addr = info_raw.info_32.all_image_info_addr;
      info.all_image_info_size = info_raw.info_32.all_image_info_size;
      info.all_image_info_format = info_raw.info_32.all_image_info_format;
      break;
    case DYLD_INFO_64_COUNT:
      info.all_image_info_addr = info_raw.info_64.all_image_info_addr;
      info.all_image_info_size = info_raw.info_64.all_image_info_size;
      info.all_image_info_format = info_raw.info_64.all_image_info_format;
      break;
    default:
      g_assert_not_reached ();
  }
#else
  count = TASK_DYLD_INFO_COUNT;
  kr = task_info (task, TASK_DYLD_INFO, (task_info_t) &info, &count);
  if (kr != KERN_SUCCESS)
    goto beach;
#endif

  if (info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_64)
  {
    DyldAllImageInfos64 * all_info;

    all_info = (DyldAllImageInfos64 *) gum_darwin_read (task,
        info.all_image_info_addr,
        sizeof (DyldAllImageInfos64),
        NULL);
    if (all_info == NULL)
      goto beach;
    info_array_count = all_info->info_array_count;
    info_array_size = info_array_count * DYLD_IMAGE_INFO_64_SIZE;
    info_array_address = all_info->info_array;
    g_free (all_info);
  }
  else
  {
    DyldAllImageInfos32 * all_info;

    all_info = (DyldAllImageInfos32 *) gum_darwin_read (task,
        info.all_image_info_addr,
        sizeof (DyldAllImageInfos32),
        NULL);
    if (all_info == NULL)
      goto beach;
    info_array_count = all_info->info_array_count;
    info_array_size = info_array_count * DYLD_IMAGE_INFO_32_SIZE;
    info_array_address = all_info->info_array;
    g_free (all_info);
  }

  if (info_array_address == 0)
    goto fallback;

  info_array =
      gum_darwin_read (task, info_array_address, info_array_size, NULL);

  for (i = 0; i != info_array_count && carry_on; i++)
  {
    GumAddress load_address, file_path_address;
    struct mach_header * header;
    guint8 * first_command, * p;
    guint cmd_index;
    GumMemoryRange dylib_range;
    gchar * name;
    GumModuleDetails details;

    if (info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_64)
    {
      DyldImageInfo64 * info = info_array + (i * DYLD_IMAGE_INFO_64_SIZE);
      load_address = info->image_load_address;
      file_path_address = info->image_file_path;
    }
    else
    {
      DyldImageInfo32 * info = info_array + (i * DYLD_IMAGE_INFO_32_SIZE);
      load_address = info->image_load_address;
      file_path_address = info->image_file_path;
    }

    header_data = gum_darwin_read (task,
        load_address,
        MAX_MACH_HEADER_SIZE,
        NULL);
    file_path = (gchar *) gum_darwin_read (task,
        file_path_address,
        2 * MAXPATHLEN,
        NULL);
    if (header_data == NULL || file_path == NULL)
      goto beach;

    header = (struct mach_header *) header_data;
    if (info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_64)
      first_command = header_data + sizeof (struct mach_header_64);
    else
      first_command = header_data + sizeof (struct mach_header);

    dylib_range.base_address = load_address;
    dylib_range.size = 4096;

    p = first_command;
    for (cmd_index = 0; cmd_index != header->ncmds; cmd_index++)
    {
      const struct load_command * lc = (struct load_command *) p;

      if (lc->cmd == GUM_LC_SEGMENT)
      {
        gum_segment_command_t * sc = (gum_segment_command_t *) lc;
        if (strcmp (sc->segname, "__TEXT") == 0)
        {
          dylib_range.size = sc->vmsize;
          break;
        }
      }

      p += lc->cmdsize;
    }

    name = g_path_get_basename (file_path);

    details.name = name;
    details.range = &dylib_range;
    details.path = file_path;

    carry_on = func (&details, user_data);

    g_free (name);

    g_free (file_path);
    file_path = NULL;
    g_free (header_data);
    header_data = NULL;
  }

  goto beach;

fallback:
  gum_darwin_enumerate_modules_slow (task, func, user_data);

beach:
  g_free (file_path);
  g_free (header_data);
  g_free (info_array);

  return;
}
Exemple #28
0
int main (int argc, char* argv[]) {
    
    mach_msg_type_number_t  actListCnt;
    thread_act_array_t      actList;
    double                  cpuTime;
    kern_return_t           kr;
    int                     i;
    char                    *procName;
    float                   scaledUsage;
    task_t                  task = 0;
    pid_t                   pid = -1;
    thread_basic_info_t     tbi;
    thread_basic_info_data_t tbiData;
    double                  waitSeconds = 0.0;
    struct timespec         tv;

    
    // Setup a Ctrl-C handler.
    //act.sa_handler = intHandler;
    //sigaction(SIGINT, &act, NULL);

    //
    // PARSE PARAMETERS
    //
    
    while ((i = getopt(argc, argv, "dn:p:vw:")) != -1) {
        
        switch (i) {

            case 'd':
                gFmpFormat = true;
                break;

            case 'h':
                print_usage();
                break;
            case 'n':
                procName = optarg;
                //printf ("Name: %s\n", procName);
                pid = get_pid_for_process(procName);
                break;

            case 'p':
                pid = atoi (optarg);
                break;

            case 'v':
                gVerbose = true;
                break;

            case 'w':
                //printf ("Wait: %s\n", argv[i+1]);
                waitSeconds = atof (optarg);
                
                if (waitSeconds <= 0.0)
                    waitSeconds = 0.0;
                if (waitSeconds > 0.0 && waitSeconds < 0.1)
                    waitSeconds = 0.1;
                break;

            default:
                printf ("Invalid arguments, please try again.\n");
                print_usage();
                exit(1);
                break;
        }
    }

    if (gVerbose) {
        print_verbose_info();
    }
    
    //printf ("PID: %i\n", pid);

    if (pid < 1) {
        printf ("No process found, please try again.\n");
        print_usage();
        return 1;
    }

    if (waitSeconds > 0.0) {
        /* Construct the timespec from the number of whole seconds...  */
        tv.tv_sec = (time_t) waitSeconds;
        /* ... and the remainder in nanoseconds.  */
        tv.tv_nsec = (long) ((waitSeconds - tv.tv_sec) * 1e+9);
    } else {
        // Default time if none specified.
        tv.tv_sec = (time_t) 1;
        tv.tv_nsec = 0;
    }
    
    //
    //  GET PROCESS INFO
    //
    
    task_basic_info_data_t basic_info;
    mach_msg_type_number_t count;

    // Get port for accessing system CPU stats.
	gHostPort = mach_host_self();
    
    do {

        // Need to load the task number?
        if (task == 0 && pid > 0) {
            if ((kr = task_for_pid(mach_task_self(), pid, &task)) != KERN_SUCCESS) {
                mach_error("processdetail", kr);
                perror ("Could not get Mach task for pid. Did you run with sudo?\n");
                exit (1);
            }
            
        }
        
        count = TASK_BASIC_INFO_COUNT;
        
        if ((kr = task_info(task, TASK_BASIC_INFO,
                            (task_info_t)&basic_info, &count)) != KERN_SUCCESS) {
                        
            if (gHasRunOnce && procName != NULL) {
                // We found the process originally, so we'll wait the regular interval and
                // see if the process restarts.
                gKeepRunning = nanosleep(&tv, NULL) == 0;
                if (!gKeepRunning) printf ("\n"); // Return after Ctrl-C
                
                pid = get_pid_for_process(procName);
                
                // Force the task number to be reloaded.
                task = 0;
                
                continue;
                
            } else {
                // Shouldn't happen unless process died in between getting pid and here.
                perror ("Process being monitored died!?\n");
                mach_error("processdetail", kr);
                exit(1);
            }
        }
        
        if (count != TASK_BASIC_INFO_COUNT) {
            fprintf(stderr, "size mismatch");
            exit(1);
        }
    
        // CPU STATS
        
        cpuTime = cpu_statistics();
        
        // NET STATS
        
        if (net_stats() != 0) {
            perror ("Error getting network stats");
            exit (1);
        }
        
         // There is a wait interval and this is the very first run?
        if (gHasRunOnce == false) {
            // Skip printing until we have a full interval.
            // We can then give difference between before & after.
            gHasRunOnce = true;
            
            // Update values but don't print.
            net_print_stats(false);
            
            gKeepRunning = nanosleep(&tv, NULL) == 0;
            if (!gKeepRunning) printf ("\n");
            continue;
        }

        //
        //  PRINT SYSTEM STATS
        //
        
        print_timestamp();
        
        cpu_print_statistics(cpuTime);
        
        net_print_stats(true);
        
        //
        //  PRINT PROCESS SPECIFIC STATS
        //
        
        if (gFmpFormat) {
            printf ("$pd.pid=%i;\n$pd.vmsize=%li;\n$pd.residentmemory=%li;\n", pid, basic_info.virtual_size,basic_info.resident_size);
        } else {
            printf ("%i, %li, %li, ", pid, basic_info.virtual_size,basic_info.resident_size);
            //printf("Suspend count: %d\n", basic_info.suspend_count);
        }
        
        task_events_info_data_t events_info;
        
        if ((kr = task_info(task, TASK_EVENTS_INFO,
                            (task_info_t)&events_info, &count)) != KERN_SUCCESS) {
            mach_error("processdetail", kr);
            exit(1);
        }
        if (count != TASK_EVENTS_INFO_COUNT) {
            fprintf(stderr, "size mismatch");
            exit(1);
        }
        
        if (gFmpFormat) {
            printf ("$pd.pagefaults=%d;\n$pd.pageins=%d;\n$pd.copyonwritefaults=%d;\n", events_info.faults, events_info.pageins, events_info.cow_faults);
        } else {
            //printf("Page faults: %d\n", events_info.faults);
            printf("%d, ", events_info.faults);
            //printf("Pageins: %d\n", events_info.pageins);
            printf("%d, ", events_info.pageins);
            //printf("Copy-on-write faults: %d\n", events_info.cow_faults);
            printf("%d, ", events_info.cow_faults);
            //printf("Messages sent: %d\n", events_info.messages_sent);
            //printf("Messages received: %d\n", events_info.messages_received);
            //printf("Mach system calls: %d\n", events_info.syscalls_mach);
            //printf("Unix system calls: %d\n", events_info.syscalls_unix);
            //printf("Context switches: %d\n", events_info.csw);
        }
        
        if (gFmpFormat) {
            switch (basic_info.policy) {
                case THREAD_STANDARD_POLICY:
                    printf("$pd.threadpolicy=Standard;\n");
                    break;
                case THREAD_TIME_CONSTRAINT_POLICY:
                    printf("$pd.threadpolicy=\"Time Constraint\";\n");
                    break;
                case THREAD_PRECEDENCE_POLICY:
                    printf("$pd.threadpolicy=Precendence;\n");
                    break;
                default:
                    printf("$pd.threadpolicy=Unknown;\n");
                    break;
            }
    
        } else {
            switch (basic_info.policy) {
                case THREAD_STANDARD_POLICY:
                    printf("Standard, ");
                    break;
                case THREAD_TIME_CONSTRAINT_POLICY:
                    printf("\"Time Constraint\", ");
                    break;
                case THREAD_PRECEDENCE_POLICY:
                    printf("Precendence, ");
                    break;
                default:
                    printf("Unknown, ");
                    break;
            }
        }

        kr = task_threads (task, &actList, &actListCnt);
        if (kr != KERN_SUCCESS) {
            fprintf(stderr, "task_threads failed");
            exit (1);
        }
        
        if (gFmpFormat) {
            printf ("$td.threadcount=%i;\n", actListCnt);
        } else {
            printf ("%i, ", actListCnt);
        }

        mach_msg_type_number_t threadInfoCnt;
        float cpuUsage;
        
        
        /*
        
         Never a pthread (!?) so this doesn't work.
        for (int i = 0; i < actListCnt; ++i) {
            pthread_t pt = pthread_from_mach_thread_np(actList[i]);
            if (pt) {
                name[0] = '\0';
                int rc = pthread_getname_np(pt, name, sizeof name);
                printf("mach thread %u: getname returned %d: %s\n", actList[i], rc, name);
            } else {
                printf("mach thread %u: no pthread found\n", actList[i]);
            }
        }
    */


        tbi = &tbiData;
        cpuUsage = 0.0;
        
        for (i = 0; i < actListCnt; i++) {
            threadInfoCnt = THREAD_BASIC_INFO_COUNT;
            kr = thread_info(
                             actList[i],                            //thread_act_t target_act
                             THREAD_BASIC_INFO,                     //thread_flavor_t flavor
                             (thread_info_t) tbi,                   //thread_info_t thread_info_out
                             &threadInfoCnt);                       //mach_msg_type_number_t *thread_info_outCnt

            
            cpuUsage += tbi->cpu_usage;
            //printf ("CPU Usage: %i\n", tbi->cpu_usage);
            scaledUsage = tbi->cpu_usage / (float)TH_USAGE_SCALE * 100.0;
            
            if (gFmpFormat) {
                printf ("$pd.threadcpu[%i]=%.2f;\n", i+1, scaledUsage);
            } else {
                printf ("%.2f, ", scaledUsage);
            }
        }

        if (gFmpFormat) {
            printf ("$pd.totalcpu=%.2f\n\n", cpuUsage / (float)TH_USAGE_SCALE * 100.0);
        } else {
            printf ("%.2f\n", cpuUsage / (float)TH_USAGE_SCALE * 100.0);
        }
        
        // If user is tailing the piped result we want them to see results quickly.
        fflush (stdout);
        
        // We've done the whole process at least once.
        gHasRunOnce = true;
        
        if (waitSeconds != 0.0) {
            gKeepRunning = nanosleep(&tv, NULL) == 0;
        } else {
            gKeepRunning = false;
        }
        
    } while (gKeepRunning);
    
    return 0;
    
}
Exemple #29
0
/** @name	getMemoryUsage
	@text	Get the current amount of memory used by MOAI and its subsystems. This will
			attempt to return reasonable estimates where exact values cannot be obtained.
			Some fields represent informational fields (i.e. are not double counted in the
			total, but present to assist debugging) and may be only available on certain
			platforms (e.g. Windows, etc). These fields begin with a '_' character.
 
	@out	table	usage		The breakdown of each subsystem's memory usage, in bytes. There is also a "total" field that contains the summed value.
*/
int MOAISim::_getMemoryUsage ( lua_State* L ) {
	
	float divisor = 1.0f;
	
	if( lua_type(L, 1) == LUA_TSTRING )
	{
		cc8* str = lua_tostring(L, 1);
		if( str[0] == 'k' || str[0] == 'K' )
			divisor = 1024.0f;
		else if( str[0] == 'm' || str[0] == 'M' )
			divisor = 1024.0f * 1024.0f;
		else if( str[0] == 'b' || str[0] == 'B' )
			divisor = 1.0f;
	}
	
	size_t total = 0;
	
	lua_newtable(L);
	
	size_t count;
	
	count = MOAILuaRuntime::Get().GetMemoryUsage ();
	lua_pushnumber(L, count / divisor);
	lua_setfield(L, -2, "lua");
	total += count;

	// This is informational only (i.e. don't double count with the previous field).
	// It doesn't actually seem to represent the real usage of lua, but maybe
	// someone is interested.
	lua_pushnumber ( L, lua_gc ( L, LUA_GCCOUNTB, 0 ) / divisor );
	lua_setfield ( L, -2, "_luagc_count" );
	
	count = MOAIGfxDevice::Get ().GetTextureMemoryUsage ();
	lua_pushnumber ( L, count / divisor );
	lua_setfield ( L, -2, "texture" );
	total += count;
	
#if defined(_WIN32)
    PROCESS_MEMORY_COUNTERS pmc;

    // Print the process identifier.
    if ( GetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) )
    {
		lua_pushnumber(L, pmc.PagefileUsage / divisor);
		lua_setfield(L, -2, "_sys_vs");
		lua_pushnumber(L, pmc.WorkingSetSize / divisor);
		lua_setfield(L, -2, "_sys_rss");
    }
#elif defined(__APPLE__) //&& defined(TARGET_IPHONE_SIMULATOR) 
	// Tricky undocumented mach polling of memory
	struct task_basic_info t_info;
	mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
	kern_return_t kr = task_info(mach_task_self(),
								 TASK_BASIC_INFO,
								 reinterpret_cast<task_info_t>(&t_info),
								 &t_info_count);
	// Most likely cause for failure: |task| is a zombie.
	if( kr == KERN_SUCCESS )
	{
		lua_pushnumber(L, t_info.virtual_size / divisor);
		lua_setfield(L, -2, "_sys_vs");
		lua_pushnumber(L, t_info.resident_size / divisor);
		lua_setfield(L, -2, "_sys_rss");
	}
#endif
	
	lua_pushnumber(L, total / divisor);
	lua_setfield(L, -2, "total");
	
	return 1;
}
Exemple #30
0
static int find_foreign_images(mach_port_t task,
                               struct foreign_image *images, size_t nimages,
                               char **error) {
    struct task_dyld_info tdi;
    mach_msg_type_number_t cnt = TASK_DYLD_INFO_COUNT;

    kern_return_t kr = task_info(task, TASK_DYLD_INFO, (void *) &tdi, &cnt);
    if (kr || cnt != TASK_DYLD_INFO_COUNT) {
        asprintf(error, "task_info(TASK_DYLD_INFO): kr=%d", kr);
        return SUBSTITUTE_ERR_MISC;
    }

    if (!tdi.all_image_info_addr || !tdi.all_image_info_size ||
        tdi.all_image_info_size > 1024 ||
        tdi.all_image_info_format > TASK_DYLD_ALL_IMAGE_INFO_64) {
        asprintf(error, "TASK_DYLD_INFO obviously malformed");
        return SUBSTITUTE_ERR_MISC;
    }

    char all_image_infos_buf[1024];

    cnt = tdi.all_image_info_size;
    mach_vm_size_t size;
    kr = mach_vm_read_overwrite(task, tdi.all_image_info_addr,
                                tdi.all_image_info_size,
                                (mach_vm_address_t) all_image_infos_buf, &size);
    if (kr || size != tdi.all_image_info_size) {
        asprintf(error, "mach_vm_read_overwrite(all_image_info): kr=%d", kr);
        return SUBSTITUTE_ERR_MISC;
    }

    bool is64 = tdi.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_64;
    const struct dyld_all_image_infos_32 *aii32 = (void *) all_image_infos_buf;
    const struct dyld_all_image_infos_64 *aii64 = (void *) all_image_infos_buf;

    #define FIELD(f) (is64 ? aii64->f : aii32->f)

    if (FIELD(version) < 2) {
        /* apparently we're on Leopard or something */
        asprintf(error, "dyld_all_image_infos version too low");
        return SUBSTITUTE_ERR_MISC;
    }

    /* If we are on the same shared cache with the same slide, then we can just
     * look up the symbols locally and don't have to do the rest of the
     * syscalls... not sure if this is any faster, but whatever. */
    if (FIELD(version) >= 13) {
        //const struct dyld_all_image_infos *local_aii = _dyld_get_all_image_infos();
        
        void* handle = dlopen("libSystem.B.dylib", 1);
        void* _dyld_get_all_image_infos = dlsym(handle, "_dyld_get_all_image_infos");
        struct dyld_all_image_infos* local_aii = ((struct dyld_all_image_infos* (*)())_dyld_get_all_image_infos)();
        
        if (local_aii->version >= 13 &&
            FIELD(sharedCacheSlide) == local_aii->sharedCacheSlide &&
            !memcmp(FIELD(sharedCacheUUID), local_aii->sharedCacheUUID, 16)) {
            return FFI_SHORT_CIRCUIT;
        }
        dlclose(handle);
    }


    uint64_t info_array_addr = FIELD(infoArray);
    uint32_t info_array_count = FIELD(infoArrayCount);
    size_t info_array_elm_size = (is64 ? sizeof(uint64_t) : sizeof(uint32_t)) * 3;

    #undef FIELD

    if (info_array_count > 2000) {
        asprintf(error, "unreasonable number of loaded libraries: %u",
                 info_array_count);
        return SUBSTITUTE_ERR_MISC;
    }
    size_t info_array_size = info_array_count * info_array_elm_size;
    void *info_array = malloc(info_array_count * info_array_elm_size);
    if (!info_array)
        return SUBSTITUTE_ERR_OOM;

    kr = mach_vm_read_overwrite(task, info_array_addr, info_array_size,
                                (mach_vm_address_t) info_array, &size);
    if (kr || size != info_array_size) {
        asprintf(error, "mach_vm_read_overwrite(info_array): kr=%d", kr);
        free(info_array);
        return SUBSTITUTE_ERR_MISC;
    }

    /* yay, slow file path reads! */

    void *info_array_ptr = info_array;
    size_t images_left = nimages;
    for (uint32_t i = 0; i < info_array_count; i++) {
        uint64_t load_address;
        uint64_t file_path;
        if (is64) {
            uint64_t *e = info_array_ptr;
            load_address = e[0];
            file_path = e[1];
        } else {
            uint32_t *e = info_array_ptr;
            load_address = e[0];
            file_path = e[1];
        }

        /* mach_vm_read_overwrite won't do partial copies, so... */

        char path_buf[MAXPATHLEN+1];
        size_t toread = MIN(MAXPATHLEN, -file_path & 0xfff);
        path_buf[toread] = '\0';
        kr = mach_vm_read_overwrite(task, file_path, toread,
                                    (mach_vm_address_t) path_buf, &size);
        if (kr) {
            /* printf("kr=%d <%p %p>\n", kr, (void *) file_path, path_buf); */
            continue;
        }
        if (strlen(path_buf) == toread && toread < MAXPATHLEN) {
            /* get the rest... */
            kr = mach_vm_read_overwrite(task, file_path + toread,
                                        MAXPATHLEN - toread,
                                        (mach_vm_address_t) path_buf + toread,
                                        &size);
            if (kr) {
                continue;
            }
            path_buf[MAXPATHLEN] = '\0';
        }

        for (size_t i = 0; i < nimages; i++) {
            if (!images[i].address &&
                !strcmp(path_buf, images[i].name)) {
                images[i].address = load_address;
                if (--images_left == 0) {
                    free(info_array);
                    return SUBSTITUTE_OK;
                }
            }
        }

        info_array_ptr += info_array_elm_size;
    }

    free(info_array);
    asprintf(error, "couldn't find libdyld or libpthread");
    return SUBSTITUTE_ERR_MISC;
}