this repo has no description
1
fork

Configure Feed

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

Support for Thread Local Storage and other new OS X dyld features

+537 -37
+2
src/dyld/CMakeLists.txt
··· 18 18 Trampoline.cpp 19 19 trampoline_helper.nasm 20 20 dyld_stub_binder.nasm 21 + tls_helper.nasm 21 22 ld.cpp 22 23 dyld.cpp 23 24 public.cpp 24 25 binfmt_misc.cpp 26 + TLS.cpp 25 27 ) 26 28 27 29 if (DEBUG)
+44 -27
src/dyld/MachOLoader.cpp
··· 38 38 #include <set> 39 39 #include <sys/mman.h> 40 40 #include <errno.h> 41 + #include <unistd.h> 41 42 #include <dlfcn.h> 42 43 #include <libgen.h> 43 44 #include "eh/EHSection.h" 45 + #include "TLS.h" 44 46 45 47 FileMap g_file_map; 46 48 static std::vector<std::string> g_bound_names; ··· 74 76 return (p + a) & ~a; 75 77 } 76 78 77 - static void dumpInt(int bound_name_id) 78 - { 79 - if (bound_name_id < 0) 80 - { 81 - fprintf(stderr, "%d: negative bound function id\n", bound_name_id); 82 - return; 83 - } 84 - if (bound_name_id >= (int)g_bound_names.size()) 85 - { 86 - fprintf(stderr, "%d: bound function id overflow\n", bound_name_id); 87 - return; 88 - } 89 - if (g_bound_names[bound_name_id].empty()) 90 - { 91 - fprintf(stderr, "%d: unbound function id\n", bound_name_id); 92 - return; 93 - } 94 - printf("calling %s(%d)\n", 95 - g_bound_names[bound_name_id].c_str(), bound_name_id); 96 - fflush(stdout); 97 - } 98 - 99 79 MachOLoader::MachOLoader() 100 80 : m_last_addr(0), m_pTrampolineMgr(0) 101 81 { ··· 166 146 if (!strcmp(name, SEG_PAGEZERO)) 167 147 continue; 168 148 169 - LOG << seg->segname << ": " 170 - << "fileoff=" << seg->fileoff 171 - << ", vmaddr=" << seg->vmaddr <<std::endl; 149 + LOG << seg->segname << ": " << "fileoff=" << seg->fileoff << ", vmaddr=" << seg->vmaddr <<std::endl; 172 150 173 151 int prot = 0, maxprot = 0; 174 152 ··· 191 169 maxprot |= PROT_EXEC; 192 170 193 171 194 - intptr filesize = alignMem(seg->filesize, 0x1000); 172 + intptr filesize = alignMem(seg->filesize, getpagesize()); 195 173 intptr vmaddr = seg->vmaddr + *slide; 174 + 175 + if (!vmaddr) 176 + throw std::runtime_error("Address 0x0 is invalid for mapping"); 196 177 197 178 if (vmaddr < m_last_addr) 198 179 { ··· 205 186 } 206 187 *base = std::min(*base, vmaddr); 207 188 208 - intptr vmsize = alignMem(seg->vmsize, 0x1000); 189 + intptr vmsize = alignMem(seg->vmsize, getpagesize()); 209 190 LOG << "mmap(file) " << mach.filename() << ' ' << name 210 191 << ": " << (void*)vmaddr << "-" << (void*)(vmaddr + filesize) 211 192 << " offset=" << mach.offset() + seg->fileoff <<std::endl; ··· 573 554 for (MachO::Export* exp : mach.exports()) 574 555 { 575 556 exp->addr += base; 557 + if (exp->resolver) // EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER support 558 + exp->resolver += base; 559 + 576 560 // TODO(hamaji): Not 100% sure, but we may need to consider weak symbols. 577 561 if (!exports->insert(make_pair(exp->name, *exp)).second) 578 562 { ··· 638 622 639 623 if (!bindLater) 640 624 { 625 + setupTLS(mach, img, slide); 641 626 for (LoaderHookFunc* func : g_machoLoaderHooks) 642 627 func(img->header, slide); 643 628 } ··· 645 630 { 646 631 LOG << mach.binds().size() << " binds pending\n"; 647 632 m_pendingBinds.push_back(PendingBind{ &mach, img->header, slide, bindLazy }); 633 + m_pendingTLS.push_back(PendingTLS { &mach, img, slide} ); 648 634 } 649 635 650 636 popCurrentLoader(); 651 637 } 652 638 639 + void MachOLoader::doPendingTLS() 640 + { 641 + for (PendingTLS& tls : m_pendingTLS) 642 + setupTLS(*tls.mach, tls.img, tls.slide); 643 + 644 + m_pendingTLS.clear(); 645 + } 646 + 647 + void MachOLoader::setupTLS(const MachO& mach, const FileMap::ImageMap* image, intptr slide) 648 + { 649 + std::vector<tlv_descriptor*> descriptors; 650 + const std::vector<MachO::TLVSection>& tlvSections = mach.tlv_sections(); 651 + std::vector<void*> initializers; 652 + 653 + if (tlvSections.empty()) 654 + return; 655 + 656 + for (MachO::TLVSection sect : tlvSections) 657 + { 658 + tlv_descriptor* des = reinterpret_cast<tlv_descriptor*>(sect.firstDescriptor+slide); 659 + for (size_t i = 0; i < sect.count; i++) 660 + descriptors.push_back(&des[i]); 661 + } 662 + 663 + for (uint64_t offset : mach.tlv_init_funcs()) 664 + initializers.push_back((void*) (offset+slide)); 665 + 666 + Darling::TLSSetup((void*) image, descriptors, initializers, (void*) mach.tlv_initial_values().first, mach.tlv_initial_values().second); 667 + } 668 + 653 669 void MachOLoader::doPendingBinds() 654 670 { 655 671 for (const PendingBind& b : m_pendingBinds) ··· 754 770 //g_timer.print(mach.filename().c_str()); 755 771 756 772 doPendingBinds(); 773 + doPendingTLS(); 757 774 runPendingInitFuncs(argc, argv, &envCopy[0], apple); 758 775 759 776 mach.close();
+16
src/dyld/MachOLoader.h
··· 31 31 #include "ld.h" 32 32 #include "UndefinedFunction.h" 33 33 #include "Trampoline.h" 34 + #include "FileMap.h" 34 35 35 36 class MachOLoader 36 37 { ··· 87 88 // Performs pending binds. Used when loading the main executable and its dependencies. 88 89 void doPendingBinds(); 89 90 91 + void doPendingTLS(); 92 + 93 + // Processes information from MachO and calls the TLS infrastructure to set things up 94 + void setupTLS(const MachO& mach, const FileMap::ImageMap* img, intptr slide); 95 + 90 96 // Starts an application 91 97 void run(MachO& mach, int argc, char** argv, char** envp, bool bindLazy = false); 92 98 ··· 135 141 bool bindLazy; 136 142 }; 137 143 std::vector<PendingBind> m_pendingBinds; 144 + 145 + // Pending TLS variables 146 + // Because of initializers, we need to run them after the binds are done 147 + struct PendingTLS 148 + { 149 + const MachO* mach; 150 + const FileMap::ImageMap* img; 151 + intptr slide; 152 + }; 153 + std::vector<PendingTLS> m_pendingTLS; 138 154 139 155 std::vector<std::string> m_rpathContext; 140 156 std::stack<std::string> m_loaderPath;
+182
src/dyld/TLS.cpp
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2013 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #include "TLS.h" 21 + #include <cstdlib> 22 + #include <map> 23 + #include <cassert> 24 + #include <cstring> 25 + #include "log.h" 26 + #include "trace.h" 27 + #include "mutex.h" 28 + 29 + static void TLSRunDestructors(void* p); 30 + 31 + static std::map<void*, Darling::ImageData*> m_images; 32 + static std::map<pthread_key_t, Darling::ImageData*> m_imagesKey; 33 + static Darling::Mutex m_imagesMutex; 34 + 35 + // Maybe not a nice solution, we could implement TLS completely on our own via the fs/gs register 36 + static __thread Darling::ThreadData m_tlsData[1024]; // 1024 = PTHREAD_KEYS_MAX 37 + 38 + // Used for a thread-local list of destructor-object pairs (DestructorLinkedListElement) 39 + static pthread_key_t m_keyDestructors; 40 + 41 + __attribute__((constructor)) 42 + static void TLSSetupDestructors() 43 + { 44 + pthread_key_create(&m_keyDestructors, TLSRunDestructors); 45 + } 46 + 47 + static void TLSRunDestructors(void* p) 48 + { 49 + TRACE1(p); 50 + 51 + Darling::DestructorLinkedListElement* dlist = static_cast<Darling::DestructorLinkedListElement*>(p); 52 + 53 + dlist = dlist->first; 54 + 55 + do 56 + { 57 + Darling::DestructorLinkedListElement* dthis = dlist; 58 + 59 + dlist->destructor(dlist->object); 60 + dlist = dlist->next; 61 + 62 + delete dthis; 63 + } 64 + while (dlist != nullptr); 65 + } 66 + 67 + __attribute__((naked)) void* Darling::TLSGetNative() 68 + { 69 + return m_tlsData; 70 + } 71 + 72 + void Darling::TLSSetup(void* imageKey, std::vector<tlv_descriptor*>& descriptors, std::vector<void*>& initializers, void* start, uintptr_t length) 73 + { 74 + Darling::MutexLock _l(&m_imagesMutex); 75 + pthread_key_t key; 76 + ImageData* id; 77 + 78 + auto it = m_images.find(imageKey); 79 + assert (it == m_images.end()); 80 + 81 + pthread_key_create(&key, (void (*)(void *)) Darling::TLSTeardownThread); 82 + 83 + m_images[imageKey] = id = new ImageData{ key, start, length, initializers }; 84 + m_imagesKey[key] = id; 85 + 86 + for (tlv_descriptor* d : descriptors) 87 + { 88 + d->thunk = Darling::TLSGetAddr; 89 + d->key = key; 90 + } 91 + } 92 + 93 + void Darling::TLSTeardown(void* imageKey) 94 + { 95 + TRACE1(imageKey); 96 + 97 + Darling::MutexLock _l(&m_imagesMutex); 98 + auto it = m_images.find(imageKey); 99 + pthread_key_t key; 100 + 101 + assert(it != m_images.end()); 102 + key = it->second->key; 103 + 104 + // TODO: What to do with live objects with C++11 destructors? Does Apple's dyld handle this? 105 + 106 + m_imagesKey.erase(key); 107 + pthread_key_delete(key); 108 + 109 + delete it->second; 110 + m_images.erase(it); 111 + } 112 + 113 + void Darling::TLSTeardownThread(Darling::ThreadData data) 114 + { 115 + TRACE1((void*) data); 116 + delete [] data; 117 + } 118 + 119 + void* Darling::TLSAllocate(pthread_key_t key) 120 + { 121 + TRACE1(key); 122 + 123 + Darling::MutexLock _l(&m_imagesMutex); 124 + 125 + Darling::ImageData* id = m_imagesKey[key]; 126 + char* data; 127 + 128 + assert(!m_tlsData[key]); 129 + 130 + // Allocate a new block for TLS variables 131 + m_tlsData[key] = data = new char[id->length]; 132 + 133 + // Copy the initial variable values into the new block 134 + memcpy(data, id->start, id->length); 135 + 136 + // Run initializers (constructors etc.) 137 + for (auto it = id->initializers.rbegin(); it != id->initializers.rend(); it++) 138 + { 139 + typedef void (*Initializer)(); 140 + Initializer in = Initializer(*it); 141 + in(); 142 + } 143 + 144 + // Delete the data upon thread exit 145 + pthread_setspecific(key, data); 146 + 147 + LOG << "TLS data allocated at " << (void*)data << std::endl; 148 + LOG << "Pointer written at " << &m_tlsData[key] << std::endl; 149 + 150 + return data; 151 + } 152 + 153 + void Darling::TLSAtExit(void (*destructor)(void*), void* object) 154 + { 155 + TRACE2(destructor, object); 156 + 157 + Darling::DestructorLinkedListElement* last = static_cast<Darling::DestructorLinkedListElement*>(pthread_getspecific(m_keyDestructors)); 158 + Darling::DestructorLinkedListElement* d = new Darling::DestructorLinkedListElement; 159 + 160 + d->destructor = destructor; 161 + d->object = object; 162 + d->next = nullptr; 163 + 164 + if (last != nullptr) 165 + { 166 + d->first = last->first; 167 + last->next = d; 168 + } 169 + else 170 + { 171 + d->first = d; 172 + } 173 + 174 + pthread_setspecific(m_keyDestructors, d); 175 + } 176 + 177 + void* Darling::TLSBootstrap(tlv_descriptor* desc) 178 + { 179 + LOG << "Darling::TLSBootstrap() called, this should never happen\n"; 180 + abort(); 181 + } 182 +
+78
src/dyld/TLS.h
··· 1 + /* 2 + This file is part of Darling. 3 + 4 + Copyright (C) 2013 Lubos Dolezel 5 + 6 + Darling is free software: you can redistribute it and/or modify 7 + it under the terms of the GNU General Public License as published by 8 + the Free Software Foundation, either version 3 of the License, or 9 + (at your option) any later version. 10 + 11 + Darling is distributed in the hope that it will be useful, 12 + but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + GNU General Public License for more details. 15 + 16 + You should have received a copy of the GNU General Public License 17 + along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + */ 19 + 20 + #ifndef TLS_H 21 + #define TLS_H 22 + #include "../libmach-o/MachO.h" 23 + #include <vector> 24 + #include <set> 25 + #include <pthread.h> 26 + #include <stdint.h> 27 + 28 + namespace Darling 29 + { 30 + typedef char* ThreadData; 31 + 32 + struct ImageData 33 + { 34 + pthread_key_t key; 35 + 36 + // Location of initial variable values 37 + void* start; 38 + uintptr_t length; 39 + 40 + std::vector<void*> initializers; 41 + }; 42 + 43 + struct DestructorLinkedListElement 44 + { 45 + void (*destructor)(void*); 46 + void* object; 47 + DestructorLinkedListElement *next, *first; 48 + }; 49 + 50 + // Called upon image load 51 + void TLSSetup(void* key, std::vector<tlv_descriptor*>& descriptors, std::vector<void*>& initializers, void* start, uintptr_t length); 52 + 53 + // Called upon image unload 54 + void TLSTeardown(void* key); 55 + 56 + // Called by pthread upon thread destruction 57 + void TLSTeardownThread(ThreadData data); 58 + 59 + // Fast-path helper for darling_tls_get_addr() 60 + void* TLSGetNative() asm("darling_tls_get_native"); 61 + 62 + // Called by darling_tls_get_addr() when the variable is accessed for the first time - slow path 63 + void* TLSAllocate(pthread_key_t key) asm("darling_tls_allocate"); 64 + 65 + // Called by object initializers to register a destructor 66 + void TLSAtExit(void (*destructor)(void*), void* object) asm("_tlv_atexit"); 67 + 68 + // If this gets called, then the image wasn't initialized properly 69 + void* TLSBootstrap(tlv_descriptor* desc) asm("_tlv_bootstrap"); 70 + 71 + // Implemented in assembly 72 + void* TLSGetAddr(tlv_descriptor* desc) asm("darling_tls_get_addr"); 73 + 74 + 75 + } 76 + 77 + #endif 78 +
+16 -2
src/dyld/ld.cpp
··· 622 622 623 623 while (it != le.end()) 624 624 { 625 - const Exports* e = *it; 626 - Exports::const_iterator itSym = e->find(symbol); 625 + Exports* e = *it; 626 + Exports::iterator itSym = e->find(symbol); 627 627 628 628 if (itSym == e->end()) 629 629 itSym = e->find(std::string("_") + symbol); // TODO: WTF? ··· 631 631 if (itSym != e->end()) 632 632 { 633 633 if (handle != __DARLING_RTLD_STRONG || !(itSym->second.flag & 4)) 634 + { 635 + MachO::Export& exp = itSym->second; 636 + 637 + // If there is a resolver function, we lazily call it now 638 + // and update the original stub address with the real one returned. 639 + 640 + if (exp.resolver) 641 + { 642 + typedef uintptr_t (ResolverFunc)(); 643 + ResolverFunc* func = (ResolverFunc*) exp.resolver; 644 + exp.addr = func(); 645 + exp.resolver = 0; 646 + } 634 647 return reinterpret_cast<void*>(itSym->second.addr); 648 + } 635 649 } 636 650 it++; 637 651 }
+114
src/dyld/tls_helper.nasm
··· 1 + ; 2 + ; This file is part of Darling. 3 + ; 4 + ; Copyright (C) 2013 Lubos Dolezel 5 + ; 6 + ; Darling is free software: you can redistribute it and/or modify 7 + ; it under the terms of the GNU General Public License as published by 8 + ; the Free Software Foundation, either version 3 of the License, or 9 + ; (at your option) any later version. 10 + ; 11 + ; Darling is distributed in the hope that it will be useful, 12 + ; but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + ; GNU General Public License for more details. 15 + ; 16 + ; You should have received a copy of the GNU General Public License 17 + ; along with Darling. If not, see <http://www.gnu.org/licenses/>. 18 + ; 19 + 20 + 21 + section .note.GNU-stack noalloc noexec nowrite progbits 22 + 23 + extern darling_tls_get_native 24 + extern darling_tls_allocate 25 + 26 + global darling_tls_get_addr 27 + 28 + %ifidn __OUTPUT_FORMAT__, elf64 29 + 30 + BITS 64 31 + section text 32 + 33 + darling_tls_get_addr: 34 + call darling_tls_get_native ; fast three-instruction function 35 + 36 + push rdi 37 + mov rdi, [rdi+8] 38 + mov rax, [rax+rdi*8] 39 + pop rdi 40 + 41 + test rax, rax 42 + jz slow_path 43 + 44 + add rax, [rdi+16] ; add the variable offset 45 + ret 46 + 47 + slow_path: 48 + enter 592, 0 49 + 50 + ; Do a register full-save, because the caller assumes that no registers 51 + ; except for rax/rdi will be modified 52 + mov [rbp-8], rdi 53 + mov [rbp-16], rsi 54 + mov [rbp-24], rdx 55 + mov [rbp-32], rcx 56 + mov [rbp-40], r8 57 + mov [rbp-48], r9 58 + mov [rbp-56], r10 59 + mov [rbp-64], r11 60 + fxsave [rbp-592] 61 + 62 + mov rdi, [rdi+8] ; pass the pthread_key 63 + call darling_tls_allocate 64 + 65 + fxrstor [rbp-592] 66 + mov r11, [rbp-64] 67 + mov r10, [rbp-56] 68 + mov r9, [rbp-48] 69 + mov r8, [rbp-40] 70 + mov rcx, [rbp-32] 71 + mov rdx, [rbp-24] 72 + mov rsi, [rbp-16] 73 + mov rdi, [rbp-8] 74 + 75 + add rax, [rdi+16] ; add the variable offset 76 + leave 77 + ret 78 + 79 + %elifidn __OUTPUT_FORMAT__, elf 80 + 81 + BITS 32 82 + section text 83 + 84 + darling_tls_get_addr: 85 + mov ecx, eax ; eax will get destroyed 86 + call darling_tls_get_native ; fast three-instruction function 87 + push ecx 88 + 89 + mov ecx, [ecx+4] ; add the pthread key 90 + mov eax, [eax+ecx*4] ; read the value at the key 91 + 92 + test eax, eax 93 + jz slow_path 94 + 95 + pop ecx 96 + add eax, [ecx+8] ; add the offset 97 + ret 98 + 99 + slow_path: 100 + mov ecx, [esp] 101 + push dword [ecx+4] ; pass the pthread_key 102 + call darling_tls_allocate 103 + pop ecx 104 + pop ecx 105 + 106 + add eax, [ecx+8] ; add the offset 107 + ret 108 + 109 + %else 110 + 111 + %error "Unsupported platform" 112 + 113 + %endif 114 +
+19 -1
src/libmach-o/MachO.h
··· 1 1 /* 2 2 This file is part of Darling. 3 3 4 - Copyright (C) 2012 Lubos Dolezel 4 + Copyright (C) 2012-2013 Lubos Dolezel 5 5 Copyright (C) 2011 Shinichiro Hamaji 6 6 7 7 Darling is free software: you can redistribute it and/or modify ··· 69 69 std::string name; 70 70 uint64_t addr; 71 71 uint32_t flag; 72 + uint64_t resolver; // address of the resolver function, addr contains a stub 72 73 }; 73 74 74 75 struct Symbol ··· 88 89 uint64_t addr; 89 90 std::string name; // symbol name 90 91 bool pcrel; // i386 92 + }; 93 + 94 + struct TLVSection 95 + { 96 + uintptr_t firstDescriptor; 97 + unsigned long count; 91 98 }; 92 99 93 100 const std::vector<segment_command_64*>& segments64() const { return m_segments64; } ··· 118 125 std::pair<uint64_t,uint64_t> get_eh_frame() const { return m_eh_frame; } 119 126 std::pair<uint64_t,uint64_t> get_unwind_info() const { return m_unwind_info; } 120 127 128 + // TLS 129 + const std::vector<uint64_t>& tlv_init_funcs() const { return m_tlv_init_funcs; } 130 + std::pair<uint64_t,uint64_t> tlv_initial_values() const { return m_tlv; } 131 + const std::vector<TLVSection>& tlv_sections() const { return m_tlv_sections; } 132 + 121 133 uint64_t dyld_data() const { return m_dyld_data; } 122 134 123 135 bool is64() const { return m_is64; } ··· 146 158 uint64_t m_entry, m_main; 147 159 std::vector<uint64_t> m_init_funcs; 148 160 std::vector<uint64_t> m_exit_funcs; 161 + std::vector<uint64_t> m_tlv_init_funcs; 162 + std::vector<TLVSection> m_tlv_sections; 149 163 uint64_t m_dyld_data; 164 + // first: address 165 + // second: length 150 166 std::pair<uint64_t,uint64_t> m_eh_frame; 151 167 std::pair<uint64_t,uint64_t> m_unwind_info; 168 + std::pair<uint64_t,uint64_t> m_tlv; // address contains initial values 169 + 152 170 bool m_is64; 153 171 int m_ptrsize; 154 172 int m_fd;
+66 -7
src/libmach-o/MachOImpl.cpp
··· 189 189 if (!m_is64) 190 190 bind_sections->push_back(sections + j); 191 191 break; 192 + 193 + // Thread Local Storage (TLS) support 194 + case S_THREAD_LOCAL_REGULAR: // initial TLS values 195 + case S_THREAD_LOCAL_ZEROFILL: // initial TLS values 196 + { 197 + LOG << "TLS initial values at " << std::hex << sec.addr << std::dec << "; " << sec.size << " bytes\n"; 198 + if (!m_tlv.first) 199 + m_tlv = std::make_pair<uint64_t,uint64_t>(uint64_t(sec.addr), uint64_t(sec.size)); 200 + else 201 + m_tlv.second = (sec.addr+sec.size) - m_tlv.first; // extend it to the end of this section 202 + break; 203 + } 204 + case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: // TLV initializers 205 + { 206 + for (uint64_t p = sec.addr; p < sec.addr + sec.size; p += m_ptrsize) 207 + m_tlv_init_funcs.push_back(p); 208 + break; 209 + } 210 + case S_THREAD_LOCAL_VARIABLES: // TLV descriptors 211 + { 212 + TLVSection sect = { uintptr_t(sec.addr), uintptr_t(sec.size / sizeof(tlv_descriptor)) }; 213 + 214 + LOG << "TLS descriptors at " << std::hex << sect.firstDescriptor << std::dec << "; count: " << sect.count << std::endl; 215 + 216 + m_tlv_sections.push_back(sect); 217 + break; 218 + } 219 + case S_THREAD_LOCAL_VARIABLE_POINTERS: // pointers to TLV descriptors 192 220 case S_ZEROFILL: 193 221 case S_CSTRING_LITERALS: // 0x2 194 222 case S_4BYTE_LITERALS: // 0x3 ··· 244 272 245 273 exp->name = *name_buf; 246 274 exp->flag = uleb128(p); 275 + exp->resolver = 0; 247 276 248 277 // TODO: flag == 8 (EXPORT_SYMBOL_FLAGS_REEXPORT) 249 278 if (exp->flag & EXPORT_SYMBOL_FLAGS_REEXPORT) ··· 256 285 LOG << "export: " << name_buf << " flags=" << std::hex << exp->flag << std::dec << " addr=" << (void*)exp->addr << std::endl; 257 286 258 287 if (exp->flag & EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 259 - { 260 - (void)uleb128(p); // TODO: save & use the resolver info for lazy pointers 261 - LOG << "FIXME: resolver not currently handled\n"; 262 - } 288 + exp->resolver = uleb128(p); 263 289 264 290 m_exports.push_back(exp); 265 291 ··· 545 571 break; 546 572 } 547 573 574 + case LC_DYLD_ENVIRONMENT: 575 + { 576 + lc_str name = reinterpret_cast<struct dylinker_command*>(cmds_ptr)->name; 577 + const char* str = ((char*)cmds_ptr + name.offset); 578 + LOG << "environment variable: " << str << std::endl; 579 + 580 + putenv(strdup(str)); 581 + 582 + break; 583 + } 584 + 548 585 case LC_UUID: 549 586 break; 550 587 ··· 591 628 break; 592 629 } 593 630 631 + case LC_VERSION_MIN_MACOSX: 632 + case LC_VERSION_MIN_IPHONEOS: 633 + { 634 + version_min_command* cmd = reinterpret_cast<version_min_command*>(cmds_ptr); 635 + LOG << "Version requirements: OS X: " 636 + << (cmd->version >> 16) << '.' 637 + << ((cmd->version >> 8) & 0xf) << '.' 638 + << (cmd->version & 0xf) 639 + << "; SDK: " 640 + << (cmd->sdk >> 16) << '.' 641 + << ((cmd->sdk >> 8) & 0xf) << '.' 642 + << (cmd->sdk & 0xf) 643 + << std::endl; 644 + break; 645 + } 646 + case LC_SOURCE_VERSION: 647 + { 648 + source_version_command* cmd = reinterpret_cast<source_version_command*>(cmds_ptr); 649 + LOG << "Original source version: " 650 + << (cmd->version >> 40) << '.' 651 + << ((cmd->version >> 30) & 0x3ff) << '.' 652 + << ((cmd->version >> 20) & 0x3ff) << '.' 653 + << ((cmd->version >> 10) & 0x3ff) << '.' 654 + << (cmd->version & 0x3ff) << std::endl; 655 + } 594 656 case LC_SUB_FRAMEWORK: 595 657 case LC_SUB_UMBRELLA: 596 658 case LC_SUB_CLIENT: ··· 600 662 case LC_CODE_SIGNATURE: 601 663 case LC_SEGMENT_SPLIT_INFO: 602 664 case LC_ID_DYLIB: 603 - case LC_VERSION_MIN_MACOSX: 604 - case LC_VERSION_MIN_IPHONEOS: 605 - case LC_SOURCE_VERSION: 606 665 case LC_DYLIB_CODE_SIGN_DRS: 607 666 break; 608 667