public/extensions/IBinTools.h
author Matt Woodrow <pred@alliedmods.net>
Thu Jan 08 18:17:17 2009 +1300 (2009-01-08)
changeset 2504 74fea7db93e4
parent 2289 44045ead61cd
child 2533 b66ce8e017a2
permissions -rw-r--r--
Added Dynamic Hooking to BinTools (bug 2616 r=dvander,DS)
faluco@739
     1
/**
faluco@739
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1226
     4
 * SourceMod BinTools Extension
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
faluco@739
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
faluco@739
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1226
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1226
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
faluco@739
    28
 *
faluco@739
    29
 * Version: $Id$
faluco@739
    30
 */
faluco@739
    31
faluco@739
    32
#ifndef _INCLUDE_SMEXT_BINTOOLS_H_
faluco@739
    33
#define _INCLUDE_SMEXT_BINTOOLS_H_
faluco@739
    34
faluco@739
    35
#include <IShareSys.h>
faluco@739
    36
pred@2504
    37
faluco@739
    38
#define SMINTERFACE_BINTOOLS_NAME		"IBinTools"
pred@2504
    39
#define SMINTERFACE_BINTOOLS_VERSION	3
pred@2504
    40
pred@2504
    41
#if defined HOOKING_ENABLED
pred@2504
    42
#include <sourcehook_pibuilder.h>
pred@2504
    43
pred@2504
    44
#define SMINTERFACE_BINTOOLS2_NAME		"IBinTools2"
pred@2504
    45
#define SMINTERFACE_BINTOOLS2_VERSION	1
pred@2504
    46
#endif
faluco@739
    47
faluco@739
    48
/**
faluco@739
    49
 * @brief Function calling encoding utilities
faluco@739
    50
 * @file IBinTools.h
faluco@739
    51
 */
faluco@739
    52
faluco@739
    53
