]>
Commit | Line | Data |
---|---|---|
8459d725 | 1 | /* |
cf37c299 | 2 | * Copyright (c) 2009-2016 Apple Inc. All rights reserved. |
8459d725 A |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
cf37c299 | 5 | * |
8459d725 A |
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. | |
cf37c299 | 14 | * |
8459d725 A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
cf37c299 | 17 | * |
8459d725 A |
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. | |
cf37c299 | 25 | * |
8459d725 A |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ | |
1815bff5 A |
28 | /* |
29 | * @OSF_COPYRIGHT@ | |
30 | */ | |
cf37c299 | 31 | /* |
1815bff5 A |
32 | * Mach Operating System |
33 | * Copyright (c) 1991,1990,1989 Carnegie Mellon University | |
34 | * All Rights Reserved. | |
cf37c299 | 35 | * |
1815bff5 A |
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. | |
cf37c299 A |
41 | * |
42 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS | |
1815bff5 A |
43 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR |
44 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
cf37c299 | 45 | * |
1815bff5 | 46 | * Carnegie Mellon requests users of this software to return to |
cf37c299 | 47 | * |
1815bff5 A |
48 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
49 | * School of Computer Science | |
50 | * Carnegie Mellon University | |
51 | * Pittsburgh PA 15213-3890 | |
cf37c299 | 52 | * |
1815bff5 A |
53 | * any improvements or extensions that they make and grant Carnegie the |
54 | * rights to redistribute these changes. | |
55 | */ | |
56 | /* | |
57 | * zprint.c | |
58 | * | |
59 | * utility for printing out zone structures | |
60 | * | |
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. | |
66 | */ | |
67 | ||
9726c137 | 68 | #include <vm_statistics.h> |
1815bff5 | 69 | #include <stdio.h> |
34d340d7 | 70 | #include <stdlib.h> |
1815bff5 A |
71 | #include <string.h> |
72 | #include <mach/mach.h> | |
73 | #include <mach_debug/mach_debug.h> | |
74 | #include <mach/mach_error.h> | |
ef8ad44b A |
75 | #include <libutil.h> |
76 | #include <errno.h> | |
9726c137 A |
77 | #include <sysexits.h> |
78 | #include <getopt.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> | |
87 | ||
1815bff5 A |
88 | #define streql(a, b) (strcmp((a), (b)) == 0) |
89 | #define strneql(a, b, n) (strncmp((a), (b), (n)) == 0) | |
9726c137 A |
90 | #define PRINTK(fmt, value) \ |
91 | printf(fmt "K", (value) / 1024 ) /* ick */ | |
1815bff5 | 92 | |
8459d725 A |
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); | |
9726c137 A |
98 | static boolean_t substr(const char *a, size_t alen, const char *b, size_t blen); |
99 | ||
887d5eed A |
100 | static int SortName(void * thunk, const void * left, const void * right); |
101 | static int SortSize(void * thunk, const void * left, const void * right); | |
102 | static void PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, | |
103 | task_zone_info_t *zoneInfo, mach_zone_name_t *zoneNames, | |
104 | unsigned int zoneCnt, uint64_t zoneElements, | |
105 | int (*func)(void *, const void *, const void *), boolean_t column); | |
1815bff5 A |
106 | |
107 | static char *program; | |
108 | ||
8459d725 A |
109 | static pid_t pid = 0; |
110 | static task_t task = TASK_NULL; | |
111 | static boolean_t ShowPid = FALSE; | |
112 | ||
113 | static boolean_t ShowDeltas = FALSE; | |
1815bff5 | 114 | static boolean_t ShowWasted = FALSE; |
8459d725 | 115 | static boolean_t ShowTotal = FALSE; |
9726c137 | 116 | static boolean_t ShowLarge = TRUE; |
1815bff5 A |
117 | static boolean_t SortZones = FALSE; |
118 | static boolean_t ColFormat = TRUE; | |
119 | static boolean_t PrintHeader = TRUE; | |
120 | ||
8459d725 A |
121 | static unsigned long long totalsize = 0; |
122 | static unsigned long long totalused = 0; | |
123 | static unsigned long long totalsum = 0; | |
124 | static unsigned long long pidsum = 0; | |
125 | ||
126 | static int last_time = 0; | |
127 | ||
128 | static char *zname = NULL; | |
9726c137 | 129 | static size_t znamelen = 0; |
8459d725 A |
130 | |
131 | static void | |
132 | sigintr(__unused int signum) | |
133 | { | |
134 | last_time = 1; | |
135 | } | |
1815bff5 A |
136 | |
137 | static void | |
8459d725 | 138 | usage(void) |
1815bff5 | 139 | { |
cf37c299 | 140 | fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [-t] [-d] [-l] [-L] [-p <pid>] [name]\n", program); |
1815bff5 A |
141 | exit(1); |
142 | } | |
143 | ||
34d340d7 | 144 | int |
8459d725 | 145 | main(int argc, char **argv) |
1815bff5 | 146 | { |
8459d725 A |
147 | mach_zone_name_t *name = NULL; |
148 | unsigned int nameCnt = 0; | |
149 | task_zone_info_t *info = NULL; | |
150 | unsigned int infoCnt = 0; | |
9726c137 A |
151 | mach_memory_info_t *wiredInfo = NULL; |
152 | unsigned int wiredInfoCnt = 0; | |
8459d725 A |
153 | task_zone_info_t *max_info = NULL; |
154 | char *deltas = NULL; | |
887d5eed | 155 | uint64_t zoneElements; |
1815bff5 A |
156 | |
157 | kern_return_t kr; | |
158 | int i, j; | |
8459d725 A |
159 | int first_time = 1; |
160 | int must_print = 1; | |
161 | int interval = 1; | |
1815bff5 | 162 | |
8459d725 | 163 | signal(SIGINT, sigintr); |
ef8ad44b | 164 | |
1815bff5 A |
165 | program = strrchr(argv[0], '/'); |
166 | if (program == NULL) | |
167 | program = argv[0]; | |
168 | else | |
169 | program++; | |
170 | ||
171 | for (i = 1; i < argc; i++) { | |
8459d725 A |
172 | if (streql(argv[i], "-d")) |
173 | ShowDeltas = TRUE; | |
174 | else if (streql(argv[i], "-t")) | |
175 | ShowTotal = TRUE; | |
176 | else if (streql(argv[i], "-T")) | |
177 | ShowTotal = FALSE; | |
178 | else if (streql(argv[i], "-w")) | |
1815bff5 A |
179 | ShowWasted = TRUE; |
180 | else if (streql(argv[i], "-W")) | |
181 | ShowWasted = FALSE; | |
9726c137 A |
182 | else if (streql(argv[i], "-l")) |
183 | ShowLarge = TRUE; | |
184 | else if (streql(argv[i], "-L")) | |
185 | ShowLarge = FALSE; | |
1815bff5 A |
186 | else if (streql(argv[i], "-s")) |
187 | SortZones = TRUE; | |
188 | else if (streql(argv[i], "-S")) | |
189 | SortZones = FALSE; | |
190 | else if (streql(argv[i], "-c")) | |
191 | ColFormat = TRUE; | |
192 | else if (streql(argv[i], "-C")) | |
193 | ColFormat = FALSE; | |
194 | else if (streql(argv[i], "-H")) | |
195 | PrintHeader = FALSE; | |
8459d725 A |
196 | else if (streql(argv[i], "-p")) { |
197 | ShowPid = TRUE; | |
198 | if (i < argc - 1) { | |
199 | pid = atoi(argv[i+1]); | |
200 | i++; | |
201 | } else | |
202 | usage(); | |
203 | } else if (streql(argv[i], "--")) { | |
1815bff5 A |
204 | i++; |
205 | break; | |
206 | } else if (argv[i][0] == '-') | |
207 | usage(); | |
208 | else | |
209 | break; | |
210 | } | |
211 | ||
212 | switch (argc - i) { | |
213 | case 0: | |
214 | zname = ""; | |
215 | znamelen = 0; | |
216 | break; | |
217 | ||
218 | case 1: | |
219 | zname = argv[i]; | |
220 | znamelen = strlen(zname); | |
221 | break; | |
222 | ||
223 | default: | |
224 | usage(); | |
225 | } | |
226 | ||
8459d725 A |
227 | if (ShowDeltas) { |
228 | SortZones = FALSE; | |
229 | ColFormat = TRUE; | |
230 | PrintHeader = TRUE; | |
231 | } | |
232 | ||
233 | if (ShowPid) { | |
234 | kr = task_for_pid(mach_task_self(), pid, &task); | |
235 | if (kr != KERN_SUCCESS) { | |
cf37c299 | 236 | fprintf(stderr, "%s: task_for_pid(%d) failed: %s (try running as root)\n", |
8459d725 A |
237 | program, pid, mach_error_string(kr)); |
238 | exit(1); | |
239 | } | |
240 | } | |
241 | ||
242 | for (;;) { | |
243 | if (ShowPid) { | |
244 | kr = task_zone_info(task, &name, &nameCnt, &info, &infoCnt); | |
245 | if (kr != KERN_SUCCESS) { | |
246 | fprintf(stderr, "%s: task_zone_info: %s\n", | |
247 | program, mach_error_string(kr)); | |
1815bff5 | 248 | exit(1); |
8459d725 A |
249 | } |
250 | } else { | |
251 | mach_zone_info_t *zinfo = NULL; | |
252 | ||
9726c137 A |
253 | kr = mach_memory_info(mach_host_self(), |
254 | &name, &nameCnt, &zinfo, &infoCnt, | |
255 | &wiredInfo, &wiredInfoCnt); | |
8459d725 A |
256 | if (kr != KERN_SUCCESS) { |
257 | fprintf(stderr, "%s: mach_zone_info: %s\n", | |
258 | program, mach_error_string(kr)); | |
259 | exit(1); | |
260 | } | |
9726c137 | 261 | |
8459d725 A |
262 | kr = vm_allocate(mach_task_self(), (vm_address_t *)&info, |
263 | infoCnt * sizeof *info, VM_FLAGS_ANYWHERE); | |
264 | if (kr != KERN_SUCCESS) { | |
265 | fprintf(stderr, "%s vm_allocate: %s\n", | |
266 | program, mach_error_string(kr)); | |
267 | exit(1); | |
268 | } | |
269 | for (i = 0; i < infoCnt; i++) { | |
270 | *(mach_zone_info_t *)(info + i) = zinfo[i]; | |
271 | info[i].tzi_caller_acct = 0; | |
272 | info[i].tzi_task_alloc = 0; | |
273 | info[i].tzi_task_free = 0; | |
274 | } | |
275 | kr = vm_deallocate(mach_task_self(), (vm_address_t) zinfo, | |
276 | (vm_size_t) (infoCnt * sizeof *zinfo)); | |
277 | if (kr != KERN_SUCCESS) { | |
278 | fprintf(stderr, "%s: vm_deallocate: %s\n", | |
279 | program, mach_error_string(kr)); | |
280 | exit(1); | |
281 | } | |
1815bff5 | 282 | } |
8459d725 A |
283 | |
284 | if (nameCnt != infoCnt) { | |
285 | fprintf(stderr, "%s: mach/task_zone_info: counts not equal?\n", | |
1815bff5 A |
286 | program); |
287 | exit(1); | |
288 | } | |
289 | ||
8459d725 A |
290 | if (first_time) { |
291 | deltas = (char *)malloc(infoCnt); | |
292 | max_info = (task_zone_info_t *)malloc((infoCnt * sizeof *info)); | |
293 | } | |
294 | ||
1815bff5 A |
295 | if (SortZones) { |
296 | for (i = 0; i < nameCnt-1; i++) | |
297 | for (j = i+1; j < nameCnt; j++) { | |
9726c137 | 298 | unsigned long long wastei, wastej; |
1815bff5 | 299 | |
8459d725 A |
300 | wastei = (info[i].tzi_cur_size - |
301 | (info[i].tzi_elem_size * | |
302 | info[i].tzi_count)); | |
303 | wastej = (info[j].tzi_cur_size - | |
304 | (info[j].tzi_elem_size * | |
305 | info[j].tzi_count)); | |
1815bff5 A |
306 | |
307 | if (wastej > wastei) { | |
8459d725 A |
308 | task_zone_info_t tinfo; |
309 | mach_zone_name_t tname; | |
1815bff5 A |
310 | |
311 | tinfo = info[i]; | |
312 | info[i] = info[j]; | |
313 | info[j] = tinfo; | |
314 | ||
315 | tname = name[i]; | |
316 | name[i] = name[j]; | |
317 | name[j] = tname; | |
318 | } | |
319 | } | |
320 | } | |
321 | ||
8459d725 | 322 | must_print = find_deltas(name, info, max_info, deltas, infoCnt, first_time); |
887d5eed | 323 | zoneElements = 0; |
8459d725 A |
324 | if (must_print) { |
325 | if (ColFormat) { | |
326 | if (!first_time) | |
327 | printf("\n"); | |
328 | colprintzoneheader(); | |
329 | } | |
330 | for (i = 0; i < nameCnt; i++) { | |
331 | if (deltas[i]) { | |
332 | if (ColFormat) | |
333 | colprintzone(&name[i], &info[i]); | |
334 | else | |
335 | printzone(&name[i], &info[i]); | |
887d5eed | 336 | zoneElements += info[i].tzi_count; |
8459d725 A |
337 | } |
338 | } | |
cf37c299 | 339 | } |
9726c137 | 340 | |
cf37c299 | 341 | if (ShowLarge && first_time) { |
887d5eed A |
342 | PrintLarge(wiredInfo, wiredInfoCnt, &info[0], &name[0], |
343 | nameCnt, zoneElements, | |
cf37c299 | 344 | SortZones ? &SortSize : &SortName, ColFormat); |
1815bff5 | 345 | } |
8459d725 A |
346 | |
347 | first_time = 0; | |
348 | ||
349 | if ((name != NULL) && (nameCnt != 0)) { | |
1815bff5 A |
350 | kr = vm_deallocate(mach_task_self(), (vm_address_t) name, |
351 | (vm_size_t) (nameCnt * sizeof *name)); | |
352 | if (kr != KERN_SUCCESS) { | |
353 | fprintf(stderr, "%s: vm_deallocate: %s\n", | |
354 | program, mach_error_string(kr)); | |
355 | exit(1); | |
356 | } | |
357 | } | |
358 | ||
8459d725 | 359 | if ((info != NULL) && (infoCnt != 0)) { |
1815bff5 A |
360 | kr = vm_deallocate(mach_task_self(), (vm_address_t) info, |
361 | (vm_size_t) (infoCnt * sizeof *info)); | |
362 | if (kr != KERN_SUCCESS) { | |
363 | fprintf(stderr, "%s: vm_deallocate: %s\n", | |
364 | program, mach_error_string(kr)); | |
365 | exit(1); | |
366 | } | |
367 | } | |
368 | ||
9726c137 A |
369 | if ((wiredInfo != NULL) && (wiredInfoCnt != 0)) { |
370 | kr = vm_deallocate(mach_task_self(), (vm_address_t) wiredInfo, | |
371 | (vm_size_t) (wiredInfoCnt * sizeof *wiredInfo)); | |
372 | if (kr != KERN_SUCCESS) { | |
373 | fprintf(stderr, "%s: vm_deallocate: %s\n", | |
374 | program, mach_error_string(kr)); | |
375 | exit(1); | |
376 | } | |
377 | } | |
378 | ||
8459d725 A |
379 | if ((ShowWasted||ShowTotal) && PrintHeader && !ShowDeltas) { |
380 | printf("TOTAL SIZE = %llu\n", totalsize); | |
381 | printf("TOTAL USED = %llu\n", totalused); | |
382 | if (ShowWasted) | |
383 | printf("TOTAL WASTED = %llu\n", totalsize - totalused); | |
384 | if (ShowTotal) | |
385 | printf("TOTAL ALLOCS = %llu\n", totalsum); | |
1815bff5 A |
386 | } |
387 | ||
8459d725 A |
388 | if (ShowDeltas == FALSE || last_time) |
389 | break; | |
1815bff5 | 390 | |
8459d725 A |
391 | sleep(interval); |
392 | } | |
393 | exit(0); | |
1815bff5 A |
394 | } |
395 | ||
396 | static boolean_t | |
9726c137 | 397 | substr(const char *a, size_t alen, const char *b, size_t blen) |
1815bff5 A |
398 | { |
399 | int i; | |
400 | ||
cf37c299 A |
401 | if (alen > blen) return FALSE; |
402 | ||
1815bff5 A |
403 | for (i = 0; i <= blen - alen; i++) |
404 | if (strneql(a, b+i, alen)) | |
405 | return TRUE; | |
406 | ||
407 | return FALSE; | |
408 | } | |
409 | ||
410 | static void | |
8459d725 | 411 | printzone(mach_zone_name_t *name, task_zone_info_t *info) |
1815bff5 | 412 | { |
8459d725 A |
413 | unsigned long long used, size; |
414 | ||
415 | printf("%.*s zone:\n", (int)sizeof name->mzn_name, name->mzn_name); | |
416 | printf("\tcur_size: %lluK bytes (%llu elements)\n", | |
417 | info->tzi_cur_size/1024, | |
418 | (info->tzi_elem_size == 0) ? 0 : | |
419 | info->tzi_cur_size/info->tzi_elem_size); | |
420 | printf("\tmax_size: %lluK bytes (%llu elements)\n", | |
421 | info->tzi_max_size/1024, | |
422 | (info->tzi_elem_size == 0) ? 0 : | |
423 | info->tzi_max_size/info->tzi_elem_size); | |
424 | printf("\telem_size: %llu bytes\n", | |
425 | info->tzi_elem_size); | |
426 | printf("\t# of elems: %llu\n", | |
427 | info->tzi_count); | |
428 | printf("\talloc_size: %lluK bytes (%llu elements)\n", | |
429 | info->tzi_alloc_size/1024, | |
430 | (info->tzi_elem_size == 0) ? 0 : | |
431 | info->tzi_alloc_size/info->tzi_elem_size); | |
432 | if (info->tzi_exhaustible) | |
433 | printf("\tEXHAUSTIBLE\n"); | |
434 | if (info->tzi_collectable) | |
1815bff5 | 435 | printf("\tCOLLECTABLE\n"); |
8459d725 A |
436 | if (ShowPid && info->tzi_caller_acct) |
437 | printf("\tCALLER ACCOUNTED\n"); | |
438 | if (ShowPid) { | |
439 | pidsum += info->tzi_task_alloc - info->tzi_task_free; | |
440 | printf("\tproc_alloc_size: %8dK bytes (%llu elements)\n", | |
441 | (int)((info->tzi_task_alloc - info->tzi_task_free)/1024), | |
442 | (info->tzi_elem_size == 0) ? 0 : | |
443 | (info->tzi_task_alloc - info->tzi_task_free)/info->tzi_elem_size); | |
444 | } | |
1815bff5 | 445 | if (ShowWasted) { |
8459d725 A |
446 | totalused += used = info->tzi_elem_size * info->tzi_count; |
447 | totalsize += size = info->tzi_cur_size; | |
448 | printf("\t\t\t\t\tWASTED: %llu\n", size - used); | |
449 | } | |
450 | if (ShowTotal) { | |
451 | totalsum += info->tzi_sum_size; | |
452 | printf("\t\t\t\t\tTOTAL: %llu\n", totalsum); | |
453 | if (ShowPid) | |
454 | printf("\t\t\t\t\tPID TOTAL: %llu\n", pidsum); | |
1815bff5 A |
455 | } |
456 | } | |
457 | ||
1815bff5 | 458 | static void |
8459d725 | 459 | colprintzone(mach_zone_name_t *zone_name, task_zone_info_t *info) |
1815bff5 | 460 | { |
8459d725 | 461 | char *name = zone_name->mzn_name; |
34d340d7 | 462 | int j, namewidth; |
8459d725 | 463 | unsigned long long used, size; |
1815bff5 A |
464 | |
465 | namewidth = 25; | |
8459d725 | 466 | if (ShowWasted || ShowTotal) { |
1815bff5 A |
467 | namewidth -= 7; |
468 | } | |
469 | for (j = 0; j < namewidth - 1 && name[j]; j++) { | |
470 | if (name[j] == ' ') { | |
471 | putchar('.'); | |
472 | } else { | |
473 | putchar(name[j]); | |
474 | } | |
475 | } | |
476 | if (j == namewidth - 1) { | |
477 | if (name[j]) { | |
478 | putchar('$'); | |
479 | } else { | |
480 | putchar(' '); | |
481 | } | |
482 | } else { | |
483 | for (; j < namewidth; j++) { | |
484 | putchar(' '); | |
485 | } | |
486 | } | |
aaff5f01 A |
487 | printf(" %6llu", info->tzi_elem_size); |
488 | PRINTK(" %10llu", info->tzi_cur_size); | |
8459d725 | 489 | if (info->tzi_max_size / 1024 > 9999999) { |
aaff5f01 | 490 | printf(" --------"); |
1815bff5 | 491 | } else { |
aaff5f01 | 492 | PRINTK(" %10llu", info->tzi_max_size); |
1815bff5 | 493 | } |
aaff5f01 | 494 | printf(" %10llu", info->tzi_cur_size / info->tzi_elem_size); |
8459d725 | 495 | if (info->tzi_max_size / 1024 >= 999999999) { |
aaff5f01 | 496 | printf(" ----------"); |
1815bff5 | 497 | } else { |
aaff5f01 | 498 | printf(" %11llu", info->tzi_max_size / info->tzi_elem_size); |
1815bff5 | 499 | } |
aaff5f01 A |
500 | printf(" %11llu", info->tzi_count); |
501 | PRINTK(" %5llu", info->tzi_alloc_size); | |
502 | printf(" %6llu", info->tzi_alloc_size / info->tzi_elem_size); | |
8459d725 A |
503 | |
504 | totalused += used = info->tzi_elem_size * info->tzi_count; | |
505 | totalsize += size = info->tzi_cur_size; | |
506 | totalsum += info->tzi_sum_size; | |
507 | ||
508 | printf(" %c%c%c", | |
509 | (info->tzi_exhaustible ? 'X' : ' '), | |
510 | (info->tzi_caller_acct ? 'A' : ' '), | |
511 | (info->tzi_collectable ? 'C' : ' ')); | |
1815bff5 | 512 | if (ShowWasted) { |
aaff5f01 | 513 | PRINTK(" %8llu", size - used); |
1815bff5 | 514 | } |
8459d725 A |
515 | if (ShowPid) { |
516 | printf("%8dK", (int)((info->tzi_task_alloc - info->tzi_task_free)/1024)); | |
517 | } | |
518 | if (ShowTotal) { | |
519 | if (info->tzi_sum_size < 1024) | |
aaff5f01 | 520 | printf(" %16lluB", info->tzi_sum_size); |
8459d725 | 521 | else |
aaff5f01 | 522 | PRINTK(" %16llu", info->tzi_sum_size); |
8459d725 A |
523 | } |
524 | printf("\n"); | |
1815bff5 A |
525 | } |
526 | ||
527 | static void | |
8459d725 | 528 | colprintzoneheader(void) |
1815bff5 A |
529 | { |
530 | if (! PrintHeader) { | |
531 | return; | |
532 | } | |
aaff5f01 A |
533 | printf("%s elem cur max cur max" |
534 | " cur alloc alloc %s%s\n", | |
535 | (ShowWasted||ShowTotal)? "" : " ", | |
536 | (ShowWasted)? " ":"", | |
537 | (ShowPid) ? " PID" : "" ); | |
538 | printf("zone name%s size size size #elts #elts" | |
539 | " inuse size count ", (ShowWasted||ShowTotal)? " " : " " ); | |
8459d725 | 540 | if (ShowWasted) |
aaff5f01 | 541 | printf(" wasted"); |
8459d725 | 542 | if (ShowPid) |
aaff5f01 | 543 | printf(" Allocs"); |
8459d725 | 544 | if (ShowTotal) |
aaff5f01 A |
545 | printf(" Total Allocs"); |
546 | printf("\n%s-------------------------------------------------------" | |
547 | "-----------------------------------------------", | |
8459d725 A |
548 | (ShowWasted||ShowTotal)? "" : "-------"); |
549 | if (ShowWasted) | |
8459d725 | 550 | printf("----------"); |
aaff5f01 A |
551 | if (ShowPid) |
552 | printf("---------"); | |
8459d725 | 553 | if (ShowTotal) |
aaff5f01 | 554 | printf("------------------"); |
8459d725 A |
555 | printf("\n"); |
556 | } | |
557 | ||
558 | int | |
559 | find_deltas(mach_zone_name_t *name, task_zone_info_t *info, task_zone_info_t *max_info, | |
560 | char *deltas, int cnt, int first_time) | |
561 | { | |
562 | int i; | |
563 | int found_one = 0; | |
564 | ||
565 | for (i = 0; i < cnt; i++) { | |
566 | deltas[i] = 0; | |
567 | if (substr(zname, znamelen, name[i].mzn_name, | |
568 | strnlen(name[i].mzn_name, sizeof name[i].mzn_name))) { | |
569 | if (first_time || info->tzi_cur_size > max_info->tzi_cur_size || | |
570 | (ShowTotal && ((info->tzi_sum_size >> 1) > max_info->tzi_sum_size))) { | |
571 | max_info->tzi_cur_size = info->tzi_cur_size; | |
572 | max_info->tzi_sum_size = info->tzi_sum_size; | |
573 | deltas[i] = 1; | |
574 | found_one = 1; | |
575 | } | |
576 | } | |
577 | info++; | |
578 | max_info++; | |
579 | } | |
580 | return(found_one); | |
1815bff5 | 581 | } |
9726c137 A |
582 | |
583 | /********************************************************************* | |
584 | *********************************************************************/ | |
585 | ||
586 | static char * | |
587 | kern_vm_tag_name(uint64_t tag) | |
588 | { | |
589 | char * result; | |
590 | const char * name; | |
591 | switch (tag) | |
592 | { | |
593 | case (VM_KERN_MEMORY_NONE): name = "VM_KERN_MEMORY_NONE"; break; | |
594 | case (VM_KERN_MEMORY_OSFMK): name = "VM_KERN_MEMORY_OSFMK"; break; | |
595 | case (VM_KERN_MEMORY_BSD): name = "VM_KERN_MEMORY_BSD"; break; | |
596 | case (VM_KERN_MEMORY_IOKIT): name = "VM_KERN_MEMORY_IOKIT"; break; | |
597 | case (VM_KERN_MEMORY_LIBKERN): name = "VM_KERN_MEMORY_LIBKERN"; break; | |
598 | case (VM_KERN_MEMORY_OSKEXT): name = "VM_KERN_MEMORY_OSKEXT"; break; | |
599 | case (VM_KERN_MEMORY_KEXT): name = "VM_KERN_MEMORY_KEXT"; break; | |
600 | case (VM_KERN_MEMORY_IPC): name = "VM_KERN_MEMORY_IPC"; break; | |
601 | case (VM_KERN_MEMORY_STACK): name = "VM_KERN_MEMORY_STACK"; break; | |
602 | case (VM_KERN_MEMORY_CPU): name = "VM_KERN_MEMORY_CPU"; break; | |
603 | case (VM_KERN_MEMORY_PMAP): name = "VM_KERN_MEMORY_PMAP"; break; | |
604 | case (VM_KERN_MEMORY_PTE): name = "VM_KERN_MEMORY_PTE"; break; | |
605 | case (VM_KERN_MEMORY_ZONE): name = "VM_KERN_MEMORY_ZONE"; break; | |
606 | case (VM_KERN_MEMORY_KALLOC): name = "VM_KERN_MEMORY_KALLOC"; break; | |
607 | case (VM_KERN_MEMORY_COMPRESSOR): name = "VM_KERN_MEMORY_COMPRESSOR"; break; | |
608 | case (VM_KERN_MEMORY_COMPRESSED_DATA): name = "VM_KERN_MEMORY_COMPRESSED_DATA"; break; | |
609 | case (VM_KERN_MEMORY_PHANTOM_CACHE): name = "VM_KERN_MEMORY_PHANTOM_CACHE"; break; | |
610 | case (VM_KERN_MEMORY_WAITQ): name = "VM_KERN_MEMORY_WAITQ"; break; | |
611 | case (VM_KERN_MEMORY_DIAG): name = "VM_KERN_MEMORY_DIAG"; break; | |
612 | case (VM_KERN_MEMORY_LOG): name = "VM_KERN_MEMORY_LOG"; break; | |
613 | case (VM_KERN_MEMORY_FILE): name = "VM_KERN_MEMORY_FILE"; break; | |
614 | case (VM_KERN_MEMORY_MBUF): name = "VM_KERN_MEMORY_MBUF"; break; | |
615 | case (VM_KERN_MEMORY_UBC): name = "VM_KERN_MEMORY_UBC"; break; | |
616 | case (VM_KERN_MEMORY_SECURITY): name = "VM_KERN_MEMORY_SECURITY"; break; | |
617 | case (VM_KERN_MEMORY_MLOCK): name = "VM_KERN_MEMORY_MLOCK"; break; | |
cf37c299 A |
618 | case (VM_KERN_MEMORY_REASON): name = "VM_KERN_MEMORY_REASON"; break; |
619 | case (VM_KERN_MEMORY_SKYWALK): name = "VM_KERN_MEMORY_SKYWALK"; break; | |
620 | case (VM_KERN_MEMORY_LTABLE): name = "VM_KERN_MEMORY_LTABLE"; break; | |
9726c137 A |
621 | case (VM_KERN_MEMORY_ANY): name = "VM_KERN_MEMORY_ANY"; break; |
622 | default: name = NULL; break; | |
623 | } | |
624 | if (name) asprintf(&result, "%s", name); | |
625 | else asprintf(&result, "VM_KERN_MEMORY_%lld", tag); | |
626 | return (result); | |
627 | } | |
628 | ||
cf37c299 | 629 | static char * |
9726c137 A |
630 | kern_vm_counter_name(uint64_t tag) |
631 | { | |
632 | char * result; | |
633 | const char * name; | |
634 | switch (tag) | |
635 | { | |
636 | case (VM_KERN_COUNT_MANAGED): name = "VM_KERN_COUNT_MANAGED"; break; | |
637 | case (VM_KERN_COUNT_RESERVED): name = "VM_KERN_COUNT_RESERVED"; break; | |
638 | case (VM_KERN_COUNT_WIRED): name = "VM_KERN_COUNT_WIRED"; break; | |
887d5eed | 639 | case (VM_KERN_COUNT_WIRED_BOOT): name = "VM_KERN_COUNT_WIRED_BOOT"; break; |
9726c137 A |
640 | case (VM_KERN_COUNT_WIRED_MANAGED): name = "VM_KERN_COUNT_WIRED_MANAGED"; break; |
641 | case (VM_KERN_COUNT_STOLEN): name = "VM_KERN_COUNT_STOLEN"; break; | |
887d5eed | 642 | case (VM_KERN_COUNT_BOOT_STOLEN): name = "VM_KERN_COUNT_BOOT_STOLEN"; break; |
9726c137 A |
643 | case (VM_KERN_COUNT_LOPAGE): name = "VM_KERN_COUNT_LOPAGE"; break; |
644 | case (VM_KERN_COUNT_MAP_KERNEL): name = "VM_KERN_COUNT_MAP_KERNEL"; break; | |
645 | case (VM_KERN_COUNT_MAP_ZONE): name = "VM_KERN_COUNT_MAP_ZONE"; break; | |
646 | case (VM_KERN_COUNT_MAP_KALLOC): name = "VM_KERN_COUNT_MAP_KALLOC"; break; | |
647 | default: name = NULL; break; | |
648 | } | |
649 | if (name) asprintf(&result, "%s", name); | |
650 | else asprintf(&result, "VM_KERN_COUNT_%lld", tag); | |
651 | return (result); | |
652 | } | |
653 | ||
654 | static void | |
655 | MakeLoadTagKeys(const void * key, const void * value, void * context) | |
656 | { | |
657 | CFMutableDictionaryRef newDict = context; | |
658 | CFDictionaryRef kextInfo = value; | |
659 | CFNumberRef loadTag; | |
660 | uint32_t loadTagValue; | |
661 | ||
662 | loadTag = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleLoadTagKey)); | |
663 | CFNumberGetValue(loadTag, kCFNumberSInt32Type, &loadTagValue); | |
664 | key = (const void *)(uintptr_t) loadTagValue; | |
665 | CFDictionarySetValue(newDict, key, value); | |
666 | } | |
667 | ||
cf37c299 | 668 | static CSSymbolicatorRef gSym; |
9726c137 A |
669 | static CFMutableDictionaryRef gTagDict; |
670 | static mach_memory_info_t * gSites; | |
671 | ||
cf37c299 | 672 | static char * |
887d5eed | 673 | GetSiteName(int siteIdx, mach_zone_name_t * zoneNames, unsigned int zoneNamesCnt) |
9726c137 A |
674 | { |
675 | const char * name; | |
887d5eed | 676 | uintptr_t kmodid; |
9726c137 | 677 | char * result; |
887d5eed | 678 | char * append; |
9726c137 A |
679 | mach_vm_address_t addr; |
680 | CFDictionaryRef kextInfo; | |
681 | CFStringRef bundleID; | |
682 | uint32_t type; | |
683 | ||
684 | const mach_memory_info_t * site; | |
685 | const char * fileName; | |
686 | CSSymbolRef symbol; | |
687 | const char * symbolName; | |
688 | CSSourceInfoRef sourceInfo; | |
689 | ||
690 | name = NULL; | |
691 | result = NULL; | |
692 | site = &gSites[siteIdx]; | |
693 | addr = site->site; | |
694 | type = (VM_KERN_SITE_TYPE & site->flags); | |
887d5eed A |
695 | kmodid = 0; |
696 | ||
697 | if (VM_KERN_SITE_NAMED & site->flags) | |
698 | { | |
699 | asprintf(&result, "%s", &site->name[0]); | |
700 | } | |
701 | else switch (type) | |
9726c137 A |
702 | { |
703 | case VM_KERN_SITE_TAG: | |
704 | result = kern_vm_tag_name(addr); | |
705 | break; | |
706 | ||
707 | case VM_KERN_SITE_COUNTER: | |
708 | result = kern_vm_counter_name(addr); | |
709 | break; | |
710 | ||
711 | case VM_KERN_SITE_KMOD: | |
887d5eed A |
712 | |
713 | kmodid = (uintptr_t) addr; | |
714 | kextInfo = CFDictionaryGetValue(gTagDict, (const void *)kmodid); | |
cf37c299 | 715 | if (kextInfo) |
9726c137 A |
716 | { |
717 | bundleID = (CFStringRef)CFDictionaryGetValue(kextInfo, kCFBundleIdentifierKey); | |
718 | name = CFStringGetCStringPtr(bundleID, kCFStringEncodingUTF8); | |
719 | // wiredSize = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleWiredSizeKey)); | |
720 | } | |
887d5eed A |
721 | |
722 | if (name) asprintf(&result, "%s", name); | |
723 | else asprintf(&result, "(unloaded kmod)"); | |
9726c137 A |
724 | break; |
725 | ||
726 | case VM_KERN_SITE_KERNEL: | |
727 | symbolName = NULL; | |
728 | if (addr) | |
729 | { | |
730 | symbol = CSSymbolicatorGetSymbolWithAddressAtTime(gSym, addr, kCSNow); | |
731 | symbolName = CSSymbolGetName(symbol); | |
732 | } | |
733 | if (symbolName) | |
734 | { | |
735 | asprintf(&result, "%s", symbolName); | |
736 | sourceInfo = CSSymbolicatorGetSourceInfoWithAddressAtTime(gSym, addr, kCSNow); | |
737 | fileName = CSSourceInfoGetPath(sourceInfo); | |
738 | if (fileName) printf(" (%s:%d)", fileName, CSSourceInfoGetLineNumber(sourceInfo)); | |
739 | } | |
740 | else | |
741 | { | |
742 | asprintf(&result, "site 0x%qx", addr); | |
743 | } | |
744 | break; | |
745 | default: | |
746 | asprintf(&result, ""); | |
747 | break; | |
748 | } | |
749 | ||
887d5eed A |
750 | if (result |
751 | && (VM_KERN_SITE_ZONE & site->flags) | |
752 | && zoneNames | |
753 | && (site->zone < zoneNamesCnt)) | |
754 | { | |
755 | size_t namelen, zonelen; | |
756 | namelen = strlen(result); | |
757 | zonelen = strnlen(zoneNames[site->zone].mzn_name, sizeof(zoneNames[site->zone].mzn_name)); | |
758 | if (((namelen + zonelen) > 61) && (zonelen < 61)) namelen = (61 - zonelen); | |
759 | asprintf(&append, "%.*s[%.*s]", | |
760 | (int)namelen, | |
761 | result, | |
762 | (int)zonelen, | |
763 | zoneNames[site->zone].mzn_name); | |
764 | free(result); | |
765 | result = append; | |
766 | } | |
767 | if (result && kmodid) | |
768 | { | |
769 | asprintf(&append, "%-64s%3ld", result, kmodid); | |
770 | free(result); | |
771 | result = append; | |
772 | } | |
773 | ||
774 | return (result); | |
9726c137 A |
775 | } |
776 | ||
887d5eed A |
777 | struct CompareThunk |
778 | { | |
779 | mach_zone_name_t *zoneNames; | |
780 | unsigned int zoneNamesCnt; | |
781 | }; | |
782 | ||
cf37c299 | 783 | static int |
887d5eed | 784 | SortName(void * thunk, const void * left, const void * right) |
9726c137 | 785 | { |
887d5eed | 786 | const struct CompareThunk * t = (typeof(t)) thunk; |
9726c137 A |
787 | const int * idxL; |
788 | const int * idxR; | |
789 | char * l; | |
790 | char * r; | |
887d5eed A |
791 | CFStringRef lcf; |
792 | CFStringRef rcf; | |
9726c137 A |
793 | int result; |
794 | ||
795 | idxL = (typeof(idxL)) left; | |
796 | idxR = (typeof(idxR)) right; | |
887d5eed A |
797 | l = GetSiteName(*idxL, t->zoneNames, t->zoneNamesCnt); |
798 | r = GetSiteName(*idxR, t->zoneNames, t->zoneNamesCnt); | |
799 | ||
800 | lcf = CFStringCreateWithCString(kCFAllocatorDefault, l, kCFStringEncodingUTF8); | |
801 | rcf = CFStringCreateWithCString(kCFAllocatorDefault, r, kCFStringEncodingUTF8); | |
802 | ||
803 | result = (int) CFStringCompareWithOptionsAndLocale(lcf, rcf, CFRangeMake(0, CFStringGetLength(lcf)), kCFCompareNumerically, NULL); | |
9726c137 | 804 | |
887d5eed A |
805 | CFRelease(lcf); |
806 | CFRelease(rcf); | |
9726c137 A |
807 | free(l); |
808 | free(r); | |
809 | ||
810 | return (result); | |
811 | } | |
812 | ||
cf37c299 | 813 | static int |
887d5eed | 814 | SortSize(void * thunk, const void * left, const void * right) |
9726c137 A |
815 | { |
816 | const mach_memory_info_t * siteL; | |
817 | const mach_memory_info_t * siteR; | |
818 | const int * idxL; | |
819 | const int * idxR; | |
820 | ||
821 | idxL = (typeof(idxL)) left; | |
822 | idxR = (typeof(idxR)) right; | |
823 | siteL = &gSites[*idxL]; | |
824 | siteR = &gSites[*idxR]; | |
825 | ||
826 | if (siteL->size > siteR->size) return (-1); | |
827 | else if (siteL->size < siteR->size) return (1); | |
828 | return (0); | |
829 | } | |
830 | ||
831 | ||
832 | static void | |
833 | PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt, | |
887d5eed A |
834 | task_zone_info_t *zoneInfo, mach_zone_name_t *zoneNames, |
835 | unsigned int zoneCnt, uint64_t zoneElements, | |
836 | int (*func)(void *, const void *, const void *), boolean_t column) | |
9726c137 A |
837 | { |
838 | uint64_t zonetotal; | |
839 | uint64_t top_wired; | |
887d5eed A |
840 | uint64_t size; |
841 | uint64_t elemsTagged; | |
9726c137 A |
842 | |
843 | CFDictionaryRef allKexts; | |
844 | unsigned int idx, site, first; | |
845 | int sorted[wiredInfoCnt]; | |
846 | char totalstr[40]; | |
847 | char * name; | |
cf37c299 | 848 | bool headerPrinted; |
9726c137 A |
849 | |
850 | zonetotal = totalsize; | |
851 | ||
852 | gSites = wiredInfo; | |
853 | ||
854 | gSym = CSSymbolicatorCreateWithMachKernel(); | |
cf37c299 | 855 | |
9726c137 | 856 | allKexts = OSKextCopyLoadedKextInfo(NULL, NULL); |
cf37c299 | 857 | gTagDict = CFDictionaryCreateMutable( |
9726c137 A |
858 | kCFAllocatorDefault, (CFIndex) 0, |
859 | (CFDictionaryKeyCallBacks *) 0, | |
860 | &kCFTypeDictionaryValueCallBacks); | |
861 | ||
862 | CFDictionaryApplyFunction(allKexts, &MakeLoadTagKeys, gTagDict); | |
863 | CFRelease(allKexts); | |
864 | ||
865 | top_wired = 0; | |
866 | ||
867 | for (idx = 0; idx < wiredInfoCnt; idx++) sorted[idx] = idx; | |
868 | first = 0; // VM_KERN_MEMORY_FIRST_DYNAMIC | |
887d5eed A |
869 | struct CompareThunk thunk; |
870 | thunk.zoneNames = zoneNames; | |
871 | thunk.zoneNamesCnt = zoneCnt; | |
872 | qsort_r(&sorted[first], | |
cf37c299 A |
873 | wiredInfoCnt - first, |
874 | sizeof(sorted[0]), | |
887d5eed | 875 | &thunk, |
9726c137 A |
876 | func); |
877 | ||
887d5eed | 878 | elemsTagged = 0; |
cf37c299 | 879 | for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++) |
9726c137 A |
880 | { |
881 | site = sorted[idx]; | |
887d5eed A |
882 | if ((VM_KERN_SITE_COUNTER & gSites[site].flags) |
883 | && (VM_KERN_COUNT_WIRED == gSites[site].site)) top_wired = gSites[site].size; | |
9726c137 | 884 | if (VM_KERN_SITE_HIDE & gSites[site].flags) continue; |
887d5eed A |
885 | if (!((VM_KERN_SITE_WIRED | VM_KERN_SITE_ZONE) & gSites[site].flags)) continue; |
886 | ||
887 | if ((VM_KERN_SITE_ZONE & gSites[site].flags) | |
888 | && gSites[site].zone < zoneCnt) | |
889 | { | |
890 | elemsTagged += gSites[site].size / zoneInfo[gSites[site].zone].tzi_elem_size; | |
891 | } | |
892 | ||
893 | if ((gSites[site].size < 1024) && (gSites[site].peak < 1024)) continue; | |
9726c137 | 894 | |
887d5eed | 895 | name = GetSiteName(site, zoneNames, zoneCnt); |
cf37c299 A |
896 | if (!substr(zname, znamelen, name, strlen(name))) continue; |
897 | if (!headerPrinted) | |
898 | { | |
899 | printf("-------------------------------------------------------------------------------------------------------------\n"); | |
887d5eed A |
900 | printf(" kmod vm peak cur\n"); |
901 | printf("wired memory id tag size waste size\n"); | |
cf37c299 A |
902 | printf("-------------------------------------------------------------------------------------------------------------\n"); |
903 | headerPrinted = true; | |
904 | } | |
9726c137 A |
905 | printf("%-67s", name); |
906 | free(name); | |
887d5eed | 907 | printf("%12d", gSites[site].tag); |
9726c137 | 908 | |
887d5eed A |
909 | if (gSites[site].peak) PRINTK(" %10llu", gSites[site].peak); |
910 | else printf(" %11s", ""); | |
911 | ||
912 | if (gSites[site].collectable_bytes) PRINTK(" %5llu", gSites[site].collectable_bytes); | |
913 | else printf(" %6s", ""); | |
914 | ||
915 | PRINTK(" %9llu", gSites[site].size); | |
916 | ||
917 | if (!(VM_KERN_SITE_ZONE & gSites[site].flags)) totalsize += gSites[site].size; | |
9726c137 A |
918 | |
919 | printf("\n"); | |
920 | } | |
921 | ||
cf37c299 A |
922 | if (!znamelen) |
923 | { | |
924 | printf("%-67s", "zones"); | |
925 | printf("%12s", ""); | |
926 | printf(" %11s", ""); | |
887d5eed A |
927 | printf(" %6s", ""); |
928 | PRINTK(" %9llu", zonetotal); | |
cf37c299 A |
929 | printf("\n"); |
930 | } | |
931 | if (headerPrinted) | |
932 | { | |
887d5eed A |
933 | if (elemsTagged) |
934 | { | |
935 | snprintf(totalstr, sizeof(totalstr), "%lld of %lld", elemsTagged, zoneElements); | |
936 | printf("zone tags%100s\n", totalstr); | |
937 | } | |
cf37c299 | 938 | snprintf(totalstr, sizeof(totalstr), "%6.2fM of %6.2fM", totalsize / 1024.0 / 1024.0, top_wired / 1024.0 / 1024.0); |
887d5eed | 939 | printf("total%104s\n", totalstr); |
cf37c299 A |
940 | } |
941 | for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++) | |
9726c137 A |
942 | { |
943 | site = sorted[idx]; | |
887d5eed A |
944 | size = gSites[site].mapped; |
945 | if (!size) continue; | |
9726c137 | 946 | if (VM_KERN_SITE_HIDE & gSites[site].flags) continue; |
887d5eed A |
947 | if ((size == gSites[site].size) |
948 | && ((VM_KERN_SITE_WIRED | VM_KERN_SITE_ZONE) & gSites[site].flags)) continue; | |
9726c137 | 949 | |
887d5eed | 950 | name = GetSiteName(site, NULL, 0); |
cf37c299 A |
951 | if (!substr(zname, znamelen, name, strlen(name))) continue; |
952 | if (!headerPrinted) | |
953 | { | |
954 | printf("-------------------------------------------------------------------------------------------------------------\n"); | |
887d5eed A |
955 | printf(" largest peak cur\n"); |
956 | printf("maps free free size size\n"); | |
cf37c299 A |
957 | printf("-------------------------------------------------------------------------------------------------------------\n"); |
958 | headerPrinted = true; | |
959 | } | |
887d5eed | 960 | printf("%-55s", name); |
9726c137 A |
961 | free(name); |
962 | ||
887d5eed A |
963 | if (gSites[site].free) PRINTK(" %10llu", gSites[site].free); |
964 | else printf(" %11s", ""); | |
965 | if (gSites[site].largest) PRINTK(" %10llu", gSites[site].largest); | |
966 | else printf(" %11s", ""); | |
967 | if (gSites[site].peak) PRINTK(" %10llu", gSites[site].peak); | |
968 | else printf(" %11s", ""); | |
969 | PRINTK(" %16llu", size); | |
9726c137 A |
970 | |
971 | printf("\n"); | |
972 | } | |
973 | } |