Skip to content

Instantly share code, notes, and snippets.

@darkfall
Last active January 24, 2021 10:03
Show Gist options
  • Save darkfall/13001c901edf0dc9fb85 to your computer and use it in GitHub Desktop.
Save darkfall/13001c901edf0dc9fb85 to your computer and use it in GitHub Desktop.
get objc subclasses via private runtime info
#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