+ switch (type) {
+ case VM_KERN_SITE_TAG:
+ result = kern_vm_tag_name(addr);
+ break;
+
+ case VM_KERN_SITE_COUNTER:
+ result = kern_vm_counter_name(addr);
+ break;
+
+ case VM_KERN_SITE_KMOD:
+
+ kmodid = (uintptr_t) addr;
+ kextInfo = CFDictionaryGetValue(gTagDict, (const void *)kmodid);
+ if (kextInfo) {
+ bundleID = (CFStringRef)CFDictionaryGetValue(kextInfo, kCFBundleIdentifierKey);
+ name = CFStringGetCStringPtr(bundleID, kCFStringEncodingUTF8);
+ // wiredSize = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleWiredSizeKey));
+ }
+
+ if (name) {
+ asprintf(&result, "%s", name);
+ } else {
+ asprintf(&result, "(unloaded kmod)");
+ }
+ break;
+
+ case VM_KERN_SITE_KERNEL:
+ symbolName = NULL;
+ if (addr) {
+ symbol = CSSymbolicatorGetSymbolWithAddressAtTime(gSym, addr, kCSNow);
+ symbolName = CSSymbolGetName(symbol);
+ }
+ if (symbolName) {
+ asprintf(&result, "%s", symbolName);
+ sourceInfo = CSSymbolicatorGetSourceInfoWithAddressAtTime(gSym, addr, kCSNow);
+ fileName = CSSourceInfoGetPath(sourceInfo);
+ if (fileName) {
+ printf(" (%s:%d)", fileName, CSSourceInfoGetLineNumber(sourceInfo));
+ }
+ } else {
+ asprintf(&result, "site 0x%qx", addr);
+ }
+ break;
+ default:
+ asprintf(&result, "");
+ break;
+ }
+ }
+
+ if (result
+ && (VM_KERN_SITE_ZONE & site->flags)
+ && zoneNames
+ && (site->zone < zoneNamesCnt)) {
+ size_t namelen, zonelen;
+ namelen = strlen(result);
+ zonelen = strnlen(zoneNames[site->zone].mzn_name, sizeof(zoneNames[site->zone].mzn_name));
+ if (((namelen + zonelen) > 61) && (zonelen < 61)) {
+ namelen = (61 - zonelen);
+ }
+ asprintf(&append, "%.*s[%.*s]",
+ (int)namelen,
+ result,
+ (int)zonelen,
+ zoneNames[site->zone].mzn_name);
+ free(result);
+ result = append;
+ }
+ if (result && kmodid) {
+ asprintf(&append, "%-64s%3ld", result, kmodid);
+ free(result);
+ result = append;
+ }
+
+ return result;
+}
+
+struct CompareThunk {
+ mach_zone_name_t *zoneNames;
+ unsigned int zoneNamesCnt;
+};
+
+static int
+SortName(void * thunk, const void * left, const void * right)
+{
+ const struct CompareThunk * t = (typeof(t))thunk;
+ const int * idxL;
+ const int * idxR;
+ char * l;
+ char * r;
+ CFStringRef lcf;
+ CFStringRef rcf;
+ int result;
+
+ idxL = (typeof(idxL))left;
+ idxR = (typeof(idxR))right;
+ l = GetSiteName(*idxL, t->zoneNames, t->zoneNamesCnt);
+ r = GetSiteName(*idxR, t->zoneNames, t->zoneNamesCnt);
+
+ lcf = CFStringCreateWithCString(kCFAllocatorDefault, l, kCFStringEncodingUTF8);
+ rcf = CFStringCreateWithCString(kCFAllocatorDefault, r, kCFStringEncodingUTF8);
+
+ result = (int) CFStringCompareWithOptionsAndLocale(lcf, rcf, CFRangeMake(0, CFStringGetLength(lcf)), kCFCompareNumerically, NULL);
+
+ CFRelease(lcf);
+ CFRelease(rcf);
+ free(l);
+ free(r);
+
+ return result;
+}
+
+static int
+SortSize(void * thunk, const void * left, const void * right)
+{
+ const mach_memory_info_t * siteL;
+ const mach_memory_info_t * siteR;
+ const int * idxL;
+ const int * idxR;
+
+ idxL = (typeof(idxL))left;
+ idxR = (typeof(idxR))right;
+ siteL = &gSites[*idxL];
+ siteR = &gSites[*idxR];
+
+ if (siteL->size > siteR->size) {
+ return -1;
+ } else if (siteL->size < siteR->size) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static void
+PrintLarge(mach_memory_info_t *wiredInfo, unsigned int wiredInfoCnt,
+ mach_zone_info_t *zoneInfo, mach_zone_name_t *zoneNames,
+ unsigned int zoneCnt, uint64_t zoneElements,
+ int (*func)(void *, const void *, const void *), boolean_t column)
+{
+ uint64_t zonetotal;
+ uint64_t top_wired;
+ uint64_t size;
+ uint64_t elemsTagged;
+
+ CFDictionaryRef allKexts;
+ unsigned int idx, site, first;
+ int sorted[wiredInfoCnt];
+ char totalstr[40];
+ char * name;
+ bool headerPrinted;
+
+ zonetotal = totalsize;
+
+ gSites = wiredInfo;
+
+ gSym = CSSymbolicatorCreateWithMachKernel();
+
+ allKexts = OSKextCopyLoadedKextInfo(NULL, NULL);
+ gTagDict = CFDictionaryCreateMutable(
+ kCFAllocatorDefault, (CFIndex) 0,
+ (CFDictionaryKeyCallBacks *) 0,
+ &kCFTypeDictionaryValueCallBacks);
+
+ CFDictionaryApplyFunction(allKexts, &MakeLoadTagKeys, gTagDict);
+ CFRelease(allKexts);
+
+ top_wired = 0;
+
+ for (idx = 0; idx < wiredInfoCnt; idx++) {
+ sorted[idx] = idx;
+ }
+ first = 0; // VM_KERN_MEMORY_FIRST_DYNAMIC
+ struct CompareThunk thunk;
+ thunk.zoneNames = zoneNames;
+ thunk.zoneNamesCnt = zoneCnt;
+ qsort_r(&sorted[first],
+ wiredInfoCnt - first,
+ sizeof(sorted[0]),
+ &thunk,
+ func);
+
+ elemsTagged = 0;
+ for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++) {
+ site = sorted[idx];
+ if ((VM_KERN_SITE_COUNTER & gSites[site].flags)
+ && (VM_KERN_COUNT_WIRED == gSites[site].site)) {
+ top_wired = gSites[site].size;
+ }
+ if (VM_KERN_SITE_HIDE & gSites[site].flags) {
+ continue;
+ }
+ if (!((VM_KERN_SITE_WIRED | VM_KERN_SITE_ZONE) & gSites[site].flags)) {
+ continue;
+ }
+
+ if ((VM_KERN_SITE_ZONE & gSites[site].flags)
+ && gSites[site].zone < zoneCnt) {
+ elemsTagged += gSites[site].size / zoneInfo[gSites[site].zone].mzi_elem_size;
+ }
+
+ if ((gSites[site].size < 1024) && (gSites[site].peak < 1024)) {
+ continue;
+ }
+
+ name = GetSiteName(site, zoneNames, zoneCnt);
+ if (!substr(zname, znamelen, name, strlen(name))) {
+ continue;
+ }
+ if (!headerPrinted) {
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ printf(" kmod vm peak cur\n");
+ printf("wired memory id tag size waste size\n");
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ headerPrinted = true;
+ }
+ printf("%-67s", name);
+ free(name);
+ printf("%12d", gSites[site].tag);
+
+ if (gSites[site].peak) {
+ PRINTK(" %10llu", gSites[site].peak);
+ } else {
+ printf(" %11s", "");
+ }
+
+ if (gSites[site].collectable_bytes) {
+ PRINTK(" %5llu", gSites[site].collectable_bytes);
+ } else {
+ printf(" %6s", "");
+ }
+
+ PRINTK(" %9llu", gSites[site].size);
+
+ if (!(VM_KERN_SITE_ZONE & gSites[site].flags)) {
+ totalsize += gSites[site].size;
+ }
+
+ printf("\n");
+ }
+
+ if (!znamelen) {
+ printf("%-67s", "zones");
+ printf("%12s", "");
+ printf(" %11s", "");
+ printf(" %6s", "");
+ PRINTK(" %9llu", zonetotal);
+ printf("\n");
+ }
+ if (headerPrinted) {
+ if (elemsTagged) {
+ snprintf(totalstr, sizeof(totalstr), "%lld of %lld", elemsTagged, zoneElements);
+ printf("zone tags%100s\n", totalstr);
+ }
+ snprintf(totalstr, sizeof(totalstr), "%6.2fM of %6.2fM", totalsize / 1024.0 / 1024.0, top_wired / 1024.0 / 1024.0);
+ printf("total%104s\n", totalstr);
+ }
+ for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++) {
+ site = sorted[idx];
+ size = gSites[site].mapped;
+ if (!size) {
+ continue;
+ }
+ if (VM_KERN_SITE_HIDE & gSites[site].flags) {
+ continue;
+ }
+ if ((size == gSites[site].size)
+ && ((VM_KERN_SITE_WIRED | VM_KERN_SITE_ZONE) & gSites[site].flags)) {
+ continue;
+ }
+
+ name = GetSiteName(site, NULL, 0);
+ if (!substr(zname, znamelen, name, strlen(name))) {
+ continue;
+ }
+ if (!headerPrinted) {
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ printf(" largest peak cur\n");
+ printf("maps free free size size\n");
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ headerPrinted = true;
+ }
+ printf("%-55s", name);
+ free(name);
+
+ if (gSites[site].free) {
+ PRINTK(" %10llu", gSites[site].free);
+ } else {
+ printf(" %11s", "");
+ }
+ if (gSites[site].largest) {
+ PRINTK(" %10llu", gSites[site].largest);
+ } else {
+ printf(" %11s", "");
+ }
+ if (gSites[site].peak) {
+ PRINTK(" %10llu", gSites[site].peak);
+ } else {
+ printf(" %11s", "");
+ }
+ PRINTK(" %16llu", size);
+
+ printf("\n");
+ }
+ for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++) {
+ site = sorted[idx];
+ size = gSites[site].size;
+ if (!size || !(VM_KERN_SITE_ZONE_VIEW & gSites[site].flags)) {
+ continue;
+ }
+
+ name = GetSiteName(site, NULL, 0);
+ if (!substr(zname, znamelen, name, strlen(name))) {
+ continue;
+ }
+ if (!headerPrinted) {
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ printf(" cur\n");
+ printf("zone views inuse\n");
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ headerPrinted = true;
+ }
+ printf("%-55s", name);
+ free(name);
+
+ printf(" %11s", "");
+ printf(" %11s", "");
+ printf(" %11s", "");
+ PRINTK(" %16llu", size);
+
+ printf("\n");