1// Copyright 2011 The Chromium Authors 2// 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 7#include <dlfcn.h> 8#include <mach-o/getsect.h> 9 10#include <string_view> 11 12#include "base/apple/foundation_util.h" 13#include "base/apple/scoped_cftyperef.h" 14#include "base/files/file_path.h" 15#include "base/files/file_util.h" 16#include "base/logging.h" 17#include "base/strings/strcat.h" 18#include "base/strings/string_util.h" 19#include "base/strings/sys_string_conversions.h" 20#include "base/strings/utf_string_conversions.h" 21#include "base/threading/thread_restrictions.h" 22 23namespace base { 24 25std::string NativeLibraryLoadError::ToString() const { 26 return message; 27} 28 29NativeLibrary LoadNativeLibraryWithOptions(const FilePath& library_path, 30 const NativeLibraryOptions& options, 31 NativeLibraryLoadError* error) { 32 // dlopen() etc. open the file off disk. 33 if (library_path.Extension() == "dylib" || !DirectoryExists(library_path)) { 34 void* dylib = dlopen(library_path.value().c_str(), RTLD_LAZY); 35 if (!dylib) { 36 if (error) { 37 error->message = dlerror(); 38 } 39 return nullptr; 40 } 41 NativeLibrary native_lib = new NativeLibraryStruct(); 42 native_lib->type = DYNAMIC_LIB; 43 native_lib->dylib = dylib; 44 return native_lib; 45 } 46 apple::ScopedCFTypeRef<CFURLRef> url = apple::FilePathToCFURL(library_path); 47 if (!url) { 48 return nullptr; 49 } 50 CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, url.get()); 51 if (!bundle) { 52 return nullptr; 53 } 54 55 NativeLibrary native_lib = new NativeLibraryStruct(); 56 native_lib->type = BUNDLE; 57 native_lib->bundle = bundle; 58 return native_lib; 59} 60 61void UnloadNativeLibrary(NativeLibrary library) { 62 if (library->type == BUNDLE) { 63 CFRelease(library->bundle); 64 } else { 65 dlclose(library->dylib); 66 } 67 delete library; 68} 69 70void* GetFunctionPointerFromNativeLibrary(NativeLibrary library, 71 const char* name) { 72 // Get the function pointer using the right API for the type. 73 if (library->type == BUNDLE) { 74 apple::ScopedCFTypeRef<CFStringRef> symbol_name = 75 SysUTF8ToCFStringRef(name); 76 return CFBundleGetFunctionPointerForName(library->bundle, 77 symbol_name.get()); 78 } 79 80 return dlsym(library->dylib, name); 81} 82 83std::string GetNativeLibraryName(std::string_view name) { 84 DCHECK(IsStringASCII(name)); 85#if BUILDFLAG(IS_IOS) 86 // Returns mylib.framework/mylib 87 return FilePath() 88 .Append(name) 89 .AddExtension("framework") 90 .Append(name) 91 .value(); 92#else 93 return StrCat({"lib", name, ".dylib"}); 94#endif 95} 96 97std::string GetLoadableModuleName(std::string_view name) { 98 DCHECK(IsStringASCII(name)); 99#if BUILDFLAG(IS_IOS) 100 // Returns mylib.framework 101 return FilePath() 102 .Append(name) 103 .AddExtension("framework") 104 .value(); 105#else 106 return StrCat({name, ".so"}); 107#endif 108} 109 110} // namespace base 111