pjs/xpcom/base/nsDebugHelpWin32.h

236 строки
8.6 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* John Bandhauer <jband@netscape.com>
*/
/* Win32 x86 code for stack walking, symbol resolution, and function hooking */
#ifndef __nsDebugHelpWin32_h__
#define __nsDebugHelpWin32_h__
#if defined(_WIN32) && defined(_M_IX86)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <imagehlp.h>
#include <crtdbg.h>
#else
#error "nsDebugHelpWin32.h should only be included in Win32 x86 builds"
#endif
// XXX temporary hack...
//#include "hacky_defines.h"
/***************************************************************************/
// useful macros...
#define DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_) \
typedef retval_ ( conv_ * typename_ ) args_ ;
#ifdef DHW_IMPLEMENT_GLOBALS
#define DHW_DECLARE_FUN_GLOBAL(typename_, name_) typename_ dhw##name_
#else
#define DHW_DECLARE_FUN_GLOBAL(typename_, name_) extern typename_ dhw##name_
#endif
#define DHW_DECLARE_FUN_PROTO(retval_, conv_, name_, args_) \
retval_ conv_ name_ args_
#define DHW_DECLARE_FUN_STATIC_PROTO(retval_, name_, args_) \
static retval_ conv_ name_ args_
#define DHW_DECLARE_FUN_TYPE_AND_PROTO(name_, retval_, conv_, typename_, args_) \
DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
DHW_DECLARE_FUN_PROTO(retval_, conv_, name_, args_)
#define DHW_DECLARE_FUN_TYPE_AND_STATIC_PROTO(name_, retval_, conv_, typename_, args_) \
DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
DHW_DECLARE_FUN_STATIC_PROTO(retval_, conv_, name_, args_)
#define DHW_DECLARE_FUN_TYPE_AND_GLOBAL(typename_, name_, retval_, conv_, args_) \
DHW_DECLARE_FUN_TYPE(retval_, conv_, typename_, args_); \
DHW_DECLARE_FUN_GLOBAL(typename_, name_)
/**********************************************************/
// These are used to get 'original' function addresses from DHWImportHooker.
#define DHW_DECLARE_ORIGINAL(type_, name_, hooker_) \
type_ name_ = (type_) hooker_ . GetOriginalFunction()
#define DHW_DECLARE_ORIGINAL_PTR(type_, name_, hooker_) \
type_ name_ = (type_) hooker_ -> GetOriginalFunction()
#define DHW_ORIGINAL(type_, hooker_) \
((type_) hooker_ . GetOriginalFunction())
#define DHW_ORIGINAL_PTR(type_, hooker_) \
((type_) hooker_ -> GetOriginalFunction())
/***************************************************************************/
// Global declarations of entry points into ImgHelp functions
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMINITIALIZEPROC, SymInitialize, \
BOOL, __stdcall, (HANDLE, LPSTR, BOOL));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMSETOPTIONS, SymSetOptions, \
DWORD, __stdcall, (DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETOPTIONS, SymGetOptions, \
DWORD, __stdcall, ());
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETMODULEINFO, SymGetModuleInfo, \
BOOL, __stdcall, (HANDLE, DWORD, PIMAGEHLP_MODULE));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETSYMFROMADDRPROC, SymGetSymFromAddr, \
BOOL, __stdcall, (HANDLE, DWORD, PDWORD, PIMAGEHLP_SYMBOL));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(ENUMERATELOADEDMODULES, EnumerateLoadedModules, \
BOOL, __stdcall, (HANDLE, PENUMLOADED_MODULES_CALLBACK, PVOID));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(IMAGEDIRECTORYENTRYTODATA, ImageDirectoryEntryToData, \
PVOID, __stdcall, (PVOID, BOOL, USHORT, PULONG));
// We aren't using any of the below yet...
/*
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMCLEANUPPROC, SymCleanup, \
BOOL, __stdcall, (HANDLE));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(STACKWALKPROC, StackWalk, \
BOOL,
__stdcall,
(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, \
PREAD_PROCESS_MEMORY_ROUTINE, \
PFUNCTION_TABLE_ACCESS_ROUTINE, \
PGET_MODULE_BASE_ROUTINE, \
PTRANSLATE_ADDRESS_ROUTINE));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMFUNCTIONTABLEACCESSPROC, SymFunctionTableAccess, \
LPVOID, __stdcall, (HANDLE, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETMODULEBASEPROC, SymGetModuleBase, \
DWORD, __stdcall, (HANDLE, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMLOADMODULE, SymLoadModule, \
DWORD, __stdcall, (HANDLE, HANDLE, PSTR, PSTR, DWORD, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(UNDECORATESYMBOLNAME, _UnDecorateSymbolName, \
DWORD, __stdcall, (LPCSTR, LPSTR, DWORD, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMUNDNAME, SymUnDName, \
BOOL, __stdcall, (PIMAGEHLP_SYMBOL, LPSTR, DWORD));
DHW_DECLARE_FUN_TYPE_AND_GLOBAL(SYMGETLINEFROMADDR, SymGetLineFromAddr, \
BOOL, __stdcall, (HANDLE, DWORD, PDWORD, PIMAGEHLP_LINE));
*/
/***************************************************************************/
extern PRBool
dhwEnsureImageHlpInitialized();
extern PRBool
dhwEnsureSymInitialized();
/***************************************************************************/
DHW_DECLARE_FUN_TYPE(FARPROC, __stdcall, GETPROCADDRESS, (HMODULE, PCSTR));
class DHWImportHooker
{
public:
DHWImportHooker(const char* aModuleName,
const char* aFunctionName,
PROC aHook,
PRBool aExcludeOurModule = PR_FALSE);
~DHWImportHooker();
PROC GetOriginalFunction() {return mOriginal;}
PRBool PatchAllModules();
PRBool PatchOneModule(HMODULE aModule, const char* name);
static PRBool ModuleLoaded(HMODULE aModule, DWORD flags);
// I think that these should be made not static members, but allocated
// things created in an explicit static 'init' method and cleaned up in
// an explicit static 'finish' method. This would allow the application
// to have proper lifetime control over all the hooks.
static DHWImportHooker &getLoadLibraryWHooker();
static DHWImportHooker &getLoadLibraryExWHooker();
static DHWImportHooker &getLoadLibraryAHooker();
static DHWImportHooker &getLoadLibraryExAHooker();
static DHWImportHooker &getGetProcAddressHooker();
static HMODULE WINAPI LoadLibraryA(PCSTR path);
private:
DHWImportHooker* mNext;
const char* mModuleName;
const char* mFunctionName;
PROC mOriginal;
PROC mHook;
HMODULE mIgnoreModule;
PRBool mHooking;
private:
static PRLock* gLock;
static DHWImportHooker* gHooks;
static GETPROCADDRESS gRealGetProcAddress;
static HMODULE WINAPI LoadLibraryW(PCWSTR path);
static HMODULE WINAPI LoadLibraryExW(PCWSTR path, HANDLE file, DWORD flags);
static HMODULE WINAPI LoadLibraryExA(PCSTR path, HANDLE file, DWORD flags);
static FARPROC WINAPI GetProcAddress(HMODULE aModule, PCSTR aFunctionName);
};
/***************************************************************************/
// This supports the _CrtSetAllocHook based hooking.
// This system sucks because you don't get to see the allocated pointer. I
// don't think it appropriate for nsTraceMalloc, but is useful as a means to make
// malloc fail for testing purposes.
#if 0 //comment out this stuff. not necessary
class DHWAllocationSizeDebugHook
{
public:
virtual PRBool AllocHook(size_t size) = 0;
virtual PRBool ReallocHook(size_t size, size_t sizeOld) = 0;
virtual PRBool FreeHook(size_t size) = 0;
};
extern PRBool dhwSetAllocationSizeDebugHook(DHWAllocationSizeDebugHook* hook);
extern PRBool dhwClearAllocationSizeDebugHook();
/***************************************************************************/
#endif //0
#endif /* __nsDebugHelpWin32_h__ */