Advertisement
Guest User

Untitled

a guest
Mar 4th, 2015
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.66 KB | None | 0 0
  1. /* ======== SourceHook ========
  2. * Copyright (C) 2004-2010 Metamod:Source Development Team
  3. * No warranties of any kind
  4. *
  5. * License: zlib/libpng
  6. *
  7. * Author(s): Pavol "PM OnoTo" Marko
  8. * ============================
  9. */
  10.  
  11. #ifndef __SOURCEHOOK_HOOKMANGEN_H__
  12. #define __SOURCEHOOK_HOOKMANGEN_H__
  13.  
  14. #include "sh_pagealloc.h"
  15.  
  16. namespace SourceHook
  17. {
  18.     namespace Impl
  19.     {
  20.  
  21.         // Code gen stuff
  22. #if SH_COMP == SH_COMP_GCC
  23. #include <stdint.h>
  24.         typedef int8_t jit_int8_t;
  25.         typedef uint8_t jit_uint8_t;
  26.         typedef int32_t jit_int32_t;
  27.         typedef uint32_t jit_uint32_t;
  28.         typedef int64_t jit_int64_t;
  29.         typedef uint64_t jit_uint64_t;
  30. #elif SH_COMP == SH_COMP_MSVC
  31.         typedef __int8 jit_int8_t;
  32.         typedef unsigned __int8 jit_uint8_t;
  33.         typedef __int32 jit_int32_t;
  34.         typedef unsigned __int32 jit_uint32_t;
  35.         typedef __int64 jit_int64_t;
  36.         typedef unsigned __int64 jit_uint64_t;
  37. #endif
  38.         typedef unsigned int jitoffs_t;
  39.         typedef signed int jitrel_t;
  40.  
  41.  
  42.         class GenBuffer
  43.         {
  44.             static CPageAlloc ms_Allocator;
  45.  
  46.             unsigned char *m_pData;
  47.             jitoffs_t m_Size;
  48.             jitoffs_t m_AllocatedSize;
  49.  
  50.         public:
  51.             GenBuffer() : m_pData(NULL), m_Size(0), m_AllocatedSize(0)
  52.             {
  53.             }
  54.             ~GenBuffer()
  55.             {
  56.                 clear();
  57.             }
  58.             jitoffs_t GetSize()
  59.             {
  60.                 return m_Size;
  61.             }
  62.             unsigned char *GetData()
  63.             {
  64.                 return m_pData;
  65.             }
  66.  
  67.             jitoffs_t alloc(jitoffs_t size)
  68.             {
  69.                 jitoffs_t start = m_Size;
  70.                 jitoffs_t newSize = m_Size + size;
  71.                 if (newSize > m_AllocatedSize)
  72.                 {
  73.                     m_AllocatedSize = newSize > m_AllocatedSize*2 ? newSize : m_AllocatedSize*2;
  74.                     if (m_AllocatedSize < 64)
  75.                         m_AllocatedSize = 64;
  76.                    
  77.                     unsigned char *newBuf;
  78.                     newBuf = reinterpret_cast<unsigned char*>(ms_Allocator.Alloc(m_AllocatedSize));
  79.                     ms_Allocator.SetRW(newBuf);
  80.                     if (!newBuf)
  81.                     {
  82.                         SH_ASSERT(0, ("bad_alloc: couldn't allocate 0x%08X bytes of memory\n", m_AllocatedSize));
  83.                         return 0;
  84.                     }
  85.                     memset((void*)newBuf, 0xCC, m_AllocatedSize);           // :TODO: remove this !
  86.                     memcpy((void*)newBuf, (const void*)m_pData, m_Size);
  87.                     if (m_pData)
  88.                     {
  89.                         ms_Allocator.SetRE(reinterpret_cast<void*>(m_pData));
  90.                         ms_Allocator.SetRW(newBuf);
  91.                         ms_Allocator.Free(reinterpret_cast<void*>(m_pData));
  92.                     }
  93.                     m_pData = newBuf;
  94.                 }
  95.                 m_Size = newSize;
  96.                 return start;
  97.             }
  98.  
  99.             template <class PT> void push(PT what)
  100.             {
  101.                 push((const unsigned char *)&what, sizeof(PT));
  102.             }
  103.  
  104.             void push(const unsigned char *data, jitoffs_t size)
  105.             {
  106.                 jitoffs_t newSize = m_Size + size;
  107.                 if (newSize > m_AllocatedSize)
  108.                 {
  109.                     m_AllocatedSize = newSize > m_AllocatedSize*2 ? newSize : m_AllocatedSize*2;
  110.                     if (m_AllocatedSize < 64)
  111.                         m_AllocatedSize = 64;
  112.  
  113.                     unsigned char *newBuf;
  114.                     newBuf = reinterpret_cast<unsigned char*>(ms_Allocator.Alloc(m_AllocatedSize));
  115.                     ms_Allocator.SetRW(newBuf);
  116.                     if (!newBuf)
  117.                     {
  118.                         SH_ASSERT(0, ("bad_alloc: couldn't allocate 0x%08X bytes of memory\n", m_AllocatedSize));
  119.                         return;
  120.                     }
  121.                     memset((void*)newBuf, 0xCC, m_AllocatedSize);           // :TODO: remove this !
  122.                     memcpy((void*)newBuf, (const void*)m_pData, m_Size);
  123.                     if (m_pData)
  124.                     {
  125.                         ms_Allocator.SetRE(reinterpret_cast<void*>(m_pData));
  126.                         ms_Allocator.SetRW(newBuf);
  127.                         ms_Allocator.Free(reinterpret_cast<void*>(m_pData));
  128.                     }
  129.                     m_pData = newBuf;
  130.                 }
  131.                 memcpy((void*)(m_pData + m_Size), (const void*)data, size);
  132.                 m_Size = newSize;
  133.             }
  134.  
  135.             template <class PT> void rewrite(jitoffs_t offset, PT what)
  136.             {
  137.                 rewrite(offset, (const unsigned char *)&what, sizeof(PT));
  138.             }
  139.  
  140.             void rewrite(jitoffs_t offset, const unsigned char *data, jitoffs_t size)
  141.             {
  142.                 SH_ASSERT(offset + size <= m_AllocatedSize, ("rewrite too far"));
  143.  
  144.                 memcpy((void*)(m_pData + offset), (const void*)data, size);
  145.             }
  146.  
  147.             void clear()
  148.             {
  149.                 if (m_pData)
  150.                     ms_Allocator.Free(reinterpret_cast<void*>(m_pData));
  151.                 m_pData = NULL;
  152.                 m_Size = 0;
  153.                 m_AllocatedSize = 0;
  154.             }
  155.  
  156.             void SetRE()
  157.             {
  158.                 ms_Allocator.SetRE(reinterpret_cast<void*>(m_pData));
  159.             }
  160.  
  161.             operator void *()
  162.             {
  163.                 return reinterpret_cast<void*>(GetData());
  164.             }
  165.  
  166.             void write_ubyte(jit_uint8_t x)         { push(x); }
  167.             void write_byte(jit_uint8_t x)          { push(x); }
  168.            
  169.             void write_ushort(unsigned short x)     { push(x); }
  170.             void write_short(signed short x)        { push(x); }
  171.  
  172.             void write_uint32(jit_uint32_t x)       { push(x); }
  173.             void write_int32(jit_uint32_t x)        { push(x); }
  174.  
  175.             jitoffs_t get_outputpos()
  176.             {
  177.                 return m_Size;
  178.             }
  179.  
  180.             void start_count(jitoffs_t &offs)
  181.             {
  182.                 offs = get_outputpos();
  183.             }
  184.             void end_count(jitoffs_t &offs)
  185.             {
  186.                 offs = get_outputpos() - offs;
  187.             }
  188.         };
  189.  
  190.         class GenContext
  191.         {
  192.             const static int SIZE_MWORD = 4;
  193.             const static int SIZE_PTR = sizeof(void*);
  194.             const static int PassFlag_ForcedByRef = (1<<30);   // ByVal in source, but actually passed by reference (GCC) -> private pass, destruct
  195.  
  196.             HookManagerPubFunc m_GeneratedPubFunc;
  197.  
  198.             CProto m_OrigProto;         // original passed-in prototype
  199.             CProto m_Proto;
  200.             int m_VtblOffs;
  201.             int m_VtblIdx;
  202.             ISourceHook *m_SHPtr;
  203.  
  204.             GenBuffer m_HookFunc;
  205.             GenBuffer m_PubFunc;
  206.  
  207.             ProtoInfo *m_BuiltPI;
  208.             PassInfo *m_BuiltPI_Params;
  209.             PassInfo::V2Info *m_BuiltPI_Params2;
  210.  
  211.             // For hookfunc
  212.             void **m_pHI;
  213.             void **m_HookfuncVfnptr;
  214.  
  215.             // Level 3 - Helpers
  216.             int m_RegCounter;
  217.             jit_int8_t NextRegEBX_ECX_EDX();
  218.  
  219.             int m_BytesPushedAfterInitialAlignment;
  220.             enum AlignStackFlags
  221.             {
  222.                 AlignStack_GCC_ThisOnStack = 1,
  223.                 AlignStack_MSVC_ThisOnStack = 2,
  224.                 AlignStack_MemRet = 4
  225.             };
  226.             jit_int32_t AlignStackBeforeCall(int paramsize, int flags);
  227.             void AlignStackAfterCall(jit_int32_t numofbytes);
  228.             void CheckAlignmentBeforeCall();
  229.  
  230.             // size info
  231.             jit_int32_t GetRealSize(const IntPassInfo &info);           // checks for reference
  232.             jit_int32_t AlignSize(jit_int32_t x, jit_int32_t boundary); // align a size
  233.             jit_int32_t GetParamStackSize(const IntPassInfo &info);     // get the size of a param in the param stack
  234.             short GetParamsTotalStackSize();        // sum(GetParamStackSize(param[i]), 0 <= i < numOfParams)
  235.  
  236.             // Helpers
  237.             void BitwiseCopy_Setup();
  238.             void BitwiseCopy_Do(size_t size);
  239.  
  240.  
  241.             // HookFunc frame
  242.             jit_int32_t m_HookFunc_FrameOffset;
  243.             jit_int32_t m_HookFunc_FrameVarsSize;
  244.  
  245.             void ResetFrame(jit_int32_t startOffset);
  246.             jit_int32_t AddVarToFrame(jit_int32_t size);
  247.             jit_int32_t ComputeVarsSize();
  248.  
  249.             // Param push
  250.             short GetForcedByRefParamsSize();       // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < numOfParams)
  251.             short GetForcedByRefParamOffset(int p);     // sum(param[i] is forcedbyref ? GetStackSize(param[i]) : 0, 0 <= i < p)
  252.             jit_int32_t PushParams(jit_int32_t param_base_offset, jit_int32_t save_ret_to,
  253.                 jit_int32_t v_place_for_memret, jit_int32_t v_place_fbrr_base);     // save_ret_to and v_place_for_memret only used for memory returns
  254.             jit_int32_t PushRef(jit_int32_t param_offset, const IntPassInfo &pi);
  255.             jit_int32_t PushBasic(jit_int32_t param_offset, const IntPassInfo &pi);
  256.             jit_int32_t PushFloat(jit_int32_t param_offset, const IntPassInfo &pi);
  257.             jit_int32_t PushObject(jit_int32_t param_offset, const IntPassInfo &pi, jit_int32_t v_place_fbrr);
  258.             jit_int32_t PushMemRetPtr(jit_int32_t save_ret_to, jit_int32_t v_place_for_memret);
  259.             void DestroyParams(jit_int32_t fbrr_base);
  260.  
  261.             // Ret val processing
  262.             void SaveRetVal(jit_int32_t v_where, jit_int32_t v_place_for_memret);
  263.             void ProcessPluginRetVal(jit_int32_t v_cur_res, jit_int32_t v_pContext, jit_int32_t v_plugin_ret);
  264.  
  265.             void PrepareReturn(jit_int32_t v_status, jit_int32_t v_pContext, jit_int32_t v_retptr);
  266.             void DoReturn(jit_int32_t v_retptr, jit_int32_t v_memret_outaddr);
  267.  
  268.             bool MemRetWithTempObj();           // do we do a memory return AND need a temporary place for it?
  269.  
  270.             // Call hooks
  271.             void GenerateCallHooks(int v_status, int v_prev_res, int v_cur_res, int v_iter,
  272.                 int v_pContext, int base_param_offset, int v_plugin_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base, jit_int32_t v_va_buf);
  273.  
  274.             // Call orig
  275.             void GenerateCallOrig(int v_status, int v_pContext, int param_base_offs, int v_this,
  276.                 int v_vfnptr_origentry, int v_orig_ret, int v_override_ret, int v_place_for_memret, jit_int32_t v_place_fbrr_base, jit_int32_t v_va_buf);
  277.  
  278.             // Hook loop
  279.             void CallSetupHookLoop(int v_orig_ret, int v_override_ret,
  280.                 int v_cur_res, int v_prev_res, int v_status, int v_vnfptr_origentry,
  281.                 int v_this, int v_pContext);
  282.  
  283.             void CallEndContext(int v_pContext);
  284.  
  285.             // Level 2 -> called from Generate()
  286.             void AutoDetectRetType();
  287.             void AutoDetectParamFlags();
  288.             bool PassInfoSupported(const IntPassInfo &pi, bool is_ret);
  289.             void Clear();
  290.             void BuildProtoInfo();
  291.             void *GenerateHookFunc();
  292.             void *GeneratePubFunc();
  293.            
  294.             HookManagerPubFunc Generate();
  295.         public:
  296.             // Level 1 -> Public interface
  297.             GenContext(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx, ISourceHook *pSHPtr);
  298.             ~GenContext();
  299.  
  300.             bool Equal(const CProto &proto, int vtbl_offs, int vtbl_idx);
  301.             bool Equal(HookManagerPubFunc other);
  302.  
  303.             HookManagerPubFunc GetPubFunc();
  304.         };
  305.  
  306.         class CHookManagerAutoGen : public IHookManagerAutoGen
  307.         {
  308.             struct StoredContext
  309.             {
  310.                 int m_RefCnt;
  311.                 GenContext *m_GenContext;
  312.             };
  313.             List<StoredContext> m_Contexts;
  314.             ISourceHook *m_pSHPtr;
  315.  
  316.         public:
  317.             CHookManagerAutoGen(ISourceHook *pSHPtr);
  318.             ~CHookManagerAutoGen();
  319.  
  320.             int GetIfaceVersion();
  321.             int GetImplVersion();
  322.  
  323.             HookManagerPubFunc MakeHookMan(const ProtoInfo *proto, int vtbl_offs, int vtbl_idx);
  324.             void ReleaseHookMan(HookManagerPubFunc pubFunc);
  325.         };
  326.  
  327.     }
  328. }
  329.  
  330.  
  331. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement