1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/components/nsNativeComponentLoader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,246 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.8 + * This Original Code has been modified by IBM Corporation. 1.9 + * Modifications made by IBM described herein are 1.10 + * Copyright (c) International Business Machines 1.11 + * Corporation, 2000 1.12 + * 1.13 + * Modifications to Mozilla code or documentation 1.14 + * identified per MPL Section 3.3 1.15 + * 1.16 + * Date Modified by Description of modification 1.17 + * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2 1.18 + */ 1.19 + 1.20 +/* Allow logging in the release build */ 1.21 +#ifdef MOZ_LOGGING 1.22 +#define FORCE_PR_LOG 1.23 +#endif 1.24 + 1.25 +#include "nsNativeComponentLoader.h" 1.26 + 1.27 +#include "prlog.h" 1.28 +#include "prinit.h" 1.29 +#include "prerror.h" 1.30 + 1.31 +#include "nsComponentManager.h" 1.32 +#include "ManifestParser.h" // for LogMessage 1.33 +#include "nsCRTGlue.h" 1.34 +#include "nsThreadUtils.h" 1.35 +#include "nsTraceRefcnt.h" 1.36 + 1.37 +#include "nsIFile.h" 1.38 +#include "mozilla/WindowsDllBlocklist.h" 1.39 + 1.40 +#ifdef XP_WIN 1.41 +#include <windows.h> 1.42 +#endif 1.43 + 1.44 +#ifdef XP_MACOSX 1.45 +#include <signal.h> 1.46 +#endif 1.47 + 1.48 +#ifdef VMS 1.49 +#include <lib$routines.h> 1.50 +#include <ssdef.h> 1.51 +#endif 1.52 + 1.53 +#ifdef DEBUG 1.54 +#define IMPLEMENT_BREAK_AFTER_LOAD 1.55 +#endif 1.56 + 1.57 +using namespace mozilla; 1.58 + 1.59 +static PRLogModuleInfo * 1.60 +GetNativeModuleLoaderLog() 1.61 +{ 1.62 + static PRLogModuleInfo *sLog; 1.63 + if (!sLog) 1.64 + sLog = PR_NewLogModule("nsNativeModuleLoader"); 1.65 + return sLog; 1.66 +} 1.67 + 1.68 +#define LOG(level, args) PR_LOG(GetNativeModuleLoaderLog(), level, args) 1.69 + 1.70 +NS_IMPL_QUERY_INTERFACE(nsNativeModuleLoader, 1.71 + mozilla::ModuleLoader) 1.72 + 1.73 +NS_IMPL_ADDREF_USING_AGGREGATOR(nsNativeModuleLoader, 1.74 + nsComponentManagerImpl::gComponentManager) 1.75 +NS_IMPL_RELEASE_USING_AGGREGATOR(nsNativeModuleLoader, 1.76 + nsComponentManagerImpl::gComponentManager) 1.77 + 1.78 +nsresult 1.79 +nsNativeModuleLoader::Init() 1.80 +{ 1.81 + MOZ_ASSERT(NS_IsMainThread(), "Startup not on main thread?"); 1.82 + LOG(PR_LOG_DEBUG, ("nsNativeModuleLoader::Init()")); 1.83 + return NS_OK; 1.84 +} 1.85 + 1.86 +class LoadModuleMainThreadRunnable : public nsRunnable 1.87 +{ 1.88 +public: 1.89 + LoadModuleMainThreadRunnable(nsNativeModuleLoader* loader, 1.90 + FileLocation &file) 1.91 + : mLoader(loader) 1.92 + , mFile(file) 1.93 + , mResult(nullptr) 1.94 + { } 1.95 + 1.96 + NS_IMETHOD Run() 1.97 + { 1.98 + mResult = mLoader->LoadModule(mFile); 1.99 + return NS_OK; 1.100 + } 1.101 + 1.102 + nsRefPtr<nsNativeModuleLoader> mLoader; 1.103 + FileLocation mFile; 1.104 + const mozilla::Module* mResult; 1.105 +}; 1.106 + 1.107 +const mozilla::Module* 1.108 +nsNativeModuleLoader::LoadModule(FileLocation &aFile) 1.109 +{ 1.110 + if (aFile.IsZip()) { 1.111 + NS_ERROR("Binary components cannot be loaded from JARs"); 1.112 + return nullptr; 1.113 + } 1.114 + nsCOMPtr<nsIFile> file = aFile.GetBaseFile(); 1.115 + nsresult rv; 1.116 + 1.117 + if (!NS_IsMainThread()) { 1.118 + // If this call is off the main thread, synchronously proxy it 1.119 + // to the main thread. 1.120 + nsRefPtr<LoadModuleMainThreadRunnable> r = new LoadModuleMainThreadRunnable(this, aFile); 1.121 + NS_DispatchToMainThread(r, NS_DISPATCH_SYNC); 1.122 + return r->mResult; 1.123 + } 1.124 + 1.125 + nsCOMPtr<nsIHashable> hashedFile(do_QueryInterface(file)); 1.126 + if (!hashedFile) { 1.127 + NS_ERROR("nsIFile is not nsIHashable"); 1.128 + return nullptr; 1.129 + } 1.130 + 1.131 + nsAutoCString filePath; 1.132 + file->GetNativePath(filePath); 1.133 + 1.134 + NativeLoadData data; 1.135 + 1.136 + if (mLibraries.Get(hashedFile, &data)) { 1.137 + NS_ASSERTION(data.module, "Corrupt mLibraries hash"); 1.138 + LOG(PR_LOG_DEBUG, 1.139 + ("nsNativeModuleLoader::LoadModule(\"%s\") - found in cache", 1.140 + filePath.get())); 1.141 + return data.module; 1.142 + } 1.143 + 1.144 + // We haven't loaded this module before 1.145 + { 1.146 +#ifdef HAS_DLL_BLOCKLIST 1.147 + AutoSetXPCOMLoadOnMainThread guard; 1.148 +#endif 1.149 + rv = file->Load(&data.library); 1.150 + } 1.151 + 1.152 + if (NS_FAILED(rv)) { 1.153 + char errorMsg[1024] = "<unknown; can't get error from NSPR>"; 1.154 + 1.155 + if (PR_GetErrorTextLength() < (int) sizeof(errorMsg)) 1.156 + PR_GetErrorText(errorMsg); 1.157 + 1.158 + LogMessage("Failed to load native module at path '%s': (%lx) %s", 1.159 + filePath.get(), rv, errorMsg); 1.160 + 1.161 + return nullptr; 1.162 + } 1.163 + 1.164 +#ifdef IMPLEMENT_BREAK_AFTER_LOAD 1.165 + nsAutoCString leafName; 1.166 + file->GetNativeLeafName(leafName); 1.167 + 1.168 + char *env = getenv("XPCOM_BREAK_ON_LOAD"); 1.169 + char *blist; 1.170 + if (env && *env && (blist = strdup(env))) { 1.171 + char *nextTok = blist; 1.172 + while (char *token = NS_strtok(":", &nextTok)) { 1.173 + if (leafName.Find(token, true) != kNotFound) { 1.174 + NS_BREAK(); 1.175 + } 1.176 + } 1.177 + 1.178 + free(blist); 1.179 + } 1.180 +#endif 1.181 + 1.182 + void *module = PR_FindSymbol(data.library, "NSModule"); 1.183 + if (!module) { 1.184 + LogMessage("Native module at path '%s' doesn't export symbol `NSModule`.", 1.185 + filePath.get()); 1.186 + PR_UnloadLibrary(data.library); 1.187 + return nullptr; 1.188 + } 1.189 + 1.190 + data.module = *(mozilla::Module const *const *) module; 1.191 + if (mozilla::Module::kVersion != data.module->mVersion) { 1.192 + LogMessage("Native module at path '%s' is incompatible with this version of Firefox, has version %i, expected %i.", 1.193 + filePath.get(), data.module->mVersion, 1.194 + mozilla::Module::kVersion); 1.195 + PR_UnloadLibrary(data.library); 1.196 + return nullptr; 1.197 + } 1.198 + 1.199 + mLibraries.Put(hashedFile, data); // infallible 1.200 + return data.module; 1.201 +} 1.202 + 1.203 +PLDHashOperator 1.204 +nsNativeModuleLoader::ReleaserFunc(nsIHashable* aHashedFile, 1.205 + NativeLoadData& aLoadData, void*) 1.206 +{ 1.207 + aLoadData.module = nullptr; 1.208 + return PL_DHASH_NEXT; 1.209 +} 1.210 + 1.211 +PLDHashOperator 1.212 +nsNativeModuleLoader::UnloaderFunc(nsIHashable* aHashedFile, 1.213 + NativeLoadData& aLoadData, void*) 1.214 +{ 1.215 + if (PR_LOG_TEST(GetNativeModuleLoaderLog(), PR_LOG_DEBUG)) { 1.216 + nsCOMPtr<nsIFile> file(do_QueryInterface(aHashedFile)); 1.217 + 1.218 + nsAutoCString filePath; 1.219 + file->GetNativePath(filePath); 1.220 + 1.221 + LOG(PR_LOG_DEBUG, 1.222 + ("nsNativeModuleLoader::UnloaderFunc(\"%s\")", filePath.get())); 1.223 + } 1.224 + 1.225 +#ifdef NS_BUILD_REFCNT_LOGGING 1.226 + nsTraceRefcnt::SetActivityIsLegal(false); 1.227 +#endif 1.228 + 1.229 +#if 0 1.230 + // XXXbsmedberg: do this as soon as the static-destructor crash(es) 1.231 + // are fixed 1.232 + PRStatus ret = PR_UnloadLibrary(aLoadData.library); 1.233 + NS_ASSERTION(ret == PR_SUCCESS, "Failed to unload library"); 1.234 +#endif 1.235 + 1.236 +#ifdef NS_BUILD_REFCNT_LOGGING 1.237 + nsTraceRefcnt::SetActivityIsLegal(true); 1.238 +#endif 1.239 + 1.240 + return PL_DHASH_REMOVE; 1.241 +} 1.242 + 1.243 +void 1.244 +nsNativeModuleLoader::UnloadLibraries() 1.245 +{ 1.246 + MOZ_ASSERT(NS_IsMainThread(), "Shutdown not on main thread?"); 1.247 + mLibraries.Enumerate(ReleaserFunc, nullptr); 1.248 + mLibraries.Enumerate(UnloaderFunc, nullptr); 1.249 +}