2 * Copyright (c) 2009-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie the
54 * rights to redistribute these changes.
59 * utility for printing out zone structures
61 * With no arguments, prints information on all zone structures.
62 * With an argument, prints information only on those zones for
63 * which the given name is a substring of the zone's name.
64 * With a "-w" flag, calculates how much much space is allocated
65 * to zones but not currently in use.
68 #include <vm_statistics.h>
72 #include <mach/mach.h>
73 #include <mach_debug/mach_debug.h>
74 #include <mach/mach_error.h>
79 #include <malloc/malloc.h>
80 #include <Kernel/IOKit/IOKitDebug.h>
81 #include <Kernel/libkern/OSKextLibPrivate.h>
82 #include <IOKit/IOKitLib.h>
83 #include <IOKit/IOKitKeys.h>
84 #include <IOKit/kext/OSKext.h>
85 #include <CoreFoundation/CoreFoundation.h>
86 #include <CoreSymbolication/CoreSymbolication.h>
88 #define streql(a, b) (strcmp((a), (b)) == 0)
89 #define strneql(a, b, n) (strncmp((a), (b), (n)) == 0)
90 #define PRINTK(fmt, value) \
91 printf(fmt "K", (value) / 1024 ) /* ick */
93 static void usage(void);
94 static void printzone(mach_zone_name_t
*, task_zone_info_t
*);
95 static void colprintzone(mach_zone_name_t
*, task_zone_info_t
*);
96 static int find_deltas(mach_zone_name_t
*, task_zone_info_t
*, task_zone_info_t
*, char *, int, int);
97 static void colprintzoneheader(void);
98 static boolean_t
substr(const char *a
, size_t alen
, const char *b
, size_t blen
);
100 static int SortName(const void * left
, const void * right
);
101 static int SortSize(const void * left
, const void * right
);
102 static void PrintLarge(mach_memory_info_t
*wiredInfo
, unsigned int wiredInfoCnt
, int (*func
)(const void *, const void *), boolean_t column
);
104 static char *program
;
106 static pid_t pid
= 0;
107 static task_t task
= TASK_NULL
;
108 static boolean_t ShowPid
= FALSE
;
110 static boolean_t ShowDeltas
= FALSE
;
111 static boolean_t ShowWasted
= FALSE
;
112 static boolean_t ShowTotal
= FALSE
;
113 static boolean_t ShowLarge
= TRUE
;
114 static boolean_t SortZones
= FALSE
;
115 static boolean_t ColFormat
= TRUE
;
116 static boolean_t PrintHeader
= TRUE
;
118 static unsigned long long totalsize
= 0;
119 static unsigned long long totalused
= 0;
120 static unsigned long long totalsum
= 0;
121 static unsigned long long pidsum
= 0;
123 static int last_time
= 0;
125 static char *zname
= NULL
;
126 static size_t znamelen
= 0;
129 sigintr(__unused
int signum
)
137 fprintf(stderr
, "usage: %s [-w] [-s] [-c] [-h] [-t] [-d] [-l] [-L] [-p <pid>] [name]\n", program
);
142 main(int argc
, char **argv
)
144 mach_zone_name_t
*name
= NULL
;
145 unsigned int nameCnt
= 0;
146 task_zone_info_t
*info
= NULL
;
147 unsigned int infoCnt
= 0;
148 mach_memory_info_t
*wiredInfo
= NULL
;
149 unsigned int wiredInfoCnt
= 0;
150 task_zone_info_t
*max_info
= NULL
;
159 signal(SIGINT
, sigintr
);
161 program
= strrchr(argv
[0], '/');
167 for (i
= 1; i
< argc
; i
++) {
168 if (streql(argv
[i
], "-d"))
170 else if (streql(argv
[i
], "-t"))
172 else if (streql(argv
[i
], "-T"))
174 else if (streql(argv
[i
], "-w"))
176 else if (streql(argv
[i
], "-W"))
178 else if (streql(argv
[i
], "-l"))
180 else if (streql(argv
[i
], "-L"))
182 else if (streql(argv
[i
], "-s"))
184 else if (streql(argv
[i
], "-S"))
186 else if (streql(argv
[i
], "-c"))
188 else if (streql(argv
[i
], "-C"))
190 else if (streql(argv
[i
], "-H"))
192 else if (streql(argv
[i
], "-p")) {
195 pid
= atoi(argv
[i
+1]);
199 } else if (streql(argv
[i
], "--")) {
202 } else if (argv
[i
][0] == '-')
216 znamelen
= strlen(zname
);
230 kr
= task_for_pid(mach_task_self(), pid
, &task
);
231 if (kr
!= KERN_SUCCESS
) {
232 fprintf(stderr
, "%s: task_for_pid(%d) failed: %s (try running as root)\n",
233 program
, pid
, mach_error_string(kr
));
240 kr
= task_zone_info(task
, &name
, &nameCnt
, &info
, &infoCnt
);
241 if (kr
!= KERN_SUCCESS
) {
242 fprintf(stderr
, "%s: task_zone_info: %s\n",
243 program
, mach_error_string(kr
));
247 mach_zone_info_t
*zinfo
= NULL
;
249 kr
= mach_memory_info(mach_host_self(),
250 &name
, &nameCnt
, &zinfo
, &infoCnt
,
251 &wiredInfo
, &wiredInfoCnt
);
252 if (kr
!= KERN_SUCCESS
) {
253 fprintf(stderr
, "%s: mach_zone_info: %s\n",
254 program
, mach_error_string(kr
));
258 kr
= vm_allocate(mach_task_self(), (vm_address_t
*)&info
,
259 infoCnt
* sizeof *info
, VM_FLAGS_ANYWHERE
);
260 if (kr
!= KERN_SUCCESS
) {
261 fprintf(stderr
, "%s vm_allocate: %s\n",
262 program
, mach_error_string(kr
));
265 for (i
= 0; i
< infoCnt
; i
++) {
266 *(mach_zone_info_t
*)(info
+ i
) = zinfo
[i
];
267 info
[i
].tzi_caller_acct
= 0;
268 info
[i
].tzi_task_alloc
= 0;
269 info
[i
].tzi_task_free
= 0;
271 kr
= vm_deallocate(mach_task_self(), (vm_address_t
) zinfo
,
272 (vm_size_t
) (infoCnt
* sizeof *zinfo
));
273 if (kr
!= KERN_SUCCESS
) {
274 fprintf(stderr
, "%s: vm_deallocate: %s\n",
275 program
, mach_error_string(kr
));
280 if (nameCnt
!= infoCnt
) {
281 fprintf(stderr
, "%s: mach/task_zone_info: counts not equal?\n",
287 deltas
= (char *)malloc(infoCnt
);
288 max_info
= (task_zone_info_t
*)malloc((infoCnt
* sizeof *info
));
292 for (i
= 0; i
< nameCnt
-1; i
++)
293 for (j
= i
+1; j
< nameCnt
; j
++) {
294 unsigned long long wastei
, wastej
;
296 wastei
= (info
[i
].tzi_cur_size
-
297 (info
[i
].tzi_elem_size
*
299 wastej
= (info
[j
].tzi_cur_size
-
300 (info
[j
].tzi_elem_size
*
303 if (wastej
> wastei
) {
304 task_zone_info_t tinfo
;
305 mach_zone_name_t tname
;
318 must_print
= find_deltas(name
, info
, max_info
, deltas
, infoCnt
, first_time
);
323 colprintzoneheader();
325 for (i
= 0; i
< nameCnt
; i
++) {
328 colprintzone(&name
[i
], &info
[i
]);
330 printzone(&name
[i
], &info
[i
]);
335 if (ShowLarge
&& first_time
) {
336 PrintLarge(wiredInfo
, wiredInfoCnt
,
337 SortZones
? &SortSize
: &SortName
, ColFormat
);
342 if ((name
!= NULL
) && (nameCnt
!= 0)) {
343 kr
= vm_deallocate(mach_task_self(), (vm_address_t
) name
,
344 (vm_size_t
) (nameCnt
* sizeof *name
));
345 if (kr
!= KERN_SUCCESS
) {
346 fprintf(stderr
, "%s: vm_deallocate: %s\n",
347 program
, mach_error_string(kr
));
352 if ((info
!= NULL
) && (infoCnt
!= 0)) {
353 kr
= vm_deallocate(mach_task_self(), (vm_address_t
) info
,
354 (vm_size_t
) (infoCnt
* sizeof *info
));
355 if (kr
!= KERN_SUCCESS
) {
356 fprintf(stderr
, "%s: vm_deallocate: %s\n",
357 program
, mach_error_string(kr
));
362 if ((wiredInfo
!= NULL
) && (wiredInfoCnt
!= 0)) {
363 kr
= vm_deallocate(mach_task_self(), (vm_address_t
) wiredInfo
,
364 (vm_size_t
) (wiredInfoCnt
* sizeof *wiredInfo
));
365 if (kr
!= KERN_SUCCESS
) {
366 fprintf(stderr
, "%s: vm_deallocate: %s\n",
367 program
, mach_error_string(kr
));
372 if ((ShowWasted
||ShowTotal
) && PrintHeader
&& !ShowDeltas
) {
373 printf("TOTAL SIZE = %llu\n", totalsize
);
374 printf("TOTAL USED = %llu\n", totalused
);
376 printf("TOTAL WASTED = %llu\n", totalsize
- totalused
);
378 printf("TOTAL ALLOCS = %llu\n", totalsum
);
381 if (ShowDeltas
== FALSE
|| last_time
)
390 substr(const char *a
, size_t alen
, const char *b
, size_t blen
)
394 if (alen
> blen
) return FALSE
;
396 for (i
= 0; i
<= blen
- alen
; i
++)
397 if (strneql(a
, b
+i
, alen
))
404 printzone(mach_zone_name_t
*name
, task_zone_info_t
*info
)
406 unsigned long long used
, size
;
408 printf("%.*s zone:\n", (int)sizeof name
->mzn_name
, name
->mzn_name
);
409 printf("\tcur_size: %lluK bytes (%llu elements)\n",
410 info
->tzi_cur_size
/1024,
411 (info
->tzi_elem_size
== 0) ? 0 :
412 info
->tzi_cur_size
/info
->tzi_elem_size
);
413 printf("\tmax_size: %lluK bytes (%llu elements)\n",
414 info
->tzi_max_size
/1024,
415 (info
->tzi_elem_size
== 0) ? 0 :
416 info
->tzi_max_size
/info
->tzi_elem_size
);
417 printf("\telem_size: %llu bytes\n",
418 info
->tzi_elem_size
);
419 printf("\t# of elems: %llu\n",
421 printf("\talloc_size: %lluK bytes (%llu elements)\n",
422 info
->tzi_alloc_size
/1024,
423 (info
->tzi_elem_size
== 0) ? 0 :
424 info
->tzi_alloc_size
/info
->tzi_elem_size
);
425 if (info
->tzi_exhaustible
)
426 printf("\tEXHAUSTIBLE\n");
427 if (info
->tzi_collectable
)
428 printf("\tCOLLECTABLE\n");
429 if (ShowPid
&& info
->tzi_caller_acct
)
430 printf("\tCALLER ACCOUNTED\n");
432 pidsum
+= info
->tzi_task_alloc
- info
->tzi_task_free
;
433 printf("\tproc_alloc_size: %8dK bytes (%llu elements)\n",
434 (int)((info
->tzi_task_alloc
- info
->tzi_task_free
)/1024),
435 (info
->tzi_elem_size
== 0) ? 0 :
436 (info
->tzi_task_alloc
- info
->tzi_task_free
)/info
->tzi_elem_size
);
439 totalused
+= used
= info
->tzi_elem_size
* info
->tzi_count
;
440 totalsize
+= size
= info
->tzi_cur_size
;
441 printf("\t\t\t\t\tWASTED: %llu\n", size
- used
);
444 totalsum
+= info
->tzi_sum_size
;
445 printf("\t\t\t\t\tTOTAL: %llu\n", totalsum
);
447 printf("\t\t\t\t\tPID TOTAL: %llu\n", pidsum
);
452 colprintzone(mach_zone_name_t
*zone_name
, task_zone_info_t
*info
)
454 char *name
= zone_name
->mzn_name
;
456 unsigned long long used
, size
;
459 if (ShowWasted
|| ShowTotal
) {
462 for (j
= 0; j
< namewidth
- 1 && name
[j
]; j
++) {
463 if (name
[j
] == ' ') {
469 if (j
== namewidth
- 1) {
476 for (; j
< namewidth
; j
++) {
480 printf(" %6llu", info
->tzi_elem_size
);
481 PRINTK(" %10llu", info
->tzi_cur_size
);
482 if (info
->tzi_max_size
/ 1024 > 9999999) {
485 PRINTK(" %10llu", info
->tzi_max_size
);
487 printf(" %10llu", info
->tzi_cur_size
/ info
->tzi_elem_size
);
488 if (info
->tzi_max_size
/ 1024 >= 999999999) {
489 printf(" ----------");
491 printf(" %11llu", info
->tzi_max_size
/ info
->tzi_elem_size
);
493 printf(" %11llu", info
->tzi_count
);
494 PRINTK(" %5llu", info
->tzi_alloc_size
);
495 printf(" %6llu", info
->tzi_alloc_size
/ info
->tzi_elem_size
);
497 totalused
+= used
= info
->tzi_elem_size
* info
->tzi_count
;
498 totalsize
+= size
= info
->tzi_cur_size
;
499 totalsum
+= info
->tzi_sum_size
;
502 (info
->tzi_exhaustible
? 'X' : ' '),
503 (info
->tzi_caller_acct
? 'A' : ' '),
504 (info
->tzi_collectable
? 'C' : ' '));
506 PRINTK(" %8llu", size
- used
);
509 printf("%8dK", (int)((info
->tzi_task_alloc
- info
->tzi_task_free
)/1024));
512 if (info
->tzi_sum_size
< 1024)
513 printf(" %16lluB", info
->tzi_sum_size
);
515 PRINTK(" %16llu", info
->tzi_sum_size
);
521 colprintzoneheader(void)
526 printf("%s elem cur max cur max"
527 " cur alloc alloc %s%s\n",
528 (ShowWasted
||ShowTotal
)? "" : " ",
529 (ShowWasted
)? " ":"",
530 (ShowPid
) ? " PID" : "" );
531 printf("zone name%s size size size #elts #elts"
532 " inuse size count ", (ShowWasted
||ShowTotal
)? " " : " " );
538 printf(" Total Allocs");
539 printf("\n%s-------------------------------------------------------"
540 "-----------------------------------------------",
541 (ShowWasted
||ShowTotal
)? "" : "-------");
543 printf("----------");
547 printf("------------------");
552 find_deltas(mach_zone_name_t
*name
, task_zone_info_t
*info
, task_zone_info_t
*max_info
,
553 char *deltas
, int cnt
, int first_time
)
558 for (i
= 0; i
< cnt
; i
++) {
560 if (substr(zname
, znamelen
, name
[i
].mzn_name
,
561 strnlen(name
[i
].mzn_name
, sizeof name
[i
].mzn_name
))) {
562 if (first_time
|| info
->tzi_cur_size
> max_info
->tzi_cur_size
||
563 (ShowTotal
&& ((info
->tzi_sum_size
>> 1) > max_info
->tzi_sum_size
))) {
564 max_info
->tzi_cur_size
= info
->tzi_cur_size
;
565 max_info
->tzi_sum_size
= info
->tzi_sum_size
;
576 /*********************************************************************
577 *********************************************************************/
580 kern_vm_tag_name(uint64_t tag
)
586 case (VM_KERN_MEMORY_NONE
): name
= "VM_KERN_MEMORY_NONE"; break;
587 case (VM_KERN_MEMORY_OSFMK
): name
= "VM_KERN_MEMORY_OSFMK"; break;
588 case (VM_KERN_MEMORY_BSD
): name
= "VM_KERN_MEMORY_BSD"; break;
589 case (VM_KERN_MEMORY_IOKIT
): name
= "VM_KERN_MEMORY_IOKIT"; break;
590 case (VM_KERN_MEMORY_LIBKERN
): name
= "VM_KERN_MEMORY_LIBKERN"; break;
591 case (VM_KERN_MEMORY_OSKEXT
): name
= "VM_KERN_MEMORY_OSKEXT"; break;
592 case (VM_KERN_MEMORY_KEXT
): name
= "VM_KERN_MEMORY_KEXT"; break;
593 case (VM_KERN_MEMORY_IPC
): name
= "VM_KERN_MEMORY_IPC"; break;
594 case (VM_KERN_MEMORY_STACK
): name
= "VM_KERN_MEMORY_STACK"; break;
595 case (VM_KERN_MEMORY_CPU
): name
= "VM_KERN_MEMORY_CPU"; break;
596 case (VM_KERN_MEMORY_PMAP
): name
= "VM_KERN_MEMORY_PMAP"; break;
597 case (VM_KERN_MEMORY_PTE
): name
= "VM_KERN_MEMORY_PTE"; break;
598 case (VM_KERN_MEMORY_ZONE
): name
= "VM_KERN_MEMORY_ZONE"; break;
599 case (VM_KERN_MEMORY_KALLOC
): name
= "VM_KERN_MEMORY_KALLOC"; break;
600 case (VM_KERN_MEMORY_COMPRESSOR
): name
= "VM_KERN_MEMORY_COMPRESSOR"; break;
601 case (VM_KERN_MEMORY_COMPRESSED_DATA
): name
= "VM_KERN_MEMORY_COMPRESSED_DATA"; break;
602 case (VM_KERN_MEMORY_PHANTOM_CACHE
): name
= "VM_KERN_MEMORY_PHANTOM_CACHE"; break;
603 case (VM_KERN_MEMORY_WAITQ
): name
= "VM_KERN_MEMORY_WAITQ"; break;
604 case (VM_KERN_MEMORY_DIAG
): name
= "VM_KERN_MEMORY_DIAG"; break;
605 case (VM_KERN_MEMORY_LOG
): name
= "VM_KERN_MEMORY_LOG"; break;
606 case (VM_KERN_MEMORY_FILE
): name
= "VM_KERN_MEMORY_FILE"; break;
607 case (VM_KERN_MEMORY_MBUF
): name
= "VM_KERN_MEMORY_MBUF"; break;
608 case (VM_KERN_MEMORY_UBC
): name
= "VM_KERN_MEMORY_UBC"; break;
609 case (VM_KERN_MEMORY_SECURITY
): name
= "VM_KERN_MEMORY_SECURITY"; break;
610 case (VM_KERN_MEMORY_MLOCK
): name
= "VM_KERN_MEMORY_MLOCK"; break;
611 case (VM_KERN_MEMORY_REASON
): name
= "VM_KERN_MEMORY_REASON"; break;
612 case (VM_KERN_MEMORY_SKYWALK
): name
= "VM_KERN_MEMORY_SKYWALK"; break;
613 case (VM_KERN_MEMORY_LTABLE
): name
= "VM_KERN_MEMORY_LTABLE"; break;
614 case (VM_KERN_MEMORY_ANY
): name
= "VM_KERN_MEMORY_ANY"; break;
615 default: name
= NULL
; break;
617 if (name
) asprintf(&result
, "%s", name
);
618 else asprintf(&result
, "VM_KERN_MEMORY_%lld", tag
);
623 kern_vm_counter_name(uint64_t tag
)
629 case (VM_KERN_COUNT_MANAGED
): name
= "VM_KERN_COUNT_MANAGED"; break;
630 case (VM_KERN_COUNT_RESERVED
): name
= "VM_KERN_COUNT_RESERVED"; break;
631 case (VM_KERN_COUNT_WIRED
): name
= "VM_KERN_COUNT_WIRED"; break;
632 case (VM_KERN_COUNT_WIRED_MANAGED
): name
= "VM_KERN_COUNT_WIRED_MANAGED"; break;
633 case (VM_KERN_COUNT_STOLEN
): name
= "VM_KERN_COUNT_STOLEN"; break;
634 case (VM_KERN_COUNT_LOPAGE
): name
= "VM_KERN_COUNT_LOPAGE"; break;
635 case (VM_KERN_COUNT_MAP_KERNEL
): name
= "VM_KERN_COUNT_MAP_KERNEL"; break;
636 case (VM_KERN_COUNT_MAP_ZONE
): name
= "VM_KERN_COUNT_MAP_ZONE"; break;
637 case (VM_KERN_COUNT_MAP_KALLOC
): name
= "VM_KERN_COUNT_MAP_KALLOC"; break;
638 default: name
= NULL
; break;
640 if (name
) asprintf(&result
, "%s", name
);
641 else asprintf(&result
, "VM_KERN_COUNT_%lld", tag
);
646 MakeLoadTagKeys(const void * key
, const void * value
, void * context
)
648 CFMutableDictionaryRef newDict
= context
;
649 CFDictionaryRef kextInfo
= value
;
651 uint32_t loadTagValue
;
653 loadTag
= (CFNumberRef
)CFDictionaryGetValue(kextInfo
, CFSTR(kOSBundleLoadTagKey
));
654 CFNumberGetValue(loadTag
, kCFNumberSInt32Type
, &loadTagValue
);
655 key
= (const void *)(uintptr_t) loadTagValue
;
656 CFDictionarySetValue(newDict
, key
, value
);
659 static CSSymbolicatorRef gSym
;
660 static CFMutableDictionaryRef gTagDict
;
661 static mach_memory_info_t
* gSites
;
664 GetSiteName(int siteIdx
)
668 mach_vm_address_t addr
;
669 CFDictionaryRef kextInfo
;
670 CFStringRef bundleID
;
673 const mach_memory_info_t
* site
;
674 const char * fileName
;
676 const char * symbolName
;
677 CSSourceInfoRef sourceInfo
;
681 site
= &gSites
[siteIdx
];
683 type
= (VM_KERN_SITE_TYPE
& site
->flags
);
686 case VM_KERN_SITE_TAG
:
687 result
= kern_vm_tag_name(addr
);
690 case VM_KERN_SITE_COUNTER
:
691 result
= kern_vm_counter_name(addr
);
694 case VM_KERN_SITE_KMOD
:
695 kextInfo
= CFDictionaryGetValue(gTagDict
, (const void *)(uintptr_t) addr
);
698 bundleID
= (CFStringRef
)CFDictionaryGetValue(kextInfo
, kCFBundleIdentifierKey
);
699 name
= CFStringGetCStringPtr(bundleID
, kCFStringEncodingUTF8
);
700 // wiredSize = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleWiredSizeKey));
702 asprintf(&result
, "%-64s%3lld", name
? name
: "(unknown kmod)", addr
);
705 case VM_KERN_SITE_KERNEL
:
709 symbol
= CSSymbolicatorGetSymbolWithAddressAtTime(gSym
, addr
, kCSNow
);
710 symbolName
= CSSymbolGetName(symbol
);
714 asprintf(&result
, "%s", symbolName
);
715 sourceInfo
= CSSymbolicatorGetSourceInfoWithAddressAtTime(gSym
, addr
, kCSNow
);
716 fileName
= CSSourceInfoGetPath(sourceInfo
);
717 if (fileName
) printf(" (%s:%d)", fileName
, CSSourceInfoGetLineNumber(sourceInfo
));
721 asprintf(&result
, "site 0x%qx", addr
);
725 asprintf(&result
, "");
733 SortName(const void * left
, const void * right
)
741 idxL
= (typeof(idxL
)) left
;
742 idxR
= (typeof(idxR
)) right
;
743 l
= GetSiteName(*idxL
);
744 r
= GetSiteName(*idxR
);
746 result
= strcmp(l
, r
);
754 SortSize(const void * left
, const void * right
)
756 const mach_memory_info_t
* siteL
;
757 const mach_memory_info_t
* siteR
;
761 idxL
= (typeof(idxL
)) left
;
762 idxR
= (typeof(idxR
)) right
;
763 siteL
= &gSites
[*idxL
];
764 siteR
= &gSites
[*idxR
];
766 if (siteL
->size
> siteR
->size
) return (-1);
767 else if (siteL
->size
< siteR
->size
) return (1);
773 PrintLarge(mach_memory_info_t
*wiredInfo
, unsigned int wiredInfoCnt
,
774 int (*func
)(const void *, const void *), boolean_t column
)
779 CFDictionaryRef allKexts
;
780 unsigned int idx
, site
, first
;
781 int sorted
[wiredInfoCnt
];
786 zonetotal
= totalsize
;
790 gSym
= CSSymbolicatorCreateWithMachKernel();
792 allKexts
= OSKextCopyLoadedKextInfo(NULL
, NULL
);
793 gTagDict
= CFDictionaryCreateMutable(
794 kCFAllocatorDefault
, (CFIndex
) 0,
795 (CFDictionaryKeyCallBacks
*) 0,
796 &kCFTypeDictionaryValueCallBacks
);
798 CFDictionaryApplyFunction(allKexts
, &MakeLoadTagKeys
, gTagDict
);
803 for (idx
= 0; idx
< wiredInfoCnt
; idx
++) sorted
[idx
] = idx
;
804 first
= 0; // VM_KERN_MEMORY_FIRST_DYNAMIC
805 qsort(&sorted
[first
],
806 wiredInfoCnt
- first
,
810 for (headerPrinted
= false, idx
= 0; idx
< wiredInfoCnt
; idx
++)
813 if (!gSites
[site
].size
) continue;
814 if (VM_KERN_COUNT_WIRED
== gSites
[site
].site
) top_wired
= gSites
[site
].size
;
815 if (VM_KERN_SITE_HIDE
& gSites
[site
].flags
) continue;
816 if (!(VM_KERN_SITE_WIRED
& gSites
[site
].flags
)) continue;
818 name
= GetSiteName(site
);
819 if (!substr(zname
, znamelen
, name
, strlen(name
))) continue;
822 printf("-------------------------------------------------------------------------------------------------------------\n");
823 printf(" kmod vm cur\n");
824 printf("wired memory id tag size\n");
825 printf("-------------------------------------------------------------------------------------------------------------\n");
826 headerPrinted
= true;
828 printf("%-67s", name
);
830 printf("%12d", site
);
833 PRINTK(" %12llu", gSites
[site
].size
);
834 totalsize
+= gSites
[site
].size
;
841 printf("%-67s", "zones");
844 PRINTK(" %12llu", zonetotal
);
849 snprintf(totalstr
, sizeof(totalstr
), "%6.2fM of %6.2fM", totalsize
/ 1024.0 / 1024.0, top_wired
/ 1024.0 / 1024.0);
850 printf("total%100s\n", totalstr
);
852 for (headerPrinted
= false, idx
= 0; idx
< wiredInfoCnt
; idx
++)
855 if (!gSites
[site
].size
) continue;
856 if (VM_KERN_SITE_HIDE
& gSites
[site
].flags
) continue;
857 if (VM_KERN_SITE_WIRED
& gSites
[site
].flags
) continue;
859 name
= GetSiteName(site
);
860 if (!substr(zname
, znamelen
, name
, strlen(name
))) continue;
863 printf("-------------------------------------------------------------------------------------------------------------\n");
864 printf(" largest\n");
865 printf("maps free free size\n");
866 printf("-------------------------------------------------------------------------------------------------------------\n");
867 headerPrinted
= true;
869 printf("%-67s", name
);
872 PRINTK(" %10llu", gSites
[site
].free
);
873 PRINTK(" %10llu", gSites
[site
].largest
);
874 PRINTK(" %12llu", gSites
[site
].size
);