+
+/*********************************************************************
+*********************************************************************/
+
+static char *
+kern_vm_tag_name(uint64_t tag)
+{
+ char * result;
+ const char * name;
+ switch (tag)
+ {
+ case (VM_KERN_MEMORY_NONE): name = "VM_KERN_MEMORY_NONE"; break;
+ case (VM_KERN_MEMORY_OSFMK): name = "VM_KERN_MEMORY_OSFMK"; break;
+ case (VM_KERN_MEMORY_BSD): name = "VM_KERN_MEMORY_BSD"; break;
+ case (VM_KERN_MEMORY_IOKIT): name = "VM_KERN_MEMORY_IOKIT"; break;
+ case (VM_KERN_MEMORY_LIBKERN): name = "VM_KERN_MEMORY_LIBKERN"; break;
+ case (VM_KERN_MEMORY_OSKEXT): name = "VM_KERN_MEMORY_OSKEXT"; break;
+ case (VM_KERN_MEMORY_KEXT): name = "VM_KERN_MEMORY_KEXT"; break;
+ case (VM_KERN_MEMORY_IPC): name = "VM_KERN_MEMORY_IPC"; break;
+ case (VM_KERN_MEMORY_STACK): name = "VM_KERN_MEMORY_STACK"; break;
+ case (VM_KERN_MEMORY_CPU): name = "VM_KERN_MEMORY_CPU"; break;
+ case (VM_KERN_MEMORY_PMAP): name = "VM_KERN_MEMORY_PMAP"; break;
+ case (VM_KERN_MEMORY_PTE): name = "VM_KERN_MEMORY_PTE"; break;
+ case (VM_KERN_MEMORY_ZONE): name = "VM_KERN_MEMORY_ZONE"; break;
+ case (VM_KERN_MEMORY_KALLOC): name = "VM_KERN_MEMORY_KALLOC"; break;
+ case (VM_KERN_MEMORY_COMPRESSOR): name = "VM_KERN_MEMORY_COMPRESSOR"; break;
+ case (VM_KERN_MEMORY_COMPRESSED_DATA): name = "VM_KERN_MEMORY_COMPRESSED_DATA"; break;
+ case (VM_KERN_MEMORY_PHANTOM_CACHE): name = "VM_KERN_MEMORY_PHANTOM_CACHE"; break;
+ case (VM_KERN_MEMORY_WAITQ): name = "VM_KERN_MEMORY_WAITQ"; break;
+ case (VM_KERN_MEMORY_DIAG): name = "VM_KERN_MEMORY_DIAG"; break;
+ case (VM_KERN_MEMORY_LOG): name = "VM_KERN_MEMORY_LOG"; break;
+ case (VM_KERN_MEMORY_FILE): name = "VM_KERN_MEMORY_FILE"; break;
+ case (VM_KERN_MEMORY_MBUF): name = "VM_KERN_MEMORY_MBUF"; break;
+ case (VM_KERN_MEMORY_UBC): name = "VM_KERN_MEMORY_UBC"; break;
+ case (VM_KERN_MEMORY_SECURITY): name = "VM_KERN_MEMORY_SECURITY"; break;
+ case (VM_KERN_MEMORY_MLOCK): name = "VM_KERN_MEMORY_MLOCK"; break;
+ case (VM_KERN_MEMORY_REASON): name = "VM_KERN_MEMORY_REASON"; break;
+ case (VM_KERN_MEMORY_SKYWALK): name = "VM_KERN_MEMORY_SKYWALK"; break;
+ case (VM_KERN_MEMORY_LTABLE): name = "VM_KERN_MEMORY_LTABLE"; break;
+ case (VM_KERN_MEMORY_ANY): name = "VM_KERN_MEMORY_ANY"; break;
+ default: name = NULL; break;
+ }
+ if (name) asprintf(&result, "%s", name);
+ else asprintf(&result, "VM_KERN_MEMORY_%lld", tag);
+ return (result);
+ }
+
+static char *
+kern_vm_counter_name(uint64_t tag)
+{
+ char * result;
+ const char * name;
+ switch (tag)
+ {
+ case (VM_KERN_COUNT_MANAGED): name = "VM_KERN_COUNT_MANAGED"; break;
+ case (VM_KERN_COUNT_RESERVED): name = "VM_KERN_COUNT_RESERVED"; break;
+ case (VM_KERN_COUNT_WIRED): name = "VM_KERN_COUNT_WIRED"; break;
+ case (VM_KERN_COUNT_WIRED_MANAGED): name = "VM_KERN_COUNT_WIRED_MANAGED"; break;
+ case (VM_KERN_COUNT_STOLEN): name = "VM_KERN_COUNT_STOLEN"; break;
+ case (VM_KERN_COUNT_LOPAGE): name = "VM_KERN_COUNT_LOPAGE"; break;
+ case (VM_KERN_COUNT_MAP_KERNEL): name = "VM_KERN_COUNT_MAP_KERNEL"; break;
+ case (VM_KERN_COUNT_MAP_ZONE): name = "VM_KERN_COUNT_MAP_ZONE"; break;
+ case (VM_KERN_COUNT_MAP_KALLOC): name = "VM_KERN_COUNT_MAP_KALLOC"; break;
+ default: name = NULL; break;
+ }
+ if (name) asprintf(&result, "%s", name);
+ else asprintf(&result, "VM_KERN_COUNT_%lld", tag);
+ return (result);
+}
+
+static void
+MakeLoadTagKeys(const void * key, const void * value, void * context)
+{
+ CFMutableDictionaryRef newDict = context;
+ CFDictionaryRef kextInfo = value;
+ CFNumberRef loadTag;
+ uint32_t loadTagValue;
+
+ loadTag = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleLoadTagKey));
+ CFNumberGetValue(loadTag, kCFNumberSInt32Type, &loadTagValue);
+ key = (const void *)(uintptr_t) loadTagValue;
+ CFDictionarySetValue(newDict, key, value);
+}
+
+static CSSymbolicatorRef gSym;
+static CFMutableDictionaryRef gTagDict;
+static mach_memory_info_t * gSites;
+
+static char *
+GetSiteName(int siteIdx)
+{
+ const char * name;
+ char * result;
+ mach_vm_address_t addr;
+ CFDictionaryRef kextInfo;
+ CFStringRef bundleID;
+ uint32_t type;
+
+ const mach_memory_info_t * site;
+ const char * fileName;
+ CSSymbolRef symbol;
+ const char * symbolName;
+ CSSourceInfoRef sourceInfo;
+
+ name = NULL;
+ result = NULL;
+ site = &gSites[siteIdx];
+ addr = site->site;
+ type = (VM_KERN_SITE_TYPE & site->flags);
+ 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:
+ kextInfo = CFDictionaryGetValue(gTagDict, (const void *)(uintptr_t) addr);
+ if (kextInfo)
+ {
+ bundleID = (CFStringRef)CFDictionaryGetValue(kextInfo, kCFBundleIdentifierKey);
+ name = CFStringGetCStringPtr(bundleID, kCFStringEncodingUTF8);
+ // wiredSize = (CFNumberRef)CFDictionaryGetValue(kextInfo, CFSTR(kOSBundleWiredSizeKey));
+ }
+ asprintf(&result, "%-64s%3lld", name ? name : "(unknown kmod)", addr);
+ 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;
+ }
+
+ return (result);
+}
+
+static int
+SortName(const void * left, const void * right)
+{
+ const int * idxL;
+ const int * idxR;
+ char * l;
+ char * r;
+ int result;
+
+ idxL = (typeof(idxL)) left;
+ idxR = (typeof(idxR)) right;
+ l = GetSiteName(*idxL);
+ r = GetSiteName(*idxR);
+
+ result = strcmp(l, r);
+ free(l);
+ free(r);
+
+ return (result);
+}
+
+static int
+SortSize(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,
+ int (*func)(const void *, const void *), boolean_t column)
+{
+ uint64_t zonetotal;
+ uint64_t top_wired;
+
+ 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
+ qsort(&sorted[first],
+ wiredInfoCnt - first,
+ sizeof(sorted[0]),
+ func);
+
+ for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++)
+ {
+ site = sorted[idx];
+ if (!gSites[site].size) continue;
+ if (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 & gSites[site].flags)) continue;
+
+ name = GetSiteName(site);
+ if (!substr(zname, znamelen, name, strlen(name))) continue;
+ if (!headerPrinted)
+ {
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ printf(" kmod vm cur\n");
+ printf("wired memory id tag size\n");
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ headerPrinted = true;
+ }
+ printf("%-67s", name);
+ free(name);
+ printf("%12d", site);
+
+ printf(" %11s", "");
+ PRINTK(" %12llu", gSites[site].size);
+ totalsize += gSites[site].size;
+
+ printf("\n");
+ }
+
+ if (!znamelen)
+ {
+ printf("%-67s", "zones");
+ printf("%12s", "");
+ printf(" %11s", "");
+ PRINTK(" %12llu", zonetotal);
+ printf("\n");
+ }
+ if (headerPrinted)
+ {
+ snprintf(totalstr, sizeof(totalstr), "%6.2fM of %6.2fM", totalsize / 1024.0 / 1024.0, top_wired / 1024.0 / 1024.0);
+ printf("total%100s\n", totalstr);
+ }
+ for (headerPrinted = false, idx = 0; idx < wiredInfoCnt; idx++)
+ {
+ site = sorted[idx];
+ if (!gSites[site].size) continue;
+ if (VM_KERN_SITE_HIDE & gSites[site].flags) continue;
+ if (VM_KERN_SITE_WIRED & gSites[site].flags) continue;
+
+ name = GetSiteName(site);
+ if (!substr(zname, znamelen, name, strlen(name))) continue;
+ if (!headerPrinted)
+ {
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ printf(" largest\n");
+ printf("maps free free size\n");
+ printf("-------------------------------------------------------------------------------------------------------------\n");
+ headerPrinted = true;
+ }
+ printf("%-67s", name);
+ free(name);
+
+ PRINTK(" %10llu", gSites[site].free);
+ PRINTK(" %10llu", gSites[site].largest);
+ PRINTK(" %12llu", gSites[site].size);
+
+ printf("\n");
+ }
+}