[SM91] Update to Spidermonkey 91.1.3 APIs
[0ad.git] / libraries / source / spidermonkey / include-win32-release / mozilla / interceptor / PatcherBase.h
blobe39a38fafd181bfc8750ef69e343876eeba397cb
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/. */
7 #ifndef mozilla_interceptor_PatcherBase_h
8 #define mozilla_interceptor_PatcherBase_h
10 #include "mozilla/interceptor/TargetFunction.h"
12 namespace mozilla {
13 namespace interceptor {
15 template <typename MMPolicy>
16 struct GetProcAddressSelector;
18 template <>
19 struct GetProcAddressSelector<MMPolicyOutOfProcess> {
20 FARPROC operator()(HMODULE aModule, const char* aName,
21 const MMPolicyOutOfProcess& aMMPolicy) const {
22 auto exportSection =
23 mozilla::nt::PEExportSection<MMPolicyOutOfProcess>::Get(aModule,
24 aMMPolicy);
25 return exportSection.GetProcAddress(aName);
29 template <>
30 struct GetProcAddressSelector<MMPolicyInProcess> {
31 FARPROC operator()(HMODULE aModule, const char* aName,
32 const MMPolicyInProcess&) const {
33 // PEExportSection works for MMPolicyInProcess, too, but the native
34 // GetProcAddress is still better because PEExportSection does not
35 // solve a forwarded entry.
36 return ::GetProcAddress(aModule, aName);
40 template <typename VMPolicy>
41 class WindowsDllPatcherBase {
42 protected:
43 typedef typename VMPolicy::MMPolicyT MMPolicyT;
45 template <typename... Args>
46 explicit WindowsDllPatcherBase(Args&&... aArgs)
47 : mVMPolicy(std::forward<Args>(aArgs)...) {}
49 ReadOnlyTargetFunction<MMPolicyT> ResolveRedirectedAddress(
50 FARPROC aOriginalFunction) {
51 uintptr_t currAddr = reinterpret_cast<uintptr_t>(aOriginalFunction);
53 #if defined(_M_IX86) || defined(_M_X64)
54 uintptr_t prevAddr = 0;
55 while (prevAddr != currAddr) {
56 ReadOnlyTargetFunction<MMPolicyT> currFunc(mVMPolicy, currAddr);
57 prevAddr = currAddr;
59 // If function entry is jmp rel8 stub to the internal implementation, we
60 // resolve redirected address from the jump target.
61 uintptr_t nextAddr = 0;
62 if (currFunc.IsRelativeShortJump(&nextAddr)) {
63 int8_t offset = nextAddr - currFunc.GetAddress() - 2;
65 # if defined(_M_X64)
66 // We redirect to the target of a short jump backwards if the target
67 // is another jump (only 32-bit displacement is currently supported).
68 // This case is used by GetFileAttributesW in Win7 x64.
69 if ((offset < 0) && (currFunc.IsValidAtOffset(2 + offset))) {
70 ReadOnlyTargetFunction<MMPolicyT> redirectFn(mVMPolicy, nextAddr);
71 if (redirectFn.IsIndirectNearJump(&nextAddr)) {
72 return redirectFn;
75 # endif
77 // We check the downstream has enough nop-space only when the offset is
78 // positive. Otherwise we stop chasing redirects and let the caller
79 // fail to hook.
80 if (offset > 0) {
81 bool isNopSpace = true;
82 for (int8_t i = 0; i < offset; i++) {
83 if (currFunc[2 + i] != 0x90) {
84 isNopSpace = false;
85 break;
89 if (isNopSpace) {
90 currAddr = nextAddr;
93 # if defined(_M_X64)
94 } else if (currFunc.IsIndirectNearJump(&nextAddr) ||
95 currFunc.IsRelativeNearJump(&nextAddr)) {
96 # else
97 } else if (currFunc.IsIndirectNearJump(&nextAddr)) {
98 # endif
99 // If function entry is jmp [disp32] such as used by kernel32, we
100 // resolve redirected address from import table. For x64, we resolve
101 // a relative near jump for TestDllInterceptor with --disable-optimize.
102 currAddr = nextAddr;
105 #endif // defined(_M_IX86) || defined(_M_X64)
107 if (currAddr != reinterpret_cast<uintptr_t>(aOriginalFunction) &&
108 !mVMPolicy.IsPageAccessible(currAddr)) {
109 currAddr = reinterpret_cast<uintptr_t>(aOriginalFunction);
111 return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy, currAddr);
114 public:
115 FARPROC GetProcAddress(HMODULE aModule, const char* aName) const {
116 GetProcAddressSelector<MMPolicyT> selector;
117 return selector(aModule, aName, mVMPolicy);
120 bool IsPageAccessible(uintptr_t aAddress) const {
121 return mVMPolicy.IsPageAccessible(aAddress);
124 #if defined(NIGHTLY_BUILD)
125 const Maybe<DetourError>& GetLastDetourError() const {
126 return mVMPolicy.GetLastDetourError();
128 #endif // defined(NIGHTLY_BUILD)
129 template <typename... Args>
130 void SetLastDetourError(Args&&... aArgs) {
131 mVMPolicy.SetLastDetourError(std::forward<Args>(aArgs)...);
134 protected:
135 VMPolicy mVMPolicy;
138 } // namespace interceptor
139 } // namespace mozilla
141 #endif // mozilla_interceptor_PatcherBase_h