| Index: base/native_library_mac.mm
|
| diff --git a/base/native_library_mac.mm b/base/native_library_mac.mm
|
| index eec586b863588d9856cc0221da1e73973e10e8de..58fc3be93ba220a6394ce3fc4519eae0333f4365 100644
|
| --- a/base/native_library_mac.mm
|
| +++ b/base/native_library_mac.mm
|
| @@ -5,19 +5,113 @@
|
| #include "base/native_library.h"
|
|
|
| #include <dlfcn.h>
|
| +#include <mach/task_info.h>
|
| +#include <mach-o/dyld_images.h>
|
| +#include <mach-o/getsect.h>
|
|
|
| #include "base/file_util.h"
|
| #include "base/files/file_path.h"
|
| +#include "base/lazy_instance.h"
|
| +#include "base/mac/mac_util.h"
|
| #include "base/mac/scoped_cftyperef.h"
|
| #include "base/string_util.h"
|
| +#include "base/synchronization/lock.h"
|
| #include "base/threading/thread_restrictions.h"
|
| #include "base/utf_string_conversions.h"
|
|
|
| +extern "C" {
|
| +
|
| +// http://opensource.apple.com/source/dyld/dyld-195.5/include/mach-o/dyld_priv.h
|
| +enum dyld_image_states
|
| +{
|
| + dyld_image_state_mapped = 10, // No batch notification for this
|
| + dyld_image_state_dependents_mapped = 20, // Only batch notification for this
|
| + dyld_image_state_rebased = 30,
|
| + dyld_image_state_bound = 40,
|
| + dyld_image_state_dependents_initialized = 45, // Only single notification for this
|
| + dyld_image_state_initialized = 50,
|
| + dyld_image_state_terminated = 60 // Only single notification for this
|
| +};
|
| +
|
| +typedef const char* (*dyld_image_state_change_handler)(
|
| + enum dyld_image_states state, uint32_t infoCount,
|
| + const struct dyld_image_info info[]);
|
| +
|
| +void dyld_register_image_state_change_handler(
|
| + enum dyld_image_states state, bool batch,
|
| + dyld_image_state_change_handler handler);
|
| +
|
| +};
|
| +
|
| +namespace {
|
| +
|
| +base::LazyInstance<base::Lock>::Leaky g_module_lock_ =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +base::LazyInstance<std::set<std::string> >::Leaky g_module_set_ =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +bool g_initial_registration = false;
|
| +
|
| +const char* Recorder(enum dyld_image_states state,
|
| + uint32_t infoCount,
|
| + const struct dyld_image_info info[]) {
|
| + if (g_initial_registration)
|
| + return NULL;
|
| +
|
| + for (uint32_t i = 0; i < infoCount; i++) {
|
| +#if __LP64__
|
| + const struct mach_header_64* hdr =
|
| + reinterpret_cast<const struct mach_header_64*>(
|
| + info[i].imageLoadAddress);
|
| +
|
| + if (hdr->magic != MH_MAGIC_64 && hdr->magic != MH_CIGAM_64)
|
| + continue;
|
| +
|
| + if (getsectbynamefromheader_64(hdr, SEG_DATA, "__objc_imageinfo")) {
|
| + LOG(ERROR) << "64-bit Objective-C found";
|
| + LOG(ERROR) << "info[i].imageFilePath: " << info[i].imageFilePath;
|
| + base::AutoLock pin(*g_module_lock_.Pointer());
|
| + g_module_set_.Pointer()->insert(info[i].imageFilePath);
|
| + }
|
| +#else
|
| + const struct mach_header* hdr =
|
| + reinterpret_cast<const struct mach_header*>(
|
| + info[i].imageLoadAddress);
|
| +
|
| + if (hdr->magic != MH_MAGIC && hdr->magic != MH_CIGAM)
|
| + continue;
|
| +
|
| + if (getsectbynamefromheader(hdr, SEG_OBJC, "__image_info")) {
|
| + LOG(ERROR) << "32-bit Objective-C found";
|
| + LOG(ERROR) << "info[i].imageFilePath: " << info[i].imageFilePath;
|
| + base::AutoLock pin(*g_module_lock_.Pointer());
|
| + g_module_set_.Pointer()->insert(info[i].imageFilePath);
|
| + }
|
| +#endif
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +void Initialize() {
|
| + static bool initialized = false;
|
| + if (!initialized) {
|
| + initialized = true;
|
| + g_initial_registration = true;
|
| + dyld_register_image_state_change_handler(dyld_image_state_mapped, 0 /* \
|
| +batch */, &Recorder);
|
| + g_initial_registration = false;
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| namespace base {
|
|
|
| // static
|
| NativeLibrary LoadNativeLibrary(const base::FilePath& library_path,
|
| std::string* error) {
|
| + Initialize();
|
| +
|
| // dlopen() etc. open the file off disk.
|
| if (library_path.Extension() == "dylib" ||
|
| !file_util::DirectoryExists(library_path)) {
|
| @@ -27,6 +121,7 @@ NativeLibrary LoadNativeLibrary(const base::FilePath& library_path,
|
| NativeLibrary native_lib = new NativeLibraryStruct();
|
| native_lib->type = DYNAMIC_LIB;
|
| native_lib->dylib = dylib;
|
| + native_lib->image_path = library_path;
|
| return native_lib;
|
| }
|
| base::mac::ScopedCFTypeRef<CFURLRef> url(
|
| @@ -45,17 +140,31 @@ NativeLibrary LoadNativeLibrary(const base::FilePath& library_path,
|
| native_lib->type = BUNDLE;
|
| native_lib->bundle = bundle;
|
| native_lib->bundle_resource_ref = CFBundleOpenBundleResourceMap(bundle);
|
| +
|
| + base::mac::ScopedCFTypeRef<CFURLRef> executable_url(
|
| + CFBundleCopyExecutableURL(bundle));
|
| + NSURL* executable_url_ns = base::mac::CFToNSCast(executable_url);
|
| + native_lib->image_path =
|
| + base::FilePath([[executable_url_ns path] fileSystemRepresentation]);
|
| +
|
| return native_lib;
|
| }
|
|
|
| // static
|
| void UnloadNativeLibrary(NativeLibrary library) {
|
| - if (library->type == BUNDLE) {
|
| - CFBundleCloseBundleResourceMap(library->bundle,
|
| - library->bundle_resource_ref);
|
| - CFRelease(library->bundle);
|
| - } else {
|
| - dlclose(library->dylib);
|
| + bool unload = true;
|
| + {
|
| + base::AutoLock pin(*g_module_lock_.Pointer());
|
| + unload = !g_module_set_.Pointer()->count(library->image_path.value().c_str());
|
| + }
|
| + if (unload) {
|
| + if (library->type == BUNDLE) {
|
| + CFBundleCloseBundleResourceMap(library->bundle,
|
| + library->bundle_resource_ref);
|
| + CFRelease(library->bundle);
|
| + } else {
|
| + dlclose(library->dylib);
|
| + }
|
| }
|
| delete library;
|
| }
|
|
|