|
24 | 24 | class CFBundleSymbolResolver : public SymbolResolver { |
25 | 25 | public: |
26 | 26 | CFBundleSymbolResolver(WTF::RetainPtr<CFBundleRef> bundle) |
27 | | - : _bundle(bundle) { |
| 27 | + : _bundle(bundle) |
| 28 | + , _loaded(false) { |
28 | 29 | } |
29 | 30 |
|
30 | 31 | virtual void* loadFunctionSymbol(const char* symbolName) override { |
|
38 | 39 | } |
39 | 40 |
|
40 | 41 | virtual bool load() override { |
41 | | - CFErrorRef error = nullptr; |
42 | | - bool loaded = CFBundleLoadExecutableAndReturnError(this->_bundle.get(), &error); |
| 42 | + if (this->_loaded) { |
| 43 | + return true; |
| 44 | + } |
| 45 | + |
| 46 | + // Use NSBundle for loading because of the following statement in the docs: |
| 47 | + // For most of its methods, NSBundle simply calls the appropriate CFBundle routine to do its work, |
| 48 | + // but loading code is different. Because CFBundle does not handle Objective-C symbols, NSBundle has |
| 49 | + // to use a different mechanism for loading code. NSBundle interacts with the Objective-C runtime |
| 50 | + // system to correctly load and register all Cocoa classes and other executable code in the bundle |
| 51 | + // executable file. |
| 52 | + // See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingCode/Concepts/CFNSBundle.html |
| 53 | + |
| 54 | + NSURL* url = (__bridge NSURL*)CFBundleCopyBundleURL(this->_bundle.get()); |
| 55 | + NSBundle* bundle = [NSBundle bundleWithURL:url]; |
| 56 | + [url release]; |
| 57 | + |
| 58 | + bool wasLoaded = bundle.loaded; |
| 59 | + NSError* error = nullptr; |
| 60 | + bool loaded = [bundle loadAndReturnError:&error]; |
| 61 | + |
| 62 | + if (loaded) { |
| 63 | + this->_loaded = true; |
| 64 | + if (!wasLoaded) { |
| 65 | + // Unload the bundle if it was not previously loaded. Sometimes framework bundles use |
| 66 | + // resource bundles of the same name and keeping the framework loaded as a bundle |
| 67 | + // breaks them. OTH, loading and unloading a framework bundle is sufficient for its |
| 68 | + // executable code to be registered with the Objective-C runtime. |
| 69 | + [bundle unload]; |
| 70 | + } |
| 71 | + } |
| 72 | + |
43 | 73 | if (error) { |
44 | | - dataLogF("%s\n", [[(NSError*)error localizedDescription] UTF8String]); |
| 74 | + dataLogF("%s\n", [[error localizedDescription] UTF8String]); |
45 | 75 | } |
46 | 76 |
|
47 | 77 | return loaded; |
48 | 78 | } |
49 | 79 |
|
50 | 80 | private: |
51 | 81 | WTF::RetainPtr<CFBundleRef> _bundle; |
| 82 | + bool _loaded; |
52 | 83 | }; |
53 | 84 |
|
54 | 85 | class DlSymbolResolver : public SymbolResolver { |
|
0 commit comments