namespace SourceMod
faluco@739
    54
{
faluco@739
    55
	/**
faluco@739
    56
	 * @brief Supported calling conventions
faluco@739
    57
	 */
faluco@739
    58
	enum CallConvention
faluco@739
    59
	{
faluco@739
    60
		CallConv_ThisCall,		/**< This call (object pointer required) */
faluco@739
    61
		CallConv_Cdecl,			/**< Standard C call */
faluco@739
    62
	};
faluco@739
    63
faluco@739
    64
	/**
faluco@739
    65
	 * @brief Describes how a parameter should be passed
faluco@739
    66
	 */
faluco@739
    67
	enum PassType
faluco@739
    68
	{
faluco@739
    69
		PassType_Basic,			/**< Plain old register data (pointers, integers) */
faluco@739
    70
		PassType_Float,			/**< Floating point data */
faluco@739
    71
		PassType_Object,		/**< Object or structure */
faluco@739
    72
	};
faluco@739
    73
faluco@739
    74
	#define PASSFLAG_BYVAL		(1<<0)		/**< Passing by value */
faluco@739
    75
	#define PASSFLAG_BYREF		(1<<1)		/**< Passing by reference */
faluco@739
    76
	#define PASSFLAG_ODTOR		(1<<2)		/**< Object has a destructor */
faluco@739
    77
	#define PASSFLAG_OCTOR		(1<<3)		/**< Object has a constructor */
faluco@739
    78
	#define PASSFLAG_OASSIGNOP	(1<<4)		/**< Object has an assignment operator */
faluco@739
    79
faluco@739
    80
	/**
faluco@739
    81
	 * @brief Parameter passing information
faluco@739
    82
	 */
faluco@739
    83
	struct PassInfo
faluco@739
    84
	{
faluco@739
    85
		PassType type;			/**< PassType value */
faluco@739
    86
		unsigned int flags;		/**< Pass/return flags */
faluco@739
    87
		size_t size;			/**< Size of the data being passed */
faluco@739
    88
	};
faluco@739
    89
faluco@739
    90
	/**
faluco@739
    91
	 * @brief Parameter encoding information
faluco@739
    92
	 */
faluco@739
    93
	struct PassEncode
faluco@739
    94
	{
faluco@739
    95
		PassInfo info;			/**< Parameter information */
faluco@739
    96
		size_t offset;			/**< Offset into the virtual stack */
faluco@739
    97
	};
faluco@739
    98
faluco@739
    99
	/**
faluco@739
   100
	 * @brief Wraps a C/C++ call.
faluco@739
   101
	 */
faluco@739
   102
	class ICallWrapper
faluco@739
   103
	{
faluco@739
   104
	public:
faluco@739
   105
		/**
faluco@739
   106
		 * @brief Returns the calling convention.
faluco@739
   107
		 *
faluco@739
   108
		 * @return				CallConvention value.
faluco@739
   109
		 */
faluco@739
   110
		virtual CallConvention GetCallConvention() =0;
faluco@739
   111
faluco@739
   112
		/**
faluco@739
   113
		 * @brief Returns parameter info.
faluco@739
   114
		 *
faluco@739
   115
		 * @param num			Parameter number to get (starting from 0).
faluco@739
   116
		 * @return				A PassInfo pointer.
faluco@739
   117
		 */
faluco@739
   118
		virtual const PassEncode *GetParamInfo(unsigned int num) =0;
faluco@739
   119
faluco@739
   120
		/**
faluco@739
   121
		 * @brief Returns return type info.
faluco@739
   122
		 *
faluco@739
   123
		 * @return				A PassInfo pointer.
faluco@739
   124
		 */
faluco@739
   125
		virtual const PassInfo *GetReturnInfo() =0;
faluco@739
   126
faluco@739
   127
		/**
faluco@739
   128
		 * @brief Returns the number of parameters.
dvander@942
   129
		 *
dvander@942
   130
		 * @return				Number of parameters.
faluco@739
   131
		 */
faluco@739
   132
		virtual unsigned int GetParamCount() =0;
faluco@739
   133
faluco@739
   134
		/**
faluco@739
   135
		 * @brief Execute the contained function.
dvander@942
   136
		 *
dvander@942
   137
		 * @param vParamStack	A blob of memory containing stack data.
dvander@942
   138
		 * @param retBuffer		Buffer to store return value.
faluco@739
   139
		 */
faluco@739
   140
		virtual void Execute(void *vParamStack, void *retBuffer) =0;
dvander@942
   141
dvander@942
   142
		/**
dvander@942
   143
		 * @brief Destroys all resources used by this object.
dvander@942
   144
		 */
dvander@942
   145
		virtual void Destroy() =0;
pred@2504
   146
pred@2504
   147
#if defined HOOKING_ENABLED
pred@2504
   148
pred@2504
   149
		/**
pred@2504
   150
		 * @brief Gets the Return type info.
pred@2504
   151
		 *
pred@2504
   152
		 * @return				A PassInfo pointer.
pred@2504
   153
		 */
pred@2504
   154
		virtual const SourceHook::PassInfo *GetSHReturnInfo() =0;
pred@2504
   155
pred@2504
   156
		/**
pred@2504
   157
		* @brief Returns the calling convention.
pred@2504
   158
		*
pred@2504
   159
		* @return				CallConvention value.
pred@2504
   160
		*/
pred@2504
   161
		virtual SourceHook::ProtoInfo::CallConvention GetSHCallConvention() =0;
pred@2504
   162
pred@2504
   163
		/**
pred@2504
   164
		* @brief Returns parameter info.
pred@2504
   165
		*
pred@2504
   166
		* @param num			Parameter number to get (starting from 0).
pred@2504
   167
		* @return				A PassInfo pointer.
pred@2504
   168
		*/
pred@2504
   169
		virtual const SourceHook::PassInfo *GetSHParamInfo(unsigned int num) =0;
pred@2504
   170
pred@2504
   171
		/**
pred@2504
   172
		 * @brief Returns the offset of a given param.
pred@2504
   173
		 *
pred@2504
   174
		 * @param num			Parameter number to get (starting from 0).
pred@2504
   175
		 * @return				Parameter offset.
pred@2504
   176
		 */
pred@2504
   177
		virtual unsigned int GetParamOffset(unsigned int num) =0;
pred@2504
   178
pred@2504
   179
#endif
faluco@739
   180
	};
faluco@739
   181
pred@2504
   182
#if defined HOOKING_ENABLED
pred@2504
   183
pred@2504
   184
	/**
pred@2504
   185
	 * @brief Delegate object that intermediates between SourceHook and the callback function.
pred@2504
   186
	 */
pred@2504
   187
	class ISMDelegate : public SourceHook::ISHDelegate
pred@2504
   188
	{
pred@2504
   189
	private:
pred@2504
   190
		/**
pred@2504
   191
		 * @brief Internally used callback function - Do not call!
pred@2504
   192
		 */
pred@2504
   193
		virtual void Call() =0;        /**< Do not call */
pred@2504
   194
	public:
pred@2504
   195
		/**
pred@2504
   196
		 * @brief Retrieves the User data buffer.
pred@2504
   197
		 *
pred@2504
   198
		 * @return					User data pointer.
pred@2504
   199
		 */
pred@2504
   200
		virtual void *GetUserData() =0;
pred@2504
   201
	};
pred@2504
   202
pred@2504
   203
	/**
pred@2504
   204
	 * @brief Wrapper around a virtual hook.
pred@2504
   205
	 */
pred@2504
   206
	class IHookWrapper
pred@2504
   207
	{
pred@2504
   208
	public:
pred@2504
   209
		/**
pred@2504
   210
		 * @brief Creates a hook delegate to pass to SourceHook.
pred@2504
   211
		 *
pred@2504
   212
		 * @param data				User data pointer.
pred@2504
   213
		 * @return					A new ISMDelegate for the hook.
pred@2504
   214
		 */
pred@2504
   215
		virtual ISMDelegate *CreateDelegate(void *data) =0;
pred@2504
   216
pred@2504
   217
		/**
pred@2504
   218
		 * @brief Gets the number of params in the hooked function.
pred@2504
   219
		 *
pred@2504
   220
		 * @return					Number of params.
pred@2504
   221
		 */
pred@2504
   222
		virtual unsigned int GetParamCount() =0;
pred@2504
   223
pred@2504
   224
		/**
pred@2504
   225
		 * @brief Returns the offset of a given param.
pred@2504
   226
		 *
pred@2504
   227
		 * @param argnum			Parameter number from 0 to GetParamCount-1.
pred@2504
   228
		 * @param size				Optional buffer to store the size of the param.
pred@2504
   229
		 * @return					Parameter offset or -1 on error.
pred@2504
   230
		 */
pred@2504
   231
		virtual unsigned int GetParamOffset(unsigned int argnum, unsigned int *size) =0;
pred@2504
   232
pred@2504
   233
		/**
pred@2504
   234
		 * @brief Initiates a recall on the function.
pred@2504
   235
		 *
pred@2504
   236
		 * @param params			Parameter buffer.
pred@2504
   237
		 * @param retval			Buffer to store the return value in.
pred@2504
   238
		 */
pred@2504
   239
		virtual void PerformRecall(void *params, void *retval) =0;
pred@2504
   240
pred@2504
   241
		/**
pred@2504
   242
		 * @brief Destroys this HookWrapper.
pred@2504
   243
		 */
pred@2504
   244
		virtual void Destroy() =0;
pred@2504
   245
	};
pred@2504
   246
pred@2504
   247
#endif
pred@2504
   248
faluco@739
   249
	/**
faluco@739
   250
	 * @brief Binary tools interface.
faluco@739
   251
	 */
faluco@739
   252
	class IBinTools : public SMInterface
faluco@739
   253
	{
faluco@739
   254
	public:
faluco@739
   255
		virtual const char *GetInterfaceName()
faluco@739
   256
		{
faluco@739
   257
			return SMINTERFACE_BINTOOLS_NAME;
faluco@739
   258
		}
faluco@739
   259
		virtual unsigned int GetInterfaceVersion()
faluco@739
   260
		{
faluco@739
   261
			return SMINTERFACE_BINTOOLS_VERSION;
faluco@739
   262
		}
faluco@739
   263
	public:
faluco@739
   264
		/**
faluco@739
   265
		 * @brief Creates a call decoder.
faluco@739
   266
		 *
faluco@739
   267
		 * Note: CallConv_ThisCall requires an implicit first parameter
faluco@739
   268
		 * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *).  However,
faluco@739
   269
		 * this should only be given to the Execute() function, and never
faluco@739
   270
		 * listed in the paramInfo array.
faluco@739
   271
		 *
faluco@739
   272
		 * @param address			Address to use as a call.
faluco@739
   273
		 * @param cv				Calling convention.
faluco@739
   274
		 * @param retInfo			Return type information, or NULL for void.
faluco@739
   275
		 * @param paramInfo			Array of parameters.
faluco@739
   276
		 * @param numParams			Number of parameters in the array.
faluco@739
   277
		 * @return					A new ICallWrapper function.
faluco@739
   278
		 */
faluco@739
   279
		virtual ICallWrapper *CreateCall(void *address,
faluco@739
   280
											CallConvention cv,
faluco@739
   281
											const PassInfo *retInfo,
faluco@739
   282
											const PassInfo paramInfo[],
faluco@739
   283
											unsigned int numParams) =0;
faluco@739
   284
faluco@739
   285
		/**
faluco@739
   286
		 * @brief Creates a vtable call decoder.
faluco@739
   287
		 *
faluco@739
   288
		 * Note: CallConv_ThisCall requires an implicit first parameter
faluco@739
   289
		 * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *).  However,
faluco@739
   290
		 * this should only be given to the Execute() function, and never
faluco@739
   291
		 * listed in the paramInfo array.
faluco@739
   292
		 *
faluco@739
   293
		 * @param vtblIdx			Index into the virtual table.
faluco@739
   294
		 * @param vtblOffs			Offset of the virtual table.
faluco@739
   295
		 * @param thisOffs			Offset of the this pointer of the virtual table.
faluco@739
   296
		 * @param retInfo			Return type information, or NULL for void.
faluco@739
   297
		 * @param paramInfo			Array of parameters.
faluco@739
   298
		 * @param numParams			Number of parameters in the array.
faluco@739
   299
		 * @return					A new ICallWrapper function.
faluco@739
   300
		 */
faluco@739
   301
		virtual ICallWrapper *CreateVCall(unsigned int vtblIdx,
faluco@739
   302
											unsigned int vtblOffs,
faluco@739
   303
											unsigned int thisOffs,
faluco@739
   304
											const PassInfo *retInfo,
faluco@739
   305
											const PassInfo paramInfo[],
faluco@739
   306
											unsigned int numParams) =0;
faluco@739
   307
	};
pred@2504
   308
pred@2504
   309
#if defined HOOKING_ENABLED
pred@2504
   310
pred@2504
   311
	/**
pred@2504
   312
	 * @brief Binary tools interface.
pred@2504
   313
	 */
pred@2504
   314
	class IBinTools2 : public SMInterface
pred@2504
   315
	{
pred@2504
   316
	public:
pred@2504
   317
		virtual const char *GetInterfaceName()
pred@2504
   318
		{
pred@2504
   319
			return SMINTERFACE_BINTOOLS2_NAME;
pred@2504
   320
		}
pred@2504
   321
		virtual unsigned int GetInterfaceVersion()
pred@2504
   322
		{
pred@2504
   323
			return SMINTERFACE_BINTOOLS2_VERSION;
pred@2504
   324
		}
pred@2504
   325
	public:
pred@2504
   326
pred@2504
   327
		/**
pred@2504
   328
		 * @brief Creates a call decoder.
pred@2504
   329
		 *
pred@2504
   330
		 * Note: CallConv_ThisCall requires an implicit first parameter
pred@2504
   331
		 * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *).  However,
pred@2504
   332
		 * this should only be given to the Execute() function, and never
pred@2504
   333
		 * listed in the paramInfo array.
pred@2504
   334
		 *
pred@2504
   335
		 * @param address			Address to use as a call.
pred@2504
   336
		 * @param protoInfo			Parameter type information.
pred@2504
   337
		 * @return					A new ICallWrapper function.
pred@2504
   338
		 */
pred@2504
   339
		virtual ICallWrapper *CreateCall(void *address,
pred@2504
   340
			const SourceHook::ProtoInfo *protoInfo) =0;
pred@2504
   341
pred@2504
   342
		/**
pred@2504
   343
		 * @brief Creates a vtable call decoder.
pred@2504
   344
		 *
pred@2504
   345
		 * Note: CallConv_ThisCall requires an implicit first parameter
pred@2504
   346
		 * of PassType_Basic / PASSFLAG_BYVAL / sizeof(void *).  However,
pred@2504
   347
		 * this should only be given to the Execute() function, and never
pred@2504
   348
		 * listed in the paramInfo array.
pred@2504
   349
		 *
pred@2504
   350
		 * @param protoInfo			Parameter type information.
pred@2504
   351
		 * @param info				Function offset information.
pred@2504
   352
		 * @return					A new ICallWrapper function.
pred@2504
   353
		 */
pred@2504
   354
		virtual ICallWrapper *CreateVirtualCall(const SourceHook::ProtoInfo *protoInfo,
pred@2504
   355
			const SourceHook::MemFuncInfo *info) =0;
pred@2504
   356
		
pred@2504
   357
pred@2504
   358
		/**
pred@2504
   359
		 * @brief Callback function pointer for Virtual Hooks.
pred@2504
   360
		 *
pred@2504
   361
		 * @param wrapper			Call wrapper for this hook.
pred@2504
   362
		 * @param deleg				Delegate for this call.
pred@2504
   363
		 * @param params				Array of parameters.
pred@2504
   364
		 * @param ret				Storage buffer for the return value.
pred@2504
   365
		 */
pred@2504
   366
		typedef void (*VIRTUAL_HOOK_PROTO)(IHookWrapper *wrapper, ISMDelegate *deleg, void *params, void *ret);
pred@2504
   367
pred@2504
   368
		/**
pred@2504
   369
		 * @brief Creates a hook on a virtual function.
pred@2504
   370
		 *
pred@2504
   371
		 * @param pSH				Global SourceHook pointer.
pred@2504
   372
		 * @param protoInfo			Parameter type information.
pred@2504
   373
		 * @param info				Function offset information.
pred@2504
   374
		 * @param f					Callback function pointer.
pred@2504
   375
		 */
pred@2504
   376
		virtual IHookWrapper *CreateVirtualHook(SourceHook::ISourceHook *pSH, 
pred@2504
   377
			const SourceHook::ProtoInfo *protoInfo, 
pred@2504
   378
			const SourceHook::MemFuncInfo *info, 
pred@2504
   379
			VIRTUAL_HOOK_PROTO f) =0;
pred@2504
   380
	};
pred@2504
   381
pred@2504
   382
#endif
pred@2504
   383
faluco@739
   384
}
faluco@739
   385
faluco@739
   386
#endif //_INCLUDE_SMEXT_BINTOOLS_H_