1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * John Bandhauer <jband@netscape.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 /* Win32 x86 code for stack walking, symbol resolution, and function hooking */
41 #ifndef __nsDebugHelpWin32_h__
42 #define __nsDebugHelpWin32_h__
44 #if defined(_WIN32) && defined(_M_IX86)
45 #ifndef WIN32_LEAN_AND_MEAN
46 #define WIN32_LEAN_AND_MEAN
52 #error "nsDebugHelpWin32.h should only be included in Win32 x86 builds"
55 // XXX temporary hack...
56 //#include "hacky_defines.h"
59 /***************************************************************************/
62 #define DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_) \
63 typedef retval_ ( conv_ * typename_ ) args_ ;
65 #ifdef DHW_IMPLEMENT_GLOBALS
66 #define DHW_DECLARE_FUN_GLOBAL(typename_, name_) typename_ dhw##name_
68 #define DHW_DECLARE_FUN_GLOBAL(typename_, name_) extern typename_ dhw##name_
71 #define DHW_DECLARE_FUN_PROTO(retval_, conv_, name_, args_) \
72 retval_ conv_ name_ args_
74 #define DHW_DECLARE_FUN_STATIC_PROTO(retval_, name_, args_) \
75 static retval_ conv_ name_ args_
77 #define DHW_DECLARE_FUN_TYPE_AND_PROTO(name_, retval_, conv_, typename_, args_) \
78 DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
79 DHW_DECLARE_FUN_PROTO(retval_, conv_, name_, args_)
81 #define DHW_DECLARE_FUN_TYPE_AND_STATIC_PROTO(name_, retval_, conv_, typename_, args_) \
82 DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
83 DHW_DECLARE_FUN_STATIC_PROTO(retval_, conv_, name_, args_)
85 #define DHW_DECLARE_FUN_TYPE_AND_GLOBAL(typename_, name_, retval_, conv_, args_) \
86 DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
87 DHW_DECLARE_FUN_GLOBAL(typename_, name_)
90 /**********************************************************/
91 // These are used to get 'original' function addresses from DHWImportHooker.
93 #define DHW_DECLARE_ORIGINAL(type_, name_, hooker_) \
94 type_ name_ = (type_) hooker_ . GetOriginalFunction()
96 #define DHW_DECLARE_ORIGINAL_PTR(type_, name_, hooker_) \
97 type_ name_ = (type_) hooker_ -> GetOriginalFunction()
99 #define DHW_ORIGINAL(type_, hooker_) \
100 ((type_) hooker_ . GetOriginalFunction())
102 #define DHW_ORIGINAL_PTR(type_, hooker_) \
103 ((type_) hooker_ -> GetOriginalFunction())
105 /***************************************************************************/
106 // Global declarations of entry points into ImgHelp functions
108 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMINITIALIZEPROC
, SymInitialize
, \
109 BOOL
, __stdcall
, (HANDLE
, LPSTR
, BOOL
));
111 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMSETOPTIONS
, SymSetOptions
, \
112 DWORD
, __stdcall
, (DWORD
));
114 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETOPTIONS
, SymGetOptions
, \
115 DWORD
, __stdcall
, ());
117 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETMODULEINFO
, SymGetModuleInfo
, \
118 BOOL
, __stdcall
, (HANDLE
, DWORD
, PIMAGEHLP_MODULE
));
120 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETSYMFROMADDRPROC
, SymGetSymFromAddr
, \
121 BOOL
, __stdcall
, (HANDLE
, DWORD
, PDWORD
, PIMAGEHLP_SYMBOL
));
125 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(ENUMERATELOADEDMODULES
, EnumerateLoadedModules
, \
126 BOOL
, __stdcall
, (HANDLE
, PENUMLOADED_MODULES_CALLBACK
, PVOID
));
128 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(IMAGEDIRECTORYENTRYTODATA
, ImageDirectoryEntryToData
, \
129 PVOID
, __stdcall
, (PVOID
, BOOL
, USHORT
, PULONG
));
131 // We aren't using any of the below yet...
134 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMCLEANUPPROC, SymCleanup, \
135 BOOL, __stdcall, (HANDLE));
137 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(STACKWALKPROC, StackWalk, \
140 (DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, \
141 PREAD_PROCESS_MEMORY_ROUTINE, \
142 PFUNCTION_TABLE_ACCESS_ROUTINE, \
143 PGET_MODULE_BASE_ROUTINE, \
144 PTRANSLATE_ADDRESS_ROUTINE));
146 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMFUNCTIONTABLEACCESSPROC, SymFunctionTableAccess, \
147 LPVOID, __stdcall, (HANDLE, DWORD));
149 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETMODULEBASEPROC, SymGetModuleBase, \
150 DWORD, __stdcall, (HANDLE, DWORD));
152 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMLOADMODULE, SymLoadModule, \
153 DWORD, __stdcall, (HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD));
155 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(UNDECORATESYMBOLNAME, _UnDecorateSymbolName, \
156 DWORD, __stdcall, (LPCSTR, LPSTR, DWORD, DWORD));
158 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMUNDNAME, SymUnDName, \
159 BOOL, __stdcall, (PIMAGEHLP_SYMBOL, LPSTR, DWORD));
161 DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETLINEFROMADDR, SymGetLineFromAddr, \
162 BOOL, __stdcall, (HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE));
166 /***************************************************************************/
169 dhwEnsureImageHlpInitialized();
171 /***************************************************************************/
173 DHW_DECLARE_FUN_TYPE(FARPROC
, __stdcall
, GETPROCADDRESS
, (HMODULE
, PCSTR
));
175 class DHWImportHooker
179 DHWImportHooker(const char* aModuleName
,
180 const char* aFunctionName
,
182 PRBool aExcludeOurModule
= PR_FALSE
);
186 PROC
GetOriginalFunction() {return mOriginal
;}
188 PRBool
PatchAllModules();
189 PRBool
PatchOneModule(HMODULE aModule
, const char* name
);
190 static PRBool
ModuleLoaded(HMODULE aModule
, DWORD flags
);
193 // I think that these should be made not static members, but allocated
194 // things created in an explicit static 'init' method and cleaned up in
195 // an explicit static 'finish' method. This would allow the application
196 // to have proper lifetime control over all the hooks.
198 static DHWImportHooker
&getLoadLibraryWHooker();
199 static DHWImportHooker
&getLoadLibraryExWHooker();
200 static DHWImportHooker
&getLoadLibraryAHooker();
201 static DHWImportHooker
&getLoadLibraryExAHooker();
202 static DHWImportHooker
&getGetProcAddressHooker();
204 static HMODULE WINAPI
LoadLibraryA(PCSTR path
);
207 DHWImportHooker
* mNext
;
208 const char* mModuleName
;
209 const char* mFunctionName
;
212 HMODULE mIgnoreModule
;
216 static PRLock
* gLock
;
217 static DHWImportHooker
* gHooks
;
218 static GETPROCADDRESS gRealGetProcAddress
;
220 static HMODULE WINAPI
LoadLibraryW(PCWSTR path
);
221 static HMODULE WINAPI
LoadLibraryExW(PCWSTR path
, HANDLE file
, DWORD flags
);
222 static HMODULE WINAPI
LoadLibraryExA(PCSTR path
, HANDLE file
, DWORD flags
);
224 static FARPROC WINAPI
GetProcAddress(HMODULE aModule
, PCSTR aFunctionName
);
227 /***************************************************************************/
228 // This supports the _CrtSetAllocHook based hooking.
229 // This system sucks because you don't get to see the allocated pointer. I
230 // don't think it appropriate for nsTraceMalloc, but is useful as a means to make
231 // malloc fail for testing purposes.
232 #if 0 //comment out this stuff. not necessary
234 class DHWAllocationSizeDebugHook
237 virtual PRBool
AllocHook(size_t size
) = 0;
238 virtual PRBool
ReallocHook(size_t size
, size_t sizeOld
) = 0;
239 virtual PRBool
FreeHook(size_t size
) = 0;
242 extern PRBool
dhwSetAllocationSizeDebugHook(DHWAllocationSizeDebugHook
* hook
);
243 extern PRBool
dhwClearAllocationSizeDebugHook();
245 /***************************************************************************/
248 #endif /* __nsDebugHelpWin32_h__ */