#include <CoreFoundation/CoreFoundation.h> CFDictionaryRef OSKextCopyLoadedKextInfo(CFArrayRef kextIdentifiers, CFArrayRef infoKeys); void printUsage() { fprintf(stderr,"Usage: kextstat [-b name] [-v] [-x]\n"); fprintf(stderr,"Where: -b: Kext name or LoadTag\n"); fprintf(stderr," -v: verbose\n"); fprintf(stderr," -x: Output as XML (implies -v)\n"); } const char *display(char *str) { // convenience function to trim "com.apple" since on iOS everything is com.apple.* if (strstr(str,"com.apple.")) return str +strlen("com.apple."); return (str); } // Convert a CFString to a standard C string: const char* cstring (CFStringRef s) { return ((const char*) CFStringGetCStringPtr(s, kCFStringEncodingMacRoman)) ; } void printKext(CFDictionaryRef dict, char *Kext, int format) { const void **keys, **values; CFIndex count = CFDictionaryGetCount(dict); CFIndex i,j; int kextNum ; if (Kext && (int) Kext < 300) { kextNum = (int) Kext; } else if (Kext) kextNum = atoi(Kext); if (format == 2) { CFDataRef xml = CFPropertyListCreateXMLData(kCFAllocatorDefault, (CFPropertyListRef)dict); if (xml) { write(1, CFDataGetBytePtr(xml), CFDataGetLength(xml)); CFRelease(xml); exit(1); } } keys = (void **) malloc (sizeof(void *) * count); values = (void **) malloc (sizeof(void *) * count); CFDictionaryGetKeysAndValues (dict, //CFDictionaryRef theDict, keys, // const void **keys, values); // const void **values i = 0; while (i < count) { // we can ignore the key // char *kextName = cstring(keys[i]); // values[i] is a dict, so: if (kextNum) if (i != kextNum) { i++; continue;} for (j = 0; j < count; j++) { int kextTag; char *name = cstring(CFDictionaryGetValue(values[j], CFSTR("CFBundleIdentifier"))); int l; if (!kextNum && Kext) { if (!strstr(name, Kext)) { continue;} } CFNumberGetValue(CFDictionaryGetValue(values[j], CFSTR("OSBundleLoadTag")), kCFNumberSInt32Type , &kextTag); if (kextTag == i) { int linked = 0; CFArrayRef linkedAgainst = CFDictionaryGetValue(values[j], CFSTR("OSBundleDependencies")); printf ("%d %s ", kextTag, display(name)); if (format == 3) { printf(" depends on:\n");} if (linkedAgainst == NULL) { printf("\n"); continue; } CFIndex linkedCount = CFArrayGetCount(linkedAgainst); CFMutableArrayRef marray = CFArrayCreateMutableCopy(NULL, linkedCount, linkedAgainst); CFArraySortValues(marray, CFRangeMake(0, linkedCount), (CFComparatorFunction)CFNumberCompare, NULL); if (format <2) printf ("<"); for (l = 0 ; l < linkedCount;l++) { CFNumberGetValue(CFArrayGetValueAtIndex(marray,l), kCFNumberSInt32Type, &linked); if (format == 3) { printf ("\t"); printKext(dict, (char *)linked , 0); } else { if (l) printf(" "); printf ("%d" , linked); } } if (format <2) printf (">\n"); else if (format ==3) printf ("\n"); } } i++; } } int main (int argc, char **argv) { int i = 0; char *kextName = NULL; int xml = 0; int verbose = 0; for (i = 1; i < argc; i++) { if (strcmp(argv[i] , "-x") == 0) { xml = 2; continue;} if (strcmp(argv[i] , "-v") == 0) { verbose = 1; continue;} if (strcmp(argv[i] , "-b") == 0) { xml = 3;kextName = argv[++i]; continue;} printUsage();exit(1); } CFDictionaryRef kextDict = OSKextCopyLoadedKextInfo(NULL, // CFArrayRef kextIdentifiers, NULL); //CFArrayRef infoKeys) printKext(kextDict ,kextName, xml); }