Bug 1927515 - [FxMS Docs] Updates Spotlight UI template documentation in source doc...
[gecko.git] / tools / profiler / core / shared-libraries-win32.cc
blob44423952620d99e1488bcd62344c44c18cf60694
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include <windows.h>
8 #include "shared-libraries.h"
9 #include "nsWindowsHelpers.h"
10 #include "mozilla/NativeNt.h"
11 #include "mozilla/WindowsEnumProcessModules.h"
12 #include "mozilla/WindowsProcessMitigations.h"
13 #include "nsPrintfCString.h"
15 static bool IsModuleUnsafeToLoad(const nsAString& aModuleName) {
16 // Hackaround for Bug 1723868. There is no safe way to prevent the module
17 // Microsoft's VP9 Video Decoder from being unloaded because mfplat.dll may
18 // have posted more than one task to unload the module in the work queue
19 // without calling LoadLibrary.
20 if (aModuleName.LowerCaseEqualsLiteral("msvp9dec_store.dll")) {
21 return true;
24 return false;
27 void AddSharedLibraryFromModuleInfo(SharedLibraryInfo& sharedLibraryInfo,
28 const wchar_t* aModulePath,
29 mozilla::Maybe<HMODULE> aModule) {
30 nsDependentSubstring moduleNameStr(
31 mozilla::nt::GetLeafName(nsDependentString(aModulePath)));
33 // If the module is unsafe to call LoadLibraryEx for, we skip.
34 if (IsModuleUnsafeToLoad(moduleNameStr)) {
35 return;
38 // If EAF+ is enabled, parsing ntdll's PE header causes a crash.
39 if (mozilla::IsEafPlusEnabled() &&
40 moduleNameStr.LowerCaseEqualsLiteral("ntdll.dll")) {
41 return;
44 // Load the module again - to make sure that its handle will remain valid as
45 // we attempt to read the PDB information from it - or for the first time if
46 // we only have a path. We want to load the DLL without running the newly
47 // loaded module's DllMain function, but not as a data file because we want
48 // to be able to do RVA computations easily. Hence, we use the flag
49 // LOAD_LIBRARY_AS_IMAGE_RESOURCE which ensures that the sections (not PE
50 // headers) will be relocated by the loader. Otherwise GetPdbInfo() and/or
51 // GetVersionInfo() can cause a crash. If the original handle |aModule| is
52 // valid, LoadLibraryEx just increments its refcount.
53 nsModuleHandle handleLock(
54 ::LoadLibraryExW(aModulePath, NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE));
55 if (!handleLock) {
56 return;
59 mozilla::nt::PEHeaders headers(handleLock.get());
60 if (!headers) {
61 return;
64 mozilla::Maybe<mozilla::Range<const uint8_t>> bounds = headers.GetBounds();
65 if (!bounds) {
66 return;
69 // Put the original |aModule| into SharedLibrary, but we get debug info
70 // from |handleLock| as |aModule| might be inaccessible.
71 const uintptr_t modStart =
72 aModule.isSome() ? reinterpret_cast<uintptr_t>(*aModule)
73 : reinterpret_cast<uintptr_t>(handleLock.get());
74 const uintptr_t modEnd = modStart + bounds->length();
76 nsAutoCString breakpadId;
77 nsAutoString pdbPathStr;
78 if (const auto* debugInfo = headers.GetPdbInfo()) {
79 MOZ_ASSERT(breakpadId.IsEmpty());
80 const GUID& pdbSig = debugInfo->pdbSignature;
81 breakpadId.AppendPrintf(
82 "%08lX" // m0
83 "%04X%04X" // m1,m2
84 "%02X%02X%02X%02X%02X%02X%02X%02X" // m3
85 "%X", // pdbAge
86 pdbSig.Data1, pdbSig.Data2, pdbSig.Data3, pdbSig.Data4[0],
87 pdbSig.Data4[1], pdbSig.Data4[2], pdbSig.Data4[3], pdbSig.Data4[4],
88 pdbSig.Data4[5], pdbSig.Data4[6], pdbSig.Data4[7], debugInfo->pdbAge);
90 // The PDB file name could be different from module filename,
91 // so report both
92 // e.g. The PDB for C:\Windows\SysWOW64\ntdll.dll is wntdll.pdb
93 pdbPathStr = NS_ConvertUTF8toUTF16(debugInfo->pdbFileName);
96 nsAutoCString codeId;
97 DWORD timestamp;
98 DWORD imageSize;
99 if (headers.GetTimeStamp(timestamp) && headers.GetImageSize(imageSize)) {
100 codeId.AppendPrintf(
101 "%08lX" // Uppercase 8 digits of hex timestamp with leading zeroes.
102 "%lx", // Lowercase hex image size
103 timestamp, imageSize);
106 nsAutoCString versionStr;
107 uint64_t version;
108 if (headers.GetVersionInfo(version)) {
109 versionStr.AppendPrintf("%u.%u.%u.%u",
110 static_cast<uint32_t>((version >> 48) & 0xFFFFu),
111 static_cast<uint32_t>((version >> 32) & 0xFFFFu),
112 static_cast<uint32_t>((version >> 16) & 0xFFFFu),
113 static_cast<uint32_t>(version & 0xFFFFu));
116 const nsString& pdbNameStr =
117 PromiseFlatString(mozilla::nt::GetLeafName(pdbPathStr));
118 SharedLibrary shlib(modStart, modEnd,
119 0, // DLLs are always mapped at offset 0 on Windows
120 breakpadId, codeId, PromiseFlatString(moduleNameStr),
121 nsDependentString(aModulePath), pdbNameStr, pdbPathStr,
122 versionStr, "");
123 sharedLibraryInfo.AddSharedLibrary(shlib);
126 SharedLibraryInfo SharedLibraryInfo::GetInfoForSelf() {
127 SharedLibraryInfo sharedLibraryInfo;
129 auto addSharedLibraryFromModuleInfo =
130 [&sharedLibraryInfo](const wchar_t* aModulePath, HMODULE aModule) {
131 AddSharedLibraryFromModuleInfo(sharedLibraryInfo, aModulePath,
132 mozilla::Some(aModule));
135 mozilla::EnumerateProcessModules(addSharedLibraryFromModuleInfo);
136 return sharedLibraryInfo;
139 SharedLibraryInfo SharedLibraryInfo::GetInfoFromPath(const wchar_t* aPath) {
140 SharedLibraryInfo sharedLibraryInfo;
141 AddSharedLibraryFromModuleInfo(sharedLibraryInfo, aPath, mozilla::Nothing());
142 return sharedLibraryInfo;
145 void SharedLibraryInfo::Initialize() { /* do nothing */ }