Last active
January 24, 2021 10:03
-
-
Save darkfall/13001c901edf0dc9fb85 to your computer and use it in GitHub Desktop.
get objc subclasses via private runtime info
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <objc/objc-runtime.h> | |
#if __LP64__ | |
typedef uint32_t mask_t; | |
#define FAST_DATA_MASK 0x00007ffffffffff8UL | |
#else | |
typedef uint64_t mask_t; | |
#define FAST_DATA_MASK 0xfffffffcUL | |
#endif | |
struct cache_t { | |
void* buckets; | |
mask_t mask; | |
mask_t occupied; | |
} ; | |
struct class_rw_t { | |
uint32_t flags; | |
uint32_t version; | |
void* ro; | |
void* methods; | |
void* properties; | |
void* protocols; | |
Class firstSubClass; | |
Class nextSiblingClass; | |
const char* demangleName; | |
}; | |
struct class_data_bits_t { | |
uintptr_t bits; | |
class_rw_t* data() { | |
return (class_rw_t*)(bits & FAST_DATA_MASK); | |
} | |
}; | |
struct objc_class_t { | |
Class isa; | |
Class superclass; | |
cache_t cache; | |
class_data_bits_t dataBits; | |
Class getFirstSubClass() { | |
return dataBits.data()->firstSubClass; | |
} | |
Class getNextSiblingClass() { | |
return dataBits.data()->nextSiblingClass; | |
} | |
}; | |
void print_subclass_tree(Class cls, int level) | |
{ | |
objc_class_t* rt_cls = (__bridge objc_class_t*)cls; | |
Class subClass = rt_cls->getFirstSubClass(); | |
while(subClass) | |
{ | |
for(int i=0; i<level; ++i) | |
printf(" "); | |
printf("%s\n", class_getName(subClass)); | |
print_subclass_tree(subClass, level + 1); | |
subClass = ((__bridge objc_class_t*)subClass)->getNextSiblingClass(); | |
} | |
} | |
int main(int argc, const char * argv[]) { | |
Class cls = objc_getClass("NSObject"); | |
print_subclass_tree(cls, 0); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment