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