Skip to content

Instantly share code, notes, and snippets.

@darkfall
Last active January 24, 2021 10:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • 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>
// from objc_runtime_new.h with some simplifications
#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 class_rw_t {
// flag, version, ro, methods, properties, protocols
uint8_t __placeholder[sizeof(uint32_t) * 2 + sizeof(void*) * 4];
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;
// buckets, masks = cache_t
uint8_t __placeholder[sizeof(void*) + sizeof(mask_t) * 2];
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