extensions/bintools/CallWrapper.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Tue Mar 19 11:19:38 2013 -0400 (2013-03-19)
changeset 3855 d8ba5eddf543
parent 3261 e4359292e59a
permissions -rw-r--r--
Updated protobuf and usermessage support for Dota 2 (bug 5656, r=asherkin).
     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 #include "extension.h"
    33 #include "CallWrapper.h"
    34 #include "CallMaker.h"
    35 
    36 CallWrapper::CallWrapper(const SourceHook::ProtoInfo *protoInfo)
    37 {
    38 	m_AddrCodeBase = NULL;
    39 	m_AddrCallee = NULL;
    40 
    41 	unsigned int argnum = protoInfo->numOfParams;
    42 
    43 	m_Info = *protoInfo;
    44 	m_Info.paramsPassInfo = new SourceHook::PassInfo[argnum + 1];
    45 	memcpy((void *)m_Info.paramsPassInfo, protoInfo->paramsPassInfo, sizeof(SourceHook::PassInfo) * (argnum+1));
    46 
    47 	if (argnum)
    48 	{
    49 		m_Params = new PassEncode[argnum];
    50 		for (size_t i=0; i<argnum; i++)
    51 		{
    52 			GetSMPassInfo(&(m_Params[i].info), &(m_Info.paramsPassInfo[i+1]));
    53 		}
    54 	} else {
    55 		m_Params = NULL;
    56 	}
    57 
    58 	if (m_Info.retPassInfo.size != 0)
    59 	{
    60 		m_RetParam = new PassInfo;
    61 		GetSMPassInfo(m_RetParam, &(m_Info.retPassInfo));
    62 	} else {
    63 		m_RetParam = NULL;
    64 	}
    65 
    66 	/* Calculate virtual stack offsets for each parameter */
    67 	size_t offs = 0;
    68 
    69 	if (m_Info.convention == SourceHook::ProtoInfo::CallConv_ThisCall)
    70 	{
    71 		offs += sizeof(void *);
    72 	}
    73 	for (size_t i=0; i<argnum; i++)
    74 	{
    75 		m_Params[i].offset = offs;
    76 		offs += m_Params[i].info.size;
    77 	}
    78 }
    79 
    80 CallWrapper::~CallWrapper()
    81 {
    82 	delete [] m_Params;
    83 	delete m_RetParam;
    84 	delete [] m_Info.paramsPassInfo;
    85 }
    86 
    87 void CallWrapper::Destroy()
    88 {
    89 	if (m_AddrCodeBase != NULL)
    90 	{
    91 		g_SPEngine->FreePageMemory(m_AddrCodeBase);
    92 		m_AddrCodeBase = NULL;
    93 	}
    94 
    95 	delete this;
    96 }
    97 
    98 CallConvention CallWrapper::GetCallConvention()
    99 {
   100 	/* Need to convert to a SourceMod convention for bcompat */
   101 	return GetSMCallConvention((SourceHook::ProtoInfo::CallConvention)m_Info.convention);
   102 }
   103 
   104 const PassEncode *CallWrapper::GetParamInfo(unsigned int num)
   105 {
   106 	if (num + 1 > GetParamCount())
   107 	{
   108 		return NULL;
   109 	}
   110 
   111 	return &m_Params[num];
   112 }
   113 
   114 const PassInfo *CallWrapper::GetReturnInfo()
   115 {
   116 	return m_RetParam;
   117 }
   118 
   119 unsigned int CallWrapper::GetParamCount()
   120 {
   121 	return m_Info.numOfParams;
   122 }
   123 
   124 void CallWrapper::Execute(void *vParamStack, void *retBuffer)
   125 {
   126 	typedef void (*CALL_EXECUTE)(void *, void *);
   127 	CALL_EXECUTE fn = (CALL_EXECUTE)GetCodeBaseAddr();
   128 	fn(vParamStack, retBuffer);
   129 }
   130 
   131 void CallWrapper::SetMemFuncInfo(const SourceHook::MemFuncInfo *funcInfo)
   132 {
   133 	m_FuncInfo = *funcInfo;
   134 }
   135 
   136 SourceHook::MemFuncInfo *CallWrapper::GetMemFuncInfo()
   137 {
   138 	return &m_FuncInfo;
   139 }
   140 
   141 void CallWrapper::SetCalleeAddr(void *addr)
   142 {
   143 	m_AddrCallee = addr;
   144 }
   145 
   146 void CallWrapper::SetCodeBaseAddr(void *addr)
   147 {
   148 	m_AddrCodeBase = addr;
   149 }
   150 
   151 void *CallWrapper::GetCalleeAddr()
   152 {
   153 	return m_AddrCallee;
   154 }
   155 
   156 void *CallWrapper::GetCodeBaseAddr()
   157 {
   158 	return m_AddrCodeBase;
   159 }
   160 
   161 const SourceHook::PassInfo *CallWrapper::GetSHReturnInfo()
   162 {
   163 	return &(m_Info.retPassInfo);
   164 }
   165 
   166 SourceHook::ProtoInfo::CallConvention CallWrapper::GetSHCallConvention()
   167 {
   168 	return (SourceHook::ProtoInfo::CallConvention)m_Info.convention;
   169 }
   170 
   171 const SourceHook::PassInfo * CallWrapper::GetSHParamInfo(unsigned int num)
   172 {
   173 	if (num + 1 > GetParamCount())
   174 	{
   175 		return NULL;
   176 	}
   177 
   178 	return &(m_Info.paramsPassInfo[num+1]);
   179 }
   180 
   181 unsigned int CallWrapper::GetParamOffset(unsigned int num)
   182 {
   183 	assert(num < GetParamCount() && num >= 0);
   184 
   185 	return m_Params[num].offset;
   186 }