+ case TASK_DYLD_INFO:
+ {
+ task_dyld_info_t info;
+
+ /*
+ * We added the format field to TASK_DYLD_INFO output. For
+ * temporary backward compatibility, accept the fact that
+ * clients may ask for the old version - distinquished by the
+ * size of the expected result structure.
+ */
+#define TASK_LEGACY_DYLD_INFO_COUNT \
+ offsetof(struct task_dyld_info, all_image_info_format)/sizeof(natural_t)
+
+ if (*task_info_count < TASK_LEGACY_DYLD_INFO_COUNT) {
+ error = KERN_INVALID_ARGUMENT;
+ break;
+ }
+
+ info = (task_dyld_info_t)task_info_out;
+ info->all_image_info_addr = task->all_image_info_addr;
+ info->all_image_info_size = task->all_image_info_size;
+
+ /* only set format on output for those expecting it */
+ if (*task_info_count >= TASK_DYLD_INFO_COUNT) {
+ info->all_image_info_format = task_has_64BitAddr(task) ?
+ TASK_DYLD_ALL_IMAGE_INFO_64 :
+ TASK_DYLD_ALL_IMAGE_INFO_32 ;
+ *task_info_count = TASK_DYLD_INFO_COUNT;
+ } else {
+ *task_info_count = TASK_LEGACY_DYLD_INFO_COUNT;
+ }
+ break;
+ }
+
+ case TASK_EXTMOD_INFO:
+ {
+ task_extmod_info_t info;
+ void *p;
+
+ if (*task_info_count < TASK_EXTMOD_INFO_COUNT) {
+ error = KERN_INVALID_ARGUMENT;
+ break;
+ }
+
+ info = (task_extmod_info_t)task_info_out;
+
+ p = get_bsdtask_info(task);
+ if (p) {
+ proc_getexecutableuuid(p, info->task_uuid, sizeof(info->task_uuid));
+ } else {
+ bzero(info->task_uuid, sizeof(info->task_uuid));
+ }
+ info->extmod_statistics = task->extmod_statistics;
+ *task_info_count = TASK_EXTMOD_INFO_COUNT;
+
+ break;
+ }
+
+ case TASK_KERNELMEMORY_INFO:
+ {
+ task_kernelmemory_info_t tkm_info;
+ ledger_amount_t credit, debit;
+
+ if (*task_info_count < TASK_KERNELMEMORY_INFO_COUNT) {
+ error = KERN_INVALID_ARGUMENT;
+ break;
+ }
+
+ tkm_info = (task_kernelmemory_info_t) task_info_out;
+ tkm_info->total_palloc = 0;
+ tkm_info->total_pfree = 0;
+ tkm_info->total_salloc = 0;
+ tkm_info->total_sfree = 0;
+
+ if (task == kernel_task) {
+ /*
+ * All shared allocs/frees from other tasks count against
+ * the kernel private memory usage. If we are looking up
+ * info for the kernel task, gather from everywhere.
+ */
+ task_unlock(task);
+
+ /* start by accounting for all the terminated tasks against the kernel */
+ tkm_info->total_palloc = tasks_tkm_private.alloc + tasks_tkm_shared.alloc;
+ tkm_info->total_pfree = tasks_tkm_private.free + tasks_tkm_shared.free;
+
+ /* count all other task/thread shared alloc/free against the kernel */
+ lck_mtx_lock(&tasks_threads_lock);
+
+ /* XXX this really shouldn't be using the function parameter 'task' as a local var! */
+ queue_iterate(&tasks, task, task_t, tasks) {
+ if (task == kernel_task) {
+ if (ledger_get_entries(task->ledger,
+ task_ledgers.tkm_private, &credit,
+ &debit) == KERN_SUCCESS) {
+ tkm_info->total_palloc += credit;
+ tkm_info->total_pfree += debit;
+ }
+ }
+ if (!ledger_get_entries(task->ledger,
+ task_ledgers.tkm_shared, &credit, &debit)) {
+ tkm_info->total_palloc += credit;
+ tkm_info->total_pfree += debit;
+ }
+ }
+ lck_mtx_unlock(&tasks_threads_lock);
+ } else {
+ if (!ledger_get_entries(task->ledger,
+ task_ledgers.tkm_private, &credit, &debit)) {
+ tkm_info->total_palloc = credit;
+ tkm_info->total_pfree = debit;
+ }
+ if (!ledger_get_entries(task->ledger,
+ task_ledgers.tkm_shared, &credit, &debit)) {
+ tkm_info->total_salloc = credit;
+ tkm_info->total_sfree = debit;
+ }
+ task_unlock(task);
+ }
+
+ *task_info_count = TASK_KERNELMEMORY_INFO_COUNT;
+ return KERN_SUCCESS;
+ }
+