Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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 https://mozilla.org/MPL/2.0/. */
#include "ModuleLoadFrame.h"
#include "LoaderPrivateAPI.h"
namespace mozilla {
namespace freestanding {
ModuleLoadFrame::ModuleLoadFrame(PCUNICODE_STRING aRequestedDllName)
: mPrev(sTopFrame.get()),
mContext(nullptr),
mLSPSubstitutionRequired(false),
mLoadNtStatus(STATUS_UNSUCCESSFUL),
mLoadInfo(aRequestedDllName) {
EnsureInitialized();
sTopFrame.set(this);
gLoaderPrivateAPI.NotifyBeginDllLoad(mLoadInfo, &mContext, aRequestedDllName);
}
ModuleLoadFrame::ModuleLoadFrame(nt::AllocatedUnicodeString&& aSectionName,
const void* aMapBaseAddr, NTSTATUS aNtStatus,
ModuleLoadInfo::Status aLoadStatus,
bool aIsDependent)
: mPrev(sTopFrame.get()),
mContext(nullptr),
mLSPSubstitutionRequired(false),
mLoadNtStatus(aNtStatus),
mLoadInfo(std::move(aSectionName), aMapBaseAddr, aLoadStatus,
aIsDependent) {
sTopFrame.set(this);
gLoaderPrivateAPI.NotifyBeginDllLoad(&mContext, mLoadInfo.mSectionName);
}
ModuleLoadFrame::~ModuleLoadFrame() {
gLoaderPrivateAPI.NotifyEndDllLoad(mContext, mLoadNtStatus,
std::move(mLoadInfo));
sTopFrame.set(mPrev);
}
/* static */
void ModuleLoadFrame::NotifyLSPSubstitutionRequired(
PCUNICODE_STRING aLeafName) {
ModuleLoadFrame* topFrame = sTopFrame.get();
if (!topFrame) {
return;
}
topFrame->SetLSPSubstitutionRequired(aLeafName);
}
void ModuleLoadFrame::SetLSPSubstitutionRequired(PCUNICODE_STRING aLeafName) {
MOZ_ASSERT(!mLoadInfo.mBaseAddr);
if (mLoadInfo.mBaseAddr) {
// If mBaseAddr is not null then |this| has already seen a module load. This
// should not be the case for a LSP substitution, so we bail.
return;
}
// Save aLeafName, as it will be used by SetLoadStatus when invoking
// SubstituteForLSP
mLoadInfo.mRequestedDllName = aLeafName;
mLSPSubstitutionRequired = true;
}
/* static */
void ModuleLoadFrame::NotifySectionMap(
nt::AllocatedUnicodeString&& aSectionName, const void* aMapBaseAddr,
NTSTATUS aMapNtStatus, ModuleLoadInfo::Status aLoadStatus,
bool aIsDependent) {
ModuleLoadFrame* topFrame = sTopFrame.get();
if (!topFrame) {
// The only time that this data is useful is during initial mapping of
// the executable's dependent DLLs. If mozglue is present then
// IsDefaultObserver will return false, indicating that we are beyond
// initial process startup.
if (gLoaderPrivateAPI.IsDefaultObserver()) {
OnBareSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
aLoadStatus, aIsDependent);
}
return;
}
topFrame->OnSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
aLoadStatus, aIsDependent);
}
/* static */
bool ModuleLoadFrame::ExistsTopFrame() { return !!sTopFrame.get(); }
void ModuleLoadFrame::OnSectionMap(nt::AllocatedUnicodeString&& aSectionName,
const void* aMapBaseAddr,
NTSTATUS aMapNtStatus,
ModuleLoadInfo::Status aLoadStatus,
bool aIsDependent) {
if (mLoadInfo.mBaseAddr) {
// If mBaseAddr is not null then |this| has already seen a module load. This
// means that we are witnessing a bare section map.
OnBareSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
aLoadStatus, aIsDependent);
return;
}
mLoadInfo.mSectionName = std::move(aSectionName);
mLoadInfo.mBaseAddr = aMapBaseAddr;
mLoadInfo.mStatus = aLoadStatus;
}
/* static */
void ModuleLoadFrame::OnBareSectionMap(
nt::AllocatedUnicodeString&& aSectionName, const void* aMapBaseAddr,
NTSTATUS aMapNtStatus, ModuleLoadInfo::Status aLoadStatus,
bool aIsDependent) {
// We call the special constructor variant that is used for bare mappings.
ModuleLoadFrame frame(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
aLoadStatus, aIsDependent);
}
NTSTATUS ModuleLoadFrame::SetLoadStatus(NTSTATUS aNtStatus,
PHANDLE aOutHandle) {
mLoadNtStatus = aNtStatus;
if (!mLSPSubstitutionRequired) {
return aNtStatus;
}
if (!gLoaderPrivateAPI.SubstituteForLSP(mLoadInfo.mRequestedDllName,
aOutHandle)) {
return aNtStatus;
}
return STATUS_SUCCESS;
}
SafeThreadLocal<ModuleLoadFrame*> ModuleLoadFrame::sTopFrame;
} // namespace freestanding
} // namespace mozilla