void ProcessImageLoad(const struct mach_header* mh, intptr_t slide) { unsigned long size; std::vector<const char*> classNames; void* dataPtr = nullptr; #ifdef OBJC_ABI_2 const class_t** classes; ProcessProtocolsNew(mh, slide); classes = reinterpret_cast<const class_t**>( getsectdata(mh, SEG_OBJC_CLASSLIST_NEW, SECT_OBJC_CLASSLIST_NEW, &size) ); if (classes) { classNames = ProcessClassesNew(mh, slide, classes, size); dataPtr = (void*)*classes; } ProcessCategoriesNew(mh, slide); #else module_info* modinfo; ProcessProtocolsOld(mh, slide); modinfo = reinterpret_cast<module_info*>( getsectdata(mh, SEG_OBJC_MODINFO_OLD, SECT_OBJC_MODINFO_OLD, &size) ); if (modinfo && modinfo->symtab) { classNames = ProcessClassesOld(mh, slide, modinfo); dataPtr = modinfo; ProcessCategoriesOld(mh, slide, modinfo); } #endif UpdateClassRefs(mh); UpdateSelectors(mh, slide); // Do this only for dynamic libs (slide > 0) if (!classNames.empty() && slide > 0) { // Generate a NSFramework_XXXX class for GNUstep's NSBundle const char* path = dyld_image_path_containing_address(dataPtr); assert(path != nullptr); RegisterFramework(&classNames[0], classNames.size(), path); } static SEL selInit = sel_getUid("load"); while (!g_pendingInitClasses.empty()) { auto pair = g_pendingInitClasses.front(); g_pendingInitClasses.pop(); pair.second(reinterpret_cast<objc_object*>(pair.first), selInit); } }
static CFStringRef _CFBundleDYLDCopyLoadedImagePathForPointer(void *p) { CFStringRef result = NULL; #if USE_DYLD_PRIV const char *name = dyld_image_path_containing_address(p); if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name); #else /* USE_DYLD_PRIV */ if (!result) { uint32_t i, j, n = _dyld_image_count(); Boolean foundIt = false; const char *name; #if TARGET_RT_64_BIT #define MACH_HEADER_TYPE struct mach_header_64 #define MACH_SEGMENT_CMD_TYPE struct segment_command_64 #define MACH_SEGMENT_FLAVOR LC_SEGMENT_64 #else #define MACH_HEADER_TYPE struct mach_header #define MACH_SEGMENT_CMD_TYPE struct segment_command #define MACH_SEGMENT_FLAVOR LC_SEGMENT #endif for (i = 0; !foundIt && i < n; i++) { const MACH_HEADER_TYPE *mh = (const MACH_HEADER_TYPE *)_dyld_get_image_header(i); uintptr_t addr = (uintptr_t)p - _dyld_get_image_vmaddr_slide(i); if (mh) { struct load_command *lc = (struct load_command *)((char *)mh + sizeof(MACH_HEADER_TYPE)); for (j = 0; !foundIt && j < mh->ncmds; j++, lc = (struct load_command *)((char *)lc + lc->cmdsize)) { if (MACH_SEGMENT_FLAVOR == lc->cmd && ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr <= addr && addr < ((MACH_SEGMENT_CMD_TYPE *)lc)->vmaddr + ((MACH_SEGMENT_CMD_TYPE *)lc)->vmsize) { foundIt = true; name = _dyld_get_image_name(i); if (name) result = CFStringCreateWithFileSystemRepresentation(kCFAllocatorSystemDefault, name); } } } } #undef MACH_HEADER_TYPE #undef MACH_SEGMENT_CMD_TYPE #undef MACH_SEGMENT_FLAVOR } #endif /* USE_DYLD_PRIV */ #if LOG_BUNDLE_LOAD printf("dyld image path for pointer %p is %p\n", p, result); #endif /* LOG_BUNDLE_LOAD */ return result; }