this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Split libobjcdarwin code into many files, using module_info on old ABI, new ABI category support and much more

+1728 -1042
+3 -2
etc/dylib.conf
··· 3 3 libiconv.2.dylib=libSystem.B.dylib.so 4 4 libstdc++.6.dylib=libSystem.B.dylib.so 5 5 #libncurses.5.4.dylib=libncurses.so.5 6 - /usr/local/lib/darling/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation=libCoreFoundation.so 7 - /usr/local/lib/darling/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices=libgnustep-base.so 6 + /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation=libCoreFoundation.so 7 + /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices=libgnustep-base.so 8 + /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation=libgnustep-base.so 8 9
-281
src/libobjcdarwin/AppleLayout.h
··· 1 - #ifndef APPLELAYOUT_H 2 - #define APPLELAYOUT_H 3 - #include <iterator> 4 - 5 - struct method_t 6 - { 7 - const char* selName; 8 - const char* types; 9 - void* impl; 10 - }; 11 - 12 - struct method_list_t 13 - { 14 - uint32_t entsize_and_flags; 15 - uint32_t count; 16 - method_t method_list[]; 17 - 18 - uint32_t entsize() const { return entsize_and_flags & ~uint32_t(3); } 19 - }; 20 - 21 - struct ivar_t 22 - { 23 - uintptr_t* offset; 24 - const char* name; 25 - const char* type; 26 - uint32_t alignment, size; 27 - }; 28 - 29 - struct ivar_list_t 30 - { 31 - uint32_t entsize, count; 32 - ivar_t ivar_list[]; 33 - }; 34 - 35 - struct protocol_list_t; 36 - struct property_list_t; 37 - struct protocol_t 38 - { 39 - id isa; 40 - const char* name; 41 - protocol_list_t* protocols; // inherited protocols 42 - method_list_t *methods, *staticMethods, *optMethods, *optStaticMethods; 43 - property_list_t* properties; 44 - uint32_t size, flags; 45 - const char** extMethTypes; // reflects the order and count of methods above as listed in this struct 46 - 47 - inline const protocol_t* next() const 48 - { 49 - uintptr_t ptr = reinterpret_cast<uintptr_t>(this); 50 - ptr += size; 51 - return reinterpret_cast<const protocol_t*>(ptr); 52 - } 53 - }; 54 - 55 - template <typename ProtoList> 56 - class protocol_iterator : public std::iterator<std::input_iterator_tag, const protocol_t*> 57 - { 58 - const ProtoList* m_list; 59 - size_t m_index; 60 - intptr_t m_slide; 61 - public: 62 - protocol_iterator(const ProtoList* list, size_t index, intptr_t slide) : m_list(list), m_index(index), m_slide(slide) {} 63 - protocol_iterator(const protocol_iterator& that) : m_list(that.m_list), m_index(that.m_index), m_slide(that.m_slide) {} 64 - protocol_iterator& operator++() { m_index++; return *this; } 65 - bool operator==(const protocol_iterator& that) { return that.m_index == m_index; } 66 - bool operator!=(const protocol_iterator& that) { return that.m_index != m_index; } 67 - const protocol_t* operator*() { return m_list->elem(m_index, m_slide); } 68 - }; 69 - 70 - struct protocol_list_t 71 - { 72 - uintptr_t count; 73 - uintptr_t list[]; // the compiler doesn't add a rebase here 74 - inline const protocol_t* elem(size_t i, uintptr_t slide) const 75 - { 76 - return reinterpret_cast<const protocol_t*>(list[i] + slide); 77 - } 78 - protocol_iterator<protocol_list_t> begin(intptr_t slide) const { return protocol_iterator<protocol_list_t>(this, 0, slide); } 79 - protocol_iterator<protocol_list_t> end(intptr_t slide) const { return protocol_iterator<protocol_list_t>(this, count, slide); } 80 - }; 81 - 82 - struct old_method_decl 83 - { 84 - const char *name, *types; 85 - }; 86 - struct old_method_decl_list 87 - { 88 - int count; 89 - old_method_decl list[]; 90 - }; 91 - struct property_t 92 - { 93 - const char *name, *attributes; 94 - }; 95 - 96 - struct property_list_t 97 - { 98 - uint32_t entsize, count; 99 - property_t list[]; 100 - }; 101 - typedef property_t old_property; 102 - typedef property_list_t old_property_list; 103 - 104 - struct old_protocol; 105 - struct old_protocol_list 106 - { 107 - old_protocol_list* linked; 108 - long count; 109 - old_protocol* list[]; 110 - }; 111 - 112 - struct old_protocol_ext 113 - { 114 - uint32_t size; 115 - old_method_decl_list *optMethods, *optStaticMethods; 116 - old_property_list* properties; 117 - const char** extMethTypes; 118 - }; 119 - 120 - struct old_protocol 121 - { 122 - union 123 - { 124 - id isa; 125 - old_protocol_ext* ext; // __protocol_ext section 126 - uintptr_t ext_ptrValue; 127 - }; 128 - const char* name; 129 - old_protocol_list* protocols; 130 - old_method_decl_list *methods, *staticMethods; 131 - }; 132 - 133 - struct class_ro_t 134 - { 135 - uint32_t flags, instStart, instSize; 136 - #ifdef __x86_64__ 137 - uint32_t nothing; 138 - #endif 139 - void* ivarLayout; 140 - const char* className; 141 - const method_list_t* baseMethods; // instance methods for classes, static methods for metaclasses 142 - const protocol_list_t* baseProtocols; 143 - const ivar_list_t* ivars; 144 - 145 - void* todo[1]; // TODO: more pointers 146 - const property_list_t* baseProperties; 147 - }; 148 - 149 - #if 0 // UNUSED 150 - struct class_rw_t 151 - { 152 - uint32_t flags, version; 153 - class_ro_t* ro; 154 - 155 - union 156 - { 157 - method_list_t* method_list; 158 - method_list_t** method_lists; 159 - }; 160 - 161 - void* todo[4]; // TODO: four more pointers 162 - }; 163 - #endif 164 - 165 - struct class_t 166 - { 167 - class_t* isa; // instance of 168 - class_t* superclass; 169 - void* cache; // empty cache imported here 170 - void* vtable; 171 - uintptr_t data_and_flags; 172 - 173 - // TODO: WTF? Should be rw data 174 - class_ro_t* data() const 175 - { 176 - uintptr_t p = data_and_flags & ~uintptr_t(3); 177 - return reinterpret_cast<class_ro_t*>(p); 178 - } 179 - }; 180 - 181 - union old_class_ptr 182 - { 183 - struct old_class* cls; 184 - const char* name; 185 - uintptr_t ptrValue; 186 - Class clsNew; 187 - }; 188 - 189 - struct old_class 190 - { 191 - old_class_ptr isa; 192 - old_class_ptr super_class; 193 - const char *name; 194 - long version; 195 - long info; 196 - long instance_size; 197 - struct old_ivar_list *ivars; 198 - struct old_method_list *methodList; 199 - void* cache; 200 - struct old_protocol_list *protocols; 201 - // CLS_EXT only 202 - const uint8_t *ivar_layout; 203 - struct old_class_ext *ext; 204 - }; 205 - 206 - struct old_class_ext 207 - { 208 - uint32_t size; 209 - const uint8_t *weak_ivar_layout; 210 - old_property_list **propertyLists; 211 - }; 212 - 213 - struct old_category 214 - { 215 - char *category_name; 216 - char *class_name; 217 - struct old_method_list *instance_methods; 218 - struct old_method_list *class_methods; 219 - struct old_protocol_list *protocols; 220 - uint32_t size; 221 - old_property_list *instance_properties; 222 - }; 223 - 224 - struct old_ivar 225 - { 226 - char *name; 227 - char *type; 228 - int offset; 229 - #ifdef __x86_64__ 230 - int space; 231 - #endif 232 - }; 233 - 234 - struct old_ivar_list 235 - { 236 - int count; 237 - #ifdef __x86_64__ 238 - int space; 239 - #endif 240 - /* variable length structure */ 241 - struct old_ivar ivar_list[1]; 242 - }; 243 - 244 - 245 - struct old_method 246 - { 247 - const char* selName; 248 - const char* types; 249 - void* impl; 250 - }; 251 - 252 - struct old_method_list 253 - { 254 - struct old_method_list *obsolete; 255 - 256 - int count; 257 - #ifdef __x86_64__ 258 - int space; 259 - #endif 260 - /* variable length structure */ 261 - struct old_method method_list[1]; 262 - }; 263 - 264 - union selref 265 - { 266 - const char* selName; 267 - SEL sel; 268 - }; 269 - struct msgref 270 - { 271 - void* objc_msgSend_fixup; // function pointer 272 - selref sel; 273 - }; 274 - union clsref 275 - { 276 - const char* clsName; 277 - Class cls; 278 - }; 279 - 280 - #endif 281 -
+17 -3
src/libobjcdarwin/CMakeLists.txt
··· 12 12 #endif (NOT "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang") 13 13 14 14 #configure_file(config.h.in config.h) 15 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fPIC -ggdb") 16 - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -fPIC -ggdb") 15 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fPIC -fvisibility=hidden -ggdb") 16 + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -fPIC -fvisibility=hidden -ggdb") 17 17 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fPIC") 18 18 19 19 set(objcdarwin_SRCS 20 20 objc_msgSend_fixup.nasm 21 21 objc_msgSendSuper.nasm 22 22 NameTranslate.cpp 23 - ClassRegister.mm 23 + ClassRegister.cpp 24 + 25 + common/attribute.cpp 26 + common/property.cpp 27 + common/selector.cpp 28 + 29 + old/category.cpp 30 + old/class.cpp 31 + old/ivar.mm 32 + old/protocol.cpp 33 + 34 + new/category.cpp 35 + new/class.cpp 36 + new/ivar.cpp 37 + new/protocol.cpp 24 38 ) 25 39 26 40 add_library(objc.A.dylib SHARED ${objcdarwin_SRCS})
+75
src/libobjcdarwin/ClassRegister.cpp
··· 1 + #include "ClassRegister.h" 2 + #include "../dyld/public.h" 3 + #include "../util/trace.h" 4 + #include "../util/log.h" 5 + #include "old/protocol.h" 6 + #include "new/protocol.h" 7 + #include "old/class.h" 8 + #include "new/class.h" 9 + #include "old/category.h" 10 + #include "new/category.h" 11 + #include "common/selector.h" 12 + #include <map> 13 + 14 + // Superclass references in Mach-O don't use classref 15 + // Neither do category class references 16 + std::map<const void*,Class> g_classPointers; 17 + 18 + // Here we process Mach-O files that have been loaded before this native library 19 + // Then we register a handler to process all images loaded in the future 20 + __attribute__((constructor)) 21 + void RegisterAlreadyLoadedClasses() 22 + { 23 + for (uint32_t i = 0; i < _dyld_image_count(); i++) 24 + { 25 + const struct mach_header* hdr = _dyld_get_image_header(i); 26 + ProcessImageLoad(hdr, 0); 27 + } 28 + 29 + _dyld_register_func_for_add_image(ProcessImageLoad); 30 + _dyld_register_func_for_remove_image(ProcessImageUnload); 31 + 32 + //std::cout << "Done registering\n"; 33 + } 34 + 35 + 36 + void ProcessImageLoad(const struct mach_header* mh, intptr_t slide) 37 + { 38 + unsigned long size; 39 + const class_t** classes; 40 + 41 + ProcessProtocolsNew(mh, slide); 42 + ProcessProtocolsOld(mh, slide); 43 + 44 + classes = reinterpret_cast<const class_t**>( 45 + getsectdata(mh, SEG_OBJC_CLASSLIST_NEW, SECT_OBJC_CLASSLIST_NEW, &size) 46 + ); 47 + 48 + if (!classes) 49 + { 50 + // Try the old runtime 51 + module_info* modinfo; 52 + 53 + modinfo = reinterpret_cast<module_info*>( 54 + getsectdata(mh, SEG_OBJC_MODINFO_OLD, SECT_OBJC_MODINFO_OLD, &size) 55 + ); 56 + 57 + if (modinfo) 58 + { 59 + ProcessClassesOld(mh, slide, modinfo); 60 + } 61 + } 62 + else 63 + { 64 + ProcessClassesNew(mh, slide, classes, size); 65 + } 66 + 67 + ProcessCategoriesNew(mh, slide); 68 + UpdateSelectors(mh, slide); 69 + } 70 + 71 + void ProcessImageUnload(const struct mach_header* mh, intptr_t) 72 + { 73 + // TODO 74 + } 75 +
+2 -97
src/libobjcdarwin/ClassRegister.h
··· 5 5 #include <cstddef> 6 6 #include <algorithm> 7 7 #include <objc/runtime.h> 8 - #include "AppleLayout.h" 9 8 #include "../util/log.h" 10 9 11 - /* TODO? 12 - * __DATA,__objc_classlist was __OBJC2,__class_list 13 - * __DATA,__objc_catlist was __OBJC2,__category_list 14 - * __DATA,__objc_protolist was __OBJC2,__protocol_list 15 - * __DATA,__objc_msgrefs was __OBJC2,__message_refs 16 - * __DATA,__objc_classrefs was __OBJC2,__class_refs 17 - * __DATA,__objc_superrefs was __OBJC2,__super_refs 18 - * __DATA,__objc_imageinfo was __OBJC,__image_info 19 - * */ 20 - 21 - static const char* SEG_DATA = "__DATA"; 22 - static const char* SEG_OBJC_CLASSLIST_NEW = SEG_DATA; 23 - static const char* SECT_OBJC_CLASSLIST_NEW = "__objc_classlist"; 24 - static const char* SEG_OBJC_CLASSREFS_NEW = SEG_DATA; 25 - static const char* SECT_OBJC_CLASSREFS_NEW = "__objc_classrefs"; 26 - static const char* SEG_OBJC_SUPERREFS_NEW = SEG_DATA; 27 - static const char* SECT_OBJC_SUPERREFS_NEW = "__objc_superrefs"; 28 - static const char* SEG_OBJC_SELREFS_NEW = SEG_DATA; 29 - static const char* SECT_OBJC_SELREFS_NEW = "__objc_selrefs"; 30 - static const char* SEG_OBJC_MSGREFS_NEW = SEG_DATA; // used with objc_msgSend_fixup 31 - static const char* SECT_OBJC_MSGREFS_NEW = "__objc_msgrefs"; 32 - static const char* SEG_OBJC_PROTOREFS_NEW = SEG_DATA; 33 - static const char* SECT_OBJC_PROTOREFS_NEW = "__objc_protorefs"; 34 - static const char* SEG_OBJC_PROTOLIST_NEW = SEG_DATA; 35 - static const char* SECT_OBJC_PROTOLIST_NEW = "__objc_protolist"; 36 - 37 - static const char* SEG_OBJC = "__OBJC"; 38 - static const char* SEG_OBJC_CLASSLIST_OLD = SEG_OBJC; 39 - static const char* SECT_OBJC_CLASSLIST_OLD = "__class"; 40 - static const char* SEG_OBJC_METALIST_OLD = SEG_OBJC; 41 - static const char* SECT_OBJC_METALIST_OLD = "__meta_class"; 42 - static const char* SEG_OBJC_CLASSREFS_OLD = SEG_OBJC; 43 - static const char* SECT_OBJC_CLASSREFS_OLD = "__cls_refs"; 44 - static const char* SEG_OBJC_SELREFS_OLD = SEG_OBJC; 45 - static const char* SECT_OBJC_SELREFS_OLD = "__message_refs"; 46 - static const char* SEG_OBJC_PROTOCOLS_OLD = SEG_OBJC; 47 - static const char* SECT_OBJC_PROTOCOLS_OLD = "__protocol"; 48 - static const char* SEG_OBJC_PROTOEXT_OLD = SEG_OBJC; 49 - static const char* SECT_OBJC_PROTOEXT_OLD = "__protocol_ext"; 50 - 51 - static void ProcessImageLoad(const struct mach_header* mh, intptr_t slide); 52 - static void ProcessImageUnload(const struct mach_header* mh, intptr_t slide); 53 - static Class RegisterClass(const class_t* cls, intptr_t slide); 54 - static Class RegisterClass(old_class* cls); 55 - static void ProcessProtocolsNew(const struct mach_header* mh, intptr_t slide); 56 - static void ProcessProtocolsOld(const struct mach_header* mh, intptr_t slide); 57 - static Protocol* RegisterProtocol(const protocol_t* prot, intptr_t slide); 58 - static Protocol* RegisterProtocol(old_protocol* prot, uintptr_t extStart, unsigned long extLen); 59 - static void UpdateSelectors(const struct mach_header* mh, intptr_t slide); 60 - static void ProcessRuntimeOld(const struct mach_header* mh, intptr_t slide, old_class* classes, unsigned long size); 61 - static void ProcessRuntimeNew(const struct mach_header* mh, intptr_t slide, const class_t** classes, unsigned long size); 62 - static void ConvertProperties(Class c, const property_list_t* props); 63 - static void RegisterProtocolMethods(Protocol* p, const method_list_t* list, const char** extTypes, size_t& extIndex, bool required, bool instance); 64 - static void RegisterProtocolMethods(Protocol* p, const old_method_decl_list* list, bool required, bool instance); 65 - 66 - template<typename OrigType, typename NewType> 67 - static void find_and_fix(OrigType** start, OrigType** end, const OrigType* what, const NewType* ptr) 68 - { 69 - OrigType** pos = std::find(start, end, const_cast<OrigType*>(what)); 70 - if (pos != end) 71 - { 72 - LOG << "ObjC fixup @" << pos << ": " << *pos << " -> " << ptr << std::endl; 73 - *reinterpret_cast<uintptr_t*>(pos) = reinterpret_cast<uintptr_t>(ptr); 74 - } 75 - } 76 - 77 - // mprotect() requires that mem be on a page boundary. 78 - // This function satisfies this requirement. 79 - static int mprotect_pagemult(void* mem, size_t len, int prot); 80 - 81 - template<typename T> 82 - int mprotect_pagemult(T** mem, size_t len, int prot) 83 - { 84 - return mprotect_pagemult(reinterpret_cast<void*>(mem), len, prot); 85 - } 86 - 87 - /* UNUSED 88 - template<typename ForwardIterator, typename T, typename Processor> process_split_sections(ForwardIterator start, ForwardIterator end, const T& sep, Processor proc) 89 - { 90 - ForwardIterator beg = start; 91 - while (start != end) 92 - { 93 - if (*start == sep) 94 - { 95 - proc(beg, start); 96 - start++; 97 - beg = start; 98 - } 99 - else 100 - start++; 101 - } 102 - 103 - if (beg != end) 104 - proc(beg, end); 105 - } 106 - */ 10 + void ProcessImageLoad(const struct mach_header* mh, intptr_t slide); 11 + void ProcessImageUnload(const struct mach_header* mh, intptr_t); 107 12 108 13 #endif 109 14
-658
src/libobjcdarwin/ClassRegister.mm
··· 1 - #include "ClassRegister.h" 2 - #include "../dyld/public.h" 3 - #include "../util/trace.h" 4 - #include "../util/log.h" 5 - #include <climits> 6 - #include <stddef.h> 7 - #include <Foundation/NSObjCRuntime.h> 8 - #include <iostream> 9 - #include <map> 10 - #include <algorithm> 11 - #include <cstring> 12 - #include <cassert> 13 - #include <sys/mman.h> 14 - #include "TopologySort.h" 15 - 16 - static std::pair<uintptr_t,uintptr_t> g_cstringSection; 17 - // Superclass references in Mach-O don't use classref 18 - static std::map<const void*,Class> g_superClasses; 19 - 20 - // Here we process Mach-O files that have been loaded before this native library 21 - // Then we register a handler to process all images loaded in the future 22 - __attribute__((constructor)) 23 - void RegisterAlreadyLoadedClasses() 24 - { 25 - for (uint32_t i = 0; i < _dyld_image_count(); i++) 26 - { 27 - const struct mach_header* hdr = _dyld_get_image_header(i); 28 - ProcessImageLoad(hdr, 0); 29 - } 30 - 31 - _dyld_register_func_for_add_image(ProcessImageLoad); 32 - _dyld_register_func_for_remove_image(ProcessImageUnload); 33 - 34 - //std::cout << "Done registering\n"; 35 - } 36 - 37 - template<typename ListType> void ConvertMethodListGen(Class c, const ListType* list) 38 - { 39 - LOG << list->count << " methods within\n"; 40 - 41 - for (size_t i = 0; i < list->count; i++) 42 - { 43 - auto* m = &list->method_list[i]; 44 - 45 - LOG << "Method: selName: " << m->selName << "; types: " << m->types << "; impl: " << m->impl << std::endl; 46 - 47 - SEL sel = sel_registerName(m->selName); 48 - class_addMethod(c, sel, reinterpret_cast<IMP>(m->impl), m->types); 49 - } 50 - } 51 - 52 - static void ConvertIvarList(Class c, const ivar_list_t* list) 53 - { 54 - LOG << list->count << " ivars within\n"; 55 - 56 - for (size_t i = 0; i < list->count; i++) 57 - { 58 - auto* v = &list->ivar_list[i]; 59 - 60 - LOG << "Ivar: name: " << v->name << "; type: " << v->type << "; offset: " << *v->offset << "; size: " << v->size << "; alignment: " << v->alignment << std::endl; 61 - class_addIvar(c, v->name, v->size, v->alignment, v->type); 62 - } 63 - } 64 - 65 - static void ConvertIvarList(Class c, const old_ivar_list* list) 66 - { 67 - LOG << list->count << " ivars within\n"; 68 - 69 - for (size_t i = 0; i < list->count; i++) 70 - { 71 - auto* v = &list->ivar_list[i]; 72 - NSUInteger size, alignment; 73 - 74 - NSGetSizeAndAlignment(v->type, &size, &alignment); 75 - alignment = 1; // TODO: why do we need alignment when we have an offset? 76 - 77 - LOG << "Ivar: name: " << v->name << "; type: " << v->type << "; offset: " << v->offset << "; size: " << size << "; alignment: " << alignment << std::endl; 78 - class_addIvar(c, v->name, size, alignment, v->type); 79 - } 80 - } 81 - 82 - static bool nextAttribute(objc_property_attribute_t& next, const char*& pos, std::vector<std::string>& strings) 83 - { 84 - if (!*pos) 85 - return false; 86 - else if (*pos == ',') 87 - pos++; 88 - 89 - if (*pos == '"') 90 - { 91 - const char* start = ++pos; 92 - while (*pos != '"' && *pos) 93 - pos++; 94 - 95 - assert(*pos != '\0'); 96 - 97 - strings.push_back(std::string(start, pos-start)); 98 - next.name = strings.back().c_str(); 99 - 100 - start = ++pos; 101 - while (*pos != ',' && *pos) 102 - pos++; 103 - 104 - strings.push_back(std::string(start, pos-start)); 105 - next.value = strings.back().c_str(); 106 - } 107 - else 108 - { 109 - strings.push_back(std::string(1, *pos)); 110 - next.name = strings.back().c_str(); 111 - const char* start = ++pos; 112 - 113 - while (*pos != ',' && *pos) 114 - pos++; 115 - 116 - strings.push_back(std::string(start, pos-start)); 117 - next.value = strings.back().c_str(); 118 - } 119 - 120 - return true; 121 - } 122 - 123 - template<typename Func> 124 - void ConvertProperties(const property_list_t* props, Func f) 125 - { 126 - for (uint32_t i = 0; i < props->count; i++) 127 - { 128 - const property_t* prop = &props->list[i]; 129 - std::vector<objc_property_attribute_t> attribs; 130 - std::vector<std::string> strings; 131 - objc_property_attribute_t next; 132 - const char* pos = prop->attributes; 133 - 134 - while (nextAttribute(next, pos, strings)) 135 - attribs.push_back(next); 136 - 137 - f(prop->name, &attribs[0], attribs.size()); 138 - } 139 - } 140 - 141 - Class RegisterClass(const class_t* cls, intptr_t slide) 142 - { 143 - LOG << "Processing ObjC class " << cls->data()->className << std::endl; 144 - 145 - const class_t* meta = cls->isa; 146 - Class conv, super; 147 - auto itSuper = g_superClasses.find(cls->superclass); 148 - 149 - if (itSuper != g_superClasses.end()) 150 - super = itSuper->second; 151 - else 152 - super = reinterpret_cast<Class>(cls->superclass); 153 - 154 - LOG << "...superclass is @" << super << std::endl; 155 - conv = objc_allocateClassPair(super, cls->data()->className, 0); 156 - 157 - const class_ro_t* ro = cls->data(); 158 - const class_ro_t* roMeta = meta->data(); 159 - 160 - if (ro->baseMethods) 161 - ConvertMethodListGen(conv, ro->baseMethods); 162 - if (roMeta->baseMethods) 163 - ConvertMethodListGen(object_getClass(id(conv)), roMeta->baseMethods); 164 - if (ro->ivars) 165 - ConvertIvarList(conv, ro->ivars); 166 - if (ro->baseProtocols) 167 - { 168 - for (size_t i = 0; i < ro->baseProtocols->count; i++) 169 - { 170 - const char* name = ro->baseProtocols->elem(i, slide)->name; 171 - Protocol* p = objc_getProtocol(name); 172 - assert(p != nullptr); 173 - class_addProtocol(conv, p); 174 - } 175 - } 176 - if (ro->baseProperties) 177 - ConvertProperties(ro->baseProperties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); }); 178 - 179 - // conv->instance_size = ro->instSize; 180 - // conv->isa->instance_size = roMeta->instSize; 181 - 182 - objc_registerClassPair(conv); 183 - LOG << "ObjC class " << cls->data()->className << " now @" << conv << std::endl; 184 - g_superClasses[cls] = conv; 185 - 186 - return conv; 187 - } 188 - 189 - 190 - // This is very wrong. Does it have to be this way? 191 - static old_class* PtrToClass(old_class_ptr ptr) 192 - { 193 - if (ptr.ptrValue >= g_cstringSection.first && ptr.ptrValue < g_cstringSection.first+g_cstringSection.second) 194 - { 195 - //std::cout << ptr.cls << " found to be a string: " << ptr.name << std::endl; 196 - id cls = objc_getClass(ptr.name); // it is a string 197 - 198 - assert(cls != nullptr); 199 - return (old_class*) cls; 200 - } 201 - else 202 - { 203 - //std::cout << ptr.cls << " found to be ptr to class.\n"; 204 - return ptr.cls; 205 - } 206 - } 207 - 208 - Class RegisterClass(old_class* cls) 209 - { 210 - LOG << "Processing old ObjC class " << cls->name << std::endl; 211 - 212 - const old_class* meta = PtrToClass(cls->isa); 213 - Class conv, super; 214 - old_class* psuper = PtrToClass(cls->super_class); 215 - auto itSuper = g_superClasses.find(psuper); // TODO: may not be needed, should always be a string 216 - 217 - if (itSuper != g_superClasses.end()) 218 - super = itSuper->second; 219 - else 220 - super = reinterpret_cast<Class>(psuper); 221 - LOG << "...with superclass @" << super << std::endl; 222 - conv = objc_allocateClassPair(super, cls->name, 0); 223 - 224 - if (cls->methodList) 225 - ConvertMethodListGen(conv, cls->methodList); 226 - if (meta->methodList) 227 - ConvertMethodListGen(object_getClass(id(conv)), meta->methodList); 228 - if (cls->ivars) 229 - ConvertIvarList(conv, cls->ivars); 230 - if (cls->protocols) 231 - { 232 - for (long i = 0; i < cls->protocols->count; i++) 233 - { 234 - Protocol* p = objc_getProtocol(cls->protocols->list[i]->name); 235 - assert(p != nullptr); 236 - class_addProtocol(conv, p); 237 - } 238 - } 239 - // TODO: properties in EXT 240 - 241 - objc_registerClassPair(conv); 242 - g_superClasses[cls] = conv; 243 - g_superClasses[cls->name] = conv; 244 - 245 - LOG << "ObjC class " << cls->name << " @" << conv << std::endl; 246 - 247 - return conv; 248 - } 249 - 250 - void RegisterProtocolMethods(Protocol* p, const method_list_t* list, const char** extTypes, size_t& extIndex, bool required, bool instance) 251 - { 252 - LOG << "Registering Protocol methods (" << required << ", " << instance << "): " << list->count << " methods within\n"; 253 - for (size_t i = 0; i < list->count; i++, extIndex++) 254 - { 255 - SEL sel = sel_registerName(list->method_list[i].selName); 256 - protocol_addMethodDescription(p, sel, list->method_list[i].types, required, instance); 257 - // TODO: what do we do with extTypes? 258 - } 259 - } 260 - 261 - Protocol* RegisterProtocol(const protocol_t* prot, intptr_t slide) 262 - { 263 - // For reasons unknown, the NSObject protocol is duplicated into the binaries 264 - if (strcmp(prot->name, "NSObject") == 0) 265 - return objc_getProtocol(prot->name); 266 - 267 - LOG << "Processing ObjC Protocol: " << prot->name << std::endl; 268 - Protocol* conv = objc_allocateProtocol(prot->name); 269 - size_t methodIndex = 0; 270 - 271 - if (prot->protocols) 272 - { 273 - for (size_t i = 0; i < prot->protocols->count; i++) 274 - { 275 - const char* name = prot->protocols->elem(i, slide)->name; 276 - protocol_addProtocol(conv, objc_getProtocol(name)); 277 - } 278 - } 279 - 280 - if (prot->methods) 281 - RegisterProtocolMethods(conv, prot->methods, prot->extMethTypes, methodIndex, true, true); 282 - if (prot->staticMethods) 283 - RegisterProtocolMethods(conv, prot->staticMethods, prot->extMethTypes, methodIndex, true, false); 284 - if (prot->optMethods) 285 - RegisterProtocolMethods(conv, prot->optMethods, prot->extMethTypes, methodIndex, false, true); 286 - if (prot->optStaticMethods) 287 - RegisterProtocolMethods(conv, prot->optStaticMethods, prot->extMethTypes, methodIndex, false, false); 288 - 289 - if (prot->properties) 290 - ConvertProperties(prot->properties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { protocol_addProperty(conv, name, attr, count, true, true); }); 291 - 292 - objc_registerProtocol(conv); 293 - return conv; 294 - } 295 - 296 - void RegisterProtocolMethods(Protocol* p, const old_method_decl_list* list, bool required, bool instance) 297 - { 298 - LOG << "Registering Protocol methods (" << required << ", " << instance << "): " << list->count << " methods within\n"; 299 - for (size_t i = 0; i < list->count; i++) 300 - { 301 - SEL sel = sel_registerName(list->list[i].name); 302 - protocol_addMethodDescription(p, sel, list->list[i].types, required, instance); 303 - // TODO: what do we do with extTypes? 304 - } 305 - } 306 - 307 - Protocol* RegisterProtocol(old_protocol* prot, uintptr_t extStart, unsigned long extLen) 308 - { 309 - // For reasons unknown, the NSObject protocol is duplicated into the binaries 310 - if (strcmp(prot->name, "NSObject") == 0) 311 - return objc_getProtocol(prot->name); 312 - 313 - LOG << "Processing old ObjC Protocol: " << prot->name << std::endl; 314 - Protocol* conv = objc_allocateProtocol(prot->name); 315 - 316 - if (prot->protocols) 317 - { 318 - for (size_t i = 0; i < prot->protocols->count; i++) 319 - { 320 - const char* name = prot->protocols->list[i]->name; 321 - protocol_addProtocol(conv, objc_getProtocol(name)); 322 - } 323 - } 324 - 325 - if (prot->methods) 326 - RegisterProtocolMethods(conv, prot->methods, true, true); 327 - if (prot->staticMethods) 328 - RegisterProtocolMethods(conv, prot->staticMethods, true, false); 329 - 330 - // Protocol EXT - weird stuff 331 - if (prot->ext_ptrValue >= extStart && prot->ext_ptrValue < extStart + extLen) 332 - { 333 - // TODO: check if rebase is present 334 - if (prot->ext->optMethods) 335 - RegisterProtocolMethods(conv, prot->ext->optMethods, false, true); 336 - if (prot->ext->optStaticMethods) 337 - RegisterProtocolMethods(conv, prot->ext->optStaticMethods, false, false); 338 - if (prot->ext->properties) 339 - ConvertProperties(prot->ext->properties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { protocol_addProperty(conv, name, attr, count, true, true); }); 340 - } 341 - 342 - objc_registerProtocol(conv); 343 - return conv; 344 - } 345 - 346 - int mprotect_pagemult(void* mem, size_t len, int prot) 347 - { 348 - /* 349 - static int psize = ::getpagesize(); 350 - uintptr_t ptr = reinterpret_cast<uintptr_t>(mem); 351 - if (uintptr_t diff = ptr % psize) 352 - { 353 - ptr -= diff; 354 - len += diff; 355 - mem = reinterpret_cast<void*>(ptr); 356 - } 357 - return ::mprotect(mem, len, prot); 358 - */ 359 - // Short circuit: the segments that are now in use are always R/W 360 - return 0; 361 - } 362 - 363 - void ProcessRuntimeOld(const struct mach_header* mh, intptr_t slide, old_class* classes, unsigned long size) 364 - { 365 - unsigned long cstrLen; 366 - void* ptr; 367 - std::vector<old_class*> vecClasses; 368 - std::set<old_class*> setClasses; 369 - std::map<const char*,old_class*> mapClassNames; 370 - 371 - ProcessProtocolsOld(mh, slide); 372 - 373 - ptr = getsectdata(mh, "__TEXT", "__cstring", &cstrLen); 374 - if (ptr) 375 - g_cstringSection = std::pair<uintptr_t,uintptr_t>(uintptr_t(ptr), cstrLen); 376 - else 377 - g_cstringSection = std::pair<uintptr_t,uintptr_t>(0, 0); 378 - 379 - for (size_t i = 0; i < size / sizeof(old_class); i++) 380 - { 381 - mapClassNames[classes[i].name] = classes+i; 382 - setClasses.insert(classes+i); 383 - } 384 - 385 - topology_sort(setClasses, vecClasses, 386 - [&mapClassNames](old_class* t) -> std::set<old_class*> { auto it = mapClassNames.find(t->super_class.name); return (it != mapClassNames.end()) ? std::set<old_class*>{it->second} : std::set<old_class*>(); } 387 - ); 388 - 389 - for (old_class* c : vecClasses) 390 - RegisterClass(c); 391 - 392 - clsref* class_refs; 393 - unsigned long refsize; 394 - 395 - class_refs = reinterpret_cast<clsref*>( 396 - getsectdata(mh, SEG_OBJC_CLASSREFS_OLD, SECT_OBJC_CLASSREFS_OLD, &refsize) 397 - ); 398 - 399 - if (class_refs) 400 - { 401 - for (size_t i = 0; i < refsize / sizeof(clsref); i++) 402 - { 403 - Class c = objc_getClass(class_refs[i].clsName); 404 - LOG << "ObjC fixup classref @" << &class_refs[i].cls << ": " << class_refs[i].cls << " -> " << c << std::endl; 405 - class_refs[i].cls = c; 406 - } 407 - } 408 - 409 - // Change class names in 'super_class' from strings to pointers to Class 410 - for (size_t i = 0; i < size / sizeof(old_class); i++) 411 - { 412 - Class c = objc_getClass(classes[i].super_class.name); 413 - LOG << "ObjC fixup super_class @" << &classes[i].super_class << ": " << classes[i].super_class.name << " -> " << c << std::endl; 414 - classes[i].super_class.clsNew = c; 415 - } 416 - 417 - // Fix the same in metaclasses 418 - classes = reinterpret_cast<old_class*>( 419 - getsectdata(mh, SEG_OBJC_METALIST_OLD, SECT_OBJC_METALIST_OLD, &size) 420 - ); 421 - 422 - if (classes) 423 - { 424 - for (size_t i = 0; i < size / sizeof(old_class); i++) 425 - { 426 - Class c = objc_getClass(classes[i].super_class.name); 427 - LOG << "ObjC fixup super_class @" << &classes[i].super_class << ": " << classes[i].super_class.name << " -> " << c << std::endl; 428 - classes[i].super_class.clsNew = c; 429 - } 430 - } 431 - } 432 - 433 - void ProcessProtocolsNew(const struct mach_header* mh, intptr_t slide) 434 - { 435 - const protocol_t** protocol_list; 436 - unsigned long protosize; 437 - 438 - protocol_list = reinterpret_cast<const protocol_t**>( 439 - getsectdata(mh, SEG_OBJC_PROTOLIST_NEW, SECT_OBJC_PROTOLIST_NEW, &protosize) 440 - ); 441 - 442 - if (protocol_list) 443 - { 444 - unsigned long refsize; 445 - protocol_t** protocol_refs; 446 - protocol_t** protocol_refs_end; 447 - std::set<const protocol_t*> setProtocols; 448 - std::vector<const protocol_t*> vecProtocols; 449 - 450 - protocol_refs = reinterpret_cast<protocol_t**>( 451 - getsectdata(mh, SEG_OBJC_PROTOREFS_NEW, SECT_OBJC_PROTOREFS_NEW, &refsize) 452 - ); 453 - 454 - if (protocol_refs) 455 - protocol_refs_end = protocol_refs + refsize / sizeof(protocol_t*); 456 - 457 - std::copy(protocol_list, protocol_list+protosize/sizeof(protocol_t*), std::inserter(setProtocols, setProtocols.begin())); 458 - topology_sort<const protocol_t>(setProtocols, vecProtocols, 459 - [&setProtocols,slide](const protocol_t* p) { return p->protocols ? std::set<const protocol_t*>(p->protocols->begin(slide), p->protocols->end(slide)) : std::set<const protocol_t*>(); }); 460 - 461 - for (const protocol_t* proto : vecProtocols) 462 - { 463 - Protocol* p = RegisterProtocol(proto, slide); 464 - 465 - if (protocol_refs) 466 - find_and_fix(protocol_refs, protocol_refs_end, proto, p); 467 - } 468 - } 469 - } 470 - 471 - void ProcessProtocolsOld(const struct mach_header* mh, intptr_t slide) 472 - { 473 - old_protocol* protocols; 474 - unsigned long protosize; 475 - 476 - protocols = reinterpret_cast<old_protocol*>( 477 - getsectdata(mh, SEG_OBJC_PROTOCOLS_OLD, SECT_OBJC_PROTOCOLS_OLD, &protosize) 478 - ); 479 - 480 - if (protocols) 481 - { 482 - std::vector<old_protocol*> vecProtocols; 483 - std::set<old_protocol*> setProtocols; 484 - // std::map<const char*,old_protocol*> mapProtocols; 485 - 486 - for (size_t i = 0; i < protosize / sizeof(old_protocol); i++) 487 - { 488 - if (strcmp(protocols[i].name, "NSObject") != 0) // No need to re-register protocol NSObject 489 - setProtocols.insert(protocols + i); 490 - // mapProtocols[protocols[i].name] = protocols + i; 491 - } 492 - 493 - topology_sort<old_protocol>(setProtocols, vecProtocols, 494 - [&setProtocols](old_protocol* p) -> std::set<old_protocol*> 495 - { 496 - std::set<old_protocol*> set; 497 - if (p->protocols) 498 - { 499 - for (size_t i = 0; i < p->protocols->count; i++) 500 - { 501 - if (setProtocols.count(p->protocols->list[i])) 502 - set.insert(p->protocols->list[i]); 503 - } 504 - } 505 - return set; 506 - } 507 - ); 508 - 509 - // Find the section that holds protocol_ext structs 510 - uintptr_t extStart; 511 - unsigned long extLen = 0; 512 - 513 - extStart = reinterpret_cast<uintptr_t>( 514 - getsectdata(mh, SEG_OBJC_PROTOEXT_OLD, SECT_OBJC_PROTOEXT_OLD, &extLen) 515 - ); 516 - 517 - for (old_protocol* old : vecProtocols) 518 - { 519 - Protocol* p = RegisterProtocol(old, extStart, extLen); 520 - old->isa = p; // This is what is referenced in the code 521 - } 522 - } 523 - } 524 - 525 - void ProcessRuntimeNew(const struct mach_header* mh, intptr_t slide, const class_t** classes, unsigned long size) 526 - { 527 - class_t **class_refs, **class_refs_end, **super_refs, **super_refs_end; 528 - unsigned long refsize, refsize_s; 529 - std::vector<const class_t*> vecClasses; 530 - std::set<const class_t*> setClasses; 531 - 532 - ProcessProtocolsNew(mh, slide); 533 - 534 - class_refs = reinterpret_cast<class_t**>( 535 - getsectdata(mh, SEG_OBJC_CLASSREFS_NEW, SECT_OBJC_CLASSREFS_NEW, &refsize) 536 - ); 537 - super_refs = reinterpret_cast<class_t**>( 538 - getsectdata(mh, SEG_OBJC_SUPERREFS_NEW, SECT_OBJC_SUPERREFS_NEW, &refsize_s) 539 - ); 540 - if (class_refs) 541 - { 542 - class_refs_end = class_refs + refsize / sizeof(class_t*); 543 - mprotect_pagemult(class_refs, refsize, PROT_READ | PROT_WRITE); 544 - } 545 - 546 - if (super_refs) 547 - { 548 - super_refs_end = super_refs + refsize_s / sizeof(class_t*); 549 - mprotect_pagemult(super_refs, refsize, PROT_READ | PROT_WRITE); 550 - } 551 - 552 - std::copy(classes, classes+size/sizeof(class_t*), std::inserter(setClasses, setClasses.begin())); 553 - 554 - topology_sort<const class_t>(setClasses, vecClasses, 555 - [&setClasses](const class_t* t) { return setClasses.count(t->superclass) ? std::set<const class_t*>{t->superclass} : std::set<const class_t*>(); } 556 - ); 557 - 558 - for (const class_t* cls : vecClasses) 559 - { 560 - Class c = RegisterClass(cls, slide); 561 - 562 - if (class_refs) 563 - find_and_fix(class_refs, class_refs_end, cls, c); 564 - if (super_refs) 565 - find_and_fix(super_refs, super_refs_end, cls, c); 566 - } 567 - 568 - if (class_refs) 569 - mprotect_pagemult(class_refs, refsize, PROT_READ); 570 - if (super_refs) 571 - mprotect_pagemult(super_refs, refsize_s, PROT_READ); 572 - } 573 - 574 - void UpdateSelectors(const struct mach_header* mh, intptr_t slide) 575 - { 576 - selref* sel_refs; 577 - msgref* msg_refs; 578 - unsigned long selsize, msgsize; 579 - 580 - sel_refs = reinterpret_cast<selref*>( 581 - getsectdata(mh, SEG_OBJC_SELREFS_NEW, SECT_OBJC_SELREFS_NEW, &selsize) 582 - ); 583 - 584 - msg_refs = reinterpret_cast<msgref*>( 585 - getsectdata(mh, SEG_OBJC_MSGREFS_NEW, SECT_OBJC_MSGREFS_NEW, &msgsize) 586 - ); 587 - 588 - if (!sel_refs) 589 - { 590 - sel_refs = reinterpret_cast<selref*>( 591 - getsectdata(mh, SEG_OBJC_SELREFS_OLD, SECT_OBJC_SELREFS_OLD, &selsize) 592 - ); 593 - } 594 - 595 - if (sel_refs) 596 - { 597 - mprotect_pagemult(sel_refs, selsize, PROT_READ | PROT_WRITE); 598 - 599 - for (size_t i = 0; i < selsize / sizeof(selref); i++) 600 - { 601 - SEL native = sel_getUid(sel_refs[i].selName); 602 - LOG << "ObjC SEL fixup @" << (sel_refs+i) << ": " << sel_refs[i].sel << " -> " << native << std::endl; 603 - sel_refs[i].sel = native; 604 - } 605 - 606 - mprotect_pagemult(sel_refs, selsize, PROT_READ); 607 - } 608 - if (msg_refs) 609 - { 610 - mprotect_pagemult(msg_refs, msgsize, PROT_READ | PROT_WRITE); 611 - 612 - for (size_t i = 0; i < msgsize / sizeof(msgref); i++) 613 - { 614 - SEL native = sel_getUid(msg_refs[i].sel.selName); 615 - LOG << "ObjC msgref fixup @" << &msg_refs[i].sel.sel << ": " << msg_refs[i].sel.sel << " -> " << native << std::endl; 616 - msg_refs[i].sel.sel = native; 617 - } 618 - 619 - mprotect_pagemult(msg_refs, msgsize, PROT_READ); 620 - } 621 - } 622 - 623 - void ProcessImageLoad(const struct mach_header* mh, intptr_t slide) 624 - { 625 - unsigned long size; 626 - const class_t** classes; 627 - 628 - classes = reinterpret_cast<const class_t**>( 629 - getsectdata(mh, SEG_OBJC_CLASSLIST_NEW, SECT_OBJC_CLASSLIST_NEW, &size) 630 - ); 631 - 632 - if (!classes) 633 - { 634 - // Try the old runtime 635 - old_class* classes; 636 - 637 - classes = reinterpret_cast<old_class*>( 638 - getsectdata(mh, SEG_OBJC_CLASSLIST_OLD, SECT_OBJC_CLASSLIST_OLD, &size) 639 - ); 640 - 641 - if (classes) 642 - { 643 - ProcessRuntimeOld(mh, slide, classes, size); 644 - } 645 - } 646 - else 647 - { 648 - ProcessRuntimeNew(mh, slide, classes, size); 649 - } 650 - 651 - UpdateSelectors(mh, slide); 652 - } 653 - 654 - void ProcessImageUnload(const struct mach_header* mh, intptr_t) 655 - { 656 - // TODO 657 - } 658 -
+16
src/libobjcdarwin/common/AppleLayout.h
··· 1 + #ifndef COMMON_APPLELAYOUT_H 2 + #define COMMON_APPLELAYOUT_H 3 + #include <objc/runtime.h> 4 + 5 + union selref 6 + { 7 + const char* selName; 8 + SEL sel; 9 + }; 10 + struct msgref 11 + { 12 + void* objc_msgSend_fixup; // function pointer 13 + selref sel; 14 + }; 15 + 16 + #endif
+43
src/libobjcdarwin/common/attribute.cpp
··· 1 + #include "attribute.h" 2 + #include <cassert> 3 + 4 + bool nextAttribute(objc_property_attribute_t& next, const char*& pos, std::vector<std::string>& strings) 5 + { 6 + if (!*pos) 7 + return false; 8 + else if (*pos == ',') 9 + pos++; 10 + 11 + if (*pos == '"') 12 + { 13 + const char* start = ++pos; 14 + while (*pos != '"' && *pos) 15 + pos++; 16 + 17 + assert(*pos != '\0'); 18 + 19 + strings.push_back(std::string(start, pos-start)); 20 + next.name = strings.back().c_str(); 21 + 22 + start = ++pos; 23 + while (*pos != ',' && *pos) 24 + pos++; 25 + 26 + strings.push_back(std::string(start, pos-start)); 27 + next.value = strings.back().c_str(); 28 + } 29 + else 30 + { 31 + strings.push_back(std::string(1, *pos)); 32 + next.name = strings.back().c_str(); 33 + const char* start = ++pos; 34 + 35 + while (*pos != ',' && *pos) 36 + pos++; 37 + 38 + strings.push_back(std::string(start, pos-start)); 39 + next.value = strings.back().c_str(); 40 + } 41 + 42 + return true; 43 + }
+11
src/libobjcdarwin/common/attribute.h
··· 1 + #ifndef COMMON_ATTRIBUTE_H 2 + #define COMMON_ATTRIBUTE_H 3 + #include <objc/runtime.h> 4 + #include <stdint.h> 5 + #include <string> 6 + #include "./AppleLayout.h" 7 + #include <vector> 8 + 9 + bool nextAttribute(objc_property_attribute_t& next, const char*& pos, std::vector<std::string>& strings); 10 + 11 + #endif
+19
src/libobjcdarwin/common/method.h
··· 1 + #ifndef COMMON_METHOD_H 2 + #define COMMON_METHOD_H 3 + 4 + template<typename ListType> void ConvertMethodListGen(Class c, const ListType* list) 5 + { 6 + LOG << list->count << " methods within\n"; 7 + 8 + for (size_t i = 0; i < list->count; i++) 9 + { 10 + auto* m = &list->method_list[i]; 11 + 12 + LOG << "Method: selName: " << m->selName << "; types: " << m->types << "; impl: " << m->impl << std::endl; 13 + 14 + SEL sel = sel_registerName(m->selName); 15 + class_addMethod(c, sel, reinterpret_cast<IMP>(m->impl), m->types); 16 + } 17 + } 18 + 19 + #endif
+10
src/libobjcdarwin/common/property.cpp
··· 1 + #include "property.h" 2 + #include "../libobjc/class.h" // For a bug workaround only 3 + #include "../libobjc/properties.h" // ditto 4 + 5 + // Fixed in GNUstep r35658 6 + void bug_gnustepFixPropertyCount(Class c) 7 + { 8 + if (c->properties->count == 0) 9 + c->properties->count = 1; 10 + }
+34
src/libobjcdarwin/common/property.h
··· 1 + #ifndef COMMON_PROPERTY_H 2 + #define COMMON_PROPERTY_H 3 + #include <objc/runtime.h> 4 + #include <stdint.h> 5 + #include "./AppleLayout.h" 6 + #include "../../util/log.h" 7 + #include "attribute.h" 8 + #include <vector> 9 + 10 + template<typename PropList, typename Func> 11 + void ConvertProperties(const PropList* props, Func f) 12 + { 13 + LOG << "Registering " << props->count << " properties\n"; 14 + for (uint32_t i = 0; i < props->count; i++) 15 + { 16 + auto* prop = &props->list[i]; 17 + std::vector<objc_property_attribute_t> attribs; 18 + std::vector<std::string> strings; 19 + objc_property_attribute_t next; 20 + const char* pos = prop->attributes; 21 + 22 + while (nextAttribute(next, pos, strings)) 23 + attribs.push_back(next); 24 + 25 + //attribs.clear(); 26 + LOG << "\tProperty " << prop->name << " with " << attribs.size() << " attributes\n"; 27 + f(prop->name, &attribs[0], attribs.size()); 28 + } 29 + } 30 + 31 + void bug_gnustepFixPropertyCount(Class c); 32 + 33 + 34 + #endif
+16
src/libobjcdarwin/common/ref.h
··· 1 + #ifndef COMMON_REF_H 2 + #define COMMON_REF_H 3 + #include <algorithm> 4 + 5 + template<typename OrigType, typename NewType> 6 + static void find_and_fix(OrigType** start, OrigType** end, const OrigType* what, const NewType* ptr) 7 + { 8 + OrigType** pos = std::find(start, end, const_cast<OrigType*>(what)); 9 + if (pos != end) 10 + { 11 + LOG << "ObjC fixup @" << pos << ": " << *pos << " -> " << ptr << std::endl; 12 + *reinterpret_cast<uintptr_t*>(pos) = reinterpret_cast<uintptr_t>(ptr); 13 + } 14 + } 15 + 16 + #endif
+46
src/libobjcdarwin/common/selector.cpp
··· 1 + #include "selector.h" 2 + #include "../new/AppleLayout.h" 3 + #include "../old/AppleLayout.h" 4 + #include "../../dyld/public.h" 5 + #include "../../util/log.h" 6 + 7 + void UpdateSelectors(const struct mach_header* mh, intptr_t slide) 8 + { 9 + selref* sel_refs; 10 + msgref* msg_refs; 11 + unsigned long selsize, msgsize; 12 + 13 + sel_refs = reinterpret_cast<selref*>( 14 + getsectdata(mh, SEG_OBJC_SELREFS_NEW, SECT_OBJC_SELREFS_NEW, &selsize) 15 + ); 16 + 17 + msg_refs = reinterpret_cast<msgref*>( 18 + getsectdata(mh, SEG_OBJC_MSGREFS_NEW, SECT_OBJC_MSGREFS_NEW, &msgsize) 19 + ); 20 + 21 + if (!sel_refs) 22 + { 23 + sel_refs = reinterpret_cast<selref*>( 24 + getsectdata(mh, SEG_OBJC_SELREFS_OLD, SECT_OBJC_SELREFS_OLD, &selsize) 25 + ); 26 + } 27 + 28 + if (sel_refs) 29 + { 30 + for (size_t i = 0; i < selsize / sizeof(selref); i++) 31 + { 32 + SEL native = sel_getUid(sel_refs[i].selName); 33 + LOG << "ObjC SEL fixup @" << (sel_refs+i) << ": " << sel_refs[i].sel << " -> " << native << std::endl; 34 + sel_refs[i].sel = native; 35 + } 36 + } 37 + if (msg_refs) 38 + { 39 + for (size_t i = 0; i < msgsize / sizeof(msgref); i++) 40 + { 41 + SEL native = sel_getUid(msg_refs[i].sel.selName); 42 + LOG << "ObjC msgref fixup @" << &msg_refs[i].sel.sel << ": " << msg_refs[i].sel.sel << " -> " << native << std::endl; 43 + msg_refs[i].sel.sel = native; 44 + } 45 + } 46 + }
+8
src/libobjcdarwin/common/selector.h
··· 1 + #ifndef COMMON_SELECTOR_H 2 + #define COMMON_SELECTOR_H 3 + #include <objc/runtime.h> 4 + #include <stdint.h> 5 + 6 + void UpdateSelectors(const struct mach_header* mh, intptr_t slide); 7 + 8 + #endif
+291
src/libobjcdarwin/libobjc/class.h
··· 1 + #ifndef __OBJC_CLASS_H_INCLUDED 2 + #define __OBJC_CLASS_H_INCLUDED 3 + #include "visibility.h" 4 + 5 + /** 6 + * Overflow bitfield. Used for bitfields that are more than 63 bits. 7 + */ 8 + struct objc_bitfield 9 + { 10 + /** 11 + * The number of elements in the values array. 12 + */ 13 + int32_t length; 14 + /** 15 + * An array of values. Each 32 bits is stored in the native endian for the 16 + * platform. 17 + */ 18 + int32_t values[0]; 19 + }; 20 + 21 + struct objc_class 22 + { 23 + /** 24 + * Pointer to the metaclass for this class. The metaclass defines the 25 + * methods use when a message is sent to the class, rather than an 26 + * instance. 27 + */ 28 + struct objc_class *isa; 29 + /** 30 + * Pointer to the superclass. The compiler will set this to the name of 31 + * the superclass, the runtime will initialize it to point to the real 32 + * class. 33 + */ 34 + struct objc_class *super_class; 35 + /** 36 + * The name of this class. Set to the same value for both the class and 37 + * its associated metaclass. 38 + */ 39 + const char *name; 40 + /** 41 + * The version of this class. This is not used by the language, but may be 42 + * set explicitly at class load time. 43 + */ 44 + long version; 45 + /** 46 + * A bitfield containing various flags. See the objc_class_flags 47 + * enumerated type for possible values. 48 + */ 49 + unsigned long info; 50 + /** 51 + * The size of this class. For classes using the non-fragile ABI, the 52 + * compiler will set this to a negative value The absolute value will be 53 + * the size of the instance variables defined on just this class. When 54 + * using the fragile ABI, the instance size is the size of instances of 55 + * this class, including any instance variables defined on superclasses. 56 + * 57 + * In both cases, this will be set to the size of an instance of the class 58 + * after the class is registered with the runtime. 59 + */ 60 + long instance_size; 61 + /** 62 + * Metadata describing the instance variables in this class. 63 + */ 64 + struct objc_ivar_list *ivars; 65 + /** 66 + * Metadata for for defining the mappings from selectors to IMPs. Linked 67 + * list of method list structures, one per class and one per category. 68 + */ 69 + struct objc_method_list *methods; 70 + /** 71 + * The dispatch table for this class. Intialized and maintained by the 72 + * runtime. 73 + */ 74 + void *dtable; 75 + /** 76 + * A pointer to the first subclass for this class. Filled in by the 77 + * runtime. 78 + */ 79 + struct objc_class *subclass_list; 80 + /** 81 + * A pointer to the next sibling class to this. You may find all 82 + * subclasses of a given class by following the subclass_list pointer and 83 + * then subsequently following the sibling_class pointers in the 84 + * subclasses. 85 + */ 86 + struct objc_class *sibling_class; 87 + 88 + /** 89 + * Metadata describing the protocols adopted by this class. Not used by 90 + * the runtime. 91 + */ 92 + struct objc_protocol_list *protocols; 93 + /** 94 + * Linked list of extra data attached to this class. 95 + */ 96 + struct reference_list *extra_data; 97 + /** 98 + * New ABI. The following fields are only available with classes compiled to 99 + * support the new ABI. You may test whether any given class supports this 100 + * ABI by using the CLS_ISNEW_ABI() macro. 101 + */ 102 + 103 + /** 104 + * The version of the ABI used for this class. Zero indicates the ABI first 105 + * implemented by clang 1.0. One indicates the presence of bitmaps 106 + * indicating the offsets of strong, weak, and unretained ivars. 107 + */ 108 + long abi_version; 109 + 110 + /** 111 + * Array of pointers to variables where the runtime will store the ivar 112 + * offset. These may be used for faster access to non-fragile ivars if all 113 + * of the code is compiled for the new ABI. Each of these pointers should 114 + * have the mangled name __objc_ivar_offset_value_{class name}.{ivar name} 115 + * 116 + * When using the compatible non-fragile ABI, this faster form should only be 117 + * used for classes declared in the same compilation unit. 118 + * 119 + * The compiler should also emit symbols of the form 120 + * __objc_ivar_offset_{class name}.{ivar name} which are pointers to the 121 + * offset values. These should be emitted as weak symbols in every module 122 + * where they are used. The legacy-compatible ABI uses these with a double 123 + * layer of indirection. 124 + */ 125 + int **ivar_offsets; 126 + /** 127 + * List of declared properties on this class (NULL if none). This contains 128 + * the accessor methods for each property. 129 + */ 130 + struct objc_property_list *properties; 131 + 132 + /** 133 + * GC / ARC ABI: Fields below this point only exist if abi_version is >= 1. 134 + */ 135 + 136 + /** 137 + * The location of all strong pointer ivars declared by this class. 138 + * 139 + * If the low bit of this field is 0, then this is a pointer to an 140 + * objc_bitfield structure. If the low bit is 1, then the remaining 63 141 + * bits are set, from low to high, for each ivar in the object that is a 142 + * strong pointer. 143 + */ 144 + intptr_t strong_pointers; 145 + /** 146 + * The location of all zeroing weak pointer ivars declared by this class. 147 + * The format of this field is the same as the format of the 148 + * strong_pointers field. 149 + */ 150 + intptr_t weak_pointers; 151 + }; 152 + 153 + /** 154 + * Structure representing the old ABI class structure. This is only ever 155 + * required so that we can take its size - struct objc_class begins with the 156 + * same fields, and you can test the new abi flag to tell whether it is safe to 157 + * access the subsequent fields. 158 + */ 159 + struct legacy_abi_objc_class 160 + { 161 + struct objc_class *isa; 162 + struct objc_class *super_class; 163 + const char *name; 164 + long version; 165 + unsigned long info; 166 + long instance_size; 167 + struct objc_ivar_list *ivars; 168 + struct objc_method_list *methods; 169 + void *dtable; 170 + struct objc_class *subclass_list; 171 + struct objc_class *sibling_class; 172 + struct objc_protocol_list *protocols; 173 + void *gc_object_type; 174 + }; 175 + 176 + 177 + /** 178 + * An enumerated type describing all of the valid flags that may be used in the 179 + * info field of a class. 180 + */ 181 + enum objc_class_flags 182 + { 183 + /** This class structure represents a class. */ 184 + objc_class_flag_class = (1<<0), 185 + /** This class structure represents a metaclass. */ 186 + objc_class_flag_meta = (1<<1), 187 + /** 188 + * This class has been sent a +initalize message. This message is sent 189 + * exactly once to every class that is sent a message by the runtime, just 190 + * before the first other message is sent. 191 + */ 192 + objc_class_flag_initialized = (1<<2), 193 + /** 194 + * The class has been initialized by the runtime. Its super_class pointer 195 + * should now point to a class, rather than a C string containing the class 196 + * name, and its subclass and sibling class links will have been assigned, 197 + * if applicable. 198 + */ 199 + objc_class_flag_resolved = (1<<3), 200 + /** 201 + * The class uses the new, Objective-C 2, runtime ABI. This ABI defines an 202 + * ABI version field inside the class, and so will be used for all 203 + * subsequent versions that retain some degree of compatibility. 204 + */ 205 + objc_class_flag_new_abi = (1<<4), 206 + /** 207 + * This class was created at run time and may be freed. 208 + */ 209 + objc_class_flag_user_created = (1<<5), 210 + /** 211 + * Instances of this class are provide ARC-safe retain / release / 212 + * autorelease implementations. 213 + */ 214 + objc_class_flag_fast_arc = (1<<6), 215 + /** 216 + * This class is a hidden class (should not be registered in the class 217 + * table nor returned from object_getClass()). 218 + */ 219 + objc_class_flag_hidden_class = (1<<7), 220 + /** 221 + * This class is a hidden class used to store associated values. 222 + */ 223 + objc_class_flag_assoc_class = (1<<8) 224 + }; 225 + 226 + #if 0 227 + 228 + /** 229 + * Sets the specific class flag. Note: This is not atomic. 230 + */ 231 + static inline void objc_set_class_flag(struct objc_class *aClass, 232 + enum objc_class_flags flag) 233 + { 234 + aClass->info |= (unsigned long)flag; 235 + } 236 + /** 237 + * Unsets the specific class flag. Note: This is not atomic. 238 + */ 239 + static inline void objc_clear_class_flag(struct objc_class *aClass, 240 + enum objc_class_flags flag) 241 + { 242 + aClass->info &= ~(unsigned long)flag; 243 + } 244 + /** 245 + * Checks whether a specific class flag is set. 246 + */ 247 + static inline BOOL objc_test_class_flag(struct objc_class *aClass, 248 + enum objc_class_flags flag) 249 + { 250 + return (aClass->info & (unsigned long)flag) == (unsigned long)flag; 251 + } 252 + 253 + /** 254 + * Adds a class to the class table. 255 + */ 256 + void class_table_insert(Class class); 257 + 258 + /** 259 + * Array of classes used for small objects. Small objects are embedded in 260 + * their pointer. In 32-bit mode, we have one small object class (typically 261 + * used for storing 31-bit signed integers. In 64-bit mode then we can have 7, 262 + * because classes are guaranteed to be word aligned. 263 + */ 264 + extern Class SmallObjectClasses[7]; 265 + 266 + static BOOL isSmallObject(id obj) 267 + { 268 + uintptr_t addr = ((uintptr_t)obj); 269 + return (addr & OBJC_SMALL_OBJECT_MASK) != 0; 270 + } 271 + 272 + __attribute__((always_inline)) 273 + static inline Class classForObject(id obj) 274 + { 275 + if (UNLIKELY(isSmallObject(obj))) 276 + { 277 + if (sizeof(Class) == 4) 278 + { 279 + return SmallObjectClasses[0]; 280 + } 281 + else 282 + { 283 + uintptr_t addr = ((uintptr_t)obj); 284 + return SmallObjectClasses[(addr & OBJC_SMALL_OBJECT_MASK)]; 285 + } 286 + } 287 + return obj->isa; 288 + } 289 + 290 + #endif 291 + #endif //__OBJC_CLASS_H_INCLUDED
+105
src/libobjcdarwin/libobjc/properties.h
··· 1 + #include "visibility.h" 2 + 3 + enum PropertyAttributeKind 4 + { 5 + /** 6 + * Property has no attributes. 7 + */ 8 + OBJC_PR_noattr = 0x00, 9 + /** 10 + * The property is declared read-only. 11 + */ 12 + OBJC_PR_readonly = (1<<0), 13 + /** 14 + * The property has a getter. 15 + */ 16 + OBJC_PR_getter = (1<<1), 17 + /** 18 + * The property has assign semantics. 19 + */ 20 + OBJC_PR_assign = (1<<2), 21 + /** 22 + * The property is declared read-write. 23 + */ 24 + OBJC_PR_readwrite = (1<<3), 25 + /** 26 + * Property has retain semantics. 27 + */ 28 + OBJC_PR_retain = (1<<4), 29 + /** 30 + * Property has copy semantics. 31 + */ 32 + OBJC_PR_copy = (1<<5), 33 + /** 34 + * Property is marked as non-atomic. 35 + */ 36 + OBJC_PR_nonatomic = (1<<6), 37 + /** 38 + * Property has setter. 39 + */ 40 + OBJC_PR_setter = (1<<7) 41 + }; 42 + 43 + /** 44 + * Structure used for property enumeration. Note that property enumeration is 45 + * currently quite broken on OS X, so achieving full compatibility there is 46 + * impossible. Instead, we strive to achieve compatibility with the 47 + * documentation. 48 + */ 49 + struct objc_property 50 + { 51 + /** 52 + * Name of this property. 53 + */ 54 + const char *name; 55 + /** 56 + * Attributes for this property. Made by ORing together 57 + * PropertyAttributeKinds. 58 + */ 59 + char attributes; 60 + /** 61 + * Flag set if the property is synthesized. 62 + */ 63 + const char isSynthesized; 64 + /** 65 + * Name of the getter for this property. 66 + */ 67 + const char *getter_name; 68 + /** 69 + * Type encoding for the get method for this property. 70 + */ 71 + const char *getter_types; 72 + /** 73 + * Name of the set method for this property. 74 + */ 75 + const char *setter_name; 76 + /** 77 + * Type encoding of the setter for this property. 78 + */ 79 + const char *setter_types; 80 + }; 81 + 82 + /** 83 + * List of property inrospection data. 84 + */ 85 + struct objc_property_list 86 + { 87 + /** 88 + * Number of properties in this array. 89 + */ 90 + int count; 91 + /* 92 + * The next property in a linked list. 93 + */ 94 + struct objc_property_list *next; 95 + /** 96 + * List of properties. 97 + */ 98 + struct objc_property properties[]; 99 + }; 100 + 101 + /** 102 + * Constructs a property description from a list of attributes. 103 + */ 104 + PRIVATE struct objc_property propertyFromAttrs(const objc_property_attribute_t *attributes, 105 + unsigned int attributeCount);
+24
src/libobjcdarwin/libobjc/visibility.h
··· 1 + #if defined _WIN32 || defined __CYGWIN__ 2 + # define PUBLIC __attribute__((dllexport)) 3 + # define PRIVATE 4 + #else 5 + # define PUBLIC __attribute__ ((visibility("default"))) 6 + # define PRIVATE __attribute__ ((visibility("hidden"))) 7 + #endif 8 + #ifdef NO_LEGACY 9 + # define LEGACY PRIVATE 10 + #else 11 + # define LEGACY PUBLIC 12 + #endif 13 + 14 + #if defined(DEBUG) || (!defined(__clang__)) 15 + # include <assert.h> 16 + # define UNREACHABLE(x) assert(0 && x) 17 + # define ASSERT(x) assert(x) 18 + #else 19 + # define UNREACHABLE(x) __builtin_unreachable() 20 + # define ASSERT(x) do { if (x) __builtin_unreachable(); } while(0) 21 + #endif 22 + 23 + #define LIKELY(x) __builtin_expect(x, 1) 24 + #define UNLIKELY(x) __builtin_expect(x, 0)
+174
src/libobjcdarwin/new/AppleLayout.h
··· 1 + #ifndef NEW_APPLELAYOUT_H 2 + #define NEW_APPLELAYOUT_H 3 + #include "../common/AppleLayout.h" 4 + #include <iterator> 5 + 6 + struct method_t 7 + { 8 + const char* selName; 9 + const char* types; 10 + void* impl; 11 + }; 12 + 13 + struct method_list_t 14 + { 15 + uint32_t entsize_and_flags; 16 + uint32_t count; 17 + method_t method_list[]; 18 + 19 + uint32_t entsize() const { return entsize_and_flags & ~uint32_t(3); } 20 + }; 21 + 22 + struct ivar_t 23 + { 24 + uintptr_t* offset; 25 + const char* name; 26 + const char* type; 27 + uint32_t alignment, size; 28 + }; 29 + 30 + struct ivar_list_t 31 + { 32 + uint32_t entsize, count; 33 + ivar_t ivar_list[]; 34 + }; 35 + 36 + struct protocol_list_t; 37 + struct property_list_t; 38 + struct protocol_t 39 + { 40 + id isa; 41 + const char* name; 42 + protocol_list_t* protocols; // inherited protocols 43 + method_list_t *methods, *staticMethods, *optMethods, *optStaticMethods; 44 + property_list_t* properties; 45 + uint32_t size, flags; 46 + const char** extMethTypes; // reflects the order and count of methods above as listed in this struct 47 + 48 + inline const protocol_t* next() const 49 + { 50 + uintptr_t ptr = reinterpret_cast<uintptr_t>(this); 51 + ptr += size; 52 + return reinterpret_cast<const protocol_t*>(ptr); 53 + } 54 + }; 55 + 56 + template <typename ProtoList> 57 + class protocol_iterator : public std::iterator<std::input_iterator_tag, const protocol_t*> 58 + { 59 + const ProtoList* m_list; 60 + size_t m_index; 61 + intptr_t m_slide; 62 + public: 63 + protocol_iterator(const ProtoList* list, size_t index, intptr_t slide) : m_list(list), m_index(index), m_slide(slide) {} 64 + protocol_iterator(const protocol_iterator& that) : m_list(that.m_list), m_index(that.m_index), m_slide(that.m_slide) {} 65 + protocol_iterator& operator++() { m_index++; return *this; } 66 + bool operator==(const protocol_iterator& that) { return that.m_index == m_index; } 67 + bool operator!=(const protocol_iterator& that) { return that.m_index != m_index; } 68 + const protocol_t* operator*() { return m_list->elem(m_index, m_slide); } 69 + }; 70 + 71 + struct protocol_list_t 72 + { 73 + uintptr_t count; 74 + uintptr_t list[]; // the compiler doesn't add a rebase here 75 + inline const protocol_t* elem(size_t i, uintptr_t slide) const 76 + { 77 + return reinterpret_cast<const protocol_t*>(list[i] + slide); 78 + } 79 + protocol_iterator<protocol_list_t> begin(intptr_t slide) const { return protocol_iterator<protocol_list_t>(this, 0, slide); } 80 + protocol_iterator<protocol_list_t> end(intptr_t slide) const { return protocol_iterator<protocol_list_t>(this, count, slide); } 81 + }; 82 + 83 + struct property_t 84 + { 85 + const char *name, *attributes; 86 + }; 87 + 88 + struct property_list_t 89 + { 90 + uint32_t entsize, count; 91 + property_t list[]; 92 + }; 93 + 94 + struct class_ro_t 95 + { 96 + uint32_t flags, instStart, instSize; 97 + #ifdef __x86_64__ 98 + uint32_t nothing; 99 + #endif 100 + void* ivarLayout; 101 + const char* className; 102 + const method_list_t* baseMethods; // instance methods for classes, static methods for metaclasses 103 + const protocol_list_t* baseProtocols; 104 + const ivar_list_t* ivars; 105 + 106 + void* todo[1]; // TODO: more pointers 107 + const property_list_t* baseProperties; 108 + }; 109 + 110 + struct class_t 111 + { 112 + class_t* isa; // instance of 113 + class_t* superclass; 114 + void* cache; // empty cache imported here 115 + void* vtable; 116 + uintptr_t data_and_flags; 117 + 118 + class_ro_t* data() const 119 + { 120 + uintptr_t p = data_and_flags & ~uintptr_t(3); 121 + return reinterpret_cast<class_ro_t*>(p); 122 + } 123 + }; 124 + 125 + struct category_t 126 + { 127 + const char* name; 128 + id cls; 129 + method_list_t *methods, *staticMethods; 130 + protocol_list_t *protocols; 131 + property_list_t *properties; 132 + }; 133 + 134 + #ifndef CLS_CLASS 135 + #define CLS_CLASS 0x1 136 + #define CLS_META 0x2 137 + #define CLS_POSING 0x8 138 + #define CLS_METHOD_ARRAY 0x100 139 + #define CLS_HAS_CXX_STRUCTORS 0x2000 140 + #define CLS_NO_METHOD_ARRAY 0x4000 141 + #define CLS_HAS_LOAD_METHOD 0x8000 142 + #define CLS_NO_PROPERTY_ARRAY 0x80000 143 + #endif 144 + 145 + static const char* SEG_DATA = "__DATA"; 146 + static const char* SEG_OBJC_CLASSLIST_NEW = SEG_DATA; 147 + static const char* SECT_OBJC_CLASSLIST_NEW = "__objc_classlist"; 148 + static const char* SEG_OBJC_CLASSREFS_NEW = SEG_DATA; 149 + static const char* SECT_OBJC_CLASSREFS_NEW = "__objc_classrefs"; 150 + static const char* SEG_OBJC_SUPERREFS_NEW = SEG_DATA; 151 + static const char* SECT_OBJC_SUPERREFS_NEW = "__objc_superrefs"; 152 + static const char* SEG_OBJC_SELREFS_NEW = SEG_DATA; 153 + static const char* SECT_OBJC_SELREFS_NEW = "__objc_selrefs"; 154 + static const char* SEG_OBJC_MSGREFS_NEW = SEG_DATA; // used with objc_msgSend_fixup 155 + static const char* SECT_OBJC_MSGREFS_NEW = "__objc_msgrefs"; 156 + static const char* SEG_OBJC_PROTOREFS_NEW = SEG_DATA; 157 + static const char* SECT_OBJC_PROTOREFS_NEW = "__objc_protorefs"; 158 + static const char* SEG_OBJC_PROTOLIST_NEW = SEG_DATA; 159 + static const char* SECT_OBJC_PROTOLIST_NEW = "__objc_protolist"; 160 + static const char* SEG_OBJC_CATLIST_NEW = SEG_DATA; 161 + static const char* SECT_OBJC_CATLIST_NEW = "__objc_catlist"; 162 + 163 + /* TODO? 164 + * __DATA,__objc_classlist was __OBJC2,__class_list 165 + * __DATA,__objc_catlist was __OBJC2,__category_list 166 + * __DATA,__objc_protolist was __OBJC2,__protocol_list 167 + * __DATA,__objc_msgrefs was __OBJC2,__message_refs 168 + * __DATA,__objc_classrefs was __OBJC2,__class_refs 169 + * __DATA,__objc_superrefs was __OBJC2,__super_refs 170 + * __DATA,__objc_imageinfo was __OBJC,__image_info 171 + * */ 172 + 173 + #endif 174 +
+51
src/libobjcdarwin/new/category.cpp
··· 1 + #include "./category.h" 2 + #include "../common/property.h" 3 + #include "../common/method.h" 4 + #include "./protocol.h" 5 + #include "../../util/log.h" 6 + #include <map> 7 + 8 + extern std::map<const void*,Class> g_classPointers; 9 + 10 + void ProcessCategoriesNew(const struct mach_header* mh, intptr_t slide) 11 + { 12 + category_t** cats; 13 + unsigned long size; 14 + 15 + cats = reinterpret_cast<category_t**>( 16 + getsectdata(mh, SEG_OBJC_CATLIST_NEW, SECT_OBJC_CATLIST_NEW, &size) 17 + ); 18 + if (!cats) 19 + { 20 + LOG << "No categories found\n"; 21 + return; 22 + } 23 + 24 + LOG << "Processing categories, " << (size / sizeof(category_t*)) << " found\n"; 25 + 26 + for (size_t i = 0; i < size / sizeof(category_t*); i++) 27 + { 28 + // g_classPointers 29 + category_t* cat = cats[i]; 30 + auto itClass = g_classPointers.find(cat->cls); 31 + Class c; 32 + 33 + if (itClass != g_classPointers.end()) 34 + c = itClass->second; 35 + else 36 + c = reinterpret_cast<Class>(cat->cls); 37 + 38 + LOG << "Processing category " << cat->name << " on top of class @" << c << std::endl; 39 + 40 + if (cat->methods) 41 + ConvertMethodListGen(c, cat->methods); 42 + if (cat->staticMethods) 43 + ConvertMethodListGen(object_getClass(id(c)), cat->staticMethods); 44 + if (cat->protocols) 45 + AddClassProtocols(c, cat->protocols, slide); 46 + if (cat->properties) 47 + { 48 + ConvertProperties(cat->properties, [c](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(c, name, attr, count); bug_gnustepFixPropertyCount(c); }); 49 + } 50 + } 51 + }
+10
src/libobjcdarwin/new/category.h
··· 1 + #ifndef NEW_CATEGORY_H 2 + #define NEW_CATEGORY_H 3 + #include "./AppleLayout.h" 4 + #include <objc/runtime.h> 5 + #include <stdint.h> 6 + #include "../../dyld/public.h" 7 + 8 + void ProcessCategoriesNew(const struct mach_header* mh, intptr_t slide); 9 + 10 + #endif
+92
src/libobjcdarwin/new/class.cpp
··· 1 + #include "./class.h" 2 + #include "../../util/trace.h" 3 + #include "../../util/log.h" 4 + #include <map> 5 + #include <algorithm> 6 + #include "../common/method.h" 7 + #include "../common/property.h" 8 + #include "../common/ref.h" 9 + #include "./ivar.h" 10 + #include "./protocol.h" 11 + #include "../TopologySort.h" 12 + 13 + extern std::map<const void*,Class> g_classPointers; 14 + 15 + Class RegisterClass(const class_t* cls, intptr_t slide) 16 + { 17 + LOG << "Processing ObjC class " << cls->data()->className << std::endl; 18 + 19 + const class_t* meta = cls->isa; 20 + Class conv, super; 21 + auto itSuper = g_classPointers.find(cls->superclass); 22 + 23 + if (itSuper != g_classPointers.end()) 24 + super = itSuper->second; 25 + else 26 + super = reinterpret_cast<Class>(cls->superclass); 27 + 28 + LOG << "...superclass is @" << super << std::endl; 29 + conv = objc_allocateClassPair(super, cls->data()->className, 0); 30 + 31 + const class_ro_t* ro = cls->data(); 32 + const class_ro_t* roMeta = meta->data(); 33 + 34 + if (ro->baseMethods) 35 + ConvertMethodListGen(conv, ro->baseMethods); 36 + if (roMeta->baseMethods) 37 + ConvertMethodListGen(object_getClass(id(conv)), roMeta->baseMethods); 38 + if (ro->ivars) 39 + ConvertIvarList(conv, ro->ivars); 40 + if (ro->baseProtocols) 41 + AddClassProtocols(conv, ro->baseProtocols, slide); 42 + if (ro->baseProperties) 43 + { 44 + ConvertProperties(ro->baseProperties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); }); 45 + } 46 + 47 + // conv->instance_size = ro->instSize; 48 + // conv->isa->instance_size = roMeta->instSize; 49 + 50 + objc_registerClassPair(conv); 51 + LOG << "ObjC class " << cls->data()->className << " now @" << conv << std::endl; 52 + g_classPointers[cls] = conv; 53 + 54 + return conv; 55 + } 56 + 57 + void ProcessClassesNew(const struct mach_header* mh, intptr_t slide, const class_t** classes, unsigned long size) 58 + { 59 + class_t **class_refs, **class_refs_end, **super_refs, **super_refs_end; 60 + unsigned long refsize, refsize_s; 61 + std::vector<const class_t*> vecClasses; 62 + std::set<const class_t*> setClasses; 63 + 64 + class_refs = reinterpret_cast<class_t**>( 65 + getsectdata(mh, SEG_OBJC_CLASSREFS_NEW, SECT_OBJC_CLASSREFS_NEW, &refsize) 66 + ); 67 + super_refs = reinterpret_cast<class_t**>( 68 + getsectdata(mh, SEG_OBJC_SUPERREFS_NEW, SECT_OBJC_SUPERREFS_NEW, &refsize_s) 69 + ); 70 + if (class_refs) 71 + class_refs_end = class_refs + refsize / sizeof(class_t*); 72 + 73 + if (super_refs) 74 + super_refs_end = super_refs + refsize_s / sizeof(class_t*); 75 + 76 + std::copy(classes, classes+size/sizeof(class_t*), std::inserter(setClasses, setClasses.begin())); 77 + 78 + topology_sort<const class_t>(setClasses, vecClasses, 79 + [&setClasses](const class_t* t) { return setClasses.count(t->superclass) ? std::set<const class_t*>{t->superclass} : std::set<const class_t*>(); } 80 + ); 81 + 82 + for (const class_t* cls : vecClasses) 83 + { 84 + Class c = RegisterClass(cls, slide); 85 + 86 + if (class_refs) 87 + find_and_fix(class_refs, class_refs_end, cls, c); 88 + if (super_refs) 89 + find_and_fix(super_refs, super_refs_end, cls, c); 90 + } 91 + 92 + }
+11
src/libobjcdarwin/new/class.h
··· 1 + #ifndef NEW_CLASS_H 2 + #define NEW_CLASS_H 3 + #include "./AppleLayout.h" 4 + #include <objc/runtime.h> 5 + #include <stdint.h> 6 + #include "../../dyld/public.h" 7 + 8 + Class RegisterClass(const class_t* cls, intptr_t slide); 9 + void ProcessClassesNew(const struct mach_header* mh, intptr_t slide, const class_t** classes, unsigned long size); 10 + 11 + #endif
+16
src/libobjcdarwin/new/ivar.cpp
··· 1 + #include "./ivar.h" 2 + #include "../../util/log.h" 3 + 4 + void ConvertIvarList(Class c, const ivar_list_t* list) 5 + { 6 + LOG << list->count << " ivars within\n"; 7 + 8 + for (size_t i = 0; i < list->count; i++) 9 + { 10 + auto* v = &list->ivar_list[i]; 11 + 12 + LOG << "Ivar: name: " << v->name << "; type: " << v->type << "; offset: " << *v->offset << "; size: " << v->size << "; alignment: " << v->alignment << std::endl; 13 + class_addIvar(c, v->name, v->size, v->alignment, v->type); 14 + } 15 + } 16 +
+9
src/libobjcdarwin/new/ivar.h
··· 1 + #ifndef NEW_IVAR_H 2 + #define NEW_IVAR_H 3 + #include "./AppleLayout.h" 4 + #include <objc/runtime.h> 5 + #include <stdint.h> 6 + 7 + void ConvertIvarList(Class c, const ivar_list_t* list); 8 + 9 + #endif
+102
src/libobjcdarwin/new/protocol.cpp
··· 1 + #include "./protocol.h" 2 + #include <cstring> 3 + #include "../../util/log.h" 4 + #include "../../dyld/public.h" 5 + #include "../common/ref.h" 6 + #include "../common/property.h" 7 + #include "../TopologySort.h" 8 + 9 + void AddClassProtocols(Class c, const protocol_list_t* list, intptr_t slide) 10 + { 11 + for (size_t i = 0; i < list->count; i++) 12 + { 13 + const char* name = list->elem(i, slide)->name; 14 + Protocol* p = objc_getProtocol(name); 15 + assert(p != nullptr); 16 + class_addProtocol(c, p); 17 + } 18 + } 19 + 20 + void RegisterProtocolMethods(Protocol* p, const method_list_t* list, const char** extTypes, size_t& extIndex, bool required, bool instance) 21 + { 22 + LOG << "Registering Protocol methods (" << required << ", " << instance << "): " << list->count << " methods within\n"; 23 + for (size_t i = 0; i < list->count; i++, extIndex++) 24 + { 25 + SEL sel = sel_registerName(list->method_list[i].selName); 26 + protocol_addMethodDescription(p, sel, list->method_list[i].types, required, instance); 27 + // TODO: what do we do with extTypes? 28 + } 29 + } 30 + 31 + Protocol* RegisterProtocol(const protocol_t* prot, intptr_t slide) 32 + { 33 + // For reasons unknown, the NSObject protocol is duplicated into the binaries 34 + if (strcmp(prot->name, "NSObject") == 0) 35 + return objc_getProtocol(prot->name); 36 + 37 + LOG << "Processing ObjC Protocol: " << prot->name << std::endl; 38 + Protocol* conv = objc_allocateProtocol(prot->name); 39 + size_t methodIndex = 0; 40 + 41 + if (prot->protocols) 42 + { 43 + for (size_t i = 0; i < prot->protocols->count; i++) 44 + { 45 + const char* name = prot->protocols->elem(i, slide)->name; 46 + protocol_addProtocol(conv, objc_getProtocol(name)); 47 + } 48 + } 49 + 50 + if (prot->methods) 51 + RegisterProtocolMethods(conv, prot->methods, prot->extMethTypes, methodIndex, true, true); 52 + if (prot->staticMethods) 53 + RegisterProtocolMethods(conv, prot->staticMethods, prot->extMethTypes, methodIndex, true, false); 54 + if (prot->optMethods) 55 + RegisterProtocolMethods(conv, prot->optMethods, prot->extMethTypes, methodIndex, false, true); 56 + if (prot->optStaticMethods) 57 + RegisterProtocolMethods(conv, prot->optStaticMethods, prot->extMethTypes, methodIndex, false, false); 58 + 59 + if (prot->properties) 60 + ConvertProperties(prot->properties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { protocol_addProperty(conv, name, attr, count, true, true); }); 61 + 62 + objc_registerProtocol(conv); 63 + return conv; 64 + } 65 + 66 + void ProcessProtocolsNew(const struct mach_header* mh, intptr_t slide) 67 + { 68 + const protocol_t** protocol_list; 69 + unsigned long protosize; 70 + 71 + protocol_list = reinterpret_cast<const protocol_t**>( 72 + getsectdata(mh, SEG_OBJC_PROTOLIST_NEW, SECT_OBJC_PROTOLIST_NEW, &protosize) 73 + ); 74 + 75 + if (protocol_list) 76 + { 77 + unsigned long refsize; 78 + protocol_t** protocol_refs; 79 + protocol_t** protocol_refs_end; 80 + std::set<const protocol_t*> setProtocols; 81 + std::vector<const protocol_t*> vecProtocols; 82 + 83 + protocol_refs = reinterpret_cast<protocol_t**>( 84 + getsectdata(mh, SEG_OBJC_PROTOREFS_NEW, SECT_OBJC_PROTOREFS_NEW, &refsize) 85 + ); 86 + 87 + if (protocol_refs) 88 + protocol_refs_end = protocol_refs + refsize / sizeof(protocol_t*); 89 + 90 + std::copy(protocol_list, protocol_list+protosize/sizeof(protocol_t*), std::inserter(setProtocols, setProtocols.begin())); 91 + topology_sort<const protocol_t>(setProtocols, vecProtocols, 92 + [&setProtocols,slide](const protocol_t* p) { return p->protocols ? std::set<const protocol_t*>(p->protocols->begin(slide), p->protocols->end(slide)) : std::set<const protocol_t*>(); }); 93 + 94 + for (const protocol_t* proto : vecProtocols) 95 + { 96 + Protocol* p = RegisterProtocol(proto, slide); 97 + 98 + if (protocol_refs) 99 + find_and_fix(protocol_refs, protocol_refs_end, proto, p); 100 + } 101 + } 102 + }
+12
src/libobjcdarwin/new/protocol.h
··· 1 + #ifndef NEW_PROTOCOL_H 2 + #define NEW_PROTOCOL_H 3 + #include "./AppleLayout.h" 4 + #include <objc/runtime.h> 5 + #include <stdint.h> 6 + 7 + Protocol* RegisterProtocol(const protocol_t* prot, intptr_t slide); 8 + void ProcessProtocolsNew(const struct mach_header* mh, intptr_t slide); 9 + void RegisterProtocolMethods(Protocol* p, const method_list_t* list, const char** extTypes, size_t& extIndex, bool required, bool instance); 10 + void AddClassProtocols(Class c, const protocol_list_t* list, intptr_t slide); 11 + 12 + #endif
+190
src/libobjcdarwin/old/AppleLayout.h
··· 1 + #ifndef APPLELAYOUT_H 2 + #define APPLELAYOUT_H 3 + #include "../common/AppleLayout.h" 4 + 5 + struct old_method_decl 6 + { 7 + const char *name, *types; 8 + }; 9 + struct old_method_decl_list 10 + { 11 + int count; 12 + old_method_decl list[]; 13 + }; 14 + struct old_property 15 + { 16 + const char *name, *attributes; 17 + }; 18 + 19 + struct old_property_list 20 + { 21 + uint32_t entsize, count; 22 + old_property list[]; 23 + }; 24 + 25 + struct old_protocol; 26 + struct old_protocol_list 27 + { 28 + old_protocol_list* linked; 29 + long count; 30 + old_protocol* list[]; 31 + }; 32 + 33 + struct old_protocol_ext 34 + { 35 + uint32_t size; 36 + old_method_decl_list *optMethods, *optStaticMethods; 37 + old_property_list* properties; 38 + const char** extMethTypes; 39 + }; 40 + 41 + struct old_protocol 42 + { 43 + union 44 + { 45 + id isa; 46 + old_protocol_ext* ext; // __protocol_ext section 47 + uintptr_t ext_ptrValue; 48 + }; 49 + const char* name; 50 + old_protocol_list* protocols; 51 + old_method_decl_list *methods, *staticMethods; 52 + }; 53 + 54 + union old_class_ptr 55 + { 56 + struct old_class* cls; 57 + const char* name; 58 + uintptr_t ptrValue; 59 + Class clsNew; 60 + }; 61 + 62 + struct old_class 63 + { 64 + old_class_ptr isa; 65 + old_class_ptr super_class; 66 + const char *name; 67 + long version; 68 + long info; 69 + long instance_size; 70 + struct old_ivar_list *ivars; 71 + struct old_method_list *methodList; 72 + void* cache; 73 + struct old_protocol_list *protocols; 74 + // CLS_EXT only 75 + const uint8_t *ivar_layout; 76 + struct old_class_ext *ext; 77 + }; 78 + 79 + struct old_class_ext 80 + { 81 + uint32_t size; 82 + const uint8_t *weak_ivar_layout; 83 + union 84 + { 85 + old_property_list **propertyLists; 86 + old_property_list *propertyList; 87 + }; 88 + }; 89 + 90 + struct old_ivar 91 + { 92 + char *name; 93 + char *type; 94 + int offset; 95 + #ifdef __x86_64__ 96 + int space; 97 + #endif 98 + }; 99 + 100 + struct old_ivar_list 101 + { 102 + int count; 103 + #ifdef __x86_64__ 104 + int space; 105 + #endif 106 + /* variable length structure */ 107 + struct old_ivar ivar_list[1]; 108 + }; 109 + 110 + 111 + struct old_method 112 + { 113 + const char* selName; 114 + const char* types; 115 + void* impl; 116 + }; 117 + 118 + struct old_method_list 119 + { 120 + struct old_method_list *obsolete; 121 + 122 + int count; 123 + #ifdef __x86_64__ 124 + int space; 125 + #endif 126 + /* variable length structure */ 127 + struct old_method method_list[1]; 128 + }; 129 + 130 + union clsref 131 + { 132 + const char* clsName; 133 + Class cls; 134 + }; 135 + 136 + struct symtab 137 + { 138 + unsigned long selCount; 139 + SEL* selectors; 140 + uint16_t countClasses, countCategories; 141 + void* classesAndCategories[]; 142 + }; 143 + 144 + struct module_info 145 + { 146 + unsigned long version, size; 147 + const char* name; 148 + struct symtab* symtab; 149 + }; 150 + 151 + struct old_category 152 + { 153 + const char* name; 154 + const char* clsName; 155 + old_method_list *methods, *staticMethods; 156 + old_protocol_list* protocols; // since version 5 157 + uint32_t size; 158 + old_property_list* properties; // since version 7 159 + }; 160 + 161 + 162 + static const char* SEG_OBJC = "__OBJC"; 163 + static const char* SEG_OBJC_CLASSLIST_OLD = SEG_OBJC; 164 + static const char* SECT_OBJC_CLASSLIST_OLD = "__class"; 165 + static const char* SEG_OBJC_METALIST_OLD = SEG_OBJC; 166 + static const char* SECT_OBJC_METALIST_OLD = "__meta_class"; 167 + static const char* SEG_OBJC_CLASSREFS_OLD = SEG_OBJC; 168 + static const char* SECT_OBJC_CLASSREFS_OLD = "__cls_refs"; 169 + static const char* SEG_OBJC_SELREFS_OLD = SEG_OBJC; 170 + static const char* SECT_OBJC_SELREFS_OLD = "__message_refs"; 171 + static const char* SEG_OBJC_PROTOCOLS_OLD = SEG_OBJC; 172 + static const char* SECT_OBJC_PROTOCOLS_OLD = "__protocol"; 173 + static const char* SEG_OBJC_PROTOEXT_OLD = SEG_OBJC; 174 + static const char* SECT_OBJC_PROTOEXT_OLD = "__protocol_ext"; 175 + static const char* SEG_OBJC_MODINFO_OLD = SEG_OBJC; 176 + static const char* SECT_OBJC_MODINFO_OLD = "__module_info"; 177 + 178 + #ifndef CLS_CLASS 179 + #define CLS_CLASS 0x1 180 + #define CLS_META 0x2 181 + #define CLS_POSING 0x8 182 + #define CLS_METHOD_ARRAY 0x100 183 + #define CLS_HAS_CXX_STRUCTORS 0x2000 184 + #define CLS_NO_METHOD_ARRAY 0x4000 185 + #define CLS_HAS_LOAD_METHOD 0x8000 186 + #define CLS_NO_PROPERTY_ARRAY 0x80000 187 + #endif 188 + 189 + #endif 190 +
src/libobjcdarwin/old/category.cpp

