this repo has no description
1
fork

Configure Feed

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

Work needed for a very-trivial ObjC app to work

+556 -68
+4 -1
src/dyld/FileMap.cpp
··· 15 15 } 16 16 } 17 17 18 - void FileMap::add(const MachO& mach, uintptr_t slide, uintptr_t base) 18 + const FileMap::ImageMap* FileMap::add(const MachO& mach, uintptr_t slide, uintptr_t base) 19 19 { 20 20 ImageMap* symbol_map = new ImageMap; 21 21 ··· 25 25 symbol_map->header = mach.header(); 26 26 symbol_map->eh_frame = mach.get_eh_frame(); 27 27 symbol_map->unwind_info = mach.get_unwind_info(); 28 + symbol_map->sections = mach.sections(); 28 29 29 30 if (!m_maps.insert(std::make_pair(base, symbol_map)).second) 30 31 { ··· 44 45 continue; 45 46 symbol_map->symbols.insert(std::make_pair(sym.addr, sym.name.substr(1))); 46 47 } 48 + 49 + return symbol_map; 47 50 } 48 51 49 52 void FileMap::addWatchDog(uintptr_t addr)
+4 -1
src/dyld/FileMap.h
··· 12 12 public: 13 13 ~FileMap(); 14 14 15 - void add(const MachO& mach, uintptr_t slide, uintptr_t base); 15 + struct ImageMap; 16 + 17 + const ImageMap* add(const MachO& mach, uintptr_t slide, uintptr_t base); 16 18 17 19 void addWatchDog(uintptr_t addr); 18 20 ··· 24 26 mach_header header; 25 27 std::pair<uint64_t,uint64_t> eh_frame; 26 28 std::pair<uint64_t,uint64_t> unwind_info; 29 + std::vector<MachO::Section> sections; 27 30 }; 28 31 29 32 const ImageMap* imageMapForAddr(const void* p);
+9 -8
src/dyld/MachOLoader.cpp
··· 6 6 #include "trace.h" 7 7 #include "FileMap.h" 8 8 #include "stlutils.h" 9 + #include "public.h" 9 10 #include <limits.h> 10 11 #include <iostream> 11 12 #include <cstring> ··· 26 27 extern int g_argc; 27 28 extern char** g_argv; 28 29 extern bool g_trampoline; 30 + extern std::set<LoaderHookFunc*> g_machoLoaderHooks; 29 31 30 32 // These are GCC internals 31 33 extern "C" void __register_frame(void*); ··· 205 207 206 208 m_last_addr = std::max(m_last_addr, (intptr)vmaddr + vmsize); 207 209 } 208 - 209 - __register_frame(reinterpret_cast<void*>(mach.get_eh_frame().first)); 210 + 211 + if (mach.get_eh_frame().first) 212 + __register_frame(reinterpret_cast<void*>(mach.get_eh_frame().first)); 210 213 } 211 214 212 215 void MachOLoader::checkMmapMinAddr(intptr addr) ··· 429 432 } 430 433 431 434 432 - void MachOLoader::loadSymbols(const MachO& mach, intptr slide, intptr base) 433 - { 434 - g_file_map.add(mach, slide, base); 435 - } 436 - 437 435 438 436 void MachOLoader::load(const MachO& mach, std::string sourcePath, Exports* exports) 439 437 { ··· 456 454 457 455 doBind(mach, slide); 458 456 459 - loadSymbols(mach, slide, base); 457 + const FileMap::ImageMap* img = g_file_map.add(mach, slide, base); 458 + 459 + for (LoaderHookFunc* func : g_machoLoaderHooks) 460 + func(&img->header, slide); 460 461 } 461 462 462 463
-3
src/dyld/MachOLoader.h
··· 49 49 // Creates a list of publicly visible functions in this module 50 50 void loadExports(const MachO& mach, intptr base, Exports* exports); 51 51 52 - // Puts all symbol addresses into a global map 53 - void loadSymbols(const MachO& mach, intptr slide, intptr base); 54 - 55 52 // Loads a Mach-O file and does all the processing 56 53 void load(const MachO& mach, std::string sourcePath, Exports* exports = 0); 57 54
+39 -8
src/dyld/ld.cpp
··· 1 + #include "config.h" 1 2 #define DARWIN_LD_INTERNAL 2 3 #include "MachOLoader.h" 3 4 #include "ld.h" ··· 6 7 #include "mutex.h" 7 8 #include "trace.h" 8 9 #include "FileMap.h" 9 - #include "config.h" 10 10 #include "log.h" 11 11 #include "IniConfig.h" 12 12 #include "stlutils.h" ··· 19 19 #include <limits.h> 20 20 #include <regex.h> 21 21 #include <cassert> 22 + #include <list> 23 + #include <algorithm> 22 24 23 25 static Darling::Mutex g_ldMutex; 24 26 static std::map<std::string, LoadedLibrary*> g_ldLibraries; ··· 38 40 static void* attemptDlopen(const char* filename, int flag); 39 41 static int translateFlags(int flags); 40 42 __attribute__((constructor)) static void initLD(); 43 + static std::list<Darling::DlsymHookFunc> g_dlsymHooks; 41 44 42 45 extern MachOLoader* g_loader; 43 46 extern char g_darwin_executable_path[PATH_MAX]; ··· 441 444 442 445 static const char* translateSymbol(const char* symbol) 443 446 { 444 - std::string s = symbol; 447 + bool translated = false; 445 448 static char symbuffer[255]; 446 - 447 - for (int i = 0; i < sizeof(g_suffixes) / sizeof(g_suffixes[0]); i++) 449 + 450 + strcpy(symbuffer, symbol); 451 + 452 + for (auto f : g_dlsymHooks) 448 453 { 449 - size_t pos = s.find(g_suffixes[i]); 450 - if (pos != std::string::npos) 451 - s.erase(pos, strlen(g_suffixes[i])); 454 + if (f(symbuffer)) 455 + { 456 + translated = true; 457 + break; 458 + } 452 459 } 453 460 454 - strcpy(symbuffer, s.c_str()); 461 + if (!translated) 462 + { 463 + std::string s = symbol; 464 + for (int i = 0; i < sizeof(g_suffixes) / sizeof(g_suffixes[0]); i++) 465 + { 466 + size_t pos = s.find(g_suffixes[i]); 467 + if (pos != std::string::npos) 468 + s.erase(pos, strlen(g_suffixes[i])); 469 + } 470 + 471 + strcpy(symbuffer, s.c_str()); 472 + } 473 + 455 474 return symbuffer; 456 475 } 457 476 ··· 581 600 return 0; 582 601 } 583 602 603 + void Darling::registerDlsymHook(Darling::DlsymHookFunc func) 604 + { 605 + g_dlsymHooks.push_front(func); 606 + } 607 + 608 + void Darling::deregisterDlsymHook(Darling::DlsymHookFunc func) 609 + { 610 + //auto it = std::find(g_dlsymHooks.begin(), g_dlsymHooks.end(), func); 611 + //if (it != g_dlsymHooks.end()) 612 + // g_dlsymHooks.erase(it); 613 + } 614 +
+7
src/dyld/ld.h
··· 47 47 Exports* exports; 48 48 }; 49 49 50 + namespace Darling 51 + { 52 + typedef bool (*DlsymHookFunc)(char* symName); 53 + void registerDlsymHook(DlsymHookFunc func); 54 + void deregisterDlsymHook(DlsymHookFunc func); 55 + }; 56 + 50 57 #endif
+40 -4
src/dyld/public.cpp
··· 6 6 #include <cstring> 7 7 #include <cstdlib> 8 8 #include <map> 9 + #include <set> 9 10 #include <link.h> 10 11 #include <stddef.h> 11 12 #include "../libmach-o/leb.h" 12 13 13 14 extern FileMap g_file_map; 14 15 extern "C" char* dyld_getDarwinExecutablePath(); 16 + 17 + std::set<LoaderHookFunc*> g_machoLoaderHooks; 15 18 16 19 uint32_t _dyld_image_count(void) 17 20 { ··· 33 36 return g_file_map.images().at(image_index)->filename.c_str(); 34 37 } 35 38 36 - void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)) 39 + char* getsectdata(const struct mach_header* header, const char* segname, const char* sectname, unsigned long* size) 37 40 { 38 - // This would be needed for the GCC libunwind 41 + FileMap::ImageMap* imageMap = 0; 42 + 43 + // Find the loaded image the header belongs to 44 + for (FileMap::ImageMap* entry : g_file_map.images()) 45 + { 46 + if (&entry->header == header) 47 + { 48 + imageMap = entry; 49 + break; 50 + } 51 + } 52 + 53 + if (!imageMap) 54 + return 0; // Original dyld's man page indicates that it would still somehow proceed, but we don't bother 55 + 56 + for (const MachO::Section& sect : imageMap->sections) 57 + { 58 + if (sect.segment == segname && sect.section == sectname) 59 + { 60 + char* addr = reinterpret_cast<char*>(sect.addr); 61 + 62 + *size = sect.size; 63 + addr += imageMap->slide; 64 + 65 + return addr; 66 + } 67 + } 68 + return 0; 39 69 } 40 70 41 - void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)) 71 + void _dyld_register_func_for_add_image(LoaderHookFunc* func) 72 + { 73 + // Needed for ObjC 74 + g_machoLoaderHooks.insert(func); 75 + } 76 + 77 + void _dyld_register_func_for_remove_image(LoaderHookFunc* func) 42 78 { 43 - // This would be needed for the GCC libunwind 79 + g_machoLoaderHooks.erase(func); 44 80 } 45 81 46 82 int32_t NSVersionOfRunTimeLibrary(const char* libraryName)
+14 -6
src/dyld/public.h
··· 1 1 #ifndef DYLD_PUBLIC_H 2 2 #define DYLD_PUBLIC_H 3 3 #include <stdint.h> 4 - #include <mach-o/dyld_priv.h> 5 4 6 5 #ifdef __cplusplus 7 6 extern "C" { 8 7 #endif 9 8 10 - uint32_t _dyld_image_count(void); 9 + struct dyld_unwind_sections 10 + { 11 + const struct mach_header* mh; 12 + const void* dwarf_section; 13 + uintptr_t dwarf_section_length; 14 + const void* compact_unwind_section; 15 + uintptr_t compact_unwind_section_length; 16 + }; 11 17 18 + typedef void (LoaderHookFunc)(const struct mach_header* mh, intptr_t vmaddr_slide); 19 + 20 + uint32_t _dyld_image_count(void); 12 21 const struct mach_header* _dyld_get_image_header(uint32_t image_index); 13 - 14 22 intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index); 15 - 16 23 const char* _dyld_get_image_name(uint32_t image_index); 17 24 18 - void _dyld_register_func_for_add_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)); 25 + char* getsectdata(const struct mach_header* header, const char* segname, const char* sectname, unsigned long* size); 19 26 20 - void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header* mh, intptr_t vmaddr_slide)); 27 + void _dyld_register_func_for_add_image(LoaderHookFunc* func); 28 + void _dyld_register_func_for_remove_image(LoaderHookFunc* func); 21 29 22 30 int32_t NSVersionOfRunTimeLibrary(const char* libraryName); 23 31
+1 -1
src/dyld/trampoline_helper.nasm
··· 59 59 jmp r10 60 60 61 61 ; This is duplicated for every mapped function 62 - trampoline: 62 + trampoline_start: 63 63 mov r10, qword 0xb0b1b2b3b4b5b6 64 64 call r10 ; call reg_saveall 65 65
+8
src/libmach-o/MachO.h
··· 84 84 std::string name; 85 85 uint64_t addr; 86 86 }; 87 + 88 + struct Section 89 + { 90 + std::string segment, section; 91 + uintptr_t addr, size; 92 + }; 87 93 88 94 const std::vector<segment_command_64*>& segments64() const { return m_segments64; } 89 95 ··· 119 125 120 126 mach_header header() const { return m_header; } 121 127 bool reverse_endian() const { return m_reverse_endian; } // true if the file has a different endianness than the current platform 128 + const std::vector<Section> sections() const { return m_sections; } 122 129 123 130 inline uint32_t fixEndian(uint32_t i) const { return m_reverse_endian ? __builtin_bswap32(i) : i; } 124 131 ··· 144 151 size_t m_offset; 145 152 mach_header m_header; 146 153 bool m_reverse_endian; 154 + std::vector<Section> m_sections; 147 155 }; 148 156 149 157 class fat_architecture_not_supported : public std::exception
+12 -4
src/libmach-o/MachOImpl.cpp
··· 95 95 for (uint32_t j = 0; j < segment->nsects; j++) 96 96 { 97 97 const section& sec = sections[j]; 98 + Section savedSection{sec.segname, sec.sectname, uintptr_t(sec.addr), uintptr_t(sec.size)}; 99 + 98 100 LOGF("section %s in %s: " 99 101 "addr=%p size=%llu offset=%u align=%u " 100 102 "reloff=%u nreloc=%u flags=%u " ··· 105 107 sec.reloff, sec.nreloc, sec.flags, 106 108 sec.reserved1, sec.reserved2); 107 109 108 - if (!strcmp(sec.sectname, "__dyld") && !strcmp(sec.segname, "__DATA")) 110 + if (savedSection.section.size() > sizeof(sec.sectname)) 111 + savedSection.section.resize(sizeof(sec.sectname)); 112 + if (savedSection.segment.size() > sizeof(sec.segname)) 113 + savedSection.segment.resize(sizeof(sec.segname)); 114 + m_sections.push_back(savedSection); 115 + 116 + if (savedSection.section == "__dyld" && savedSection.segment == "__DATA") 109 117 m_dyld_data = sec.addr; 110 - if (!strcmp(sec.segname, "__TEXT")) 118 + if (savedSection.segment == "__TEXT") 111 119 { 112 - if (!strcmp(sec.sectname, "__eh_frame")) 120 + if (savedSection.section == "__eh_frame") 113 121 { 114 122 m_eh_frame.first = sec.addr; 115 123 m_eh_frame.second = sec.size; 116 124 } 117 - else if (!strcmp(sec.sectname, "__unwind_info")) 125 + else if (savedSection.section == "__unwind_info") 118 126 { 119 127 m_unwind_info.first = sec.addr; 120 128 m_unwind_info.second = sec.size;
+5 -4
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} -fblocks -std=c++0x") 16 - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") 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") 17 17 18 18 set(objcdarwin_SRCS 19 19 objc_msgSend.nasm 20 20 objc_msgSend_fixup.nasm 21 - dummy.c 21 + NameTranslate.cpp 22 + ClassRegister.cpp 22 23 ) 23 24 24 25 add_library(objc.A.dylib SHARED ${objcdarwin_SRCS}) 25 - target_link_libraries(objc.A.dylib -l:libobjc.so.4) 26 + target_link_libraries(objc.A.dylib -l:libobjc.so.4 -lgnustep-base) 26 27 27 28 install(TARGETS objc.A.dylib DESTINATION lib${SUFFIX}) 28 29
+214
src/libobjcdarwin/ClassRegister.cpp
··· 1 + #include "ClassRegister.h" 2 + #include "../dyld/public.h" 3 + #include "class.h" 4 + #include "method_list.h" 5 + #include <iostream> 6 + #include <map> 7 + #include <cstring> 8 + #include <cassert> 9 + 10 + /* 11 + __DATA,__objc_classlist was __OBJC2,__class_list 12 + __DATA,__objc_catlist was __OBJC2,__category_list 13 + __DATA,__objc_protolist was __OBJC2,__protocol_list 14 + __DATA,__objc_msgrefs was __OBJC2,__message_refs 15 + __DATA,__objc_classrefs was __OBJC2,__class_refs 16 + __DATA,__objc_superrefs was __OBJC2,__super_refs 17 + __DATA,__objc_imageinfo was __OBJC,__image_info 18 + */ 19 + 20 + #define SEG_OBJC_CLASSLIST_NEW "__DATA" 21 + #define SECT_OBJC_CLASSLIST_NEW "__objc_classlist" 22 + #define SEG_OBJC_CLASSLIST_OLD "__OBJC" 23 + #define SECT_OBJC_CLASSLIST_OLD "__class" // TODO: check if correct 24 + 25 + static std::map<const void*, objc_class*> g_convertedClasses; 26 + static std::pair<uintptr_t, uintptr_t> g_cstringSection; 27 + 28 + static void ProcessImageLoad(const struct mach_header* mh, intptr_t slide); 29 + static void ProcessImageUnload(const struct mach_header* mh, intptr_t slide); 30 + static void RegisterClass(const class_t* cls); 31 + static void RegisterClass(const old_class* cls); 32 + static old_class* PtrToClass(old_class_ptr ptr); 33 + 34 + // Here we process Mach-O files that have been loaded before this native library 35 + // Then we register a handler to process all images loaded in the future 36 + __attribute__((constructor)) 37 + void RegisterAlreadyLoadedClasses() 38 + { 39 + for (uint32_t i = 0; i < _dyld_image_count(); i++) 40 + { 41 + const struct mach_header* hdr = _dyld_get_image_header(i); 42 + ProcessImageLoad(hdr, 0); 43 + } 44 + 45 + _dyld_register_func_for_add_image(ProcessImageLoad); 46 + _dyld_register_func_for_remove_image(ProcessImageUnload); 47 + 48 + //std::cout << "Done registering\n"; 49 + } 50 + 51 + Class objcdarwin_class_lookup(const class_t* cls) 52 + { 53 + //std::cout << "Looking up " << cls << std::endl << std::flush; 54 + auto it = g_convertedClasses.find(cls); 55 + if (it != g_convertedClasses.end()) 56 + return it->second; 57 + else 58 + return Class(cls); // assume native or instance ptr 59 + } 60 + 61 + // This is very wrong. Does it have to be this way?s 62 + old_class* PtrToClass(old_class_ptr ptr) 63 + { 64 + if (ptr.ptrValue >= g_cstringSection.first && ptr.ptrValue < g_cstringSection.first+g_cstringSection.second) 65 + { 66 + //std::cout << ptr.cls << " found to be a string: " << ptr.name << std::endl; 67 + id cls = objc_getClass(ptr.name); // it is a string 68 + 69 + assert(cls != nullptr); 70 + return (old_class*) cls; 71 + } 72 + else 73 + { 74 + //std::cout << ptr.cls << " found to be ptr to class.\n"; 75 + return ptr.cls; 76 + } 77 + } 78 + 79 + template<typename ListType> void ConvertMethodListGen(Class c, const ListType* list) 80 + { 81 + std::cout << list->count << " methods within\n"; 82 + 83 + for (size_t i = 0; i < list->count; i++) 84 + { 85 + auto* m = &list->method_list[i]; 86 + 87 + std::cout << "Method: selName: " << m->selName << "; types: " << m->types << "; impl: " << m->impl << std::endl; 88 + 89 + SEL sel = sel_registerName(m->selName); 90 + class_addMethod(c, sel, reinterpret_cast<IMP>(m->impl), m->types); 91 + } 92 + } 93 + 94 + void RegisterClass(const class_t* cls) 95 + { 96 + std::cout << "Processing ObjC class " << cls->data()->className; 97 + std::cout << std::endl; 98 + 99 + // objc_allocateClassPair 100 + // objc_registerClassPair 101 + const class_t* meta = cls->isa; 102 + Class conv, super; 103 + if (g_convertedClasses.find(cls->superclass) != g_convertedClasses.end()) 104 + super = g_convertedClasses[cls->superclass]; 105 + else 106 + super = reinterpret_cast<objc_class*>(cls->superclass); 107 + 108 + conv = objc_allocateClassPair(super, cls->data()->className, 0); 109 + 110 + const class_ro_t* ro = cls->data(); 111 + const class_ro_t* roMeta = meta->data(); 112 + 113 + if (ro->baseMethods) 114 + ConvertMethodListGen(conv, ro->baseMethods); 115 + if (roMeta->baseMethods) 116 + ConvertMethodListGen(conv->isa, roMeta->baseMethods); 117 + 118 + conv->instance_size = ro->instSize; 119 + conv->isa->instance_size = roMeta->instSize; 120 + 121 + objc_registerClassPair(conv); 122 + g_convertedClasses[cls] = conv; 123 + g_convertedClasses[meta] = conv->isa; 124 + } 125 + 126 + void RegisterClass(const old_class* cls) 127 + { 128 + std::cout << "Processing old ObjC class " << cls->name; 129 + std::cout << std::endl; 130 + 131 + const old_class* meta = PtrToClass(cls->isa); 132 + Class conv, super; 133 + old_class* psuper = PtrToClass(cls->super_class); 134 + 135 + if (g_convertedClasses.find(psuper) != g_convertedClasses.end()) 136 + super = g_convertedClasses[psuper]; 137 + else 138 + super = reinterpret_cast<objc_class*>(psuper); 139 + 140 + conv = objc_allocateClassPair(super, cls->name, 0); 141 + 142 + std::cout << "Instance methods...\n"; 143 + if (cls->methodList) 144 + ConvertMethodListGen(conv, cls->methodList); 145 + std::cout << "Class methods...\n"; 146 + if (meta->methodList) 147 + ConvertMethodListGen(conv->isa, meta->methodList); 148 + 149 + objc_registerClassPair(conv); 150 + 151 + assert(id(conv) == objc_getClass(cls->name)); 152 + assert(id(conv->isa) == objc_getMetaClass(cls->name)); 153 + assert(class_isMetaClass(conv->isa)); 154 + assert(!class_isMetaClass(conv)); 155 + 156 + g_convertedClasses[cls] = conv; 157 + g_convertedClasses[cls->name] = conv; 158 + g_convertedClasses[meta] = conv->isa; 159 + 160 + /* 161 + SEL ss = sel_get_any_uid("doHello:::::::"); 162 + std::cout << "objc_msg_lookup: " << conv << ' ' << ss << std::endl; 163 + void* p = (void*) objc_msg_lookup(id(conv), ss); 164 + 165 + std::cout << "Impl: " << p << "; Sel: " << ss << std::endl; 166 + */ 167 + } 168 + 169 + void ProcessImageLoad(const struct mach_header* mh, intptr_t) 170 + { 171 + unsigned long size; 172 + const class_t** classes; 173 + 174 + classes = reinterpret_cast<const class_t**>( 175 + getsectdata(mh, SEG_OBJC_CLASSLIST_NEW, SECT_OBJC_CLASSLIST_NEW, &size) 176 + ); 177 + 178 + if (!classes) 179 + { 180 + // Try the old runtime 181 + const old_class* classes; 182 + 183 + classes = reinterpret_cast<const old_class*>( 184 + getsectdata(mh, SEG_OBJC_CLASSLIST_OLD, SECT_OBJC_CLASSLIST_OLD, &size) 185 + ); 186 + 187 + if (classes) 188 + { 189 + // g_cstringSection 190 + unsigned long cstrLen; 191 + void* ptr; 192 + 193 + ptr = getsectdata(mh, "__TEXT", "__cstring", &cstrLen); 194 + if (ptr) 195 + g_cstringSection = std::pair<uintptr_t,uintptr_t>(uintptr_t(ptr), cstrLen); 196 + else 197 + g_cstringSection = std::pair<uintptr_t,uintptr_t>(0, 0); 198 + 199 + for (size_t i = 0; i < size / sizeof(old_class); i++) 200 + RegisterClass(classes+i); 201 + } 202 + } 203 + else 204 + { 205 + for (size_t i = 0; i < size / sizeof(class_t*); i++) 206 + RegisterClass(classes[i]); 207 + } 208 + } 209 + 210 + void ProcessImageUnload(const struct mach_header* mh, intptr_t) 211 + { 212 + // TODO 213 + } 214 +
+153
src/libobjcdarwin/ClassRegister.h
··· 1 + #ifndef CLASSREGISTER_H 2 + #define CLASSREGISTER_H 3 + #include <stdint.h> 4 + #include <cstddef> 5 + #include <objc/runtime.h> 6 + 7 + struct method_t 8 + { 9 + const char* selName; 10 + const char* types; 11 + void* impl; 12 + }; 13 + 14 + struct method_list_t 15 + { 16 + uint32_t entsize_and_flags; 17 + uint32_t count; 18 + method_t method_list[0]; 19 + 20 + uint32_t entsize() const { return entsize_and_flags & ~uint32_t(3); } 21 + }; 22 + 23 + struct class_ro_t 24 + { 25 + uint32_t flags, instStart, instSize; 26 + #ifdef __x86_64__ 27 + uint32_t nothing; 28 + #endif 29 + void* ivarLayout; 30 + const char* className; 31 + const method_list_t* baseMethods; // instance methods for classes, static methods for metaclasses 32 + const void* baseProtocols; 33 + 34 + void* todo[2]; // TODO: two more pointers 35 + }; 36 + 37 + struct class_rw_t 38 + { 39 + uint32_t flags, version; 40 + class_ro_t* ro; 41 + 42 + union 43 + { 44 + method_list_t* method_list; 45 + method_list_t** method_lists; 46 + }; 47 + 48 + void* todo[4]; // TODO: four more pointers 49 + }; 50 + 51 + struct class_t 52 + { 53 + class_t* isa; // instance of 54 + class_t* superclass; 55 + void* cache; // empty cache imported here 56 + void* vtable; 57 + uintptr_t data_and_flags; 58 + 59 + // TODO: WTF? Should be rw data 60 + class_ro_t* data() const 61 + { 62 + uintptr_t p = data_and_flags & ~uintptr_t(3); 63 + return reinterpret_cast<class_ro_t*>(p); 64 + } 65 + }; 66 + 67 + union old_class_ptr 68 + { 69 + struct old_class* cls; 70 + const char* name; 71 + uintptr_t ptrValue; 72 + }; 73 + 74 + struct old_class 75 + { 76 + old_class_ptr isa; 77 + old_class_ptr super_class; 78 + const char *name; 79 + long version; 80 + long info; 81 + long instance_size; 82 + struct old_ivar_list *ivars; 83 + struct old_method_list *methodList; 84 + void* cache; 85 + struct old_protocol_list *protocols; 86 + // CLS_EXT only 87 + const uint8_t *ivar_layout; 88 + struct old_class_ext *ext; 89 + }; 90 + 91 + struct old_class_ext 92 + { 93 + uint32_t size; 94 + const uint8_t *weak_ivar_layout; 95 + struct old_property_list **propertyLists; 96 + }; 97 + 98 + struct old_category 99 + { 100 + char *category_name; 101 + char *class_name; 102 + struct old_method_list *instance_methods; 103 + struct old_method_list *class_methods; 104 + struct old_protocol_list *protocols; 105 + uint32_t size; 106 + struct old_property_list *instance_properties; 107 + }; 108 + 109 + struct old_ivar 110 + { 111 + char *ivar_name; 112 + char *ivar_type; 113 + int ivar_offset; 114 + #ifdef __x86_64__ 115 + int space; 116 + #endif 117 + }; 118 + 119 + struct old_ivar_list 120 + { 121 + int ivar_count; 122 + #ifdef __x86_64__ 123 + int space; 124 + #endif 125 + /* variable length structure */ 126 + struct old_ivar ivar_list[1]; 127 + }; 128 + 129 + 130 + struct old_method 131 + { 132 + const char* selName; 133 + const char* types; 134 + void* impl; 135 + }; 136 + 137 + struct old_method_list 138 + { 139 + struct old_method_list *obsolete; 140 + 141 + int count; 142 + #ifdef __x86_64__ 143 + int space; 144 + #endif 145 + /* variable length structure */ 146 + struct old_method method_list[1]; 147 + }; 148 + 149 + 150 + extern "C" Class objcdarwin_class_lookup(const class_t* cls); 151 + 152 + #endif 153 +
-1
src/libobjcdarwin/dummy.c
··· 1 - /* This file is needed for CMake to use the GCC linker */
+46 -27
src/libobjcdarwin/objc_msgSend.nasm
··· 1 - global objc_msgSend 1 + global __darwin_objc_msgSend 2 2 3 + extern objcdarwin_class_lookup 3 4 extern objc_msg_lookup 4 5 extern sel_get_any_uid 5 6 ··· 10 11 11 12 SaveRegisters: 12 13 pop r11 14 + 15 + push r9 16 + push r8 17 + push rcx 18 + push rdx 19 + push rsi 13 20 push rdi 14 - push rsi 15 - push rdx 16 - push rcx 17 - push r8 18 - push r9 21 + 19 22 ; save xmms? 20 23 jmp r11 21 24 22 25 RestoreRegisters: 23 26 pop r11 24 - pop r9 27 + pop rdi 28 + pop rsi 29 + pop rdx 30 + pop rcx 25 31 pop r8 26 - pop rcx 27 - pop rdx 28 - pop rsi 29 - pop rdi 32 + pop r9 30 33 jmp r11 31 34 32 - objc_msgSend: 35 + __darwin_objc_msgSend: 33 36 ; Procedure: 34 - ; 1) convert Apple selector to GNU 35 - ; 2) run objc_msg_lookup 36 - ; 3) jump to the pointer returned by objc_msg_lookup 37 + ; 1) get the converted GNU class from an Apple class 38 + ; 2) convert Apple selector to GNU 39 + ; 3) run objc_msg_lookup 40 + ; 4) jump to the pointer returned by objc_msg_lookup 37 41 38 42 call SaveRegisters 43 + call objcdarwin_class_lookup WRT ..plt 44 + mov [rsp], rax ; save the converted value 45 + 39 46 ; move the second argument into the first argument 40 - mov rdi, rsi 47 + mov rdi, [rsp+8] 41 48 call sel_get_any_uid WRT ..plt 42 49 ; rax now has the GNU selector 43 50 ; move rax to the second argument ··· 54 61 BITS 32 55 62 section text 56 63 57 - objc_msgSend: 58 - ; swap the first two arguments 64 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; TODO!!! 65 + 66 + __darwin_objc_msgSend: 67 + ;enter 8 68 + 59 69 mov ecx, [esp+4] 60 - xchg [esp+8], ecx 61 - mov [esp+4], ecx 70 + push ecx ; arg for func call 62 71 63 - call sel_get_any_uid WRT ..plt 72 + call objcdarwin_class_lookup ;WRT ..plt 64 73 65 - ; eax now has the GNU selector 66 - ; swap the arguments back 74 + add esp, 4 ; remove argument 75 + mov [esp+4], eax ; change the class id 67 76 68 - mov ecx, [esp+8] 69 - mov [esp+4], ecx 70 - xchg [esp+8], eax 71 - call objc_msg_lookup WRT ..plt 77 + mov ecx, [esp+8] ; second argument 78 + push ecx 79 + 80 + call sel_get_any_uid ;WRT ..plt 81 + 82 + add esp, 4 83 + mov [esp+8], eax 84 + 85 + push eax ; reuse the sel_get_any_uid retval 86 + mov eax, [esp+8] 87 + push eax ; class id 88 + 89 + call objc_msg_lookup ;WRT ..plt 90 + add esp, 8 72 91 73 92 jmp eax 74 93