···11-/*
22-This file is part of Darling.
33-44-Copyright (C) 2012 Lubos Dolezel
55-Copyright (C) 2011 Shinichiro Hamaji
66-77-Darling is free software: you can redistribute it and/or modify
88-it under the terms of the GNU General Public License as published by
99-the Free Software Foundation, either version 3 of the License, or
1010-(at your option) any later version.
1111-1212-Darling is distributed in the hope that it will be useful,
1313-but WITHOUT ANY WARRANTY; without even the implied warranty of
1414-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515-GNU General Public License for more details.
1616-1717-You should have received a copy of the GNU General Public License
1818-along with Darling. If not, see <http://www.gnu.org/licenses/>.
1919-*/
2020-2121-#include "FileMap.h"
2222-#include <cassert>
2323-#include <cstring>
2424-#include <cstdio>
2525-#include <iostream>
2626-#include <stdexcept>
2727-#include <sstream>
2828-2929-FileMap::~FileMap()
3030-{
3131- for (auto m : m_maps)
3232- {
3333- if (m.second)
3434- delete m.second->header;
3535- delete m.second;
3636- }
3737-}
3838-3939-const FileMap::ImageMap* FileMap::add(const MachO& mach, uintptr_t slide, uintptr_t base, bool bindLazy)
4040-{
4141- ImageMap* symbol_map = new ImageMap;
4242-4343- symbol_map->filename = mach.filename();
4444- symbol_map->base = base;
4545- symbol_map->slide = slide;
4646-4747- // This needs to be allocated dynamically, because its memory location must be permanent.
4848- // It is used in certain silly APIs as a handle.
4949- symbol_map->header = new mach_header;
5050- *symbol_map->header = mach.header();
5151-5252- symbol_map->eh_frame = mach.get_eh_frame();
5353- symbol_map->unwind_info = mach.get_unwind_info();
5454- symbol_map->sections = mach.sections();
5555-5656- if (!bindLazy)
5757- {
5858- for (auto* b : mach.binds())
5959- {
6060- if (!b->is_lazy)
6161- continue;
6262- symbol_map->lazy_binds.push_back(*b);
6363- }
6464- }
6565-6666- if (!m_maps.insert(std::make_pair(base, symbol_map)).second)
6767- {
6868- std::stringstream ss;
6969- ss << "dupicated base addr: " << (void*) base << " in " << mach.filename();
7070- throw std::runtime_error(ss.str());
7171- }
7272-7373- m_maps_vec.push_back(symbol_map);
7474- m_maps_mach[symbol_map->header] = symbol_map;
7575-7676- for (MachO::Symbol sym : mach.symbols())
7777- {
7878- if (sym.name.empty() || sym.name[0] != '_')
7979- continue;
8080- sym.addr += slide;
8181- if (sym.addr < base)
8282- continue;
8383- symbol_map->symbols.insert(std::make_pair(sym.addr, sym.name.substr(1)));
8484- }
8585- for (const char* rpath : mach.rpaths())
8686- symbol_map->rpaths.push_back(rpath);
8787-8888- return symbol_map;
8989-}
9090-9191-void FileMap::addWatchDog(uintptr_t addr)
9292-{
9393- bool r = m_maps.insert(std::make_pair(addr, (ImageMap*)NULL)).second;
9494- assert(r);
9595-}
9696-9797-const char* FileMap::gdbInfoForAddr(const void* p) const
9898-{
9999- Dl_info i;
100100-101101- if (!findSymbolInfo(p, &i))
102102- return 0;
103103-104104- if (i.dli_fbase)
105105- {
106106-#ifdef __i386__
107107- const char* fmt_string = "0x%08lx in %s+%x () from %s";
108108-#else
109109- const char* fmt_string = "0x%016lx in %s%x () from %s";
110110-#endif
111111-112112- ptrdiff_t func_offset = uintptr_t(p) - uintptr_t(i.dli_saddr);
113113- snprintf(m_dumped_stack_frame_buf, sizeof(m_dumped_stack_frame_buf)-1, fmt_string, p, i.dli_sname, func_offset, i.dli_fname);
114114- }
115115- else
116116- {
117117-#ifdef __i386__
118118- const char* fmt_string = "0x%08lx in ?? () from %s";
119119-#else
120120- const char* fmt_string = "0x%016lx in ?? () from %s";
121121-#endif
122122- snprintf(m_dumped_stack_frame_buf, sizeof(m_dumped_stack_frame_buf)-1, fmt_string, p, i.dli_fname);
123123- }
124124-125125- return m_dumped_stack_frame_buf;
126126-}
127127-128128-const FileMap::ImageMap* FileMap::mainExecutable() const
129129-{
130130- assert(!m_maps_vec.empty());
131131- return m_maps_vec[0];
132132-}
133133-134134-const char* FileMap::fileNameForAddr(const void* p) const
135135-{
136136- const ImageMap* map = imageMapForAddr(p);
137137- if (!map)
138138- return 0;
139139- return map->filename.c_str();
140140-}
141141-142142-const FileMap::ImageMap* FileMap::imageMapForAddr(const void* p) const
143143-{
144144- uintptr_t addr = reinterpret_cast<uintptr_t>(p);
145145- const ImageMap* symbol_map;
146146-147147- std::map<uintptr_t, ImageMap*>::const_iterator found = m_maps.upper_bound(addr);
148148- if (found == m_maps.begin() || found == m_maps.end())
149149- return 0;
150150-151151- --found;
152152- return found->second;
153153-}
154154-155155-const FileMap::ImageMap* FileMap::imageMapForHeader(const mach_header* p) const
156156-{
157157- auto it = m_maps_mach.find(const_cast<mach_header*>(p));
158158- if (it == m_maps_mach.end())
159159- return nullptr;
160160- else
161161- return it->second;
162162-}
163163-164164-/*
165165-const FileMap::ImageMap* FileMap::imageMapForName(const std::string& name) const
166166-{
167167- auto it = m_maps.find(name);
168168- if (it == m_maps.end())
169169- return nullptr;
170170- else
171171- return it->second;
172172-}
173173-*/
174174-175175-bool FileMap::findSymbolInfo(const void* p, Dl_info* info) const
176176-{
177177- uintptr_t addr = reinterpret_cast<uintptr_t>(p);
178178- const ImageMap* symbol_map;
179179-180180- std::map<uintptr_t, ImageMap*>::const_iterator found = m_maps.upper_bound(addr);
181181- if (found == m_maps.begin() || found == m_maps.end())
182182- return false;
183183-184184- --found;
185185- symbol_map = found->second;
186186-187187- std::map<uintptr_t, std::string>::const_iterator sfound = symbol_map->symbols.lower_bound(addr);
188188- if (sfound != symbol_map->symbols.begin())
189189- {
190190- // found in lib and in symbols
191191- info->dli_sname = sfound->second.c_str();
192192- info->dli_saddr = reinterpret_cast<void*>(sfound->first);
193193- }
194194-195195- info->dli_fname = symbol_map->filename.c_str();
196196- info->dli_fbase = reinterpret_cast<void*>(symbol_map->base);
197197-198198- return true;
199199-}
200200-
-76
src/dyld/FileMap.h
···11-/*
22-This file is part of Darling.
33-44-Copyright (C) 2012 Lubos Dolezel
55-Copyright (C) 2011 Shinichiro Hamaji
66-77-Darling is free software: you can redistribute it and/or modify
88-it under the terms of the GNU General Public License as published by
99-the Free Software Foundation, either version 3 of the License, or
1010-(at your option) any later version.
1111-1212-Darling is distributed in the hope that it will be useful,
1313-but WITHOUT ANY WARRANTY; without even the implied warranty of
1414-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515-GNU General Public License for more details.
1616-1717-You should have received a copy of the GNU General Public License
1818-along with Darling. If not, see <http://www.gnu.org/licenses/>.
1919-*/
2020-2121-#ifndef FILEMAP_H
2222-#define FILEMAP_H
2323-#include <stdint.h>
2424-#include <string>
2525-#include <map>
2626-#include <list>
2727-#include <libmach-o/MachO.h>
2828-#include <dlfcn.h>
2929-#include "../util/mutex.h"
3030-3131-class FileMap
3232-{
3333-public:
3434- ~FileMap();
3535-3636- struct ImageMap;
3737-3838- const ImageMap* add(const MachO& mach, uintptr_t slide, uintptr_t base, bool bindLazy);
3939-4040- void addWatchDog(uintptr_t addr);
4141-4242- struct ImageMap
4343- {
4444- std::string filename;
4545- std::map<uintptr_t, std::string> symbols;
4646- uintptr_t base, slide;
4747- mach_header* header;
4848- std::pair<uint64_t,uint64_t> eh_frame;
4949- std::pair<uint64_t,uint64_t> unwind_info;
5050- std::vector<MachO::Section> sections;
5151- std::vector<std::string> rpaths;
5252-5353- std::list<MachO::Bind> lazy_binds;
5454- mutable Darling::Mutex mutex_lazy_binds;
5555- };
5656-5757- const ImageMap* imageMapForAddr(const void* p) const;
5858- const ImageMap* imageMapForHeader(const mach_header* p) const;
5959- // const ImageMap* imageMapForName(const std::string& name) const;
6060- const char* fileNameForAddr(const void* p) const;
6161- const char* gdbInfoForAddr(const void* p) const;
6262- bool findSymbolInfo(const void* addr, Dl_info* p) const; // used by __darwin_dladdr
6363-6464- const std::vector<ImageMap*>& images() const { return m_maps_vec; }
6565- const ImageMap* mainExecutable() const;
6666-6767-private:
6868-6969- std::map<uintptr_t, ImageMap*> m_maps;
7070- std::map<mach_header*, ImageMap*> m_maps_mach;
7171- std::vector<ImageMap*> m_maps_vec; // for easier access
7272- mutable char m_dumped_stack_frame_buf[4096];
7373-};
7474-7575-7676-#endif
···11-/*
22-This file is part of Darling.
33-44-Copyright (C) 2012 Lubos Dolezel
55-Copyright (C) 2011 Shinichiro Hamaji
66-77-Darling is free software: you can redistribute it and/or modify
88-it under the terms of the GNU General Public License as published by
99-the Free Software Foundation, either version 3 of the License, or
1010-(at your option) any later version.
1111-1212-Darling is distributed in the hope that it will be useful,
1313-but WITHOUT ANY WARRANTY; without even the implied warranty of
1414-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515-GNU General Public License for more details.
1616-1717-You should have received a copy of the GNU General Public License
1818-along with Darling. If not, see <http://www.gnu.org/licenses/>.
1919-*/
2020-2121-#ifndef MACHOLOADER_H
2222-#define MACHOLOADER_H
2323-#include <vector>
2424-#include <string>
2525-#include <map>
2626-#include <utility>
2727-#include <stack>
2828-#include <stdint.h>
2929-#include <libmach-o/MachO.h>
3030-#include "arch.h"
3131-#include "ld.h"
3232-#include "UndefinedFunction.h"
3333-#include "Trampoline.h"
3434-#include "FileMap.h"
3535-3636-class MachOLoader
3737-{
3838-#ifdef __x86_64__
3939-public:
4040- typedef segment_command_64 Segment;
4141-private:
4242- static inline const std::vector<Segment*>& getSegments(const MachO& mach) { return mach.segments64(); }
4343-#else
4444-public:
4545- typedef segment_command Segment;
4646-private:
4747- static inline const std::vector<Segment*>& getSegments(const MachO& mach) { return mach.segments(); }
4848-#endif
4949-5050-public:
5151- MachOLoader();
5252- ~MachOLoader();
5353-5454- // Maps module segments into the memory
5555- void loadSegments(const MachO& mach, intptr* slide, intptr* base);
5656-5757-5858- void doRebase(const MachO& mach, intptr slide);
5959-6060- // Puts initializer functions of that module into the list of initializers to be run
6161- void loadInitFuncs(const MachO& mach, intptr slide);
6262-6363- // Loads libraries this module depends on
6464- void loadDylibs(const MachO& mach, bool nobinds, bool bindLazy);
6565-6666- // Resolves all external symbols required by this module
6767- void* doBind(const std::vector<MachO::Bind*>& binds, intptr slide, bool resolveLazy = false);
6868-6969- // Binds external relocations
7070- void doRelocations(const std::vector<MachO::Relocation*>& rels, intptr slide);
7171-7272- // Calls mprotect() to switch segment protections to the "initial" value.
7373- // We initially set the maximum value.
7474- void doMProtect();
7575-7676- // Creates a list of publicly visible functions in this module
7777- void loadExports(const MachO& mach, intptr slide, Exports* exports);
7878-7979- // Loads a Mach-O file and does all the processing
8080- void load(const MachO& mach, std::string sourcePath, Exports* exports = 0, bool bindLater = false, bool bindLazy = false);
8181-8282- // Dyld data contains an accessor to internal dyld functionality. This stores the accessor pointer.
8383- void setupDyldData(const MachO& mach);
8484-8585- // Runs initializer functions that have not been run yet
8686- void runPendingInitFuncs(int argc, char** argv, char** envp, char** apple);
8787-8888- // Performs pending binds. Used when loading the main executable and its dependencies.
8989- void doPendingBinds();
9090-9191- void doPendingTLS();
9292-9393- // Processes information from MachO and calls the TLS infrastructure to set things up
9494- void setupTLS(const MachO& mach, const FileMap::ImageMap* img, intptr slide);
9595-9696- // Starts an application
9797- void run(MachO& mach, int argc, char** argv, char** envp, bool bindLazy = false);
9898-9999- const std::list<Exports*>& getExports() const { return m_exports; }
100100- Exports* getMainExecutableExports() const { return m_mainExports; }
101101-102102- // Gets the path to the currently loaded Mach-O file
103103- const std::string& getCurrentLoader() const;
104104-105105-private:
106106- // Jumps to the application entry
107107- void boot(uint64_t entry, int argc, char** argv, char** envp, char** apple);
108108-109109- void writeBind(int type, uintptr_t* ptr, uintptr_t newAddr);
110110- // The name should include the extra underscore at the beginning
111111- uintptr_t getSymbolAddress(const std::string& name, const MachO::Bind* bind = nullptr, intptr slide = 0);
112112-113113- // checks sysctl mmap_min_addr
114114- static void checkMmapMinAddr(intptr addr);
115115- void pushCurrentLoader(const char* currentLoader);
116116- void popCurrentLoader();
117117-118118- void fillInProgramVars(Exports* exports);
119119-private:
120120- intptr m_last_addr;
121121- std::vector<uint64_t> m_init_funcs;
122122- std::list<Exports*> m_exports;
123123- Exports* m_mainExports;
124124- std::vector<std::pair<std::string, uintptr_t> > m_seen_weak_binds;
125125- UndefMgr* m_pUndefMgr;
126126- TrampolineMgr* m_pTrampolineMgr;
127127-128128- // Pending calls to mprotect
129129- struct MProtect
130130- {
131131- void* addr;
132132- size_t len;
133133- int prot;
134134- };
135135- std::vector<MProtect> m_mprotects;
136136-137137- // Pending libs that require binding
138138- struct PendingBind
139139- {
140140- const MachO* macho;
141141- const mach_header* header;
142142- intptr slide;
143143- bool bindLazy;
144144- };
145145- std::vector<PendingBind> m_pendingBinds;
146146-147147- // Pending TLS variables
148148- // Because of initializers, we need to run them after the binds are done
149149- struct PendingTLS
150150- {
151151- const MachO* mach;
152152- const FileMap::ImageMap* img;
153153- intptr slide;
154154- };
155155- std::vector<PendingTLS> m_pendingTLS;
156156-157157- std::vector<std::string> m_rpathContext;
158158- std::stack<std::string> m_loaderPath;
159159-160160- std::string m_lastResolvedSymbol;
161161- uintptr_t m_lastResolvedAddress;
162162-};
163163-164164-#endif
+174-33
src/dyld/MachOMgr.cpp
···33#include <algorithm>
44#include <bits/wordsize.h>
55#include "MachOObject.h"
66+#include "NativeObject.h"
77+#include <dlfcn.h>
88+99+namespace Darling {
610711MachOMgr::MachOMgr()
812: m_mainModule(nullptr), m_bindAtLaunch(false), m_printInitializers(false),
99- m_printLibraries(false), m_useTrampolines(false), m_ignoreMissingSymbols(false)
1313+ m_printLibraries(false),
1414+ m_printSegments(false), m_printBindings(false), m_printRpathExpansion(false),
1515+ m_pUndefMgr(nullptr), m_pTrampolineMgr(nullptr), m_addedDefaultLoader(false)
1016{
1117}
12181319MachOMgr::~MachOMgr()
1420{
1515- while (!m_objects.empty())
2121+ if (m_mainModule)
2222+ m_mainModule->unload();
2323+2424+ while (!m_loadablesInOrder.empty())
1625 {
1717- MachOObject* obj = m_objectsInOrder.front();
2626+ LoadableObject* obj = m_loadablesInOrder.front();
1827 obj->unload();
1928 }
2029}
···31403241 if (m_objects.empty())
3342 {
3434- // This is normally used only for:
3535- // a) DYLD_PRELOAD
3636- // b) Standalone use of libdyld
3737-3838-#if (__WORDSIZE == 64)
3939- return (void*) 0x200000000L;
4040-#else
4141- return (void*) 0x1000000;
4242-#endif
4343+ return nullptr;
4344 }
4445 else
4546 {
···55565657 auto it = m_objects.upper_bound(addr);
57585858- if (it == m_objects.begin() || it == m_objects.end())
5959+ if (it == m_objects.begin())
5960 return nullptr;
60616162 it--;
6363+6464+ if (it->second->maxAddress() < addr)
6565+ return nullptr;
6666+6267 return it->second;
6368}
64697070+void MachOMgr::registerLoadHook(LoaderHookFunc* func)
7171+{
7272+ Darling::RWMutexWriteLock l(m_lock);
7373+7474+ m_loadHooks.insert(func);
7575+}
7676+7777+void MachOMgr::registerUnloadHook(LoaderHookFunc* func)
7878+{
7979+ Darling::RWMutexWriteLock l(m_lock);
8080+8181+ m_unloadHooks.insert(func);
8282+}
8383+6584void MachOMgr::add(MachOObject* obj, bool mainModule)
6685{
6786 Darling::RWMutexWriteLock l(m_lock);
8787+8888+ if (!m_addedDefaultLoader && mainModule)
8989+ {
9090+ add(new NativeObject(RTLD_DEFAULT, "<default>"));
9191+ m_addedDefaultLoader = true;
9292+ }
68936994 m_objects[obj->baseAddress()] = obj;
7095 m_objectNames[obj->path()] = obj;
9696+ m_objectHeaders[obj->getMachHeader()] = obj;
7197 m_objectsInOrder.push_back(obj);
9898+ m_loadablesInOrder.push_back(obj);
729973100 if (mainModule)
74101 {
75102 assert(m_mainModule == nullptr);
76103 m_mainModule = obj;
77104 }
7878-7979- // TODO: add support for loader hooks
80105}
811068282-template <typename Key, typename Value> void mapEraseByValue(std::map<Key, Value>& map, const Value& v)
107107+void MachOMgr::notifyAdd(MachOObject* obj)
83108{
8484- for (auto it = map.begin(); it != map.end(); it++)
8585- {
8686- if (it->second == v)
8787- {
8888- map.erase(it);
8989- break;
9090- }
9191- }
109109+ assert(m_objects.find(obj->baseAddress()) != m_objects.end());
110110+111111+ for (LoaderHookFunc* func : m_loadHooks)
112112+ func(obj->getMachHeader(), obj->slide());
92113}
9311494115void MachOMgr::remove(MachOObject* obj)
95116{
96117 Darling::RWMutexWriteLock l(m_lock);
971189898- // slow!
9999- mapEraseByValue(m_objects, obj);
100100- mapEraseByValue(m_objectNames, obj);
119119+ for (LoaderHookFunc* func : m_unloadHooks)
120120+ func(obj->getMachHeader(), obj->slide());
121121+122122+ m_objects.erase(obj->baseAddress());
123123+ m_objectNames.erase(obj->path());
124124+ m_objectHeaders.erase(obj->getMachHeader());
101125102126 auto it = std::find(m_objectsInOrder.begin(), m_objectsInOrder.end(), obj);
103127 if (it != m_objectsInOrder.end())
104128 m_objectsInOrder.erase(it);
129129+130130+ auto itl = std::find(m_loadablesInOrder.begin(), m_loadablesInOrder.end(), obj);
131131+ if (itl != m_loadablesInOrder.end())
132132+ m_loadablesInOrder.erase(itl);
105133106134 if (m_mainModule == obj)
107135 m_mainModule = nullptr;
136136+}
137137+138138+void MachOMgr::add(NativeObject* obj)
139139+{
140140+ m_loadablesInOrder.push_back(obj);
141141+ m_nativeRefToObject[obj->nativeRef()] = obj;
142142+}
143143+144144+void MachOMgr::remove(NativeObject* obj)
145145+{
146146+ auto it = std::find(m_loadablesInOrder.begin(), m_loadablesInOrder.end(), obj);
147147+ if (it != m_loadablesInOrder.end())
148148+ m_loadablesInOrder.erase(it);
149149+ m_nativeRefToObject.erase(obj->nativeRef());
150150+}
151151+152152+MachOObject* MachOMgr::objectByIndex(size_t index)
153153+{
154154+ Darling::RWMutexReadLock l(m_lock);
108155109109- // TODO: add support for loader hooks
156156+ if (index >= m_objectsInOrder.size())
157157+ return nullptr;
158158+ else
159159+ return m_objectsInOrder[index];
110160}
111161112112-void* MachOMgr::getExportedSymbol(const std::string& symbolName)
162162+MachOObject* MachOMgr::objectByHeader(struct mach_header* hdr)
113163{
164164+ Darling::RWMutexReadLock l(m_lock);
165165+166166+ auto it = m_objectHeaders.find(hdr);
167167+ if (it == m_objectHeaders.end())
168168+ return nullptr;
169169+ else
170170+ return it->second;
171171+}
172172+173173+NativeObject* MachOMgr::objectByNativeRef(void* nativeRef)
174174+{
175175+ auto it = m_nativeRefToObject.find(nativeRef);
176176+ if (it == m_nativeRefToObject.end())
177177+ return nullptr;
178178+ else
179179+ return it->second;
180180+}
181181+182182+void* MachOMgr::getExportedSymbol(const std::string& symbolName, LoadableObject* nextAfter)
183183+{
184184+ Darling::RWMutexReadLock l(m_lock);
114185 void* weak = nullptr;
115115- for (MachOObject* obj : m_objectsInOrder)
186186+ bool isAfter = false;
187187+188188+ // TODO: add default loader if missing
189189+190190+ for (auto it = m_loadablesInOrder.begin(); it != m_loadablesInOrder.end(); it++)
116191 {
117117- void* p = obj->getExportedSymbol(symbolName, true); // try non-weak only
192192+ void* p;
193193+194194+ if (nextAfter && !isAfter)
195195+ {
196196+ if (*it == nextAfter)
197197+ isAfter = true;
198198+199199+ continue;
200200+ }
201201+202202+ if (!(*it)->globalExports())
203203+ continue;
204204+205205+ p = (*it)->getExportedSymbol(symbolName, true); // try non-weak only
118206 if (p)
119207 return p;
120208121209 if (!weak)
122122- weak = obj->getExportedSymbol(symbolName, false); // save the first weak export as a fallback
210210+ weak = (*it)->getExportedSymbol(symbolName, false); // save the first weak export as a fallback
123211 }
124212125213 return weak;
126214}
127215128128-MachOObject* MachOMgr::lookup(const std::string& absolutePath)
216216+LoadableObject* MachOMgr::lookup(const std::string& absolutePath)
129217{
218218+ Darling::RWMutexReadLock l(m_lock);
219219+130220 auto it = m_objectNames.find(absolutePath);
131221 if (it != m_objectNames.end())
132222 return it->second;
···134224 return nullptr;
135225}
136226227227+bool MachOMgr::detectSysRootFromPath(std::string path)
228228+{
229229+ if (path.empty())
230230+ return false;
231231+ if (path[0] != '/')
232232+ {
233233+ char* rp = realpath(path.c_str(), nullptr);
234234+ if (!rp)
235235+ return false;
236236+237237+ path = rp;
238238+ free(rp);
239239+ }
240240+241241+ size_t pos = path.find("/usr/");
242242+ if (pos != std::string::npos && pos != 0)
243243+ {
244244+ m_sysroot = path.substr(0, pos);
245245+ return true;
246246+ }
247247+248248+ return false;
249249+}
250250+251251+void MachOMgr::setUseTrampolines(bool useTrampolines, const std::string& funcInfo)
252252+{
253253+ delete m_pTrampolineMgr;
254254+255255+ if (useTrampolines)
256256+ {
257257+ m_pTrampolineMgr = new TrampolineMgr;
258258+ m_pTrampolineMgr->loadFunctionInfo(funcInfo.c_str());
259259+ }
260260+ else
261261+ {
262262+ m_pTrampolineMgr = nullptr;
263263+ }
264264+}
265265+266266+void MachOMgr::setIgnoreMissingSymbols(bool ignoreMissingSymbols)
267267+{
268268+ delete m_pUndefMgr;
269269+270270+ if (ignoreMissingSymbols)
271271+ m_pUndefMgr = new UndefMgr;
272272+ else
273273+ m_pUndefMgr = nullptr;
274274+}
275275+276276+} // namespace Darling
277277+
···9898 auto it = m_images.find(imageKey);
9999 pthread_key_t key;
100100101101- assert(it != m_images.end());
101101+ if (it == m_images.end())
102102+ return;
103103+102104 key = it->second->key;
103105104106 // TODO: What to do with live objects with C++11 destructors? Does Apple's dyld handle this?
···11+/*
22+This file is part of Darling.
33+44+Copyright (C) 2012-2013 Lubos Dolezel
55+66+Darling is free software: you can redistribute it and/or modify
77+it under the terms of the GNU General Public License as published by
88+the Free Software Foundation, either version 3 of the License, or
99+(at your option) any later version.
1010+1111+Darling is distributed in the hope that it will be useful,
1212+but WITHOUT ANY WARRANTY; without even the implied warranty of
1313+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414+GNU General Public License for more details.
1515+1616+You should have received a copy of the GNU General Public License
1717+along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818+*/
1919+2020+#include "config.h"
2121+#include "dyld_public.h"
2222+#include "MachOMgr.h"
2323+#include "MachOObject.h"
2424+#include <util/debug.h>
2525+#include <cstring>
2626+#include <cstdlib>
2727+#include <map>
2828+#include <set>
2929+#include <link.h>
3030+#include <stddef.h>
3131+#include "../util/log.h"
3232+#include "../util/leb.h"
3333+3434+using namespace Darling;
3535+3636+uint32_t _dyld_image_count(void)
3737+{
3838+ return MachOMgr::instance()->objectCount();
3939+}
4040+4141+const struct ::mach_header* _dyld_get_image_header(uint32_t image_index)
4242+{
4343+ return MachOMgr::instance()->objectByIndex(image_index)->getMachHeader();
4444+}
4545+4646+intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index)
4747+{
4848+ return MachOMgr::instance()->objectByIndex(image_index)->slide();
4949+}
5050+5151+const char* _dyld_get_image_name(uint32_t image_index)
5252+{
5353+ return MachOMgr::instance()->objectByIndex(image_index)->path().c_str();
5454+}
5555+5656+char* getsectdata(const struct mach_header* header, const char* segname, const char* sectname, unsigned long* size)
5757+{
5858+ MachOObject* obj = MachOMgr::instance()->objectByHeader((mach_header*) header);
5959+6060+ if (!obj || !sectname)
6161+ {
6262+ if (size)
6363+ *size = 0;
6464+ return nullptr;
6565+ }
6666+ if (!segname)
6767+ segname = "";
6868+6969+ return (char*) obj->getSection(segname, sectname, size);
7070+}
7171+7272+void _dyld_register_func_for_add_image(MachOMgr::LoaderHookFunc* func)
7373+{
7474+ MachOMgr::instance()->registerLoadHook(func);
7575+}
7676+7777+void _dyld_register_func_for_remove_image(MachOMgr::LoaderHookFunc* func)
7878+{
7979+ MachOMgr::instance()->registerUnloadHook(func);
8080+}
8181+8282+8383+const char* dyld_image_path_containing_address(const void* addr)
8484+{
8585+ MachOObject* module = MachOMgr::instance()->objectForAddress((void*) addr);
8686+ if (!module)
8787+ return nullptr;
8888+ else
8989+ return module->path().c_str();
9090+}
9191+9292+9393+bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
9494+{
9595+#if 0
9696+ TRACE1(addr);
9797+ const FileMap::ImageMap* map = g_file_map.imageMapForAddr(addr);
9898+9999+ if (!map) // in ELF
100100+ {
101101+ memset(info, 0, sizeof(*info));
102102+103103+ CBData data = { addr, info };
104104+105105+ dl_iterate_phdr(dlCallback, &data);
106106+ std::cout << "Dwarf section at " << info->dwarf_section << std::endl;
107107+ return info->dwarf_section != 0;
108108+ }
109109+ else // in Mach-O
110110+ {
111111+ info->mh = map->header;
112112+ info->dwarf_section = reinterpret_cast<const void*>(map->eh_frame.first + map->slide);
113113+ info->dwarf_section_length = map->eh_frame.second;
114114+115115+ // FIXME: we would get "malformed __unwind_info" warnings otherwise
116116+ // info->compact_unwind_section = reinterpret_cast<const void*>(map->unwind_info.first + map->slide);
117117+ // info->compact_unwind_section_length = map->unwind_info.second;
118118+ info->compact_unwind_section = 0;
119119+ info->compact_unwind_section_length = 0;
120120+121121+ return true;
122122+ }
123123+#endif
124124+ return false;
125125+}
126126+127127+int32_t NSVersionOfRunTimeLibrary(const char* libraryName)
128128+{
129129+ return -1;
130130+}
131131+132132+int32_t NSVersionOfLinkTimeLibrary(const char* libraryName)
133133+{
134134+ return -1;
135135+}
136136+137137+int _NSGetExecutablePath(char* buf, unsigned int* size)
138138+{
139139+ std::string path;
140140+141141+ MachOObject* mainModule = MachOMgr::instance()->mainModule();
142142+143143+ if (mainModule)
144144+ path = mainModule->path();
145145+146146+ if (*size > path.length()+1)
147147+ *size = path.length()+1;
148148+149149+ strncpy(buf, path.c_str(), *size);
150150+ buf[(*size)-1] = 0;
151151+152152+ return 0;
153153+}
154154+155155+void __dyld_make_delayed_module_initializer_calls()
156156+{
157157+}
158158+159159+void __dyld_mod_term_funcs()
160160+{
161161+}
162162+
-843
src/dyld/ld.cpp
···11-/*
22-This file is part of Darling.
33-44-Copyright (C) 2012 Lubos Dolezel
55-66-Darling is free software: you can redistribute it and/or modify
77-it under the terms of the GNU General Public License as published by
88-the Free Software Foundation, either version 3 of the License, or
99-(at your option) any later version.
1010-1111-Darling is distributed in the hope that it will be useful,
1212-but WITHOUT ANY WARRANTY; without even the implied warranty of
1313-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414-GNU General Public License for more details.
1515-1616-You should have received a copy of the GNU General Public License
1717-along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818-*/
1919-2020-#include "config.h"
2121-#define DARWIN_LD_INTERNAL
2222-#include "MachOLoader.h"
2323-#include "ld.h"
2424-#include "arch.h"
2525-#include <libmach-o/MachO.h>
2626-#include "mutex.h"
2727-#include "trace.h"
2828-#include "FileMap.h"
2929-#include "log.h"
3030-#include "IniConfig.h"
3131-#include "stlutils.h"
3232-#include <unistd.h>
3333-#include <map>
3434-#include <string>
3535-#include <cstring>
3636-#include <sys/types.h>
3737-#include <sys/stat.h>
3838-#include <limits.h>
3939-#include <regex.h>
4040-#include <libgen.h>
4141-#include <cassert>
4242-#include <list>
4343-#include <algorithm>
4444-#include <execinfo.h>
4545-#include "dyld.h"
4646-#include <glob.h>
4747-4848-static Darling::Mutex g_ldMutex;
4949-static std::map<std::string, LoadedLibrary*> g_ldLibraries;
5050-static __thread char g_ldError[256] = "";
5151-static regex_t g_reFrameworkPath;
5252-static LoadedLibrary g_dummyLibrary;
5353-5454-static std::list<std::string> g_searchPath;
5555-5656-static const char* g_suffixes[] = { "$DARWIN_EXTSN", "$UNIX2003", "$NOCANCEL" };
5757-static IniConfig* g_iniConfig = 0;
5858-5959-static void* attemptDlopen(const char* filename, int flag);
6060-static int translateFlags(int flags);
6161-6262-static std::list<Darling::DlsymHookFunc> g_dlsymHooks;
6363-6464-static void* g_libStdCxxDarwin = nullptr;
6565-6666-extern MachOLoader* g_loader;
6767-extern char g_darwin_executable_path[PATH_MAX];
6868-extern char g_sysroot[PATH_MAX];
6969-extern FileMap g_file_map;
7070-7171-#define RET_IF(x) { if (void* p = x) return p; }
7272-7373-static void findSearchpathsWildcard(std::string ldconfig_file_pattern);
7474-7575-static void findSearchpaths(std::string ldconfig_file)
7676-{
7777- std::ifstream read(ldconfig_file);
7878-7979- if(!read.is_open())
8080- LOG << "can't read ldconfig config file - " << ldconfig_file << std::endl;
8181-8282- std::string line;
8383- while(std::getline(read,line))
8484- {
8585- line.erase(line.begin(), std::find_if(line.begin(), line.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
8686-8787- if(line.find("include") == 0)
8888- {
8989- line = line.substr(7);
9090- line.erase(line.begin(), std::find_if(line.begin(), line.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
9191-9292- if (line.find('*') == std::string::npos)
9393- findSearchpaths(line);
9494- else
9595- findSearchpathsWildcard(line);
9696- }
9797- else
9898- {
9999- size_t pos = line.find('#');
100100- if (pos != std::string::npos)
101101- line.resize(pos);
102102- // TODO: trim
103103- g_searchPath.push_back(line);
104104- }
105105- }
106106-}
107107-108108-static void findSearchpathsWildcard(std::string ldconfig_file_pattern)
109109-{
110110- // Use glob to break down wildcards (ex. "/etc/ld.so.conf.d/*.conf")
111111- glob_t globbuf;
112112-113113- glob(ldconfig_file_pattern.c_str(), GLOB_NOSORT, nullptr, &globbuf);
114114-115115- for (size_t i = 0; i < globbuf.gl_pathc; i++)
116116- findSearchpaths(globbuf.gl_pathv[i]);
117117-118118- globfree(&globbuf);
119119-}
120120-121121-void Darling::initLD()
122122-{
123123- int rv = regcomp(&g_reFrameworkPath, "/System/Library/Frameworks/([a-zA-Z0-9\\.]+)/Versions/([a-zA-Z0-9\\.]+)/.*", REG_EXTENDED);
124124- assert(rv == 0);
125125-126126- g_dummyLibrary.name = "/dev/null";
127127- g_dummyLibrary.refCount = 1;
128128- g_dummyLibrary.type = LoadedLibraryDummy;
129129- g_dummyLibrary.nativeRef = 0;
130130- g_dummyLibrary.exports = 0;
131131-132132- try
133133- {
134134- g_iniConfig = new IniConfig(ETC_DARLING_PATH "/dylib.conf");
135135- }
136136- catch (const std::exception& e)
137137- {
138138- std::cerr << e.what() << std::endl;
139139- }
140140- //add hardcoded library paths
141141- g_searchPath.push_back(LIB_PATH);
142142- g_searchPath.push_back("/lib");
143143- g_searchPath.push_back("/usr/lib");
144144- //find paths from ldconfig
145145- findSearchpathsWildcard(LD_SO_CONFIG);
146146-}
147147-148148-static std::string replacePathPrefix(const char* prefix, const char* prefixed, const char* replacement)
149149-{
150150- std::string path = replacement;
151151- path += (prefixed + strlen(prefix));
152152- return path;
153153-}
154154-155155-void* __darwin_dlopen(const char* filename, int flag)
156156-{
157157- void* callerLocation;
158158- std::vector<std::string> rpathList;
159159- const FileMap::ImageMap *mainExecutable, *callerExecutable;
160160-161161- callerLocation = __builtin_return_address(0);
162162- mainExecutable = g_file_map.mainExecutable();
163163- callerExecutable = g_file_map.imageMapForAddr(callerLocation);
164164-165165- rpathList.insert(rpathList.end(), mainExecutable->rpaths.begin(), mainExecutable->rpaths.end());
166166- if (callerExecutable != nullptr && callerExecutable != mainExecutable)
167167- rpathList.insert(rpathList.end(), callerExecutable->rpaths.begin(), callerExecutable->rpaths.end());
168168-169169- return Darling::DlopenWithContext(filename, flag, rpathList);
170170-}
171171-172172-static const char* resolveAlias(const char* library)
173173-{
174174- if (!g_iniConfig)
175175- return nullptr;
176176- if (g_iniConfig->hasSection("dylibs"))
177177- {
178178- const IniConfig::ValueMap* m = g_iniConfig->getSection("dylibs");
179179- auto it = m->find(library);
180180- if (it != m->end())
181181- return it->second.c_str();
182182- }
183183- if (strncmp(library, "/System/Library/Frameworks/", 27) == 0)
184184- {
185185- regmatch_t match[3];
186186- if (regexec(&g_reFrameworkPath, library, sizeof(match)/sizeof(match[0]), match, 0) != REG_NOMATCH)
187187- {
188188- std::string name, version;
189189-190190- name = std::string(library+match[1].rm_so, match[1].rm_eo - match[1].rm_so);
191191- version = std::string(library+match[2].rm_so, match[2].rm_eo - match[2].rm_so);
192192-193193- if (g_iniConfig->hasSection(name.c_str()))
194194- {
195195- const IniConfig::ValueMap* m = g_iniConfig->getSection(name.c_str());
196196- auto it = m->find(version);
197197-198198- if (it != m->end())
199199- return it->second.c_str();
200200- }
201201- }
202202- }
203203- return nullptr;
204204-}
205205-206206-void* Darling::DlopenWithContext(const char* filename, int flag, const std::vector<std::string>& rpaths, bool* notFoundError)
207207-{
208208- TRACE2(filename, flag);
209209-210210- Darling::MutexLock l(g_ldMutex);
211211- std::string path;
212212-213213- g_ldError[0] = 0;
214214-215215- if (notFoundError != nullptr)
216216- *notFoundError = false;
217217-218218- if (!filename)
219219- {
220220- strcpy(g_ldError, "Invalid argument");
221221- return 0;
222222- }
223223-224224- flag = translateFlags(flag);
225225-226226- if (strncmp(filename, "@executable_path", 16) == 0)
227227- {
228228- path = replacePathPrefix("@executable_path", filename, g_darwin_executable_path);
229229- LOG << "Full path after replacing @executable_path: " << path << std::endl;
230230- if (::access(path.c_str(), R_OK) == 0)
231231- RET_IF( attemptDlopen(path.c_str(), flag) );
232232- }
233233- else if (strncmp(filename, "@loader_path", 12) == 0)
234234- {
235235- path = replacePathPrefix("@loader_path", filename, g_loader->getCurrentLoader().c_str());
236236- LOG << "Current ldr: " << g_loader->getCurrentLoader() << std::endl;
237237- LOG << "Full path after replacing @loader_path: " << path << std::endl;
238238- if (::access(path.c_str(), R_OK) == 0)
239239- RET_IF( attemptDlopen(path.c_str(), flag) );
240240- }
241241- else if (strncmp(filename, "@rpath", 6) == 0)
242242- {
243243- // @rpath - https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath
244244- for (std::string rpathSearch : rpaths)
245245- {
246246- bool recNotFoundError;
247247- path = replacePathPrefix("@rpath", filename, rpathSearch.c_str());
248248-249249- RET_IF( DlopenWithContext(path.c_str(), flag, rpaths, &recNotFoundError) );
250250-251251- // Stop if there was an error, vs just not found
252252- if (!recNotFoundError)
253253- return nullptr;
254254- }
255255- }
256256- else
257257- {
258258- if (const char* ldp = getenv("DYLD_LIBRARY_PATH"))
259259- {
260260- path = std::string(ldp) + "/" + filename;
261261- if (::access(path.c_str(), R_OK) == 0)
262262- RET_IF( attemptDlopen(path.c_str(), flag) );
263263- }
264264-265265- if (const char* realPath = resolveAlias(filename))
266266- RET_IF( attemptDlopen(realPath, flag) );
267267-268268- if (strncmp(filename, "/usr/lib/", 9) == 0)
269269- filename = filename + 9;
270270-271271- if (g_sysroot[0])
272272- {
273273- path = g_sysroot;
274274- path += filename;
275275- LOG << "Trying " << path << std::endl;
276276- RET_IF( attemptDlopen(path.c_str(), flag) );
277277- }
278278-279279- std::list<std::string>::iterator it;
280280- for (it=g_searchPath.begin(); it!=g_searchPath.end(); ++it)
281281- {
282282- path = *it + "/" + filename;
283283- LOG << "Trying " << path << std::endl;
284284- if (::access(path.c_str(), R_OK) == 0)
285285- {
286286- RET_IF( attemptDlopen(path.c_str(), flag) );
287287- }
288288- else
289289- {
290290- if (::access((path+".so").c_str(), R_OK) == 0)
291291- RET_IF( attemptDlopen(path.c_str(), flag) );
292292- }
293293- }
294294-295295- // Unlike ld-linux, dyld seems to search in . too
296296- if (!strchr(filename, '/'))
297297- {
298298- if (::access(filename, R_OK) == 0)
299299- RET_IF( attemptDlopen(filename, flag) );
300300- }
301301- }
302302-303303- if (!g_ldError[0])
304304- {
305305- snprintf(g_ldError, sizeof(g_ldError)-1, "File not found: %s", filename);
306306-307307- if (notFoundError != nullptr)
308308- *notFoundError = true;
309309- }
310310-311311- return nullptr;
312312-}
313313-314314-static int translateFlags(int flag)
315315-{
316316- int native_flags = 0;
317317- if (flag & DARWIN_RTLD_LAZY)
318318- native_flags |= RTLD_LAZY;
319319- if (flag & DARWIN_RTLD_NOW)
320320- native_flags |= RTLD_NOW;
321321- if (flag & DARWIN_RTLD_LOCAL)
322322- native_flags |= RTLD_LOCAL;
323323- if (flag & DARWIN_RTLD_GLOBAL)
324324- native_flags |= RTLD_GLOBAL;
325325- if (flag & DARWIN_RTLD_NOLOAD)
326326- native_flags |= RTLD_NOLOAD;
327327- if (flag & DARWIN_RTLD_NODELETE)
328328- native_flags |= RTLD_NODELETE;
329329- if (flag & __DARLING_RTLD_NOBIND)
330330- native_flags |= __DARLING_RTLD_NOBIND;
331331- return native_flags;
332332-}
333333-334334-static bool isSymlink(const char* path)
335335-{
336336- struct stat st;
337337- if (::lstat(path, &st) == -1)
338338- return false;
339339- return S_ISLNK(st.st_mode);
340340-}
341341-342342-void* attemptDlopen(const char* filename, int flag)
343343-{
344344- char name[2048];
345345-346346- TRACE2(filename,flag);
347347-348348- // We need to run access() here not to use realpath for "libncurses.so.5" for example
349349- if (::access(filename, R_OK) == 0)
350350- {
351351- if (!realpath(filename, name))
352352- {
353353- strcpy(g_ldError, strerror(errno));
354354- return 0;
355355- }
356356- }
357357- else
358358- strcpy(name, filename);
359359-360360- if (strcmp(name, "/dev/null") == 0)
361361- {
362362- // We return a dummy
363363- return &g_dummyLibrary;
364364- }
365365-366366- std::map<std::string,LoadedLibrary*>::iterator it = g_ldLibraries.find(name);
367367- if (it != g_ldLibraries.end())
368368- {
369369- // TODO: flags
370370- it->second->refCount++;
371371- if (it->second->type == LoadedLibraryNative)
372372- {
373373- // add a reference in native ld
374374- ::dlopen(name, RTLD_NOW);
375375- }
376376-377377- return it->second;
378378- }
379379- else
380380- {
381381- // actually load the library
382382- char* p = strstr(name, ".so");
383383- // we followed a link, so we need to check for .so., too
384384- if ((p && name+strlen(name)-p == 3) || strstr(name, ".so.")) // endsWith()
385385- {
386386- LOG << "Loading a native library " << name << std::endl;
387387- // We're loading a native library
388388- // TODO: flags
389389- int flags = RTLD_NOW | RTLD_GLOBAL;
390390- void* d;
391391-392392- // TODO: another hack location for libstdc++darwin.so
393393- if (strcmp(name, "libstdc++darwin.so") == 0)
394394- flags |= RTLD_DEEPBIND;
395395-396396- d = ::dlopen(name, flags);
397397-398398- if (d != 0)
399399- {
400400- LOG << "Native library loaded\n";
401401-402402- LoadedLibrary* lib = new LoadedLibrary;
403403- lib->name = name;
404404- lib->refCount = 1;
405405- lib->type = LoadedLibraryNative;
406406- lib->nativeRef = d;
407407- //lib->slide = lib->base = 0;
408408-409409- if (strstr(name, "libstdc++darwin") != nullptr)
410410- g_libStdCxxDarwin = d;
411411-412412- g_ldLibraries[name] = lib;
413413- return lib;
414414- }
415415- else
416416- {
417417- const char* err = ::dlerror();
418418- LOG << "Native library failed to load: " << err << std::endl;
419419-420420- if (err && !g_ldError[0]) // we don't overwrite previous errors
421421- {
422422- LOG << "Library failed to load: " << err << std::endl;
423423- strcpy(g_ldError, err);
424424- }
425425- return 0;
426426- }
427427- }
428428- else
429429- {
430430- LOG << "Loading a Mach-O library\n";
431431- // We're loading a Mach-O library
432432- try
433433- {
434434- MachO* machO = MachO::readFile(name, ARCH_NAME);
435435- if (!machO)
436436- {
437437- snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot parse Mach-O library: %s", name);
438438- return 0;
439439- }
440440-441441- LoadedLibrary* lib = new LoadedLibrary;
442442- bool nobind = (flag & __DARLING_RTLD_NOBIND) != 0;
443443-444444- lib->name = name;
445445- lib->refCount = 1;
446446- lib->type = LoadedLibraryDylib;
447447- lib->machoRef = machO;
448448-449449- bool global = flag & RTLD_GLOBAL && !(flag & RTLD_LOCAL);
450450- bool lazy = flag & RTLD_LAZY && !(flag & RTLD_NOW);
451451-452452- // Insert an entry before doing the full load to prevent recursive loading
453453- g_ldLibraries[name] = lib;
454454-455455- //if (!global)
456456- //{
457457- lib->exports = new Exports;
458458- g_loader->load(*machO, name, lib->exports, nobind, lazy);
459459- //}
460460- //else
461461- // g_loader->load(*machO, name, 0, nobind, lazy);
462462-463463- if (!nobind)
464464- {
465465- char* apple[2] = { g_darwin_executable_path, 0 };
466466- g_loader->runPendingInitFuncs(g_argc, g_argv, environ, apple);
467467- }
468468-469469- return lib;
470470- }
471471- catch (const std::exception& e)
472472- {
473473- strcpy(g_ldError, e.what());
474474- return 0;
475475- }
476476- }
477477- }
478478-}
479479-480480-int __darwin_dlclose(void* handle)
481481-{
482482- TRACE1(handle);
483483-484484- Darling::MutexLock l(g_ldMutex);
485485- g_ldError[0] = 0;
486486-487487- if (!handle)
488488- return 0;
489489-490490- LoadedLibrary* lib = reinterpret_cast<LoadedLibrary*>(handle);
491491- /*if (!lib)
492492- {
493493- strcpy(g_ldError, "Invalid handle passed to __darwin_dlclose()");
494494- return -1;
495495- }*/
496496-497497- lib->refCount--;
498498-499499- if (lib->type == LoadedLibraryNative)
500500- ::dlclose(lib->nativeRef);
501501- if (!lib->refCount)
502502- {
503503- if (lib->type == LoadedLibraryDylib)
504504- {
505505- // TODO: unmap in g_loader!
506506- delete lib->exports;
507507-508508- for (std::map<std::string,LoadedLibrary*>::iterator it = g_ldLibraries.begin(); it != g_ldLibraries.end(); it++)
509509- {
510510- if (it->second == lib)
511511- {
512512- g_ldLibraries.erase(it);
513513- delete lib;
514514- break;
515515- }
516516- }
517517- }
518518- }
519519-520520- return 0;
521521-}
522522-523523-const char* __darwin_dlerror(void)
524524-{
525525- //TRACE();
526526-527527- return g_ldError[0] ? g_ldError : 0;
528528-}
529529-530530-static const char* translateSymbol(const char* symbol)
531531-{
532532- bool translated = false;
533533- static char symbuffer[255];
534534-535535- strcpy(symbuffer, symbol);
536536-537537- for (auto f : g_dlsymHooks)
538538- {
539539- if (f(symbuffer))
540540- {
541541- translated = true;
542542- break;
543543- }
544544- }
545545-546546- if (!translated)
547547- {
548548- std::string s = symbol;
549549- for (int i = 0; i < sizeof(g_suffixes) / sizeof(g_suffixes[0]); i++)
550550- {
551551- size_t pos = s.find(g_suffixes[i]);
552552- if (pos != std::string::npos)
553553- s.erase(pos, strlen(g_suffixes[i]));
554554- }
555555-556556- strcpy(symbuffer, s.c_str());
557557- }
558558-559559- return symbuffer;
560560-}
561561-562562-NSSymbol NSLookupAndBindSymbol(const char* symbolName)
563563-{
564564- return __darwin_dlsym(DARWIN_RTLD_DEFAULT, symbolName);
565565-}
566566-567567-NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName)
568568-{
569569- return __darwin_dlsym(module, symbolName);
570570-}
571571-572572-const char* NSNameOfSymbol(NSSymbol symbolAddr)
573573-{
574574- Dl_info info;
575575-576576- if (!__darwin_dladdr(symbolAddr, &info))
577577- return nullptr;
578578-579579- return info.dli_sname;
580580-}
581581-582582-void* NSAddressOfSymbol(NSSymbol nssymbol)
583583-{
584584- return nssymbol;
585585-}
586586-587587-int NSIsSymbolNameDefined(const char* name)
588588-{
589589- return NSLookupAndBindSymbol(name) != nullptr;
590590-}
591591-592592-NSModule NSModuleForSymbol(NSSymbol symbol)
593593-{
594594- const FileMap::ImageMap* map = g_file_map.imageMapForAddr(symbol);
595595-596596- if (!map)
597597- return nullptr;
598598-599599- auto it = g_ldLibraries.find(map->filename);
600600- if (it == g_ldLibraries.end())
601601- return nullptr;
602602-603603- return it->second;
604604-}
605605-606606-int NSIsSymbolNameDefinedInImage(const struct mach_header *image, const char *symbolName)
607607-{
608608- // TODO: this inefficient double search will be avoided when we unite LoadedLibrary and FileMap::ImageMap
609609- const FileMap::ImageMap* map = g_file_map.imageMapForHeader(image);
610610- LoadedLibrary* ldlib = g_ldLibraries[map->filename];
611611-612612- return __darwin_dlsym(ldlib, symbolName) != nullptr;
613613-}
614614-615615-const char* NSNameOfModule(NSModule m)
616616-{
617617- if (!m)
618618- return nullptr;
619619-620620- LoadedLibrary* ldlib = static_cast<LoadedLibrary*>(m);
621621- return ldlib->name.c_str();
622622-}
623623-624624-const char* NSLibraryNameForModule(NSModule m)
625625-{
626626- // TODO: we need to check what these two functions return on a real system
627627- return NSNameOfModule(m);
628628-}
629629-630630-void* __darwin_dlsym(void* handle, const char* symbol, void* extra)
631631-{
632632- // TRACE2(handle, symbol);
633633-634634- Darling::MutexLock l(g_ldMutex);
635635- g_ldError[0] = 0;
636636-637637- if (!handle)
638638- handle = DARWIN_RTLD_DEFAULT;
639639-640640- //if (handle == DARWIN_RTLD_NEXT || handle == DARWIN_RTLD_SELF || handle == DARWIN_RTLD_MAIN_ONLY || !handle)
641641- //{
642642- // LOG << "Cannot yet handle certain DARWIN_RTLD_* search strategies, falling back to RTLD_DEFAULT\n";
643643- // handle = DARWIN_RTLD_DEFAULT;
644644- //}
645645-646646-//handling:
647647- if (handle == DARWIN_RTLD_DEFAULT || handle == __DARLING_RTLD_STRONG)
648648- {
649649- // First try native with the __darwin prefix
650650- void* sym;
651651- char* buf = reinterpret_cast<char*>(malloc(strlen(symbol)+20));
652652- strcpy(buf, "__darwin_");
653653- strcat(buf, symbol);
654654-655655- sym = ::dlsym(RTLD_DEFAULT, buf);
656656- if (sym)
657657- return sym;
658658-659659- // Now try Darwin libraries
660660- const std::list<Exports*>& le = g_loader->getExports();
661661- std::list<Exports*>::const_iterator it = le.begin();
662662-663663- while (it != le.end())
664664- {
665665- Exports* e = *it;
666666- Exports::iterator itSym = e->find(symbol);
667667-668668- if (itSym == e->end())
669669- itSym = e->find(std::string("_") + symbol); // TODO: WTF?
670670-671671- if (itSym != e->end())
672672- {
673673- if (handle != __DARLING_RTLD_STRONG || !(itSym->second.flag & 4))
674674- {
675675- MachO::Export& exp = itSym->second;
676676-677677- // If there is a resolver function, we lazily call it now
678678- // and update the original stub address with the real one returned.
679679-680680- if (exp.resolver)
681681- {
682682- typedef uintptr_t (ResolverFunc)();
683683- ResolverFunc* func = (ResolverFunc*) exp.resolver;
684684- exp.addr = func();
685685- exp.resolver = 0;
686686- }
687687- return reinterpret_cast<void*>(itSym->second.addr);
688688- }
689689- }
690690- it++;
691691- }
692692-693693- // Now try without a prefix
694694- const char* translated = translateSymbol(symbol);
695695- LOG << "Trying " << translated << std::endl;
696696-#if 0 // FIXME: This causes serious regressions!
697697- for (auto& pair : g_ldLibraries)
698698- {
699699- if (pair.second->type == LoadedLibraryNative)
700700- {
701701- LOG << "Trying in " << pair.first << std::endl;
702702- RET_IF(::dlsym(pair.second->nativeRef, translated));
703703- if (strcmp(translated, symbol) != 0)
704704- RET_IF(::dlsym(pair.second->nativeRef, symbol));
705705- }
706706- }
707707-#endif
708708-709709- // FIXME: this is very crude, but simple and effective...
710710- // "St" == namespace std
711711- if (g_libStdCxxDarwin && strstr(translated, "St") != nullptr)
712712- {
713713- //static void* self = ::dlopen(nullptr, RTLD_LAZY);
714714- //RET_IF(::dlsym(self, translated));
715715- if (strcmp(translated, "_ZSt4cout") && strcmp(translated, "_ZSt4cin") && strcmp(translated, "_ZSt4cerr"))
716716- {
717717- RET_IF(::dlsym(g_libStdCxxDarwin, translated));
718718- }
719719- }
720720-721721- RET_IF(::dlsym(RTLD_DEFAULT, translated));
722722-723723- if (strcmp(translated, symbol) != 0)
724724- RET_IF(::dlsym(RTLD_DEFAULT, symbol));
725725-726726- // Now we fail
727727- snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot find symbol '%s'", symbol);
728728- return nullptr;
729729- }
730730- else if (handle == DARWIN_RTLD_NEXT)
731731- {
732732- // For this, we'll have to rethink and integrate Exports in MachOLoader and LoadedLibrary in here
733733- abort();
734734- }
735735- else if (handle == DARWIN_RTLD_MAIN_ONLY || handle == DARWIN_RTLD_SELF)
736736- {
737737- Exports* exports = nullptr;
738738- if (handle == DARWIN_RTLD_MAIN_ONLY)
739739- exports = g_loader->getMainExecutableExports();
740740- else
741741- {
742742- void* retaddr;
743743- const char* name;
744744-745745- backtrace(&retaddr, 1);
746746-747747- name = g_file_map.fileNameForAddr(retaddr);
748748- if (!name)
749749- {
750750- strcpy(g_ldError, "Couldn't determine the current module");
751751- return nullptr;
752752- }
753753-754754- auto it = g_ldLibraries.find(name);
755755- if (it == g_ldLibraries.end())
756756- {
757757- strcpy(g_ldError, "Couldn't determine the current module by path");
758758- return nullptr;
759759- }
760760-761761- exports = it->second->exports;
762762- }
763763-764764- Exports::iterator itSym = exports->find(symbol);
765765- if (itSym == exports->end())
766766- {
767767- snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot find symbol '%s'", symbol);
768768- return 0;
769769- }
770770- else
771771- return reinterpret_cast<void*>(itSym->second.addr);
772772- }
773773- else
774774- {
775775- LoadedLibrary* lib = nullptr;
776776-777777- lib = reinterpret_cast<LoadedLibrary*>(handle);
778778-779779- if (lib->type == LoadedLibraryNative)
780780- {
781781- void* rv = ::dlsym(lib->nativeRef, symbol);
782782- if (!rv)
783783- strcpy(g_ldError, ::dlerror());
784784- return rv;
785785- }
786786- else if (lib->type == LoadedLibraryDummy)
787787- {
788788- snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot find symbol '%s'", symbol);
789789- return 0;
790790- }
791791- //else if (!lib->exports)
792792- //{
793793- // // TODO: this isn't 100% correct
794794- // handle = DARWIN_RTLD_DEFAULT;
795795- // goto handling;
796796- //}
797797- else
798798- {
799799- Exports::iterator itSym = lib->exports->find(symbol);
800800- if (itSym == lib->exports->end())
801801- {
802802- snprintf(g_ldError, sizeof(g_ldError)-1, "Cannot find symbol '%s'", symbol);
803803- return 0;
804804- }
805805- else
806806- return reinterpret_cast<void*>(itSym->second.addr);
807807- }
808808- }
809809-}
810810-811811-int __darwin_dladdr(void *addr, Dl_info *info)
812812-{
813813- TRACE2(addr, info);
814814-815815- Darling::MutexLock l(g_ldMutex);
816816- g_ldError[0] = 0;
817817-818818- if (!g_file_map.findSymbolInfo(addr, info))
819819- {
820820- strcpy(g_ldError, "Specified address not mapped to a Mach-O file");
821821- return -1;
822822- }
823823- if (!info->dli_fbase)
824824- {
825825- strcpy(g_ldError, "Specified address not resolvable to a symbol");
826826- return -1;
827827- }
828828-829829- return 0;
830830-}
831831-832832-void Darling::registerDlsymHook(Darling::DlsymHookFunc func)
833833-{
834834- g_dlsymHooks.push_front(func);
835835-}
836836-837837-void Darling::deregisterDlsymHook(Darling::DlsymHookFunc func)
838838-{
839839- //auto it = std::find(g_dlsymHooks.begin(), g_dlsymHooks.end(), func);
840840- //if (it != g_dlsymHooks.end())
841841- // g_dlsymHooks.erase(it);
842842-}
843843-
-103
src/dyld/ld.h
···11-/*
22-This file is part of Darling.
33-44-Copyright (C) 2012 Lubos Dolezel
55-66-Darling is free software: you can redistribute it and/or modify
77-it under the terms of the GNU General Public License as published by
88-the Free Software Foundation, either version 3 of the License, or
99-(at your option) any later version.
1010-1111-Darling is distributed in the hope that it will be useful,
1212-but WITHOUT ANY WARRANTY; without even the implied warranty of
1313-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414-GNU General Public License for more details.
1515-1616-You should have received a copy of the GNU General Public License
1717-along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818-*/
1919-2020-#ifndef DARWIN_LD_H
2121-#define DARWIN_LD_H
2222-#include <dlfcn.h>
2323-#include <unordered_map>
2424-//#include "MachOLoader.h"
2525-2626-#define DARWIN_RTLD_LAZY 0x1
2727-#define DARWIN_RTLD_NOW 0x2
2828-#define DARWIN_RTLD_LOCAL 0x4
2929-#define DARWIN_RTLD_GLOBAL 0x8
3030-#define DARWIN_RTLD_NOLOAD 0x10
3131-#define DARWIN_RTLD_NODELETE 0x80
3232-#define DARWIN_RTLD_FIRST 0x100
3333-#define __DARLING_RTLD_NOBIND 0x20000000
3434-3535-#define DARWIN_RTLD_NEXT ((void*)-1)
3636-#define DARWIN_RTLD_DEFAULT ((void*)-2)
3737-#define DARWIN_RTLD_SELF ((void*)-3)
3838-#define DARWIN_RTLD_MAIN_ONLY ((void*)-5)
3939-4040-// Internal, only for weak symbol resolution
4141-#define __DARLING_RTLD_STRONG ((void*)-20)
4242-4343-#define LD_SO_CONFIG "/etc/ld.so.conf"
4444-4545-typedef void* NSSymbol;
4646-typedef void* NSModule;
4747-4848-extern "C"
4949-{
5050-5151-void* __darwin_dlopen(const char* filename, int flag);
5252-int __darwin_dlclose(void* handle);
5353-const char* __darwin_dlerror(void);
5454-void* __darwin_dlsym(void* handle, const char* symbol, void* extra = nullptr);
5555-int __darwin_dladdr(void *addr, Dl_info *info);
5656-5757-// Obsolete (or "not recommended") APIs
5858-NSSymbol NSLookupAndBindSymbol(const char* symbolName);
5959-void* NSAddressOfSymbol(NSSymbol nssymbol);
6060-NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName);
6161-const char* NSNameOfSymbol(NSSymbol nssymbol);
6262-int NSIsSymbolNameDefined(const char* name);
6363-NSModule NSModuleForSymbol(NSSymbol symbol);
6464-int NSIsSymbolNameDefinedInImage(const struct mach_header *image, const char *symbolName);
6565-const char* NSNameOfModule(NSModule m);
6666-const char* NSLibraryNameForModule(NSModule m);
6767-// TODO: rest of these NS* calls if used anywhere
6868-6969-}
7070-7171-// FIXME: cleanup urgently needed!
7272-#ifdef MACHOLOADER_H
7373-enum LoadedLibraryType { LoadedLibraryDylib, LoadedLibraryNative, LoadedLibraryDummy };
7474-7575-typedef std::unordered_map<std::string, MachO::Export> Exports;
7676-7777-// TODO: this should be united with the list in FileMap
7878-struct LoadedLibrary
7979-{
8080- std::string name;
8181- int refCount;
8282- LoadedLibraryType type;
8383- union
8484- {
8585- void* nativeRef;
8686- MachO* machoRef;
8787- };
8888- //intptr slide;
8989- //intptr base;
9090- Exports* exports;
9191-};
9292-#endif
9393-9494-namespace Darling
9595-{
9696- typedef bool (*DlsymHookFunc)(char* symName);
9797- void registerDlsymHook(DlsymHookFunc func);
9898- void deregisterDlsymHook(DlsymHookFunc func);
9999- void* DlopenWithContext(const char* filename, int flag, const std::vector<std::string>& rpaths, bool* notFoundError = nullptr);
100100- void initLD();
101101-};
102102-103103-#endif
-299
src/dyld/public.cpp
···11-/*
22-This file is part of Darling.
33-44-Copyright (C) 2012 Lubos Dolezel
55-66-Darling is free software: you can redistribute it and/or modify
77-it under the terms of the GNU General Public License as published by
88-the Free Software Foundation, either version 3 of the License, or
99-(at your option) any later version.
1010-1111-Darling is distributed in the hope that it will be useful,
1212-but WITHOUT ANY WARRANTY; without even the implied warranty of
1313-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1414-GNU General Public License for more details.
1515-1616-You should have received a copy of the GNU General Public License
1717-along with Darling. If not, see <http://www.gnu.org/licenses/>.
1818-*/
1919-2020-#include "config.h"
2121-#include "public.h"
2222-#include "MachOLoader.h"
2323-#include "FileMap.h"
2424-#include "trace.h"
2525-#include <cstring>
2626-#include <cstdlib>
2727-#include <map>
2828-#include <set>
2929-#include <link.h>
3030-#include <stddef.h>
3131-#include "../util/log.h"
3232-#include "../util/leb.h"
3333-3434-extern FileMap g_file_map;
3535-extern "C" char* dyld_getDarwinExecutablePath();
3636-3737-std::set<LoaderHookFunc*> g_machoLoaderHooks;
3838-3939-uint32_t _dyld_image_count(void)
4040-{
4141- return g_file_map.images().size();
4242-}
4343-4444-const struct mach_header* _dyld_get_image_header(uint32_t image_index)
4545-{
4646- return g_file_map.images().at(image_index)->header;
4747-}
4848-4949-intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index)
5050-{
5151- return g_file_map.images().at(image_index)->slide;
5252-}
5353-5454-const char* _dyld_get_image_name(uint32_t image_index)
5555-{
5656- return g_file_map.images().at(image_index)->filename.c_str();
5757-}
5858-5959-char* getsectdata(const struct mach_header* header, const char* segname, const char* sectname, unsigned long* size)
6060-{
6161- FileMap::ImageMap* imageMap = 0;
6262-6363- if (!segname || !sectname || !size)
6464- {
6565- LOG << "Warning: getsectdata() called with NULL pointers\n";
6666- // abort();
6767- return nullptr;
6868- }
6969-7070- // Find the loaded image the header belongs to
7171- for (FileMap::ImageMap* entry : g_file_map.images())
7272- {
7373- if (entry->header == header)
7474- {
7575- imageMap = entry;
7676- break;
7777- }
7878- }
7979-8080- if (!imageMap)
8181- return 0; // Original dyld's man page indicates that it would still somehow proceed, but we don't bother
8282-8383- for (const MachO::Section& sect : imageMap->sections)
8484- {
8585- if (sect.segment == segname && sect.section == sectname)
8686- {
8787- char* addr = reinterpret_cast<char*>(sect.addr);
8888-8989- *size = sect.size;
9090- addr += imageMap->slide;
9191-9292- return addr;
9393- }
9494- }
9595- return 0;
9696-}
9797-9898-void _dyld_register_func_for_add_image(LoaderHookFunc* func)
9999-{
100100- // Needed for ObjC
101101- g_machoLoaderHooks.insert(func);
102102-}
103103-104104-void _dyld_register_func_for_remove_image(LoaderHookFunc* func)
105105-{
106106- g_machoLoaderHooks.erase(func);
107107-}
108108-109109-int32_t NSVersionOfRunTimeLibrary(const char* libraryName)
110110-{
111111- return -1;
112112-}
113113-114114-int32_t NSVersionOfLinkTimeLibrary(const char* libraryName)
115115-{
116116- return -1;
117117-}
118118-119119-int _NSGetExecutablePath(char* buf, unsigned int* size)
120120-{
121121- strncpy(buf, dyld_getDarwinExecutablePath(), (*size)-1);
122122- buf[(*size)-1] = 0;
123123-124124- *size = strlen(buf);
125125-126126- return 0;
127127-}
128128-129129-const char* dyld_image_path_containing_address(const void* addr)
130130-{
131131- return g_file_map.fileNameForAddr(addr);
132132-}
133133-134134-struct CBData
135135-{
136136- void* addr;
137137- struct dyld_unwind_sections* info;
138138-};
139139-140140-#pragma pack(1)
141141-struct eh_frame_hdr
142142-{
143143- uint8_t version, eh_frame_ptr_enc, fde_count_enc, table_enc;
144144- uint8_t eh_frame_ptr[];
145145-};
146146-#pragma pack()
147147-148148-static uintptr_t readEncodedPointer(const eh_frame_hdr* hdr)
149149-{
150150- uint8_t format = hdr->eh_frame_ptr_enc & 0xf;
151151- uint8_t rel = hdr->eh_frame_ptr_enc & 0xf0;
152152- uintptr_t val;
153153- bool isSigned = false;
154154-155155- if (hdr->eh_frame_ptr_enc == 0xff)
156156- return 0;
157157-158158- switch (format)
159159- {
160160- case 1: // unsigned LEB
161161- {
162162- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(hdr->eh_frame_ptr);
163163- val = uleb128(ptr);
164164- break;
165165- }
166166- case 2: // 2 bytes
167167- val = *reinterpret_cast<const uint16_t*>(hdr->eh_frame_ptr);
168168- break;
169169- case 3:
170170- val = *reinterpret_cast<const uint32_t*>(hdr->eh_frame_ptr);
171171- break;
172172- case 4:
173173- val = *reinterpret_cast<const uint64_t*>(hdr->eh_frame_ptr);
174174- break;
175175- case 9: // signed LEB
176176- {
177177- const uint8_t* ptr = reinterpret_cast<const uint8_t*>(hdr->eh_frame_ptr);
178178- val = sleb128(ptr);
179179- break;
180180- }
181181- // FIXME: add 'dlpi_addr' (base address) to these?
182182- case 0xa:
183183- val = *reinterpret_cast<const int16_t*>(hdr->eh_frame_ptr);
184184- break;
185185- case 0xb:
186186- val = *reinterpret_cast<const int32_t*>(hdr->eh_frame_ptr);
187187- break;
188188- case 0xc:
189189- val = *reinterpret_cast<const int64_t*>(hdr->eh_frame_ptr);
190190- break;
191191- default:
192192- return 0;
193193- }
194194-195195- switch (rel)
196196- {
197197- case 0: // no change
198198- break;
199199- case 0x10: // pcrel
200200- val += reinterpret_cast<uintptr_t>(hdr) + 4;
201201- break;
202202- case 0x30: // eh_frame_hdr rel
203203- val += reinterpret_cast<uintptr_t>(hdr);
204204- break;
205205- default:
206206- return 0;
207207- }
208208-209209- return val;
210210-}
211211-212212-static int dlCallback(struct dl_phdr_info *info, size_t size, void *data)
213213-{
214214- CBData* cbdata = static_cast<CBData*>(data);
215215- bool addrMatch = false;
216216- void* maxAddr = 0;
217217- const eh_frame_hdr* ehdr = 0;
218218-219219- if (cbdata->info->dwarf_section) // we already have a match
220220- return 0;
221221-222222- //std::cout << "Looking into " << info->dlpi_name << std::endl;
223223-224224- if (size < offsetof(struct dl_phdr_info, dlpi_phnum))
225225- return 0;
226226-227227- for (int i = 0; i < info->dlpi_phnum; i++)
228228- {
229229- const ElfW(Phdr)* phdr = &info->dlpi_phdr[i];
230230- /*
231231- if (strstr(info->dlpi_name, "cxxdarwin"))
232232- {
233233- std::cout << "type: " << phdr->p_type << "; vaddr: " << phdr->p_vaddr << std::endl;
234234- }
235235- */
236236-237237- if (phdr->p_type == PT_LOAD)
238238- {
239239- void* from = reinterpret_cast<void*>(uintptr_t(info->dlpi_addr) + uintptr_t(phdr->p_vaddr));
240240- void* to = reinterpret_cast<char*>(from) + phdr->p_memsz;
241241-242242- if (cbdata->addr >= from && cbdata->addr < to)
243243- addrMatch = true;
244244- if (to > maxAddr)
245245- maxAddr = to; // TODO: could this be improved? libunwind does the same
246246- }
247247- else if (phdr->p_type == PT_GNU_EH_FRAME)
248248- {
249249- //std::cout << "Found .eh_frame_hdr in " << info->dlpi_name << std::endl;
250250- ehdr = reinterpret_cast<eh_frame_hdr*>(uintptr_t(info->dlpi_addr) + phdr->p_vaddr);
251251- // cbdata->info->dwarf_section_length = phdr->p_memsz;
252252- }
253253- }
254254-255255- if (addrMatch && ehdr)
256256- {
257257- //std::cout << "*** Match found! " << info->dlpi_name << std::endl;
258258-259259- // Now we find .eh_frame from .eh_frame_hdr
260260- if (ehdr->version != 1)
261261- return 0;
262262- cbdata->info->dwarf_section = reinterpret_cast<void*>(readEncodedPointer(ehdr));
263263- cbdata->info->dwarf_section_length = uintptr_t(maxAddr) - uintptr_t(cbdata->info->dwarf_section);
264264- }
265265-266266- return 0;
267267-}
268268-269269-bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info)
270270-{
271271- TRACE1(addr);
272272- const FileMap::ImageMap* map = g_file_map.imageMapForAddr(addr);
273273-274274- if (!map) // in ELF
275275- {
276276- memset(info, 0, sizeof(*info));
277277-278278- CBData data = { addr, info };
279279-280280- dl_iterate_phdr(dlCallback, &data);
281281- std::cout << "Dwarf section at " << info->dwarf_section << std::endl;
282282- return info->dwarf_section != 0;
283283- }
284284- else // in Mach-O
285285- {
286286- info->mh = map->header;
287287- info->dwarf_section = reinterpret_cast<const void*>(map->eh_frame.first + map->slide);
288288- info->dwarf_section_length = map->eh_frame.second;
289289-290290- // FIXME: we would get "malformed __unwind_info" warnings otherwise
291291- // info->compact_unwind_section = reinterpret_cast<const void*>(map->unwind_info.first + map->slide);
292292- // info->compact_unwind_section_length = map->unwind_info.second;
293293- info->compact_unwind_section = 0;
294294- info->compact_unwind_section_length = 0;
295295-296296- return true;
297297- }
298298-}
299299-
+15-8
src/dyld/public.h
src/dyld/dyld_public.h
···11/*
22This file is part of Darling.
3344-Copyright (C) 2012 Lubos Dolezel
44+Copyright (C) 2012-2013 Lubos Dolezel
5566Darling is free software: you can redistribute it and/or modify
77it under the terms of the GNU General Public License as published by
···2020#ifndef DYLD_PUBLIC_H
2121#define DYLD_PUBLIC_H
2222#include <stdint.h>
2323+#include "MachOMgr.h"
2424+2525+namespace Darling {
2626+ class MachOObject;
2727+}
23282429#ifdef __cplusplus
2530extern "C" {
···3439 uintptr_t compact_unwind_section_length;
3540};
36413737-typedef void (LoaderHookFunc)(const struct mach_header* mh, intptr_t vmaddr_slide);
3838-3942uint32_t _dyld_image_count(void);
4043const struct mach_header* _dyld_get_image_header(uint32_t image_index);
4144intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index);
4245const char* _dyld_get_image_name(uint32_t image_index);
4646+void* dyld_stub_binder_fixup(Darling::MachOObject** obj, uintptr_t lazyOffset);
43474448char* getsectdata(const struct mach_header* header, const char* segname, const char* sectname, unsigned long* size);
45494646-void _dyld_register_func_for_add_image(LoaderHookFunc* func);
4747-void _dyld_register_func_for_remove_image(LoaderHookFunc* func);
5050+void _dyld_register_func_for_add_image(Darling::MachOMgr::LoaderHookFunc* func);
5151+void _dyld_register_func_for_remove_image(Darling::MachOMgr::LoaderHookFunc* func);
5252+5353+void __dyld_make_delayed_module_initializer_calls();
5454+void __dyld_mod_term_funcs();
5555+5656+const char* dyld_image_path_containing_address(const void* addr);
5757+bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info);
48584959int32_t NSVersionOfRunTimeLibrary(const char* libraryName);
50605161int32_t NSVersionOfLinkTimeLibrary(const char* libraryName);
52625363int _NSGetExecutablePath(char* buf, uint32_t* bufsize);
5454-5555-const char* dyld_image_path_containing_address(const void* addr);
5656-bool _dyld_find_unwind_sections(void* addr, struct dyld_unwind_sections* info);
57645865#ifdef __cplusplus
5966}
+4-4
src/dyld/trampoline_helper.nasm
···8787 mov rsi, rsp
8888 mov rcx, qword 0xaabbccddeeff ; print function (saves orig ret address)
89899090- sub rsp, 8 ; align stack to 16
9090+ ;sub rsp, 8 ; align stack to 16
9191 call rcx
9292- add rsp, 8
9292+ ;add rsp, 8
93939494 mov r11, rax ; save the right addr
9595···111111 mov rsi, rsp
112112 mov rcx, qword 0xa0a1a2a3a4a5a6 ; retval print function (returns orig ret address)
113113114114- sub rsp, 8 ; align stack to 16
114114+ ;sub rsp, 8 ; align stack to 16
115115 call rcx
116116- add rsp, 8
116116+ ;add rsp, 8
117117118118 mov r11, rax
119119