ModuleLoadFrame.cpp (4956B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 6 7 #include "ModuleLoadFrame.h" 8 9 #include "LoaderPrivateAPI.h" 10 11 namespace mozilla { 12 namespace freestanding { 13 14 ModuleLoadFrame::ModuleLoadFrame(PCUNICODE_STRING aRequestedDllName) 15 : mPrev(sTopFrame.get()), 16 mContext(nullptr), 17 mLSPSubstitutionRequired(false), 18 mLoadNtStatus(STATUS_UNSUCCESSFUL), 19 mLoadInfo(aRequestedDllName) { 20 EnsureInitialized(); 21 sTopFrame.set(this); 22 23 gLoaderPrivateAPI.NotifyBeginDllLoad(mLoadInfo, &mContext, aRequestedDllName); 24 } 25 26 ModuleLoadFrame::ModuleLoadFrame(nt::AllocatedUnicodeString&& aSectionName, 27 const void* aMapBaseAddr, NTSTATUS aNtStatus, 28 ModuleLoadInfo::Status aLoadStatus, 29 bool aIsDependent) 30 : mPrev(sTopFrame.get()), 31 mContext(nullptr), 32 mLSPSubstitutionRequired(false), 33 mLoadNtStatus(aNtStatus), 34 mLoadInfo(std::move(aSectionName), aMapBaseAddr, aLoadStatus, 35 aIsDependent) { 36 sTopFrame.set(this); 37 38 gLoaderPrivateAPI.NotifyBeginDllLoad(&mContext, mLoadInfo.mSectionName); 39 } 40 41 ModuleLoadFrame::~ModuleLoadFrame() { 42 gLoaderPrivateAPI.NotifyEndDllLoad(mContext, mLoadNtStatus, 43 std::move(mLoadInfo)); 44 sTopFrame.set(mPrev); 45 } 46 47 /* static */ 48 void ModuleLoadFrame::NotifyLSPSubstitutionRequired( 49 PCUNICODE_STRING aLeafName) { 50 ModuleLoadFrame* topFrame = sTopFrame.get(); 51 if (!topFrame) { 52 return; 53 } 54 55 topFrame->SetLSPSubstitutionRequired(aLeafName); 56 } 57 58 void ModuleLoadFrame::SetLSPSubstitutionRequired(PCUNICODE_STRING aLeafName) { 59 MOZ_ASSERT(!mLoadInfo.mBaseAddr); 60 if (mLoadInfo.mBaseAddr) { 61 // If mBaseAddr is not null then |this| has already seen a module load. This 62 // should not be the case for a LSP substitution, so we bail. 63 return; 64 } 65 66 // Save aLeafName, as it will be used by SetLoadStatus when invoking 67 // SubstituteForLSP 68 mLoadInfo.mRequestedDllName = aLeafName; 69 mLSPSubstitutionRequired = true; 70 } 71 72 /* static */ 73 void ModuleLoadFrame::NotifySectionMap( 74 nt::AllocatedUnicodeString&& aSectionName, const void* aMapBaseAddr, 75 NTSTATUS aMapNtStatus, ModuleLoadInfo::Status aLoadStatus, 76 bool aIsDependent) { 77 ModuleLoadFrame* topFrame = sTopFrame.get(); 78 if (!topFrame) { 79 // The only time that this data is useful is during initial mapping of 80 // the executable's dependent DLLs. If mozglue is present then 81 // IsDefaultObserver will return false, indicating that we are beyond 82 // initial process startup. 83 if (gLoaderPrivateAPI.IsDefaultObserver()) { 84 OnBareSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus, 85 aLoadStatus, aIsDependent); 86 } 87 return; 88 } 89 90 topFrame->OnSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus, 91 aLoadStatus, aIsDependent); 92 } 93 94 /* static */ 95 bool ModuleLoadFrame::ExistsTopFrame() { return !!sTopFrame.get(); } 96 97 void ModuleLoadFrame::OnSectionMap(nt::AllocatedUnicodeString&& aSectionName, 98 const void* aMapBaseAddr, 99 NTSTATUS aMapNtStatus, 100 ModuleLoadInfo::Status aLoadStatus, 101 bool aIsDependent) { 102 if (mLoadInfo.mBaseAddr) { 103 // If mBaseAddr is not null then |this| has already seen a module load. This 104 // means that we are witnessing a bare section map. 105 OnBareSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus, 106 aLoadStatus, aIsDependent); 107 return; 108 } 109 110 mLoadInfo.mSectionName = std::move(aSectionName); 111 mLoadInfo.mBaseAddr = aMapBaseAddr; 112 mLoadInfo.mStatus = aLoadStatus; 113 } 114 115 /* static */ 116 void ModuleLoadFrame::OnBareSectionMap( 117 nt::AllocatedUnicodeString&& aSectionName, const void* aMapBaseAddr, 118 NTSTATUS aMapNtStatus, ModuleLoadInfo::Status aLoadStatus, 119 bool aIsDependent) { 120 // We call the special constructor variant that is used for bare mappings. 121 ModuleLoadFrame frame(std::move(aSectionName), aMapBaseAddr, aMapNtStatus, 122 aLoadStatus, aIsDependent); 123 } 124 125 NTSTATUS ModuleLoadFrame::SetLoadStatus(NTSTATUS aNtStatus, 126 PHANDLE aOutHandle) { 127 mLoadNtStatus = aNtStatus; 128 129 if (!mLSPSubstitutionRequired) { 130 return aNtStatus; 131 } 132 133 if (!gLoaderPrivateAPI.SubstituteForLSP(mLoadInfo.mRequestedDllName, 134 aOutHandle)) { 135 return aNtStatus; 136 } 137 138 return STATUS_SUCCESS; 139 } 140 141 SafeThreadLocal<ModuleLoadFrame*> ModuleLoadFrame::sTopFrame; 142 143 } // namespace freestanding 144 } // namespace mozilla