This is a binary file and will not be displayed.

src/libobjcdarwin/old/category.h

This is a binary file and will not be displayed.

+139
src/libobjcdarwin/old/class.cpp
··· 1 + #include "./class.h" 2 + #include "../../util/log.h" 3 + #include "../TopologySort.h" 4 + #include "../common/method.h" 5 + #include "ivar.h" 6 + #include "../common/property.h" 7 + #include <map> 8 + 9 + extern std::map<const void*,Class> g_classPointers; 10 + 11 + Class RegisterClass(old_class* cls, bool hasExt) 12 + { 13 + LOG << "Processing old ObjC class " << cls->name << std::endl; 14 + 15 + const old_class* meta = cls->isa.cls; 16 + Class conv, super; 17 + /* 18 + old_class* psuper = cls->super_class.cls; 19 + auto itSuper = g_classPointers.find(psuper); // TODO: may not be needed, should always be a string 20 + 21 + if (itSuper != g_classPointers.end()) 22 + super = itSuper->second; 23 + else 24 + super = reinterpret_cast<Class>(psuper); 25 + */ 26 + 27 + super = (Class) objc_getClass(cls->super_class.name); 28 + LOG << "...with superclass @" << super << std::endl; 29 + conv = objc_allocateClassPair(super, cls->name, 0); 30 + 31 + if (cls->methodList) 32 + ConvertMethodListGen(conv, cls->methodList); 33 + if (meta->methodList) 34 + ConvertMethodListGen(object_getClass(id(conv)), meta->methodList); 35 + if (cls->ivars) 36 + ConvertIvarList(conv, cls->ivars); 37 + if (cls->protocols) 38 + { 39 + for (long i = 0; i < cls->protocols->count; i++) 40 + { 41 + Protocol* p = objc_getProtocol(cls->protocols->list[i]->name); 42 + assert(p != nullptr); 43 + class_addProtocol(conv, p); 44 + } 45 + } 46 + 47 + if (hasExt && cls->ext && cls->ext->propertyLists) 48 + { 49 + LOG << "Class has EXT and a property list/lists\n"; 50 + //if (cls->info & CLS_NO_PROPERTY_ARRAY) 51 + if (true) 52 + { 53 + ConvertProperties(cls->ext->propertyList, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); }); 54 + } 55 + else 56 + { 57 + for (size_t i = 0; cls->ext->propertyLists[i] != nullptr; i++) 58 + { 59 + const old_property_list* l = cls->ext->propertyLists[i]; 60 + ConvertProperties(l, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { class_addProperty(conv, name, attr, count); bug_gnustepFixPropertyCount(conv); }); 61 + } 62 + } 63 + } 64 + 65 + objc_registerClassPair(conv); 66 + g_classPointers[cls] = conv; 67 + g_classPointers[cls->name] = conv; 68 + 69 + LOG << "ObjC class " << cls->name << " @" << conv << std::endl; 70 + 71 + return conv; 72 + } 73 + 74 + 75 + void ProcessClassesOld(const struct mach_header* mh, intptr_t slide, module_info* info) 76 + { 77 + unsigned long cstrLen; 78 + void* ptr; 79 + std::vector<old_class*> vecClasses; 80 + std::set<old_class*> setClasses; 81 + std::map<const char*,old_class*> mapClassNames; 82 + 83 + // ptr = getsectdata(mh, "__TEXT", "__cstring", &cstrLen); 84 + // if (ptr) 85 + // g_cstringSection = std::pair<uintptr_t,uintptr_t>(uintptr_t(ptr), cstrLen); 86 + // else 87 + // g_cstringSection = std::pair<uintptr_t,uintptr_t>(0, 0); 88 + 89 + for (uint16_t i = 0; i < info->symtab->countClasses; i++) 90 + { 91 + old_class* cls = static_cast<old_class*>(info->symtab->classesAndCategories[i]); 92 + mapClassNames[cls->name] = cls; 93 + setClasses.insert(cls); 94 + } 95 + 96 + topology_sort(setClasses, vecClasses, 97 + [&mapClassNames](old_class* t) -> std::set<old_class*> { auto it = mapClassNames.find(t->super_class.name); return (it != mapClassNames.end()) ? std::set<old_class*>{it->second} : std::set<old_class*>(); } 98 + ); 99 + 100 + for (old_class* c : vecClasses) 101 + RegisterClass(c, info->version >= 6); 102 + 103 + clsref* class_refs; 104 + unsigned long refsize; 105 + 106 + class_refs = reinterpret_cast<clsref*>( 107 + getsectdata(mh, SEG_OBJC_CLASSREFS_OLD, SECT_OBJC_CLASSREFS_OLD, &refsize) 108 + ); 109 + 110 + if (class_refs) 111 + { 112 + for (size_t i = 0; i < refsize / sizeof(clsref); i++) 113 + { 114 + Class c = (Class) objc_getClass(class_refs[i].clsName); 115 + LOG << "ObjC fixup classref @" << &class_refs[i].cls << ": " << class_refs[i].cls << " -> " << c << std::endl; 116 + class_refs[i].cls = c; 117 + } 118 + } 119 + 120 + // Change class names in 'super_class' from strings to pointers to Class 121 + // for (size_t i = 0; i < size / sizeof(old_class); i++) 122 + for (uint16_t i = 0; i < info->symtab->countClasses; i++) 123 + { 124 + old_class* cls = static_cast<old_class*>(info->symtab->classesAndCategories[i]); 125 + Class c = (Class) objc_getClass(cls->super_class.name); 126 + LOG << "ObjC fixup super_class @" << &cls->super_class << ": " << cls->super_class.name << " -> " << c << std::endl; 127 + cls->super_class.clsNew = c; 128 + } 129 + 130 + // Fix the same in metaclasses 131 + // for (size_t i = 0; i < size / sizeof(old_class); i++) 132 + for (uint16_t i = 0; i < info->symtab->countClasses; i++) 133 + { 134 + old_class* cls = static_cast<old_class*>(info->symtab->classesAndCategories[i])->isa.cls; 135 + Class c = (Class) objc_getClass(cls->name); 136 + LOG << "ObjC fixup super_class @" << cls << ": " << cls->name << " -> " << c << std::endl; 137 + cls->super_class.clsNew = c; 138 + } 139 + }
+11
src/libobjcdarwin/old/class.h
··· 1 + #ifndef OLD_CLASS_H 2 + #define OLD_CLASS_H 3 + #include "./AppleLayout.h" 4 + #include <objc/runtime.h> 5 + #include <stdint.h> 6 + #include "../../dyld/public.h" 7 + 8 + Class RegisterClass(old_class* cls, bool hasExt); 9 + void ProcessClassesOld(const struct mach_header* mh, intptr_t slide, module_info* info); 10 + 11 + #endif
+9
src/libobjcdarwin/old/ivar.h
··· 1 + #ifndef OLD_IVAR_H 2 + #define OLD_IVAR_H 3 + #include "./AppleLayout.h" 4 + #include <objc/runtime.h> 5 + #include <stdint.h> 6 + 7 + void ConvertIvarList(Class c, const old_ivar_list* list); 8 + 9 + #endif
+20
src/libobjcdarwin/old/ivar.mm
··· 1 + #include "./ivar.h" 2 + #include <Foundation/NSObjCRuntime.h> 3 + #include "../../util/log.h" 4 + 5 + void ConvertIvarList(Class c, const old_ivar_list* list) 6 + { 7 + LOG << list->count << " ivars within\n"; 8 + 9 + for (size_t i = 0; i < list->count; i++) 10 + { 11 + auto* v = &list->ivar_list[i]; 12 + NSUInteger size, alignment; 13 + 14 + NSGetSizeAndAlignment(v->type, &size, &alignment); 15 + alignment = 1; // TODO: why do we need alignment when we have an offset? 16 + 17 + LOG << "Ivar: name: " << v->name << "; type: " << v->type << "; offset: " << v->offset << "; size: " << size << "; alignment: " << alignment << std::endl; 18 + class_addIvar(c, v->name, size, alignment, v->type); 19 + } 20 + }
+110
src/libobjcdarwin/old/protocol.cpp
··· 1 + #include "./protocol.h" 2 + #include "../../util/log.h" 3 + #include "../TopologySort.h" 4 + #include "../common/property.h" 5 + #include <cstring> 6 + 7 + void RegisterProtocolMethods(Protocol* p, const old_method_decl_list* list, bool required, bool instance) 8 + { 9 + LOG << "Registering Protocol methods (" << required << ", " << instance << "): " << list->count << " methods within\n"; 10 + for (size_t i = 0; i < list->count; i++) 11 + { 12 + SEL sel = sel_registerName(list->list[i].name); 13 + protocol_addMethodDescription(p, sel, list->list[i].types, required, instance); 14 + // TODO: what do we do with extTypes? 15 + } 16 + } 17 + 18 + Protocol* RegisterProtocol(old_protocol* prot, uintptr_t extStart, unsigned long extLen) 19 + { 20 + // For reasons unknown, the NSObject protocol is duplicated into the binaries 21 + if (strcmp(prot->name, "NSObject") == 0) 22 + return objc_getProtocol(prot->name); 23 + 24 + LOG << "Processing old ObjC Protocol: " << prot->name << std::endl; 25 + Protocol* conv = objc_allocateProtocol(prot->name); 26 + 27 + if (prot->protocols) 28 + { 29 + for (size_t i = 0; i < prot->protocols->count; i++) 30 + { 31 + const char* name = prot->protocols->list[i]->name; 32 + protocol_addProtocol(conv, objc_getProtocol(name)); 33 + } 34 + } 35 + 36 + if (prot->methods) 37 + RegisterProtocolMethods(conv, prot->methods, true, true); 38 + if (prot->staticMethods) 39 + RegisterProtocolMethods(conv, prot->staticMethods, true, false); 40 + 41 + // Protocol EXT - weird stuff 42 + if (prot->ext_ptrValue >= extStart && prot->ext_ptrValue < extStart + extLen) 43 + { 44 + // TODO: check if rebase is present 45 + if (prot->ext->optMethods) 46 + RegisterProtocolMethods(conv, prot->ext->optMethods, false, true); 47 + if (prot->ext->optStaticMethods) 48 + RegisterProtocolMethods(conv, prot->ext->optStaticMethods, false, false); 49 + if (prot->ext->properties) 50 + ConvertProperties(prot->ext->properties, [conv](const char* name, const objc_property_attribute_t* attr, unsigned int count) { protocol_addProperty(conv, name, attr, count, true, true); }); 51 + } 52 + 53 + objc_registerProtocol(conv); 54 + return conv; 55 + } 56 + 57 + 58 + void ProcessProtocolsOld(const struct mach_header* mh, intptr_t slide) 59 + { 60 + old_protocol* protocols; 61 + unsigned long protosize; 62 + 63 + protocols = reinterpret_cast<old_protocol*>( 64 + getsectdata(mh, SEG_OBJC_PROTOCOLS_OLD, SECT_OBJC_PROTOCOLS_OLD, &protosize) 65 + ); 66 + 67 + if (protocols) 68 + { 69 + std::vector<old_protocol*> vecProtocols; 70 + std::set<old_protocol*> setProtocols; 71 + // std::map<const char*,old_protocol*> mapProtocols; 72 + 73 + for (size_t i = 0; i < protosize / sizeof(old_protocol); i++) 74 + { 75 + if (strcmp(protocols[i].name, "NSObject") != 0) // No need to re-register protocol NSObject 76 + setProtocols.insert(protocols + i); 77 + // mapProtocols[protocols[i].name] = protocols + i; 78 + } 79 + 80 + topology_sort<old_protocol>(setProtocols, vecProtocols, 81 + [&setProtocols](old_protocol* p) -> std::set<old_protocol*> 82 + { 83 + std::set<old_protocol*> set; 84 + if (p->protocols) 85 + { 86 + for (size_t i = 0; i < p->protocols->count; i++) 87 + { 88 + if (setProtocols.count(p->protocols->list[i])) 89 + set.insert(p->protocols->list[i]); 90 + } 91 + } 92 + return set; 93 + } 94 + ); 95 + 96 + // Find the section that holds protocol_ext structs 97 + uintptr_t extStart; 98 + unsigned long extLen = 0; 99 + 100 + extStart = reinterpret_cast<uintptr_t>( 101 + getsectdata(mh, SEG_OBJC_PROTOEXT_OLD, SECT_OBJC_PROTOEXT_OLD, &extLen) 102 + ); 103 + 104 + for (old_protocol* old : vecProtocols) 105 + { 106 + Protocol* p = RegisterProtocol(old, extStart, extLen); 107 + old->isa = (id) p; // This is what is referenced in the code 108 + } 109 + } 110 + }
+12
src/libobjcdarwin/old/protocol.h
··· 1 + #ifndef OLD_PROTOCOL_H 2 + #define OLD_PROTOCOL_H 3 + #include "./AppleLayout.h" 4 + #include <objc/runtime.h> 5 + #include <stdint.h> 6 + #include "../../dyld/public.h" 7 + 8 + void RegisterProtocolMethods(Protocol* p, const old_method_decl_list* list, bool required, bool instance); 9 + Protocol* RegisterProtocol(old_protocol* prot, uintptr_t extStart, unsigned long extLen); 10 + void ProcessProtocolsOld(const struct mach_header* mh, intptr_t slide); 11 + 12 + #endif
+14
src/libobjcdarwin/old/ptr.h
··· 1 + #ifndef OLD_PTR_H 2 + #define OLD_PTR_H 3 + 4 + 5 + template<typename T> 6 + static T* advance_ptr(T* ptr, size_t bytes) 7 + { 8 + uintptr_t v = reinterpret_cast<uintptr_t>(ptr); 9 + v += bytes; 10 + return reinterpret_cast<T*>(v); 11 + } 12 + 13 + 14 + #endif
+1 -1
tests/runtest
··· 36 36 darwin_tool="gcc" 37 37 native_tool="clang" 38 38 cflags_native="-l:libobjc.so.4 -lgnustep-base" 39 - cflags_darwin="-lobjc" 39 + cflags_darwin="-lobjc -framework foundation" 40 40 ;; 41 41 *) 42 42 echo "Unsupported file type: $extension"
+20
tests/src/objc_category.m
··· 1 + #import <Foundation/NSString.h> 2 + #include <stdio.h> 3 + 4 + @interface NSString (MyCategory) 5 + +(void) dummy; 6 + @end 7 + 8 + @implementation NSString (MyCategory) 9 + +(void) dummy 10 + { 11 + puts("dummy called"); 12 + } 13 + @end 14 + 15 + int main() 16 + { 17 + [NSString dummy]; 18 + return 0; 19 + } 20 +
+5
tests/src/objc_properties.m
··· 19 19 20 20 unsigned int outCount, i; 21 21 objc_property_t *properties = class_copyPropertyList([helloclass class], &outCount); 22 + printf("%u properties\n", outCount); 22 23 for(i = 0; i < outCount; i++) 23 24 { 24 25 objc_property_t property = properties[i]; 25 26 printf("%s %s\n", property_getName(property), property_getAttributes(property)); 26 27 } 27 28 free(properties); 29 + 30 + Method* methods = class_copyMethodList([helloclass class], &outCount); 31 + printf("%u methods\n", outCount); 32 + free(methods); 28 33 29 34 return 0; 30 35 }