Files
tubestation/xpcom/components/nsNativeModuleLoader.cpp
Wes Kocher 2a7ed059f1 Backed out 14 changesets (bug 1165515) for b2g mochitest-6 permafail CLOSED TREE
Backed out changeset 9b97e2aa2ed9 (bug 1165515)
Backed out changeset 150606c022a2 (bug 1165515)
Backed out changeset 4e875a488349 (bug 1165515)
Backed out changeset 467e7feeb546 (bug 1165515)
Backed out changeset d6b6cc373197 (bug 1165515)
Backed out changeset 0615265b593c (bug 1165515)
Backed out changeset fafd1dce9f08 (bug 1165515)
Backed out changeset d1df869245f9 (bug 1165515)
Backed out changeset 6876a7c63611 (bug 1165515)
Backed out changeset b7841c94a9a3 (bug 1165515)
Backed out changeset e5e3617f7c73 (bug 1165515)
Backed out changeset 39be3db95978 (bug 1165515)
Backed out changeset 0ec74176f8de (bug 1165515)
Backed out changeset 5b928dd10d71 (bug 1165515)
2015-06-01 17:57:58 -07:00

241 lines
6.0 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* This Original Code has been modified by IBM Corporation.
* Modifications made by IBM described herein are
* Copyright (c) International Business Machines
* Corporation, 2000
*
* Modifications to Mozilla code or documentation
* identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
*/
#include "nsNativeModuleLoader.h"
#include "mozilla/Logging.h"
#include "prinit.h"
#include "prerror.h"
#include "nsComponentManager.h"
#include "ManifestParser.h" // for LogMessage
#include "nsCRTGlue.h"
#include "nsThreadUtils.h"
#include "nsTraceRefcnt.h"
#include "nsIFile.h"
#include "mozilla/WindowsDllBlocklist.h"
#ifdef XP_WIN
#include <windows.h>
#endif
#ifdef XP_MACOSX
#include <signal.h>
#endif
#ifdef VMS
#include <lib$routines.h>
#include <ssdef.h>
#endif
#ifdef DEBUG
#define IMPLEMENT_BREAK_AFTER_LOAD
#endif
using namespace mozilla;
static PRLogModuleInfo*
GetNativeModuleLoaderLog()
{
static PRLogModuleInfo* sLog;
if (!sLog) {
sLog = PR_NewLogModule("nsNativeModuleLoader");
}
return sLog;
}
#define LOG(level, args) MOZ_LOG(GetNativeModuleLoaderLog(), level, args)
nsresult
nsNativeModuleLoader::Init()
{
MOZ_ASSERT(NS_IsMainThread(), "Startup not on main thread?");
LOG(PR_LOG_DEBUG, ("nsNativeModuleLoader::Init()"));
return NS_OK;
}
class LoadModuleMainThreadRunnable : public nsRunnable
{
public:
LoadModuleMainThreadRunnable(nsNativeModuleLoader* aLoader,
FileLocation& aFile)
: mManager(nsComponentManagerImpl::gComponentManager)
, mLoader(aLoader)
, mFile(aFile)
, mResult(nullptr)
{
}
NS_IMETHOD Run()
{
mResult = mLoader->LoadModule(mFile);
return NS_OK;
}
nsRefPtr<nsComponentManagerImpl> mManager;
nsNativeModuleLoader* mLoader;
FileLocation mFile;
const mozilla::Module* mResult;
};
const mozilla::Module*
nsNativeModuleLoader::LoadModule(FileLocation& aFile)
{
if (aFile.IsZip()) {
NS_ERROR("Binary components cannot be loaded from JARs");
return nullptr;
}
nsCOMPtr<nsIFile> file = aFile.GetBaseFile();
nsresult rv;
if (!NS_IsMainThread()) {
// If this call is off the main thread, synchronously proxy it
// to the main thread.
nsRefPtr<LoadModuleMainThreadRunnable> r =
new LoadModuleMainThreadRunnable(this, aFile);
NS_DispatchToMainThread(r, NS_DISPATCH_SYNC);
return r->mResult;
}
nsCOMPtr<nsIHashable> hashedFile(do_QueryInterface(file));
if (!hashedFile) {
NS_ERROR("nsIFile is not nsIHashable");
return nullptr;
}
nsAutoCString filePath;
file->GetNativePath(filePath);
NativeLoadData data;
if (mLibraries.Get(hashedFile, &data)) {
NS_ASSERTION(data.mModule, "Corrupt mLibraries hash");
LOG(PR_LOG_DEBUG,
("nsNativeModuleLoader::LoadModule(\"%s\") - found in cache",
filePath.get()));
return data.mModule;
}
// We haven't loaded this module before
{
#ifdef HAS_DLL_BLOCKLIST
AutoSetXPCOMLoadOnMainThread guard;
#endif
rv = file->Load(&data.mLibrary);
}
if (NS_FAILED(rv)) {
char errorMsg[1024] = "<unknown; can't get error from NSPR>";
if (PR_GetErrorTextLength() < (int)sizeof(errorMsg)) {
PR_GetErrorText(errorMsg);
}
LogMessage("Failed to load native module at path '%s': (%lx) %s",
filePath.get(), rv, errorMsg);
return nullptr;
}
#ifdef IMPLEMENT_BREAK_AFTER_LOAD
nsAutoCString leafName;
file->GetNativeLeafName(leafName);
char* env = getenv("XPCOM_BREAK_ON_LOAD");
char* blist;
if (env && *env && (blist = strdup(env))) {
char* nextTok = blist;
while (char* token = NS_strtok(":", &nextTok)) {
if (leafName.Find(token, true) != kNotFound) {
NS_BREAK();
}
}
free(blist);
}
#endif
void* module = PR_FindSymbol(data.mLibrary, "NSModule");
if (!module) {
LogMessage("Native module at path '%s' doesn't export symbol `NSModule`.",
filePath.get());
PR_UnloadLibrary(data.mLibrary);
return nullptr;
}
data.mModule = *(mozilla::Module const* const*)module;
if (mozilla::Module::kVersion != data.mModule->mVersion) {
LogMessage("Native module at path '%s' is incompatible with this version of Firefox, has version %i, expected %i.",
filePath.get(), data.mModule->mVersion,
mozilla::Module::kVersion);
PR_UnloadLibrary(data.mLibrary);
return nullptr;
}
mLibraries.Put(hashedFile, data); // infallible
return data.mModule;
}
PLDHashOperator
nsNativeModuleLoader::ReleaserFunc(nsIHashable* aHashedFile,
NativeLoadData& aLoadData, void*)
{
aLoadData.mModule = nullptr;
return PL_DHASH_NEXT;
}
PLDHashOperator
nsNativeModuleLoader::UnloaderFunc(nsIHashable* aHashedFile,
NativeLoadData& aLoadData, void*)
{
if (PR_LOG_TEST(GetNativeModuleLoaderLog(), PR_LOG_DEBUG)) {
nsCOMPtr<nsIFile> file(do_QueryInterface(aHashedFile));
nsAutoCString filePath;
file->GetNativePath(filePath);
LOG(PR_LOG_DEBUG,
("nsNativeModuleLoader::UnloaderFunc(\"%s\")", filePath.get()));
}
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::SetActivityIsLegal(false);
#endif
#if 0
// XXXbsmedberg: do this as soon as the static-destructor crash(es)
// are fixed
PRStatus ret = PR_UnloadLibrary(aLoadData.mLibrary);
NS_ASSERTION(ret == PR_SUCCESS, "Failed to unload library");
#endif
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::SetActivityIsLegal(true);
#endif
return PL_DHASH_REMOVE;
}
void
nsNativeModuleLoader::UnloadLibraries()
{
MOZ_ASSERT(NS_IsMainThread(), "Shutdown not on main thread?");
mLibraries.Enumerate(ReleaserFunc, nullptr);
mLibraries.Enumerate(UnloaderFunc, nullptr);
}