blob: f2df0a711a436087c3ff15f99fa2406c3b9b8957 [file] [log] [blame]
[email protected]84479322011-04-18 22:06:221// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]f38e25f2009-04-21 00:56:072// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/native_library.h"
6
[email protected]108c2a12009-06-05 22:18:097#include <dlfcn.h>
[email protected]5625f3cf2013-03-15 12:10:588#include <mach-o/getsect.h>
[email protected]f38e25f2009-04-21 00:56:079
[email protected]57999812013-02-24 05:40:5210#include "base/files/file_path.h"
[email protected]e3177dd52014-08-13 20:22:1411#include "base/files/file_util.h"
[email protected]5625f3cf2013-03-15 12:10:5812#include "base/logging.h"
[email protected]df0ca6c82010-10-17 04:09:0613#include "base/mac/scoped_cftyperef.h"
[email protected]d529cb02013-06-10 19:06:5714#include "base/strings/string_util.h"
[email protected]a4ea1f12013-06-07 18:37:0715#include "base/strings/utf_string_conversions.h"
[email protected]3d169832011-01-02 20:10:0516#include "base/threading/thread_restrictions.h"
[email protected]f38e25f2009-04-21 00:56:0717
18namespace base {
19
[email protected]5625f3cf2013-03-15 12:10:5820static NativeLibraryObjCStatus GetObjCStatusForImage(
21 const void* function_pointer) {
22 Dl_info info;
23 if (!dladdr(function_pointer, &info))
24 return OBJC_UNKNOWN;
25
26 // See if the the image contains an "ObjC image info" segment. This method
27 // of testing is used in _CFBundleGrokObjcImageInfoFromFile in
28 // CF-744/CFBundle.c, around lines 2447-2474.
29 //
thestige38fbd62016-06-10 21:54:4030 // In 64-bit images, ObjC can be recognized in __DATA,__objc_imageinfo.
[email protected]5625f3cf2013-03-15 12:10:5831 const section_64* section = getsectbynamefromheader_64(
32 reinterpret_cast<const struct mach_header_64*>(info.dli_fbase),
33 SEG_DATA, "__objc_imageinfo");
thestige38fbd62016-06-10 21:54:4034 return section ? OBJC_PRESENT : OBJC_NOT_PRESENT;
[email protected]5625f3cf2013-03-15 12:10:5835}
36
[email protected]0f998442014-03-25 01:59:0937std::string NativeLibraryLoadError::ToString() const {
38 return message;
39}
40
[email protected]f38e25f2009-04-21 00:56:0741// static
thestige38fbd62016-06-10 21:54:4042NativeLibrary LoadNativeLibrary(const FilePath& library_path,
[email protected]7712c0aea2014-07-01 00:50:3043 NativeLibraryLoadError* error) {
[email protected]be130682010-11-12 21:53:1644 // dlopen() etc. open the file off disk.
[email protected]dcd16612013-07-15 20:18:0945 if (library_path.Extension() == "dylib" || !DirectoryExists(library_path)) {
[email protected]108c2a12009-06-05 22:18:0946 void* dylib = dlopen(library_path.value().c_str(), RTLD_LAZY);
[email protected]7712c0aea2014-07-01 00:50:3047 if (!dylib) {
xhwang6a01b392015-11-10 07:48:3048 if (error)
49 error->message = dlerror();
thestig02c965b2016-06-14 18:52:2350 return nullptr;
[email protected]7712c0aea2014-07-01 00:50:3051 }
[email protected]108c2a12009-06-05 22:18:0952 NativeLibrary native_lib = new NativeLibraryStruct();
53 native_lib->type = DYNAMIC_LIB;
54 native_lib->dylib = dylib;
[email protected]5625f3cf2013-03-15 12:10:5855 native_lib->objc_status = OBJC_UNKNOWN;
[email protected]108c2a12009-06-05 22:18:0956 return native_lib;
57 }
thestige38fbd62016-06-10 21:54:4058 ScopedCFTypeRef<CFURLRef> url(CFURLCreateFromFileSystemRepresentation(
[email protected]3df79f42013-06-24 18:49:0559 kCFAllocatorDefault,
60 (const UInt8*)library_path.value().c_str(),
61 library_path.value().length(),
62 true));
[email protected]f38e25f2009-04-21 00:56:0763 if (!url)
thestig02c965b2016-06-14 18:52:2364 return nullptr;
[email protected]108c2a12009-06-05 22:18:0965 CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, url.get());
66 if (!bundle)
thestig02c965b2016-06-14 18:52:2367 return nullptr;
[email protected]f38e25f2009-04-21 00:56:0768
[email protected]108c2a12009-06-05 22:18:0969 NativeLibrary native_lib = new NativeLibraryStruct();
70 native_lib->type = BUNDLE;
71 native_lib->bundle = bundle;
[email protected]d8921c432010-01-28 16:08:0972 native_lib->bundle_resource_ref = CFBundleOpenBundleResourceMap(bundle);
[email protected]5625f3cf2013-03-15 12:10:5873 native_lib->objc_status = OBJC_UNKNOWN;
[email protected]108c2a12009-06-05 22:18:0974 return native_lib;
[email protected]f38e25f2009-04-21 00:56:0775}
76
77// static
78void UnloadNativeLibrary(NativeLibrary library) {
[email protected]5625f3cf2013-03-15 12:10:5879 if (library->objc_status == OBJC_NOT_PRESENT) {
80 if (library->type == BUNDLE) {
81 CFBundleCloseBundleResourceMap(library->bundle,
82 library->bundle_resource_ref);
83 CFRelease(library->bundle);
84 } else {
85 dlclose(library->dylib);
86 }
[email protected]d8921c432010-01-28 16:08:0987 } else {
[email protected]5625f3cf2013-03-15 12:10:5888 VLOG(2) << "Not unloading NativeLibrary because it may contain an ObjC "
89 "segment. library->objc_status = " << library->objc_status;
90 // Deliberately do not CFRelease the bundle or dlclose the dylib because
91 // doing so can corrupt the ObjC runtime method caches. See
92 // http://crbug.com/172319 for details.
[email protected]d8921c432010-01-28 16:08:0993 }
[email protected]108c2a12009-06-05 22:18:0994 delete library;
[email protected]f38e25f2009-04-21 00:56:0795}
96
97// static
98void* GetFunctionPointerFromNativeLibrary(NativeLibrary library,
thestige38fbd62016-06-10 21:54:4099 StringPiece name) {
thestig02c965b2016-06-14 18:52:23100 void* function_pointer = nullptr;
[email protected]5625f3cf2013-03-15 12:10:58101
102 // Get the function pointer using the right API for the type.
[email protected]b7efd7692009-12-15 22:34:09103 if (library->type == BUNDLE) {
thestige38fbd62016-06-10 21:54:40104 ScopedCFTypeRef<CFStringRef> symbol_name(CFStringCreateWithCString(
105 kCFAllocatorDefault, name.data(), kCFStringEncodingUTF8));
[email protected]5625f3cf2013-03-15 12:10:58106 function_pointer = CFBundleGetFunctionPointerForName(library->bundle,
107 symbol_name);
108 } else {
thestige38fbd62016-06-10 21:54:40109 function_pointer = dlsym(library->dylib, name.data());
[email protected]b7efd7692009-12-15 22:34:09110 }
[email protected]5625f3cf2013-03-15 12:10:58111
112 // If this library hasn't been tested for having ObjC, use the function
113 // pointer to look up the section information for the library.
114 if (function_pointer && library->objc_status == OBJC_UNKNOWN)
115 library->objc_status = GetObjCStatusForImage(function_pointer);
116
117 return function_pointer;
[email protected]108c2a12009-06-05 22:18:09118}
119
120// static
thestig02c965b2016-06-14 18:52:23121std::string GetNativeLibraryName(StringPiece name) {
122 DCHECK(IsStringASCII(name));
123 return "lib" + name.as_string() + ".dylib";
[email protected]f38e25f2009-04-21 00:56:07124}
125
126} // namespace base