[add] mm injector,[add] latest schema dump
This commit is contained in:
+11
-1
@@ -1,10 +1,12 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36603.0 d17.14
|
||||
VisualStudioVersion = 17.14.36603.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Andromeda-CS2-Base", "Andromeda-CS2-Base\Andromeda-CS2-Base.vcxproj", "{0011461C-0E5F-401C-AC58-23719D1EF845}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Andromeda-Injector", "Andromeda-Injector\Andromeda-Injector.vcxproj", "{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@@ -21,6 +23,14 @@ Global
|
||||
{0011461C-0E5F-401C-AC58-23719D1EF845}.Release|x64.Build.0 = Release|x64
|
||||
{0011461C-0E5F-401C-AC58-23719D1EF845}.Release|x86.ActiveCfg = Release|Win32
|
||||
{0011461C-0E5F-401C-AC58-23719D1EF845}.Release|x86.Build.0 = Release|Win32
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Debug|x64.ActiveCfg = Release|x64
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Debug|x64.Build.0 = Release|x64
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Debug|x86.ActiveCfg = Release|x64
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Debug|x86.Build.0 = Release|x64
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Release|x64.ActiveCfg = Release|x64
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Release|x64.Build.0 = Release|x64
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Release|x86.ActiveCfg = Release|x64
|
||||
{CCCB11FE-9B54-44BF-8C77-29DBB3B83B74}.Release|x86.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#ifdef RELEASE_BUILD
|
||||
|
||||
#define ENABLE_CONSOLE_DEBUG 1
|
||||
#define ENABLE_MANUAL_MAP 0
|
||||
#define ENABLE_MANUAL_MAP 1
|
||||
#define ENABLE_CPP_EH_EXCEPTION 0
|
||||
|
||||
#define LOG_SDK 1
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
struct ManualMapParam_t
|
||||
{
|
||||
uint64_t ArgsSize = 0;
|
||||
DWORD64 DllLoaderCode = 0;
|
||||
char DllPath[MAX_PATH] = { 0 };
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{cccb11fe-9b54-44bf-8c77-29dbb3b83b74}</ProjectGuid>
|
||||
<RootNamespace>AndromedaInjector</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(MSBuildProjectDirectory)\Andromeda-Injector\Common\Include\;$(IncludePath)</IncludePath>
|
||||
<TargetName>Andromeda-CS2-Base</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<LanguageStandard_C>stdclatest</LanguageStandard_C>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Andromeda-Injector\CInjector.cpp" />
|
||||
<ClCompile Include="Andromeda-Injector\Main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Andromeda-Injector\CInjector.h" />
|
||||
<ClInclude Include="Andromeda-Injector\Common\Common.h" />
|
||||
<ClInclude Include="Andromeda-Injector\Common\Singleton.h" />
|
||||
<ClInclude Include="Andromeda-Injector\Main.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\.gitattributes" />
|
||||
<None Include="..\.gitignore" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Andromeda-Injector">
|
||||
<UniqueIdentifier>{9c07d84f-e39a-4705-8217-1dbb5ae8bdb2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Andromeda-Injector\Common">
|
||||
<UniqueIdentifier>{59b7c3b3-cff8-4adf-854f-183274448de6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Andromeda-Injector\CInjector.cpp">
|
||||
<Filter>Andromeda-Injector</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Andromeda-Injector\Main.cpp">
|
||||
<Filter>Andromeda-Injector</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Andromeda-Injector\CInjector.h">
|
||||
<Filter>Andromeda-Injector</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Andromeda-Injector\Main.h">
|
||||
<Filter>Andromeda-Injector</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Andromeda-Injector\Common\Common.h">
|
||||
<Filter>Andromeda-Injector\Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Andromeda-Injector\Common\Singleton.h">
|
||||
<Filter>Andromeda-Injector\Common</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\.gitattributes" />
|
||||
<None Include="..\.gitignore" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,188 @@
|
||||
#include "CInjector.h"
|
||||
|
||||
#include <BlackBone/Process/Process.h>
|
||||
|
||||
auto CInjector::Init() -> bool
|
||||
{
|
||||
GetModuleFileNameA( 0 , szDllFilePath , MAX_PATH );
|
||||
GetCurrentDirectoryA( MAX_PATH , szCurrentDir );
|
||||
|
||||
int len = lstrlenA( szDllFilePath );
|
||||
|
||||
szDllFilePath[len - 1] = 'l';
|
||||
szDllFilePath[len - 2] = 'l';
|
||||
szDllFilePath[len - 3] = 'd';
|
||||
|
||||
if ( GetPrivileges() && FileExist( szDllFilePath ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto CInjector::GetPrivileges() -> bool
|
||||
{
|
||||
HANDLE hToken = NULL;
|
||||
LUID luid;
|
||||
TOKEN_PRIVILEGES tp;
|
||||
|
||||
OpenProcessToken( GetCurrentProcess() , TOKEN_ALL_ACCESS , &hToken );
|
||||
|
||||
LookupPrivilegeValue( NULL , SE_DEBUG_NAME , &luid );
|
||||
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if ( AdjustTokenPrivileges( hToken , FALSE , &tp , sizeof( TOKEN_PRIVILEGES ) , NULL , NULL ) )
|
||||
{
|
||||
CloseHandle( hToken );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto CInjector::GetProcessIdByName( const char* szProcName )->DWORD
|
||||
{
|
||||
HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 );
|
||||
DWORD dwGetProcessID = 0;
|
||||
|
||||
if ( hSnapshot != INVALID_HANDLE_VALUE )
|
||||
{
|
||||
PROCESSENTRY32 ProcEntry32 = { 0 };
|
||||
ProcEntry32.dwSize = sizeof( MODULEENTRY32 );
|
||||
|
||||
if ( Process32First( hSnapshot , &ProcEntry32 ) )
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( _stricmp( ProcEntry32.szExeFile , szProcName ) == 0 )
|
||||
{
|
||||
dwGetProcessID = (DWORD)ProcEntry32.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
} while ( Process32Next( hSnapshot , &ProcEntry32 ) );
|
||||
}
|
||||
|
||||
CloseHandle( hSnapshot );
|
||||
}
|
||||
|
||||
return dwGetProcessID;
|
||||
}
|
||||
|
||||
auto CInjector::InjectManualMap( const char* szProcessName ) -> bool
|
||||
{
|
||||
bool Result = false;
|
||||
DWORD PID = 0;
|
||||
|
||||
DEV_LOG( "[info] Wait for start %s\n" , szProcessName );
|
||||
|
||||
while ( !PID )
|
||||
{
|
||||
PID = GetProcessIdByName( szProcessName );
|
||||
Sleep( 100 );
|
||||
}
|
||||
|
||||
m_hProcess = OpenProcess( PROCESS_ALL_ACCESS , FALSE , PID );
|
||||
|
||||
if ( !m_hProcess )
|
||||
{
|
||||
DEV_LOG( "[-] inject code: #1\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read Dll File
|
||||
{
|
||||
auto hFile = CreateFileA( szDllFilePath , GENERIC_READ , 0 , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL );
|
||||
|
||||
if ( !hFile )
|
||||
{
|
||||
DEV_LOG( "[-] inject code: #2\n" );
|
||||
CloseHandle( m_hProcess );
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dwLength = GetFileSize( hFile , NULL );
|
||||
|
||||
if ( dwLength == INVALID_FILE_SIZE || dwLength == 0 )
|
||||
{
|
||||
DEV_LOG( "[-] inject code: #3\n" );
|
||||
|
||||
CloseHandle( hFile );
|
||||
CloseHandle( m_hProcess );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pDllFile = (PBYTE)HeapAlloc( GetProcessHeap() , 0 , dwLength );
|
||||
|
||||
if ( !m_pDllFile )
|
||||
{
|
||||
DEV_LOG( "[-] inject code: #4\n" );
|
||||
|
||||
CloseHandle( hFile );
|
||||
CloseHandle( m_hProcess );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ReadFile( hFile , m_pDllFile , dwLength , &m_DllFileSize , NULL ) == FALSE )
|
||||
{
|
||||
DEV_LOG( "[-] inject code: #5\n" );
|
||||
|
||||
CloseHandle( hFile );
|
||||
CloseHandle( m_hProcess );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( dwLength != m_DllFileSize )
|
||||
{
|
||||
DEV_LOG( "[-] inject code: #6\n" );
|
||||
|
||||
CloseHandle( hFile );
|
||||
CloseHandle( m_hProcess );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CloseHandle( hFile );
|
||||
}
|
||||
|
||||
DllLoaderData_t LoaderData = { 0 };
|
||||
|
||||
// Loader Data
|
||||
memcpy( LoaderData.DllPath , szCurrentDir , MAX_PATH );
|
||||
|
||||
// Inject To Process
|
||||
{
|
||||
blackbone::Process CS2Process;
|
||||
CS2Process.Attach( m_hProcess );
|
||||
|
||||
blackbone::CustomArgs_t Args;
|
||||
|
||||
Args.push_back( &LoaderData , sizeof( DllLoaderData_t ) );
|
||||
|
||||
auto pImage = CS2Process.mmap().MapImage( m_DllFileSize , m_pDllFile , false , blackbone::WipeHeader , nullptr , nullptr , &Args );
|
||||
|
||||
if ( pImage )
|
||||
Result = true;
|
||||
else
|
||||
DEV_LOG( "[-] inject: %ws\n" , blackbone::Utils::GetErrorDescription( pImage.status ).c_str() );
|
||||
}
|
||||
|
||||
// Free And Close
|
||||
{
|
||||
if ( m_pDllFile )
|
||||
HeapFree( GetProcessHeap() , 0 , m_pDllFile );
|
||||
|
||||
CloseHandle( m_hProcess );
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
auto GetInjector() -> CInjector*
|
||||
{
|
||||
return CInjector::Instance();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "Main.h"
|
||||
|
||||
struct DllLoaderData_t
|
||||
{
|
||||
char DllPath[MAX_PATH] = { 0 };
|
||||
};
|
||||
|
||||
class CInjector : Singleton<CInjector>
|
||||
{
|
||||
public:
|
||||
auto Init() -> bool;
|
||||
|
||||
public:
|
||||
auto InjectManualMap( const char* szProcessName ) -> bool;
|
||||
|
||||
private:
|
||||
auto GetPrivileges() -> bool;
|
||||
auto GetProcessIdByName( const char* szName ) -> DWORD;
|
||||
|
||||
private:
|
||||
bool __forceinline FileExist( const char* szFileName )
|
||||
{
|
||||
return GetFileAttributesA( szFileName ) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
public:
|
||||
char szCurrentDir[MAX_PATH] = { 0 };
|
||||
char szDllFilePath[MAX_PATH] = { 0 };
|
||||
|
||||
private:
|
||||
HANDLE m_hProcess;
|
||||
PBYTE m_pDllFile = nullptr;
|
||||
DWORD m_DllFileSize = 0;
|
||||
|
||||
private:
|
||||
friend auto GetInjector() -> CInjector*;
|
||||
};
|
||||
|
||||
auto GetInjector() -> CInjector*;
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <TlHelp32.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
#include "Singleton.h"
|
||||
|
||||
#pragma warning( disable : 26812 )
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
#if !defined(_ASMJIT_BUILD_H)
|
||||
#include "build.h"
|
||||
#endif // !_ASMJIT_BUILD_H
|
||||
|
||||
// ============================================================================
|
||||
// [MSVC]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Disable some warnings we know about
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
# pragma warning(disable: 4201) // nameless struct/union
|
||||
# pragma warning(disable: 4244) // '+=' : conversion from 'int' to 'x', possible
|
||||
// loss of data
|
||||
# pragma warning(disable: 4251) // struct needs to have dll-interface to be used
|
||||
// by clients of struct ...
|
||||
# pragma warning(disable: 4275) // non dll-interface struct ... used as base for
|
||||
// dll-interface struct
|
||||
# pragma warning(disable: 4355) // this used in base member initializer list
|
||||
# pragma warning(disable: 4480) // specifying underlying type for enum
|
||||
# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
|
||||
|
||||
// Rename symbols.
|
||||
# if !defined(vsnprintf)
|
||||
# define ASMJIT_DEFINED_VSNPRINTF
|
||||
# define vsnprintf _vsnprintf
|
||||
# endif // !vsnprintf
|
||||
# if !defined(snprintf)
|
||||
# define ASMJIT_DEFINED_SNPRINTF
|
||||
# define snprintf _snprintf
|
||||
# endif // !snprintf
|
||||
#endif // _MSC_VER
|
||||
|
||||
// ============================================================================
|
||||
// [GNUC]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
# if __GNUC__ >= 4 && !defined(__MINGW32__)
|
||||
# pragma GCC visibility push(hidden)
|
||||
# endif // __GNUC__ >= 4
|
||||
#endif // __GNUC__
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// ============================================================================
|
||||
// [MSVC]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Pop disabled warnings by ApiBegin.h
|
||||
# pragma warning(pop)
|
||||
// Rename symbols back.
|
||||
# if defined(ASMJIT_DEFINED_VSNPRINTF)
|
||||
# undef ASMJIT_DEFINED_VSNPRINTF
|
||||
# undef vsnprintf
|
||||
# endif // ASMJIT_DEFINED_VSNPRINTF
|
||||
# if defined(ASMJIT_DEFINED_SNPRINTF)
|
||||
# undef ASMJIT_DEFINED_SNPRINTF
|
||||
# undef snprintf
|
||||
# endif // ASMJIT_DEFINED_SNPRINTF
|
||||
#endif // _MSC_VER
|
||||
|
||||
// ============================================================================
|
||||
// [GNUC]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
# if __GNUC__ >= 4 && !defined(__MINGW32__)
|
||||
# pragma GCC visibility pop
|
||||
# endif // __GNUC__ >= 4
|
||||
#endif // __GNUC__
|
||||
+379
@@ -0,0 +1,379 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_ASMJIT_H
|
||||
#define _ASMJIT_ASMJIT_H
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_mainpage]
|
||||
// ============================================================================
|
||||
|
||||
//! @mainpage
|
||||
//!
|
||||
//! AsmJit - Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//!
|
||||
//! AsmJit is a complete JIT and remote assembler for C++ language. It can
|
||||
//! generate native code for x86 and x64 architectures having support for
|
||||
//! a full instruction set, from legacy MMX to the newest AVX2. It has a
|
||||
//! type-safe API that allows C++ compiler to do a semantic checks at
|
||||
//! compile-time even before the assembled code is generated or run.
|
||||
//!
|
||||
//! AsmJit is not a virtual machine (VM). It doesn't have functionality to
|
||||
//! implement VM out of the box; however, it can be be used as a JIT backend
|
||||
//! for your own VM. The usage of AsmJit is not limited at all; it's suitable
|
||||
//! for multimedia, VM backends or remote code generation.
|
||||
//!
|
||||
//! @section AsmJit_Concepts Code Generation Concepts
|
||||
//!
|
||||
//! AsmJit has two completely different code generation concepts. The difference
|
||||
//! is in how the code is generated. The first concept, also referred as the low
|
||||
//! level concept, is called 'Assembler' and it's the same as writing RAW
|
||||
//! assembly by using physical registers directly. In this case AsmJit does only
|
||||
//! instruction encoding, verification and relocation.
|
||||
//!
|
||||
//! The second concept, also referred as the high level concept, is called
|
||||
//! 'Compiler'. Compiler lets you use virtually unlimited number of registers
|
||||
//! (called variables) significantly simplifying the code generation process.
|
||||
//! Compiler allocates these virtual registers to physical registers after the
|
||||
//! code generation is done. This requires some extra effort - Compiler has to
|
||||
//! generate information for each node (instruction, function declaration,
|
||||
//! function call) in the code, perform a variable liveness analysis and
|
||||
//! translate the code having variables into code having only registers.
|
||||
//!
|
||||
//! In addition, Compiler understands functions and function calling conventions.
|
||||
//! It has been designed in a way that the code generated is always a function
|
||||
//! having prototype like in a programming language. By having a function
|
||||
//! prototype the Compiler is able to insert prolog and epilog to a function
|
||||
//! being generated and it is able to call a function inside a generated one.
|
||||
//!
|
||||
//! There is no conclusion on which concept is better. Assembler brings full
|
||||
//! control on how the code is generated, while Compiler makes the generation
|
||||
//! more portable.
|
||||
//!
|
||||
//! @section AsmJit_Main_CodeGeneration Code Generation
|
||||
//!
|
||||
//! - \ref asmjit_base_general "Assembler core" - Operands, intrinsics and low-level assembler.
|
||||
//! - \ref asmjit_compiler "Compiler" - High level code generation.
|
||||
//! - \ref asmjit_cpuinfo "Cpu Information" - Get information about host processor.
|
||||
//! - \ref asmjit_logging "Logging" - Logging and error handling.
|
||||
//! - \ref AsmJit_MemoryManagement "Memory Management" - Virtual memory management.
|
||||
//!
|
||||
//! @section AsmJit_Main_HomePage AsmJit Homepage
|
||||
//!
|
||||
//! - https://github.com/kobalicek/asmjit
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_base AsmJit
|
||||
//!
|
||||
//! \brief AsmJit.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_general]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_base_general AsmJit General API
|
||||
//! \ingroup asmjit_base
|
||||
//!
|
||||
//! \brief AsmJit general API.
|
||||
//!
|
||||
//! Contains all `asmjit` classes and helper functions that are architecture
|
||||
//! independent or abstract. Abstract classes are implemented by the backend,
|
||||
//! for example `Assembler` is implemented by `X86Assembler`.
|
||||
//!
|
||||
//! - See `Assembler` for low level code generation documentation.
|
||||
//! - See `Compiler` for high level code generation documentation.
|
||||
//! - See `Operand` for operand's overview.
|
||||
//!
|
||||
//! Logging and Error Handling
|
||||
//! --------------------------
|
||||
//!
|
||||
//! AsmJit contains robust interface that can be used to log the generated code
|
||||
//! and to handle possible errors. Base logging interface is defined in `Logger`
|
||||
//! class that is abstract and can be overridden. AsmJit contains two loggers
|
||||
//! that can be used out of the box - `FileLogger` that logs into a pure C
|
||||
//! `FILE*` stream and `StringLogger` that just concatenates all log messages
|
||||
//! by using a `StringBuilder` class.
|
||||
//!
|
||||
//! The following snippet shows how to setup a logger that logs to `stderr`:
|
||||
//!
|
||||
//! ~~~
|
||||
//! // `FileLogger` instance.
|
||||
//! FileLogger logger(stderr);
|
||||
//!
|
||||
//! // `Compiler` or any other `CodeGen` interface.
|
||||
//! host::Compiler c;
|
||||
//!
|
||||
//! // use `setLogger` to replace the `CodeGen` logger.
|
||||
//! c.setLogger(&logger);
|
||||
//! ~~~
|
||||
//!
|
||||
//! \sa \ref Logger, \ref FileLogger, \ref StringLogger.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_compiler]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_base_compiler AsmJit Compiler
|
||||
//! \ingroup asmjit_base
|
||||
//!
|
||||
//! \brief AsmJit code-tree used by Compiler.
|
||||
//!
|
||||
//! AsmJit intermediate code-tree is a double-linked list that is made of nodes
|
||||
//! that represent assembler instructions, directives, labels and high-level
|
||||
//! constructs compiler is using to represent functions and function calls. The
|
||||
//! node list can only be used together with \ref Compiler.
|
||||
//!
|
||||
//! TODO
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_base_util]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_base_util AsmJit Utilities
|
||||
//! \ingroup asmjit_base
|
||||
//!
|
||||
//! \brief AsmJit utility classes.
|
||||
//!
|
||||
//! AsmJit contains numerous utility classes that are needed by the library
|
||||
//! itself. The most useful ones have been made public and are now exported.
|
||||
//!
|
||||
//! POD Containers
|
||||
//! --------------
|
||||
//!
|
||||
//! POD containers are used by AsmJit to manage its own data structures. The
|
||||
//! following classes can be used by AsmJit consumers:
|
||||
//!
|
||||
//! - \ref PodVector - Simple growing array-like container for POD data.
|
||||
//! - \ref StringBuilder - Simple string builder that can append string
|
||||
//! and integers.
|
||||
//!
|
||||
//! Zone Memory Allocator
|
||||
//! ---------------------
|
||||
//!
|
||||
//! Zone memory allocator is an incremental memory allocator that can be used
|
||||
//! to allocate data of short life-time. It has much better performance
|
||||
//! characteristics than all other allocators, because the only thing it can do
|
||||
//! is to increment a pointer and return its previous address. See \ref Zone
|
||||
//! for more details.
|
||||
//!
|
||||
//! CPU Ticks
|
||||
//! ---------
|
||||
//!
|
||||
//! CPU Ticks is a simple helper that can be used to do basic benchmarks. See
|
||||
//! \ref CpuTicks class for more details.
|
||||
//!
|
||||
//! Integer Utilities
|
||||
//! -----------------
|
||||
//!
|
||||
//! Integer utilities are all implemented by a static class \ref IntUtil.
|
||||
//! There are utilities for bit manipulation and bit counting, utilities to get
|
||||
//! an integer minimum / maximum and various other helpers required to perform
|
||||
//! alignment checks and binary casting from float to integer and vica versa.
|
||||
//!
|
||||
//! Vector Utilities
|
||||
//! ----------------
|
||||
//!
|
||||
//! SIMD code generation often requires to embed constants after each function
|
||||
//! or a block of functions generated. AsmJit contains classes `Vec64`,
|
||||
//! `Vec128` and `Vec256` that can be used to prepare data useful when
|
||||
//! generating SIMD code.
|
||||
//!
|
||||
//! X86/X64 code generator contains member functions `dmm`, `dxmm` and `dymm`
|
||||
//! which can be used to embed 64-bit, 128-bit and 256-bit data structures into
|
||||
//! machine code (both assembler and compiler are supported).
|
||||
//!
|
||||
//! \note Compiler contains a constant pool, which should be used instead of
|
||||
//! embedding constants manually after the function body.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_x86 X86/X64
|
||||
//!
|
||||
//! \brief X86/X64 module
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86_general]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_x86_general X86/X64 General API
|
||||
//! \ingroup asmjit_x86
|
||||
//!
|
||||
//! \brief X86/X64 general API.
|
||||
//!
|
||||
//! X86/X64 Registers
|
||||
//! -----------------
|
||||
//!
|
||||
//! There are static objects that represents X86 and X64 registers. They can
|
||||
//! be used directly (like `eax`, `mm`, `xmm`, ...) or created through
|
||||
//! these functions:
|
||||
//!
|
||||
//! - `asmjit::gpb_lo()` - Get Gpb-lo register.
|
||||
//! - `asmjit::gpb_hi()` - Get Gpb-hi register.
|
||||
//! - `asmjit::gpw()` - Get Gpw register.
|
||||
//! - `asmjit::gpd()` - Get Gpd register.
|
||||
//! - `asmjit::gpq()` - Get Gpq Gp register.
|
||||
//! - `asmjit::gpz()` - Get Gpd/Gpq register.
|
||||
//! - `asmjit::fp()` - Get Fp register.
|
||||
//! - `asmjit::mm()` - Get Mm register.
|
||||
//! - `asmjit::xmm()` - Get Xmm register.
|
||||
//! - `asmjit::ymm()` - Get Ymm register.
|
||||
//!
|
||||
//! X86/X64 Addressing
|
||||
//! ------------------
|
||||
//!
|
||||
//! X86 and x64 architectures contains several addressing modes and most ones
|
||||
//! are possible with AsmJit library. Memory represents are represented by
|
||||
//! `BaseMem` class. These functions are used to make operands that represents
|
||||
//! memory addresses:
|
||||
//!
|
||||
//! - `asmjit::ptr()` - Address size not specified.
|
||||
//! - `asmjit::byte_ptr()` - 1 byte.
|
||||
//! - `asmjit::word_ptr()` - 2 bytes (Gpw size).
|
||||
//! - `asmjit::dword_ptr()` - 4 bytes (Gpd size).
|
||||
//! - `asmjit::qword_ptr()` - 8 bytes (Gpq/Mm size).
|
||||
//! - `asmjit::tword_ptr()` - 10 bytes (FPU).
|
||||
//! - `asmjit::oword_ptr()` - 16 bytes (Xmm size).
|
||||
//! - `asmjit::yword_ptr()` - 32 bytes (Ymm size).
|
||||
//! - `asmjit::zword_ptr()` - 64 bytes (Zmm size).
|
||||
//!
|
||||
//! Most useful function to make pointer should be `asmjit::ptr()`. It creates
|
||||
//! pointer to the target with unspecified size. Unspecified size works in all
|
||||
//! intrinsics where are used registers (this means that size is specified by
|
||||
//! register operand or by instruction itself). For example `asmjit::ptr()`
|
||||
//! can't be used with `Assembler::inc()` instruction. In this case size must
|
||||
//! be specified and it's also reason to make difference between pointer sizes.
|
||||
//!
|
||||
//! Supported are simple address forms `[base + displacement]` and complex
|
||||
//! address forms `[base + index * scale + displacement]`.
|
||||
//!
|
||||
//! X86/X64 Immediates
|
||||
//! ------------------
|
||||
//!
|
||||
//! Immediate values are constants thats passed directly after instruction
|
||||
//! opcode. To create such value use `imm()` or `imm_u()` methods to create
|
||||
//! signed or unsigned immediate value.
|
||||
//!
|
||||
//! X86/X64 CPU Information
|
||||
//! -----------------------
|
||||
//!
|
||||
//! The CPUID instruction can be used to get an exhaustive information about
|
||||
//! the host X86/X64 processor. AsmJit contains utilities that can get the most
|
||||
//! important information related to the features supported by the CPU and the
|
||||
//! host operating system, in addition to host processor name and number of
|
||||
//! cores. Class `X86CpuInfo` extends `CpuInfo` and provides functionality
|
||||
//! specific to X86 and X64.
|
||||
//!
|
||||
//! By default AsmJit queries the CPU information after the library is loaded
|
||||
//! and the queried information is reused by all instances of `JitRuntime`.
|
||||
//! The global instance of `X86CpuInfo` can't be changed, because it will affect
|
||||
//! the code generation of all `Runtime`s. If there is a need to have a
|
||||
//! specific CPU information which contains modified features or processor
|
||||
//! vendor it's possible by creating a new instance of `X86CpuInfo` and setting
|
||||
//! up its members. `X86CpuUtil::detect` can be used to detect CPU features into
|
||||
//! an existing `X86CpuInfo` instance - it may become handly if only one property
|
||||
//! has to be turned on/off.
|
||||
//!
|
||||
//! If the high-level interface `X86CpuInfo` offers is not enough there is also
|
||||
//! `X86CpuUtil::callCpuId` helper that can be used to call CPUID instruction
|
||||
//! with a given parameters and to consume the output.
|
||||
//!
|
||||
//! Cpu detection is important when generating a JIT code that may or may not
|
||||
//! use certain CPU features. For example there used to be a SSE/SSE2 detection
|
||||
//! in the past and today there is often AVX/AVX2 detection.
|
||||
//!
|
||||
//! The example below shows how to detect SSE2:
|
||||
//!
|
||||
//! ~~~
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! // Get `X86CpuInfo` global instance.
|
||||
//! const X86CpuInfo* cpuInfo = X86CpuInfo::getHost();
|
||||
//!
|
||||
//! if (cpuInfo->hasFeature(kX86CpuFeatureSSE2)) {
|
||||
//! // Processor has SSE2.
|
||||
//! }
|
||||
//! else if (cpuInfo->hasFeature(kX86CpuFeatureMMX)) {
|
||||
//! // Processor doesn't have SSE2, but has MMX.
|
||||
//! }
|
||||
//! else {
|
||||
//! // Processor is archaic; it's a wonder AsmJit works here!
|
||||
//! }
|
||||
//! ~~~
|
||||
//!
|
||||
//! The next example shows how to call `CPUID` directly:
|
||||
//!
|
||||
//! ~~~
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! // Call cpuid, first two arguments are passed in Eax/Ecx.
|
||||
//! X86CpuId out;
|
||||
//! X86CpuUtil::callCpuId(0, 0, &out);
|
||||
//!
|
||||
//! // If Eax argument is 0, Ebx, Ecx and Edx registers are filled with a cpu vendor.
|
||||
//! char cpuVendor[13];
|
||||
//! ::memcpy(cpuVendor, &out.ebx, 4);
|
||||
//! ::memcpy(cpuVendor + 4, &out.edx, 4);
|
||||
//! ::memcpy(cpuVendor + 8, &out.ecx, 4);
|
||||
//! vendor[12] = '\0';
|
||||
//!
|
||||
//! // Print a CPU vendor retrieved from CPUID.
|
||||
//! ::printf("%s", cpuVendor);
|
||||
//! ~~~
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86_compiler]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_x86_compiler X86/X64 Code-Tree
|
||||
//! \ingroup asmjit_x86
|
||||
//!
|
||||
//! \brief X86/X64 code-tree and helpers.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86_inst]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_x86_inst X86/X64 Instructions
|
||||
//! \ingroup asmjit_x86
|
||||
//!
|
||||
//! \brief X86/X64 low-level instruction definitions.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_x86_util]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_x86_util X86/X64 Utilities
|
||||
//! \ingroup asmjit_x86
|
||||
//!
|
||||
//! \brief X86/X64 utility classes.
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_contrib]
|
||||
// ============================================================================
|
||||
|
||||
//! \defgroup asmjit_contrib Contributions
|
||||
//!
|
||||
//! \brief Contributions.
|
||||
|
||||
// [Dependencies - Base]
|
||||
#include "base.h"
|
||||
|
||||
// [Dependencies - X86/X64]
|
||||
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
|
||||
#include "x86.h"
|
||||
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64
|
||||
|
||||
// [Dependencies - Host]
|
||||
#include "host.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_ASMJIT_H
|
||||
+385
@@ -0,0 +1,385 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BUILD_H
|
||||
#define _ASMJIT_BUILD_H
|
||||
|
||||
// [Include]
|
||||
#if defined(ASMJIT_CONFIG_FILE)
|
||||
# include ASMJIT_CONFIG_FILE
|
||||
#else
|
||||
# include "./config.h"
|
||||
#endif // ASMJIT_CONFIG_FILE
|
||||
|
||||
// Turn off deprecation warnings when compiling AsmJit.
|
||||
#if defined(ASMJIT_EXPORTS) && defined(_MSC_VER)
|
||||
# if !defined(_CRT_SECURE_NO_DEPRECATE)
|
||||
# define _CRT_SECURE_NO_DEPRECATE
|
||||
# endif // !_CRT_SECURE_NO_DEPRECATE
|
||||
# if !defined(_CRT_SECURE_NO_WARNINGS)
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
# endif // !_CRT_SECURE_NO_WARNINGS
|
||||
#endif // ASMJIT_EXPORTS
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// [Dependencies - C++]
|
||||
#include <new>
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Sanity]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_DISABLE_NAMES) && !defined(ASMJIT_DISABLE_LOGGER)
|
||||
# error "ASMJIT_DISABLE_NAMES requires ASMJIT_DISABLE_LOGGER to be defined."
|
||||
#endif // ASMJIT_DISABLE_NAMES && !ASMJIT_DISABLE_LOGGER
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - OS]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_WINDOWS) || defined(__WINDOWS__) || defined(_WIN32) || defined(_WIN64)
|
||||
# define ASMJIT_OS_WINDOWS
|
||||
#elif defined(__linux) || defined(__linux__)
|
||||
# define ASMJIT_OS_POSIX
|
||||
# define ASMJIT_OS_LINUX
|
||||
#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
# define ASMJIT_OS_POSIX
|
||||
# define ASMJIT_OS_BSD
|
||||
#elif defined(__APPLE__)
|
||||
# define ASMJIT_OS_POSIX
|
||||
# define ASMJIT_OS_MAC
|
||||
#else
|
||||
# warning "AsmJit - Unable to detect host operating system, using ASMJIT_OS_POSIX"
|
||||
# define ASMJIT_OS_POSIX
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Arch]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_M_X64 ) || \
|
||||
defined(_M_AMD64 ) || \
|
||||
defined(_WIN64 ) || \
|
||||
defined(__amd64__ ) || \
|
||||
defined(__LP64 ) || \
|
||||
defined(__x86_64__)
|
||||
# define ASMJIT_HOST_X64
|
||||
# define ASMJIT_HOST_LE
|
||||
# define ASMJIT_HOST_UNALIGNED_16
|
||||
# define ASMJIT_HOST_UNALIGNED_32
|
||||
# define ASMJIT_HOST_UNALIGNED_64
|
||||
#elif \
|
||||
defined(_M_IX86 ) || \
|
||||
defined(__INTEL__) || \
|
||||
defined(__i386__ )
|
||||
# define ASMJIT_HOST_X86
|
||||
# define ASMJIT_HOST_LE
|
||||
# define ASMJIT_HOST_UNALIGNED_16
|
||||
# define ASMJIT_HOST_UNALIGNED_32
|
||||
# define ASMJIT_HOST_UNALIGNED_64
|
||||
#elif \
|
||||
defined(_ARM ) || \
|
||||
defined(_M_ARM_FP ) || \
|
||||
defined(__ARM_NEON__ ) || \
|
||||
defined(__arm ) || \
|
||||
defined(__arm__ ) || \
|
||||
defined(__TARGET_ARCH_ARM ) || \
|
||||
defined(__TARGET_ARCH_THUMB) || \
|
||||
defined(__thumb__ )
|
||||
# define ASMJIT_HOST_ARM
|
||||
# define ASMJIT_HOST_LE
|
||||
#else
|
||||
# warning "AsmJit - Unable to detect host architecture"
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Build]
|
||||
// ============================================================================
|
||||
|
||||
// Build host architecture if no architecture is selected.
|
||||
#if !defined(ASMJIT_BUILD_HOST) && \
|
||||
!defined(ASMJIT_BUILD_X86) && \
|
||||
!defined(ASMJIT_BUILD_X64)
|
||||
# define ASMJIT_BUILD_HOST
|
||||
#endif
|
||||
|
||||
// Autodetect host architecture if enabled.
|
||||
#if defined(ASMJIT_BUILD_HOST)
|
||||
# if defined(ASMJIT_HOST_X86) && !defined(ASMJIT_BUILD_X86)
|
||||
# define ASMJIT_BUILD_X86
|
||||
# endif // ASMJIT_HOST_X86 && !ASMJIT_BUILD_X86
|
||||
# if defined(ASMJIT_HOST_X64) && !defined(ASMJIT_BUILD_X64)
|
||||
# define ASMJIT_BUILD_X64
|
||||
# endif // ASMJIT_HOST_X64 && !ASMJIT_BUILD_X64
|
||||
#endif // ASMJIT_BUILD_HOST
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Decorators]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_EMBED) && !defined(ASMJIT_STATIC)
|
||||
# define ASMJIT_STATIC
|
||||
#endif // ASMJIT_EMBED && !ASMJIT_STATIC
|
||||
|
||||
#if defined(ASMJIT_STATIC)
|
||||
# define ASMJIT_API
|
||||
#elif defined(ASMJIT_OS_WINDOWS)
|
||||
# if (defined(__GNUC__) || defined(__clang__)) && !defined(__MINGW32__)
|
||||
# if defined(ASMJIT_EXPORTS)
|
||||
# define ASMJIT_API __attribute__((dllexport))
|
||||
# else
|
||||
# define ASMJIT_API __attribute__((dllimport))
|
||||
# endif // ASMJIT_EXPORTS
|
||||
# else
|
||||
# if defined(ASMJIT_EXPORTS)
|
||||
# define ASMJIT_API __declspec(dllexport)
|
||||
# else
|
||||
# define ASMJIT_API __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define ASMJIT_API __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_API)
|
||||
# define ASMJIT_API
|
||||
#endif // ASMJIT_API
|
||||
|
||||
// This is basically a workaround. When using MSVC and marking class as DLL
|
||||
// export everything is exported, which is unwanted since there are many
|
||||
// inlines which mimic instructions. MSVC automatically exports typeinfo and
|
||||
// vtable if at least one symbol of that class is exported. However, GCC has
|
||||
// some strange behavior that even if one or more symbol is exported it doesn't
|
||||
// export `typeinfo` unless the class itself is marked as "visibility(default)".
|
||||
#if !defined(ASMJIT_OS_WINDOWS) && (defined(__GNUC__) || defined (__clang__))
|
||||
# define ASMJIT_VCLASS ASMJIT_API
|
||||
#else
|
||||
# define ASMJIT_VCLASS
|
||||
#endif
|
||||
|
||||
#if !defined(ASMJIT_VAR)
|
||||
# define ASMJIT_VAR extern ASMJIT_API
|
||||
#endif // !ASMJIT_VAR
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define ASMJIT_INLINE __forceinline
|
||||
#elif defined(__clang__)
|
||||
# define ASMJIT_INLINE inline __attribute__((always_inline)) __attribute__((visibility("hidden")))
|
||||
#elif defined(__GNUC__)
|
||||
# define ASMJIT_INLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
# define ASMJIT_INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined(ASMJIT_HOST_X86)
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define ASMJIT_REGPARM_1 __attribute__((regparm(1)))
|
||||
# define ASMJIT_REGPARM_2 __attribute__((regparm(2)))
|
||||
# define ASMJIT_REGPARM_3 __attribute__((regparm(3)))
|
||||
# define ASMJIT_FASTCALL __attribute__((fastcall))
|
||||
# define ASMJIT_STDCALL __attribute__((stdcall))
|
||||
# define ASMJIT_CDECL __attribute__((cdecl))
|
||||
# else
|
||||
# define ASMJIT_FASTCALL __fastcall
|
||||
# define ASMJIT_STDCALL __stdcall
|
||||
# define ASMJIT_CDECL __cdecl
|
||||
# endif
|
||||
#else
|
||||
# define ASMJIT_FASTCALL
|
||||
# define ASMJIT_STDCALL
|
||||
# define ASMJIT_CDECL
|
||||
#endif // ASMJIT_HOST_X86
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Enum]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define ASMJIT_ENUM(_Name_) enum _Name_ : uint32_t
|
||||
#else
|
||||
# define ASMJIT_ENUM(_Name_) enum _Name_
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Memory Management]
|
||||
// ============================================================================
|
||||
|
||||
#if !defined(ASMJIT_ALLOC) && !defined(ASMJIT_REALLOC) && !defined(ASMJIT_FREE)
|
||||
# define ASMJIT_ALLOC(_Size_) ::malloc(_Size_)
|
||||
# define ASMJIT_REALLOC(_Ptr_, _Size_) ::realloc(_Ptr_, _Size_)
|
||||
# define ASMJIT_FREE(_Ptr_) ::free(_Ptr_)
|
||||
#else
|
||||
# if !defined(ASMJIT_ALLOC) || !defined(ASMJIT_REALLOC) || !defined(ASMJIT_FREE)
|
||||
# error "AsmJit - You must redefine ASMJIT_ALLOC, ASMJIT_REALLOC and ASMJIT_FREE."
|
||||
# endif
|
||||
#endif // !ASMJIT_ALLOC && !ASMJIT_REALLOC && !ASMJIT_FREE
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - _ASMJIT_HOST_INDEX]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
# define _ASMJIT_HOST_INDEX(_Total_, _Index_) (_Index_)
|
||||
#else
|
||||
# define _ASMJIT_HOST_INDEX(_Total_, _Index_) ((_Total_) - 1 - (_Index_))
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - BLEND_OFFSET_OF]
|
||||
// ============================================================================
|
||||
|
||||
//! Cross-platform solution to get offset of `_Field_` in `_Struct_`.
|
||||
#define ASMJIT_OFFSET_OF(_Struct_, _Field_) \
|
||||
static_cast<int>((intptr_t) ((const uint8_t*) &((const _Struct_*)0x1)->_Field_) - 1)
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - ASMJIT_ARRAY_SIZE]
|
||||
// ============================================================================
|
||||
|
||||
#define ASMJIT_ARRAY_SIZE(_Array_) \
|
||||
(sizeof(_Array_) / sizeof(*_Array_))
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - ASMJIT_DEBUG / ASMJIT_TRACE]
|
||||
// ============================================================================
|
||||
|
||||
// If ASMJIT_DEBUG and ASMJIT_RELEASE is not defined ASMJIT_DEBUG will be
|
||||
// detected using the compiler specific macros. This enables to set the build
|
||||
// type using IDE.
|
||||
#if !defined(ASMJIT_DEBUG) && !defined(ASMJIT_RELEASE)
|
||||
# if defined(_DEBUG)
|
||||
# define ASMJIT_DEBUG
|
||||
# endif // _DEBUG
|
||||
#endif // !ASMJIT_DEBUG && !ASMJIT_RELEASE
|
||||
|
||||
// ASMJIT_TRACE is only used by sources and private headers. It's safe to make
|
||||
// it unavailable outside of AsmJit.
|
||||
#if defined(ASMJIT_EXPORTS)
|
||||
namespace asmjit { static inline int disabledTrace(...) { return 0; } }
|
||||
# if defined(ASMJIT_TRACE)
|
||||
# define ASMJIT_TSEC(_Section_) _Section_
|
||||
# define ASMJIT_TLOG ::printf(__VA_ARGS__)
|
||||
# else
|
||||
# define ASMJIT_TSEC(_Section_) do {} while(0)
|
||||
# define ASMJIT_TLOG 0 && ::asmjit::disabledTrace
|
||||
# endif // ASMJIT_TRACE
|
||||
#endif // ASMJIT_EXPORTS
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - ASMJIT_UNUSED]
|
||||
// ============================================================================
|
||||
|
||||
#if !defined(ASMJIT_UNUSED)
|
||||
# define ASMJIT_UNUSED(_Var_) ((void)_Var_)
|
||||
#endif // ASMJIT_UNUSED
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - ASMJIT_NOP]
|
||||
// ============================================================================
|
||||
|
||||
#if !defined(ASMJIT_NOP)
|
||||
# define ASMJIT_NOP() ((void)0)
|
||||
#endif // ASMJIT_NOP
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - ASMJIT_NO_COPY]
|
||||
// ============================================================================
|
||||
|
||||
#define ASMJIT_NO_COPY(_Type_) \
|
||||
private: \
|
||||
ASMJIT_INLINE _Type_(const _Type_& other); \
|
||||
ASMJIT_INLINE _Type_& operator=(const _Type_& other); \
|
||||
public:
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - StdInt]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
# include <sys/types.h>
|
||||
#endif // __MINGW32__
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
# if !defined(ASMJIT_SUPRESS_STD_TYPES)
|
||||
# if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
# endif // _MSC_VER
|
||||
# endif // ASMJIT_SUPRESS_STD_TYPES
|
||||
#else
|
||||
# include <stdint.h>
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define ASMJIT_INT64_C(_Num_) _Num_##i64
|
||||
# define ASMJIT_UINT64_C(_Num_) _Num_##ui64
|
||||
#else
|
||||
# define ASMJIT_INT64_C(_Num_) _Num_##LL
|
||||
# define ASMJIT_UINT64_C(_Num_) _Num_##ULL
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Windows]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS) && !defined(ASMJIT_SUPRESS_WINDOWS_H)
|
||||
|
||||
# if !defined(WIN32_LEAN_AND_MEAN)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# define ASMJIT_UNDEF_WIN32_LEAN_AND_MEAN
|
||||
# endif // !WIN32_LEAN_AND_MEAN
|
||||
|
||||
# if !defined(NOMINMAX)
|
||||
# define NOMINMAX
|
||||
# define ASMJIT_UNDEF_NOMINMAX
|
||||
# endif // !NOMINMAX
|
||||
|
||||
# include <windows.h>
|
||||
|
||||
# if defined(ASMJIT_UNDEF_NOMINMAX)
|
||||
# undef NOMINMAX
|
||||
# undef ASMJIT_UNDEF_NOMINMAX
|
||||
# endif
|
||||
|
||||
# if defined(ASMJIT_UNDEF_WIN32_LEAN_AND_MEAN)
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
# undef ASMJIT_UNDEF_WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
|
||||
#endif // ASMJIT_OS_WINDOWS && !ASMJIT_SUPRESS_WINDOWS_H
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::build - Test]
|
||||
// ============================================================================
|
||||
|
||||
// Include a unit testing package if this is a `asmjit_test` build.
|
||||
#if defined(ASMJIT_TEST)
|
||||
#include "./test/broken.h"
|
||||
#endif // ASMJIT_TEST
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BUILD_H
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_CONFIG_H
|
||||
#define _ASMJIT_CONFIG_H
|
||||
|
||||
// This file can be used to modify built-in features of AsmJit. AsmJit is by
|
||||
// default compiled only for host processor to enable JIT compilation. Both
|
||||
// Assembler and Compiler code generators are compiled by default.
|
||||
//
|
||||
// ASMJIT_BUILD_... flags can be defined to build additional backends that can
|
||||
// be used for remote code generation.
|
||||
//
|
||||
// ASMJIT_DISABLE_... flags can be defined to disable standard features. These
|
||||
// are handy especially when building asmjit statically and some features are
|
||||
// not needed or unwanted (like Compiler).
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define ASMJIT_DEBUG // Define to enable debug-mode.
|
||||
#else
|
||||
#define ASMJIT_RELEASE // Define to enable release-mode.
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// [AsmJit - Build-Type]
|
||||
// ============================================================================
|
||||
|
||||
#ifdef BLACKBONE_STATIC
|
||||
#define ASMJIT_STATIC
|
||||
#elif BLACKBONE_EXPORTS
|
||||
#define ASMJIT_EXPORTS
|
||||
#endif
|
||||
|
||||
// #define ASMJIT_EMBED // Asmjit is embedded (implies ASMJIT_STATIC).
|
||||
// #define ASMJIT_STATIC // Define to enable static-library build.
|
||||
|
||||
// ============================================================================
|
||||
// [AsmJit - Build-Mode]
|
||||
// ============================================================================
|
||||
|
||||
// #define ASMJIT_DEBUG // Define to enable debug-mode.
|
||||
// #define ASMJIT_RELEASE // Define to enable release-mode.
|
||||
// #define ASMJIT_TRACE // Define to enable tracing.
|
||||
|
||||
// ============================================================================
|
||||
// [AsmJit - Features]
|
||||
// ============================================================================
|
||||
|
||||
// If none of these is defined AsmJit will select host architecture by default.
|
||||
#define ASMJIT_BUILD_X86 // Define to enable x86 instruction set (32-bit).
|
||||
#define ASMJIT_BUILD_X64 // Define to enable x64 instruction set (64-bit).
|
||||
// #define ASMJIT_BUILD_HOST // Define to enable host instruction set.
|
||||
|
||||
// AsmJit features are enabled by default.
|
||||
#define ASMJIT_DISABLE_COMPILER // Disable Compiler (completely).
|
||||
#define ASMJIT_DISABLE_LOGGER // Disable Logger (completely).
|
||||
#define ASMJIT_DISABLE_NAMES // Disable everything that uses strings
|
||||
// (instruction names, error names, ...).
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_CONFIG_H
|
||||
@@ -0,0 +1,34 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_H
|
||||
#define _ASMJIT_BASE_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "build.h"
|
||||
|
||||
#include "base/assembler.h"
|
||||
#include "base/codegen.h"
|
||||
#include "base/compiler.h"
|
||||
#include "base/constpool.h"
|
||||
#include "base/containers.h"
|
||||
#include "base/cpuinfo.h"
|
||||
#include "base/cputicks.h"
|
||||
#include "base/error.h"
|
||||
#include "base/globals.h"
|
||||
#include "base/intutil.h"
|
||||
#include "base/lock.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/operand.h"
|
||||
#include "base/runtime.h"
|
||||
#include "base/string.h"
|
||||
#include "base/vectypes.h"
|
||||
#include "base/vmem.h"
|
||||
#include "base/zone.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_H
|
||||
+542
@@ -0,0 +1,542 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_ASSEMBLER_H
|
||||
#define _ASMJIT_BASE_ASSEMBLER_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/codegen.h"
|
||||
#include "../base/containers.h"
|
||||
#include "../base/error.h"
|
||||
#include "../base/logger.h"
|
||||
#include "../base/operand.h"
|
||||
#include "../base/runtime.h"
|
||||
#include "../base/zone.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_general
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kInstId]
|
||||
// ============================================================================
|
||||
|
||||
//! Instruction codes (stub).
|
||||
ASMJIT_ENUM(kInstId) {
|
||||
//! No instruction.
|
||||
kInstIdNone = 0
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kInstOptions]
|
||||
// ============================================================================
|
||||
|
||||
//! Instruction options (stub).
|
||||
ASMJIT_ENUM(kInstOptions) {
|
||||
//! No instruction options.
|
||||
kInstOptionNone = 0x00000000,
|
||||
|
||||
//! Emit short form of the instruction.
|
||||
//!
|
||||
//! X86/X64:
|
||||
//!
|
||||
//! Short form is mostly related to jmp and jcc instructions, but can be used
|
||||
//! by other instructions supporting 8-bit or 32-bit immediates. This option
|
||||
//! can be dangerous if the short jmp/jcc is required, but not encodable due
|
||||
//! to large displacement, in such case an error happens and the whole
|
||||
//! assembler/compiler stream is unusable.
|
||||
kInstOptionShortForm = 0x00000001,
|
||||
|
||||
//! Emit long form of the instruction.
|
||||
//!
|
||||
//! X86/X64:
|
||||
//!
|
||||
//! Long form is mosrlt related to jmp and jcc instructions, but like the
|
||||
//! `kInstOptionShortForm` option it can be used by other instructions
|
||||
//! supporting both 8-bit and 32-bit immediates.
|
||||
kInstOptionLongForm = 0x00000002,
|
||||
|
||||
//! Condition is likely to be taken.
|
||||
kInstOptionTaken = 0x00000004,
|
||||
|
||||
//! Condition is unlikely to be taken.
|
||||
kInstOptionNotTaken = 0x00000008
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::LabelLink]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Data structure used to link linked-labels.
|
||||
struct LabelLink {
|
||||
//! Previous link.
|
||||
LabelLink* prev;
|
||||
//! Offset.
|
||||
intptr_t offset;
|
||||
//! Inlined displacement.
|
||||
intptr_t displacement;
|
||||
//! RelocId if link must be absolute when relocated.
|
||||
intptr_t relocId;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::LabelData]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Label data.
|
||||
struct LabelData {
|
||||
//! Label offset.
|
||||
intptr_t offset;
|
||||
//! Label links chain.
|
||||
LabelLink* links;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::RelocData]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Code relocation data (relative vs absolute addresses).
|
||||
//!
|
||||
//! X86/X64:
|
||||
//!
|
||||
//! X86 architecture uses 32-bit absolute addressing model by memory operands,
|
||||
//! but 64-bit mode uses relative addressing model (RIP + displacement). In
|
||||
//! code we are always using relative addressing model for referencing labels
|
||||
//! and embedded data. In 32-bit mode we must patch all references to absolute
|
||||
//! address before we can call generated function.
|
||||
struct RelocData {
|
||||
//! Type of relocation.
|
||||
uint32_t type;
|
||||
//! Size of relocation (4 or 8 bytes).
|
||||
uint32_t size;
|
||||
|
||||
//! Offset from code begin address.
|
||||
Ptr from;
|
||||
|
||||
//! Relative displacement from code begin address (not to `offset`) or
|
||||
//! absolute address.
|
||||
Ptr data;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Assembler]
|
||||
// ============================================================================
|
||||
|
||||
//! Base assembler.
|
||||
//!
|
||||
//! This class implements the base interface to an assembler. The architecture
|
||||
//! specific API is implemented by backends.
|
||||
//!
|
||||
//! \sa Compiler.
|
||||
struct ASMJIT_VCLASS Assembler : public CodeGen {
|
||||
ASMJIT_NO_COPY(Assembler)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new `Assembler` instance.
|
||||
ASMJIT_API Assembler(Runtime* runtime);
|
||||
//! Destroy the `Assembler` instance.
|
||||
ASMJIT_API virtual ~Assembler();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Reset the assembler.
|
||||
//!
|
||||
//! If `releaseMemory` is true all buffers will be released to the system.
|
||||
ASMJIT_API void reset(bool releaseMemory = false);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Buffer]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get capacity of the code buffer.
|
||||
ASMJIT_INLINE size_t getCapacity() const {
|
||||
return (size_t)(_end - _buffer);
|
||||
}
|
||||
|
||||
//! Get the number of remaining bytes (space between cursor and the end of
|
||||
//! the buffer).
|
||||
ASMJIT_INLINE size_t getRemainingSpace() const {
|
||||
return (size_t)(_end - _cursor);
|
||||
}
|
||||
|
||||
//! Get buffer.
|
||||
ASMJIT_INLINE uint8_t* getBuffer() const {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
//! Get the end of the buffer (points to the first byte that is outside).
|
||||
ASMJIT_INLINE uint8_t* getEnd() const {
|
||||
return _end;
|
||||
}
|
||||
|
||||
//! Get the current position in the buffer.
|
||||
ASMJIT_INLINE uint8_t* getCursor() const {
|
||||
return _cursor;
|
||||
}
|
||||
|
||||
//! Set the current position in the buffer.
|
||||
ASMJIT_INLINE void setCursor(uint8_t* cursor) {
|
||||
ASMJIT_ASSERT(cursor >= _buffer && cursor <= _end);
|
||||
_cursor = cursor;
|
||||
}
|
||||
|
||||
//! Get the current offset in the buffer.
|
||||
ASMJIT_INLINE size_t getOffset() const {
|
||||
return (size_t)(_cursor - _buffer);
|
||||
}
|
||||
|
||||
//! Set the current offset in the buffer to `offset` and get the previous
|
||||
//! offset value.
|
||||
ASMJIT_INLINE size_t setOffset(size_t offset) {
|
||||
ASMJIT_ASSERT(offset < getCapacity());
|
||||
|
||||
size_t oldOffset = (size_t)(_cursor - _buffer);
|
||||
_cursor = _buffer + offset;
|
||||
return oldOffset;
|
||||
}
|
||||
|
||||
//! Grow the internal buffer.
|
||||
//!
|
||||
//! The internal buffer will grow at least by `n` bytes so `n` bytes can be
|
||||
//! added to it. If `n` is zero or `getOffset() + n` is not greater than the
|
||||
//! current capacity of the buffer this function does nothing.
|
||||
ASMJIT_API Error _grow(size_t n);
|
||||
|
||||
//! Reserve the internal buffer to at least `n` bytes.
|
||||
ASMJIT_API Error _reserve(size_t n);
|
||||
|
||||
//! Get BYTE at position `pos`.
|
||||
ASMJIT_INLINE uint8_t getByteAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint8_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! Get WORD at position `pos`.
|
||||
ASMJIT_INLINE uint16_t getWordAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint16_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! Get DWORD at position `pos`.
|
||||
ASMJIT_INLINE uint32_t getDWordAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! Get QWORD at position `pos`.
|
||||
ASMJIT_INLINE uint64_t getQWordAt(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint64_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! Get int32_t at position `pos`.
|
||||
ASMJIT_INLINE int32_t getInt32At(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const int32_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! Get uint32_t at position `pos`.
|
||||
ASMJIT_INLINE uint32_t getUInt32At(size_t pos) const {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
return *reinterpret_cast<const uint32_t*>(_buffer + pos);
|
||||
}
|
||||
|
||||
//! Set BYTE at position `pos`.
|
||||
ASMJIT_INLINE void setByteAt(size_t pos, uint8_t x) {
|
||||
ASMJIT_ASSERT(pos + 1 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint8_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! Set WORD at position `pos`.
|
||||
ASMJIT_INLINE void setWordAt(size_t pos, uint16_t x) {
|
||||
ASMJIT_ASSERT(pos + 2 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint16_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! Set DWORD at position `pos`.
|
||||
ASMJIT_INLINE void setDWordAt(size_t pos, uint32_t x) {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint32_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! Set QWORD at position `pos`.
|
||||
ASMJIT_INLINE void setQWordAt(size_t pos, uint64_t x) {
|
||||
ASMJIT_ASSERT(pos + 8 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint64_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! Set int32_t at position `pos`.
|
||||
ASMJIT_INLINE void setInt32At(size_t pos, int32_t x) {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<int32_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
//! Set uint32_t at position `pos`.
|
||||
ASMJIT_INLINE void setUInt32At(size_t pos, uint32_t x) {
|
||||
ASMJIT_ASSERT(pos + 4 <= (size_t)(_end - _buffer));
|
||||
*reinterpret_cast<uint32_t*>(_buffer + pos) = x;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [GetCodeSize]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get current offset in buffer, same as `getOffset() + getTramplineSize()`.
|
||||
ASMJIT_INLINE size_t getCodeSize() const {
|
||||
return getOffset() + getTrampolineSize();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [GetTrampolineSize]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get size of all possible trampolines.
|
||||
//!
|
||||
//! Trampolines are needed to successfuly generate relative jumps to absolute
|
||||
//! addresses. This value is only non-zero if jmp of call instructions were
|
||||
//! used with immediate operand (this means jumping or calling an absolute
|
||||
//! address directly).
|
||||
ASMJIT_INLINE size_t getTrampolineSize() const {
|
||||
return _trampolineSize;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Label]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get number of labels created.
|
||||
ASMJIT_INLINE size_t getLabelsCount() const {
|
||||
return _labelList.getLength();
|
||||
}
|
||||
|
||||
//! Get whether the `label` is valid (created by the assembler).
|
||||
ASMJIT_INLINE bool isLabelValid(const Label& label) const {
|
||||
return isLabelValid(label.getId());
|
||||
}
|
||||
|
||||
//! \overload
|
||||
ASMJIT_INLINE bool isLabelValid(uint32_t id) const {
|
||||
return static_cast<size_t>(id) < _labelList.getLength();
|
||||
}
|
||||
|
||||
//! Get whether the `label` is bound.
|
||||
//!
|
||||
//! \note It's an error to pass label that is not valid. Check the validity
|
||||
//! of the label by using `isLabelValid()` method before the bound check if
|
||||
//! you are not sure about its validity, otherwise you may hit an assertion
|
||||
//! failure in debug mode, and undefined behavior in release mode.
|
||||
ASMJIT_INLINE bool isLabelBound(const Label& label) const {
|
||||
return isLabelBound(label.getId());
|
||||
}
|
||||
|
||||
//! \overload
|
||||
ASMJIT_INLINE bool isLabelBound(uint32_t id) const {
|
||||
ASMJIT_ASSERT(isLabelValid(id));
|
||||
|
||||
return _labelList[id].offset != -1;
|
||||
}
|
||||
|
||||
//! Get `label` offset or -1 if the label is not yet bound.
|
||||
ASMJIT_INLINE intptr_t getLabelOffset(const Label& label) const {
|
||||
return getLabelOffset(label.getId());
|
||||
}
|
||||
|
||||
//! \overload
|
||||
ASMJIT_INLINE intptr_t getLabelOffset(uint32_t id) const {
|
||||
ASMJIT_ASSERT(isLabelValid(id));
|
||||
return _labelList[id].offset;
|
||||
}
|
||||
|
||||
//! Get `LabelData` by `label`.
|
||||
ASMJIT_INLINE LabelData* getLabelData(const Label& label) const {
|
||||
return getLabelData(label.getId());
|
||||
}
|
||||
|
||||
//! \overload
|
||||
ASMJIT_INLINE LabelData* getLabelData(uint32_t id) const {
|
||||
ASMJIT_ASSERT(isLabelValid(id));
|
||||
return const_cast<LabelData*>(&_labelList[id]);
|
||||
}
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Register labels for other code generator, i.e. `Compiler`.
|
||||
ASMJIT_API Error _registerIndexedLabels(size_t index);
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Create and initialize a new `Label`.
|
||||
ASMJIT_API Error _newLabel(Label* dst);
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! New LabelLink instance.
|
||||
ASMJIT_API LabelLink* _newLabelLink();
|
||||
|
||||
//! Create and return a new `Label`.
|
||||
ASMJIT_INLINE Label newLabel() {
|
||||
Label result(NoInit);
|
||||
_newLabel(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Bind label to the current offset.
|
||||
//!
|
||||
//! \note Label can be bound only once!
|
||||
ASMJIT_API virtual Error bind(const Label& label);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Embed]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Embed data into the code buffer.
|
||||
ASMJIT_API virtual Error embed(const void* data, uint32_t size);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Align]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Align target buffer to `m` bytes.
|
||||
//!
|
||||
//! Typical usage of this is to align labels at start of the inner loops.
|
||||
//!
|
||||
//! Inserts `nop()` instructions or CPU optimized NOPs.
|
||||
virtual Error align(uint32_t mode, uint32_t offset) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reloc]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Relocate the code to `baseAddress` and copy to `dst`.
|
||||
//!
|
||||
//! \param dst Contains the location where the relocated code should be
|
||||
//! copied. The pointer can be address returned by virtual memory allocator
|
||||
//! or any other address that has sufficient space.
|
||||
//!
|
||||
//! \param base Base address used for relocation. The `JitRuntime` always
|
||||
//! sets the `base` address to be the same as `dst`, but other runtimes, for
|
||||
//! example `StaticRuntime`, do not have to follow this rule.
|
||||
//!
|
||||
//! \retval The number bytes actually used. If the code generator reserved
|
||||
//! space for possible trampolines, but didn't use it, the number of bytes
|
||||
//! used can actually be less than the expected worst case. Virtual memory
|
||||
//! allocator can shrink the memory allocated first time.
|
||||
//!
|
||||
//! A given buffer will be overwritten, to get the number of bytes required,
|
||||
//! use `getCodeSize()`.
|
||||
ASMJIT_API size_t relocCode(void* dst, Ptr baseAddress = kNoBaseAddress) const;
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Reloc code.
|
||||
virtual size_t _relocCode(void* dst, Ptr baseAddress) const = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Make]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API virtual void* make();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Emit an instruction.
|
||||
ASMJIT_API Error emit(uint32_t code);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2);
|
||||
//! \overload
|
||||
ASMJIT_INLINE Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3) {
|
||||
return _emit(code, o0, o1, o2, o3);
|
||||
}
|
||||
|
||||
//! Emit an instruction with integer immediate operand.
|
||||
ASMJIT_API Error emit(uint32_t code, int o0);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, uint64_t o0);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, int o1);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, uint64_t o1);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, int o2);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, uint64_t o2);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, int o3);
|
||||
//! \overload
|
||||
ASMJIT_API Error emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, uint64_t o3);
|
||||
|
||||
//! Emit an instruction (virtual).
|
||||
virtual Error _emit(uint32_t code, const Operand& o0, const Operand& o1, const Operand& o2, const Operand& o3) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Buffer where the code is emitted (either live or temporary).
|
||||
//!
|
||||
//! This is actually the base pointer of the buffer, to get the current
|
||||
//! position (cursor) look at the `_cursor` member.
|
||||
uint8_t* _buffer;
|
||||
//! The end of the buffer (points to the first invalid byte).
|
||||
//!
|
||||
//! The end of the buffer is calculated as <code>_buffer + size</code>.
|
||||
uint8_t* _end;
|
||||
//! The current position in code `_buffer`.
|
||||
uint8_t* _cursor;
|
||||
|
||||
//! Size of possible trampolines.
|
||||
uint32_t _trampolineSize;
|
||||
|
||||
//! Inline comment that will be logged by the next instruction and set to NULL.
|
||||
const char* _comment;
|
||||
//! Unused `LabelLink` structures pool.
|
||||
LabelLink* _unusedLinks;
|
||||
|
||||
//! LabelData list.
|
||||
PodVector<LabelData> _labelList;
|
||||
//! RelocData list.
|
||||
PodVector<RelocData> _relocList;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
// ============================================================================
|
||||
// [Defined-Later]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_INLINE Label::Label(Assembler& a) : Operand(NoInit) {
|
||||
a._newLabel(this);
|
||||
}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_ASSEMBLER_H
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_CODEGEN_H
|
||||
#define _ASMJIT_BASE_CODEGEN_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/error.h"
|
||||
#include "../base/logger.h"
|
||||
#include "../base/runtime.h"
|
||||
#include "../base/zone.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_general
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kCodeGen]
|
||||
// ============================================================================
|
||||
|
||||
//! Features of \ref CodeGen.
|
||||
ASMJIT_ENUM(kCodeGen) {
|
||||
//! Emit optimized code-alignment sequences (`Assembler` and `Compiler`).
|
||||
//!
|
||||
//! Default `true`.
|
||||
//!
|
||||
//! X86/X64
|
||||
//! -------
|
||||
//!
|
||||
//! Default align sequence used by X86/X64 architecture is one-byte 0x90
|
||||
//! opcode that is mostly shown by disassemblers as nop. However there are
|
||||
//! more optimized align sequences for 2-11 bytes that may execute faster.
|
||||
//! If this feature is enabled asmjit will generate specialized sequences
|
||||
//! for alignment between 1 to 11 bytes. Also when `X86Compiler` is used,
|
||||
//! it can add REX prefixes into the code to make some instructions greater
|
||||
//! so no alignment sequence is needed.
|
||||
kCodeGenOptimizedAlign = 0,
|
||||
|
||||
//! Emit jump-prediction hints (`Assembler` and `Compiler`).
|
||||
//!
|
||||
//! Default `false`.
|
||||
//!
|
||||
//! X86/X64
|
||||
//! -------
|
||||
//!
|
||||
//! Jump prediction is usually based on the direction of the jump. If the
|
||||
//! jump is backward it is usually predicted as taken; and if the jump is
|
||||
//! forward it is usually predicted as not-taken. The reason is that loops
|
||||
//! generally use backward jumps and conditions usually use forward jumps.
|
||||
//! However this behavior can be overridden by using instruction prefixes.
|
||||
//! If this option is enabled these hints will be emitted.
|
||||
//!
|
||||
//! This feature is disabled by default, because the only processor that
|
||||
//! used to take into consideration prediction hints was P4. Newer processors
|
||||
//! implement heuristics for branch prediction that ignores any static hints.
|
||||
kCodeGenPredictedJumps = 1,
|
||||
|
||||
//! Schedule instructions so they can be executed faster (`Compiler` only).
|
||||
//!
|
||||
//! Default `false` - has to be explicitly enabled as the scheduler needs
|
||||
//! some time to run.
|
||||
//!
|
||||
//! X86/X64
|
||||
//! -------
|
||||
//!
|
||||
//! If scheduling is enabled AsmJit will try to reorder instructions to
|
||||
//! minimize dependency chain. Scheduler always runs after the registers are
|
||||
//! allocated so it doesn't change count of register allocs/spills.
|
||||
//!
|
||||
//! This feature is highly experimental and untested.
|
||||
kCodeGenEnableScheduler = 2
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kAlignMode]
|
||||
// ============================================================================
|
||||
|
||||
//! Code aligning mode.
|
||||
ASMJIT_ENUM(kAlignMode) {
|
||||
//! Align by emitting a sequence that can be executed (code).
|
||||
kAlignCode = 0,
|
||||
//! Align by emitting sequence that shouldn't be executed (data).
|
||||
kAlignData = 1
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kRelocMode]
|
||||
// ============================================================================
|
||||
|
||||
//! Relocation mode.
|
||||
ASMJIT_ENUM(kRelocMode) {
|
||||
//! Relocate an absolute address to an absolute address.
|
||||
kRelocAbsToAbs = 0,
|
||||
//! Relocate a relative address to an absolute address.
|
||||
kRelocRelToAbs = 1,
|
||||
//! Relocate an absolute address to a relative address.
|
||||
kRelocAbsToRel = 2,
|
||||
//! Relocate an absolute address to a relative address or use trampoline.
|
||||
kRelocTrampoline = 3
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CodeGen]
|
||||
// ============================================================================
|
||||
|
||||
//! Abstract class defining basics of \ref Assembler and \ref Compiler.
|
||||
struct ASMJIT_VCLASS CodeGen {
|
||||
ASMJIT_NO_COPY(CodeGen)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new `CodeGen` instance.
|
||||
ASMJIT_API CodeGen(Runtime* runtime);
|
||||
//! Destroy the `CodeGen` instance.
|
||||
ASMJIT_API virtual ~CodeGen();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Runtime]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get runtime.
|
||||
ASMJIT_INLINE Runtime* getRuntime() const {
|
||||
return _runtime;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Logger]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if !defined(ASMJIT_DISABLE_LOGGER)
|
||||
//! Get whether the code generator has a logger.
|
||||
ASMJIT_INLINE bool hasLogger() const {
|
||||
return _logger != NULL;
|
||||
}
|
||||
|
||||
//! Get logger.
|
||||
ASMJIT_INLINE Logger* getLogger() const {
|
||||
return _logger;
|
||||
}
|
||||
|
||||
//! Set logger to `logger`.
|
||||
ASMJIT_API Error setLogger(Logger* logger);
|
||||
#endif // !ASMJIT_DISABLE_LOGGER
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Arch]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get target architecture.
|
||||
ASMJIT_INLINE uint32_t getArch() const {
|
||||
return _arch;
|
||||
}
|
||||
|
||||
//! Get default register size (4 or 8 bytes).
|
||||
ASMJIT_INLINE uint32_t getRegSize() const {
|
||||
return _regSize;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [BaseAddress]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether the code-generator has a base address.
|
||||
//!
|
||||
//! \sa \ref getBaseAddress()
|
||||
ASMJIT_INLINE bool hasBaseAddress() const {
|
||||
return _baseAddress != kNoBaseAddress;
|
||||
}
|
||||
|
||||
//! Get the base address.
|
||||
ASMJIT_INLINE Ptr getBaseAddress() const {
|
||||
return _baseAddress;
|
||||
}
|
||||
|
||||
//! Set the base address to `baseAddress`.
|
||||
ASMJIT_INLINE void setBaseAddress(Ptr baseAddress) {
|
||||
_baseAddress = baseAddress;
|
||||
}
|
||||
|
||||
//! Reset the base address.
|
||||
ASMJIT_INLINE void resetBaseAddress() {
|
||||
setBaseAddress(kNoBaseAddress);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [LastError / ErrorHandler]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get last error code.
|
||||
ASMJIT_INLINE Error getError() const {
|
||||
return _error;
|
||||
}
|
||||
|
||||
//! Set last error code and propagate it through the error handler.
|
||||
ASMJIT_API Error setError(Error error, const char* message = NULL);
|
||||
|
||||
//! Clear the last error code.
|
||||
ASMJIT_INLINE void resetError() {
|
||||
_error = kErrorOk;
|
||||
}
|
||||
|
||||
//! Get error handler.
|
||||
ASMJIT_INLINE ErrorHandler* getErrorHandler() const {
|
||||
return _errorHandler;
|
||||
}
|
||||
|
||||
//! Set error handler.
|
||||
ASMJIT_API Error setErrorHandler(ErrorHandler* handler);
|
||||
|
||||
//! Clear error handler.
|
||||
ASMJIT_INLINE Error resetErrorHandler() {
|
||||
return setErrorHandler(NULL);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Code-Generation Features]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get code-generator `feature`.
|
||||
ASMJIT_INLINE bool hasFeature(uint32_t feature) const {
|
||||
ASMJIT_ASSERT(feature < 32);
|
||||
|
||||
return (_features & (1 << feature)) != 0;
|
||||
}
|
||||
|
||||
//! Set code-generator `feature` to `value`.
|
||||
ASMJIT_INLINE void setFeature(uint32_t feature, bool value) {
|
||||
ASMJIT_ASSERT(feature < 32);
|
||||
|
||||
feature = static_cast<uint32_t>(value) << feature;
|
||||
_features = (_features & ~feature) | feature;
|
||||
}
|
||||
|
||||
//! Get code-generator features.
|
||||
ASMJIT_INLINE uint32_t getFeatures() const {
|
||||
return _features;
|
||||
}
|
||||
|
||||
//! Set code-generator features.
|
||||
ASMJIT_INLINE void setFeatures(uint32_t features) {
|
||||
_features = features;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Instruction Options]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get options of the next instruction.
|
||||
ASMJIT_INLINE uint32_t getInstOptions() const {
|
||||
return _instOptions;
|
||||
}
|
||||
|
||||
//! Get options of the next instruction and reset them.
|
||||
ASMJIT_INLINE uint32_t getInstOptionsAndReset() {
|
||||
uint32_t instOptions = _instOptions;
|
||||
_instOptions = 0;
|
||||
return instOptions;
|
||||
};
|
||||
|
||||
//! Set options of the next instruction.
|
||||
ASMJIT_INLINE void setInstOptions(uint32_t instOptions) {
|
||||
_instOptions = instOptions;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Make]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Make is a convenience method to make and relocate the current code and
|
||||
//! add it to the associated `Runtime`.
|
||||
//!
|
||||
//! What is needed is only to cast the returned pointer to your function type
|
||||
//! and then use it. If there was an error during `make()` `NULL` is returned
|
||||
//! and the last error code can be obtained by calling `getError()`.
|
||||
virtual void* make() = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Target runtime.
|
||||
Runtime* _runtime;
|
||||
|
||||
#if !defined(ASMJIT_DISABLE_LOGGER)
|
||||
//! Logger.
|
||||
Logger* _logger;
|
||||
#else
|
||||
//! \internal
|
||||
//!
|
||||
//! Makes libraries built with or without logging support binary compatible.
|
||||
void* _logger;
|
||||
#endif // ASMJIT_DISABLE_LOGGER
|
||||
|
||||
//! Error handler, called by \ref setError().
|
||||
ErrorHandler* _errorHandler;
|
||||
|
||||
//! Base address (-1 if unknown/not used).
|
||||
Ptr _baseAddress;
|
||||
|
||||
//! Target architecture ID.
|
||||
uint8_t _arch;
|
||||
//! Target architecture GP register size in bytes (4 or 8).
|
||||
uint8_t _regSize;
|
||||
//! \internal
|
||||
uint16_t _reserved;
|
||||
|
||||
//! Code-Generation features, used by \ref hasFeature() and \ref setFeature().
|
||||
uint32_t _features;
|
||||
//! Options affecting the next instruction.
|
||||
uint32_t _instOptions;
|
||||
|
||||
//! Last error code.
|
||||
uint32_t _error;
|
||||
|
||||
//! Base zone.
|
||||
Zone _baseZone;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_CODEGEN_H
|
||||
+3159
File diff suppressed because it is too large
Load Diff
+303
@@ -0,0 +1,303 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_CONSTPOOL_H
|
||||
#define _ASMJIT_BASE_CONSTPOOL_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/error.h"
|
||||
#include "../base/zone.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPoolNode]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Zone-allocated constant-pool node.
|
||||
struct ConstPoolNode {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE void* getData() const {
|
||||
return static_cast<void*>(const_cast<ConstPoolNode*>(this) + 1);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Left/Right nodes.
|
||||
ConstPoolNode* _link[2];
|
||||
//! Horizontal level for balance.
|
||||
uint32_t _level : 31;
|
||||
//! Whether this constant is shared with another.
|
||||
uint32_t _shared : 1;
|
||||
//! Data offset from the beginning of the pool.
|
||||
uint32_t _offset;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPoolTree]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Zone-allocated constant-pool tree.
|
||||
struct ConstPoolTree {
|
||||
enum {
|
||||
//! Maximum tree height == log2(1 << 64).
|
||||
kHeightLimit = 64
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE ConstPoolTree(size_t dataSize = 0) :
|
||||
_root(NULL),
|
||||
_length(0),
|
||||
_dataSize(dataSize) {}
|
||||
ASMJIT_INLINE ~ConstPoolTree() {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE void reset() {
|
||||
_root = NULL;
|
||||
_length = 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE bool isEmpty() const {
|
||||
return _length == 0;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE size_t getLength() const {
|
||||
return _length;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void setDataSize(size_t dataSize) {
|
||||
ASMJIT_ASSERT(isEmpty());
|
||||
_dataSize = dataSize;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Ops]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API ConstPoolNode* get(const void* data);
|
||||
ASMJIT_API void put(ConstPoolNode* node);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Iterate]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
template<typename Visitor>
|
||||
ASMJIT_INLINE void iterate(Visitor& visitor) const {
|
||||
ConstPoolNode* node = const_cast<ConstPoolNode*>(_root);
|
||||
ConstPoolNode* link;
|
||||
|
||||
ConstPoolNode* stack[kHeightLimit];
|
||||
|
||||
if (node == NULL)
|
||||
return;
|
||||
|
||||
size_t top = 0;
|
||||
|
||||
for (;;) {
|
||||
link = node->_link[0];
|
||||
|
||||
if (link != NULL) {
|
||||
ASMJIT_ASSERT(top != kHeightLimit);
|
||||
stack[top++] = node;
|
||||
|
||||
node = link;
|
||||
continue;
|
||||
}
|
||||
|
||||
_Visit:
|
||||
visitor.visit(node);
|
||||
link = node->_link[1];
|
||||
|
||||
if (link != NULL) {
|
||||
node = link;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (top == 0)
|
||||
break;
|
||||
|
||||
node = stack[--top];
|
||||
goto _Visit;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Helpers]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
static ASMJIT_INLINE ConstPoolNode* _newNode(Zone* zone, const void* data, size_t size, size_t offset, bool shared) {
|
||||
ConstPoolNode* node = zone->allocT<ConstPoolNode>(sizeof(ConstPoolNode) + size);
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
node->_link[0] = NULL;
|
||||
node->_link[1] = NULL;
|
||||
node->_level = 1;
|
||||
node->_shared = shared;
|
||||
node->_offset = static_cast<uint32_t>(offset);
|
||||
|
||||
::memcpy(node->getData(), data, size);
|
||||
return node;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Root of the tree
|
||||
ConstPoolNode* _root;
|
||||
//! Length of the tree (count of nodes).
|
||||
size_t _length;
|
||||
//! Size of the data.
|
||||
size_t _dataSize;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPoolGap]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Zone-allocated constant-pool gap.
|
||||
struct ConstPoolGap {
|
||||
//! Link to the next gap
|
||||
ConstPoolGap* _next;
|
||||
//! Offset of the gap.
|
||||
size_t _offset;
|
||||
//! Remaining bytes of the gap (basically a gap size).
|
||||
size_t _length;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ConstPool]
|
||||
// ============================================================================
|
||||
|
||||
//! Constant pool.
|
||||
struct ConstPool {
|
||||
ASMJIT_NO_COPY(ConstPool)
|
||||
|
||||
enum {
|
||||
kIndex1 = 0,
|
||||
kIndex2 = 1,
|
||||
kIndex4 = 2,
|
||||
kIndex8 = 3,
|
||||
kIndex16 = 4,
|
||||
kIndex32 = 5,
|
||||
kIndexCount = 6
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API ConstPool(Zone* zone);
|
||||
ASMJIT_API ~ConstPool();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API void reset();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Ops]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether the constant-pool is empty.
|
||||
ASMJIT_INLINE bool isEmpty() const {
|
||||
return _size == 0;
|
||||
}
|
||||
|
||||
//! Get the size of the constant-pool in bytes.
|
||||
ASMJIT_INLINE size_t getSize() const {
|
||||
return _size;
|
||||
}
|
||||
|
||||
//! Get minimum alignment.
|
||||
ASMJIT_INLINE size_t getAlignment() const {
|
||||
return _alignment;
|
||||
}
|
||||
|
||||
//! Add a constant to the constant pool.
|
||||
//!
|
||||
//! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes.
|
||||
//! The constant is added to the pool only if it doesn't not exist, otherwise
|
||||
//! cached value is returned.
|
||||
//!
|
||||
//! AsmJit is able to subdivide added constants, so for example if you add
|
||||
//! 8-byte constant 0x1122334455667788 it will create the following slots:
|
||||
//!
|
||||
//! 8-byte: 0x1122334455667788
|
||||
//! 4-byte: 0x11223344, 0x55667788
|
||||
//!
|
||||
//! The reason is that when combining MMX/SSE/AVX code some patterns are used
|
||||
//! frequently. However, AsmJit is not able to reallocate a constant that has
|
||||
//! been already added. For example if you try to add 4-byte constant and then
|
||||
//! 8-byte constant having the same 4-byte pattern as the previous one, two
|
||||
//! independent slots will be generated by the pool.
|
||||
ASMJIT_API Error add(const void* data, size_t size, size_t& dstOffset);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Fill]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Fill the destination with the constants from the pool.
|
||||
ASMJIT_API void fill(void* dst);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Zone allocator.
|
||||
Zone* _zone;
|
||||
//! Tree per size.
|
||||
ConstPoolTree _tree[kIndexCount];
|
||||
//! Gaps per size.
|
||||
ConstPoolGap* _gaps[kIndexCount];
|
||||
//! Gaps pool
|
||||
ConstPoolGap* _gapPool;
|
||||
|
||||
//! Size of the pool (in bytes).
|
||||
size_t _size;
|
||||
//! Alignemnt.
|
||||
size_t _alignment;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_CONSTPOOL_H
|
||||
+350
@@ -0,0 +1,350 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_CONTAINERS_H
|
||||
#define _ASMJIT_BASE_CONTAINERS_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/error.h"
|
||||
#include "../base/globals.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::PodVectorData]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
struct PodVectorData {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get data.
|
||||
ASMJIT_INLINE void* getData() const {
|
||||
return (void*)(this + 1);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Capacity of the vector.
|
||||
size_t capacity;
|
||||
//! Length of the vector.
|
||||
size_t length;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::PodVectorBase]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
struct PodVectorBase {
|
||||
static ASMJIT_API const PodVectorData _nullData;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new instance of `PodVectorBase`.
|
||||
ASMJIT_INLINE PodVectorBase() :
|
||||
_d(const_cast<PodVectorData*>(&_nullData)) {}
|
||||
|
||||
//! Destroy the `PodVectorBase` and data.
|
||||
ASMJIT_INLINE ~PodVectorBase() {
|
||||
reset(true);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Reset the vector data and set its `length` to zero.
|
||||
//!
|
||||
//! If `releaseMemory` is true the vector buffer will be released to the
|
||||
//! system.
|
||||
ASMJIT_API void reset(bool releaseMemory = false);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Grow / Reserve]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
protected:
|
||||
ASMJIT_API Error _grow(size_t n, size_t sizeOfT);
|
||||
ASMJIT_API Error _reserve(size_t n, size_t sizeOfT);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
PodVectorData* _d;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::PodVector<T>]
|
||||
// ============================================================================
|
||||
|
||||
//! Template used to store and manage array of POD data.
|
||||
//!
|
||||
//! This template has these adventages over other vector<> templates:
|
||||
//! - Non-copyable (designed to be non-copyable, we want it)
|
||||
//! - No copy-on-write (some implementations of stl can use it)
|
||||
//! - Optimized for working only with POD types
|
||||
//! - Uses ASMJIT_... memory management macros
|
||||
template <typename T>
|
||||
struct PodVector : PodVectorBase {
|
||||
ASMJIT_NO_COPY(PodVector<T>)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new instance of `PodVector<T>`.
|
||||
ASMJIT_INLINE PodVector() {}
|
||||
//! Destroy the `PodVector<>` and data.
|
||||
ASMJIT_INLINE ~PodVector() {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Data]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether the vector is empty.
|
||||
ASMJIT_INLINE bool isEmpty() const {
|
||||
return _d->length == 0;
|
||||
}
|
||||
|
||||
//! Get length.
|
||||
ASMJIT_INLINE size_t getLength() const {
|
||||
return _d->length;
|
||||
}
|
||||
|
||||
//! Get capacity.
|
||||
ASMJIT_INLINE size_t getCapacity() const {
|
||||
return _d->capacity;
|
||||
}
|
||||
|
||||
//! Get data.
|
||||
ASMJIT_INLINE T* getData() {
|
||||
return static_cast<T*>(_d->getData());
|
||||
}
|
||||
|
||||
//! \overload
|
||||
ASMJIT_INLINE const T* getData() const {
|
||||
return static_cast<const T*>(_d->getData());
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Grow / Reserve]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Called to grow the buffer to fit at least `n` elements more.
|
||||
ASMJIT_INLINE Error _grow(size_t n) {
|
||||
return PodVectorBase::_grow(n, sizeof(T));
|
||||
}
|
||||
|
||||
//! Realloc internal array to fit at least `n` items.
|
||||
ASMJIT_INLINE Error _reserve(size_t n) {
|
||||
return PodVectorBase::_reserve(n, sizeof(T));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Ops]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Prepend `item` to vector.
|
||||
Error prepend(const T& item) {
|
||||
PodVectorData* d = _d;
|
||||
|
||||
if (d->length == d->capacity) {
|
||||
ASMJIT_PROPAGATE_ERROR(_grow(1));
|
||||
_d = d;
|
||||
}
|
||||
|
||||
::memmove(static_cast<T*>(d->getData()) + 1, d->getData(), d->length * sizeof(T));
|
||||
::memcpy(d->getData(), &item, sizeof(T));
|
||||
|
||||
d->length++;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//! Insert an `item` at the `index`.
|
||||
Error insert(size_t index, const T& item) {
|
||||
PodVectorData* d = _d;
|
||||
ASMJIT_ASSERT(index <= d->length);
|
||||
|
||||
if (d->length == d->capacity) {
|
||||
ASMJIT_PROPAGATE_ERROR(_grow(1));
|
||||
d = _d;
|
||||
}
|
||||
|
||||
T* dst = static_cast<T*>(d->getData()) + index;
|
||||
::memmove(dst + 1, dst, d->length - index);
|
||||
::memcpy(dst, &item, sizeof(T));
|
||||
|
||||
d->length++;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//! Append `item` to vector.
|
||||
Error append(const T& item) {
|
||||
PodVectorData* d = _d;
|
||||
|
||||
if (d->length == d->capacity) {
|
||||
ASMJIT_PROPAGATE_ERROR(_grow(1));
|
||||
d = _d;
|
||||
}
|
||||
|
||||
::memcpy(static_cast<T*>(d->getData()) + d->length, &item, sizeof(T));
|
||||
|
||||
d->length++;
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//! Get index of `val` or `kInvalidIndex` if not found.
|
||||
size_t indexOf(const T& val) const {
|
||||
PodVectorData* d = _d;
|
||||
|
||||
const T* data = static_cast<const T*>(d->getData());
|
||||
size_t len = d->length;
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
if (data[i] == val)
|
||||
return i;
|
||||
|
||||
return kInvalidIndex;
|
||||
}
|
||||
|
||||
//! Remove item at index `i`.
|
||||
void removeAt(size_t i) {
|
||||
PodVectorData* d = _d;
|
||||
ASMJIT_ASSERT(i < d->length);
|
||||
|
||||
T* data = static_cast<T*>(d->getData()) + i;
|
||||
d->length--;
|
||||
::memmove(data, data + 1, d->length - i);
|
||||
}
|
||||
|
||||
//! Swap this pod-vector with `other`.
|
||||
void swap(PodVector<T>& other) {
|
||||
T* otherData = other._d;
|
||||
other._d = _d;
|
||||
_d = otherData;
|
||||
}
|
||||
|
||||
//! Get item at index `i`.
|
||||
ASMJIT_INLINE T& operator[](size_t i) {
|
||||
ASMJIT_ASSERT(i < getLength());
|
||||
return getData()[i];
|
||||
}
|
||||
|
||||
//! Get item at index `i`.
|
||||
ASMJIT_INLINE const T& operator[](size_t i) const {
|
||||
ASMJIT_ASSERT(i < getLength());
|
||||
return getData()[i];
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::PodList<T>]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
template <typename T>
|
||||
struct PodList {
|
||||
ASMJIT_NO_COPY(PodList<T>)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Link]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
struct Link {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get next node.
|
||||
ASMJIT_INLINE Link* getNext() const { return _next; }
|
||||
|
||||
//! Get value.
|
||||
ASMJIT_INLINE T getValue() const { return _value; }
|
||||
//! Set value to `value`.
|
||||
ASMJIT_INLINE void setValue(const T& value) { _value = value; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
Link* _next;
|
||||
T _value;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE PodList() : _first(NULL), _last(NULL) {}
|
||||
ASMJIT_INLINE ~PodList() {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Data]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE bool isEmpty() const { return _first != NULL; }
|
||||
|
||||
ASMJIT_INLINE Link* getFirst() const { return _first; }
|
||||
ASMJIT_INLINE Link* getLast() const { return _last; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Ops]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE void reset() {
|
||||
_first = NULL;
|
||||
_last = NULL;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void prepend(Link* link) {
|
||||
link->_next = _first;
|
||||
if (_first == NULL)
|
||||
_last = link;
|
||||
_first = link;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void append(Link* link) {
|
||||
link->_next = NULL;
|
||||
if (_first == NULL)
|
||||
_first = link;
|
||||
else
|
||||
_last->_next = link;
|
||||
_last = link;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
Link* _first;
|
||||
Link* _last;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_CONTAINERS_H
|
||||
+307
@@ -0,0 +1,307 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_CONTEXT_P_H
|
||||
#define _ASMJIT_BASE_CONTEXT_P_H
|
||||
|
||||
#include "../build.h"
|
||||
#if !defined(ASMJIT_DISABLE_COMPILER)
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/compiler.h"
|
||||
#include "../base/zone.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_compiler
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Context]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Code generation context is the logic behind `Compiler`. The context is
|
||||
//! used to compile the code stored in `Compiler`.
|
||||
struct Context {
|
||||
ASMJIT_NO_COPY(Context)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
Context(Compiler* compiler);
|
||||
virtual ~Context();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Reset the whole context.
|
||||
virtual void reset(bool releaseMemory = false);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get compiler.
|
||||
ASMJIT_INLINE Compiler* getCompiler() const { return _compiler; }
|
||||
|
||||
//! Get function.
|
||||
ASMJIT_INLINE FuncNode* getFunc() const { return _func; }
|
||||
//! Get stop node.
|
||||
ASMJIT_INLINE Node* getStop() const { return _stop; }
|
||||
|
||||
//! Get start of the current scope.
|
||||
ASMJIT_INLINE Node* getStart() const { return _start; }
|
||||
//! Get end of the current scope.
|
||||
ASMJIT_INLINE Node* getEnd() const { return _end; }
|
||||
|
||||
//! Get extra block.
|
||||
ASMJIT_INLINE Node* getExtraBlock() const { return _extraBlock; }
|
||||
//! Set extra block.
|
||||
ASMJIT_INLINE void setExtraBlock(Node* node) { _extraBlock = node; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Error]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get the last error code.
|
||||
ASMJIT_INLINE Error getError() const {
|
||||
return getCompiler()->getError();
|
||||
}
|
||||
|
||||
//! Set the last error code and propagate it through the error handler.
|
||||
ASMJIT_INLINE Error setError(Error error, const char* message = NULL) {
|
||||
return getCompiler()->setError(error, message);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [State]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get current state.
|
||||
ASMJIT_INLINE VarState* getState() const {
|
||||
return _state;
|
||||
}
|
||||
|
||||
//! Load current state from `target` state.
|
||||
virtual void loadState(VarState* src) = 0;
|
||||
|
||||
//! Save current state, returning new `VarState` instance.
|
||||
virtual VarState* saveState() = 0;
|
||||
|
||||
//! Change the current state to `target` state.
|
||||
virtual void switchState(VarState* src) = 0;
|
||||
|
||||
//! Change the current state to the intersection of two states `a` and `b`.
|
||||
virtual void intersectStates(VarState* a, VarState* b) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Context]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE Error _registerContextVar(VarData* vd) {
|
||||
if (vd->hasContextId())
|
||||
return kErrorOk;
|
||||
|
||||
uint32_t cid = static_cast<uint32_t>(_contextVd.getLength());
|
||||
ASMJIT_PROPAGATE_ERROR(_contextVd.append(vd));
|
||||
|
||||
vd->setContextId(cid);
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Mem]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
MemCell* _newVarCell(VarData* vd);
|
||||
MemCell* _newStackCell(uint32_t size, uint32_t alignment);
|
||||
|
||||
ASMJIT_INLINE MemCell* getVarCell(VarData* vd) {
|
||||
MemCell* cell = vd->getMemCell();
|
||||
return cell ? cell : _newVarCell(vd);
|
||||
}
|
||||
|
||||
virtual Error resolveCellOffsets();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Bits]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE VarBits* newBits(uint32_t len) {
|
||||
return static_cast<VarBits*>(
|
||||
_baseZone.allocZeroed(static_cast<size_t>(len) * VarBits::kEntitySize));
|
||||
}
|
||||
|
||||
ASMJIT_INLINE VarBits* copyBits(const VarBits* src, uint32_t len) {
|
||||
return static_cast<VarBits*>(
|
||||
_baseZone.dup(src, static_cast<size_t>(len) * VarBits::kEntitySize));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Fetch]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Fetch.
|
||||
//!
|
||||
//! Fetch iterates over all nodes and gathers information about all variables
|
||||
//! used. The process generates information required by register allocator,
|
||||
//! variable liveness analysis and translator.
|
||||
virtual Error fetch() = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [RemoveUnreachableCode]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Remove unreachable code.
|
||||
virtual Error removeUnreachableCode();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Analyze]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Perform variable liveness analysis.
|
||||
//!
|
||||
//! Analysis phase iterates over nodes in reverse order and generates a bit
|
||||
//! array describing variables that are alive at every node in the function.
|
||||
//! When the analysis start all variables are assumed dead. When a read or
|
||||
//! read/write operations of a variable is detected the variable becomes
|
||||
//! alive; when only write operation is detected the variable becomes dead.
|
||||
//!
|
||||
//! When a label is found all jumps to that label are followed and analysis
|
||||
//! repeats until all variables are resolved.
|
||||
virtual Error livenessAnalysis();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Annotate]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error annotate() = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Translate]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Translate code by allocating registers and handling state changes.
|
||||
virtual Error translate() = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Schedule]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error schedule();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Cleanup]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Compile]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error compile(FuncNode* func);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Serialize]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error serialize(Assembler* assembler, Node* start, Node* stop) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Compiler.
|
||||
Compiler* _compiler;
|
||||
//! Function.
|
||||
FuncNode* _func;
|
||||
|
||||
//! Zone allocator.
|
||||
Zone _baseZone;
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Offset (how many bytes to add) to `VarMap` to get `VarAttr` array. Used
|
||||
//! by liveness analysis shared across all backends. This is needed because
|
||||
//! `VarMap` is a base class for a specialized version that liveness analysis
|
||||
//! doesn't use, it just needs `VarAttr` array.
|
||||
uint32_t _varMapToVaListOffset;
|
||||
|
||||
//! Start of the current active scope.
|
||||
Node* _start;
|
||||
//! End of the current active scope.
|
||||
Node* _end;
|
||||
|
||||
//! Node that is used to insert extra code after the function body.
|
||||
Node* _extraBlock;
|
||||
//! Stop node.
|
||||
Node* _stop;
|
||||
|
||||
//! Unreachable nodes.
|
||||
PodList<Node*> _unreachableList;
|
||||
//! Jump nodes.
|
||||
PodList<Node*> _jccList;
|
||||
|
||||
//! All variables used by the current function.
|
||||
PodVector<VarData*> _contextVd;
|
||||
|
||||
//! Memory used to spill variables.
|
||||
MemCell* _memVarCells;
|
||||
//! Memory used to alloc memory on the stack.
|
||||
MemCell* _memStackCells;
|
||||
|
||||
//! Count of 1-byte cells.
|
||||
uint32_t _mem1ByteVarsUsed;
|
||||
//! Count of 2-byte cells.
|
||||
uint32_t _mem2ByteVarsUsed;
|
||||
//! Count of 4-byte cells.
|
||||
uint32_t _mem4ByteVarsUsed;
|
||||
//! Count of 8-byte cells.
|
||||
uint32_t _mem8ByteVarsUsed;
|
||||
//! Count of 16-byte cells.
|
||||
uint32_t _mem16ByteVarsUsed;
|
||||
//! Count of 32-byte cells.
|
||||
uint32_t _mem32ByteVarsUsed;
|
||||
//! Count of 64-byte cells.
|
||||
uint32_t _mem64ByteVarsUsed;
|
||||
//! Count of stack memory cells.
|
||||
uint32_t _memStackCellsUsed;
|
||||
|
||||
//! Maximum memory alignment used by the function.
|
||||
uint32_t _memMaxAlign;
|
||||
//! Count of bytes used by variables.
|
||||
uint32_t _memVarTotal;
|
||||
//! Count of bytes used by stack.
|
||||
uint32_t _memStackTotal;
|
||||
//! Count of bytes used by variables and stack after alignment.
|
||||
uint32_t _memAllTotal;
|
||||
|
||||
//! Default lenght of annotated instruction.
|
||||
uint32_t _annotationLength;
|
||||
|
||||
//! Current state (used by register allocator).
|
||||
VarState* _state;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // !ASMJIT_DISABLE_COMPILER
|
||||
#endif // _ASMJIT_BASE_CONTEXT_P_H
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_CPUINFO_H
|
||||
#define _ASMJIT_BASE_CPUINFO_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/globals.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_general
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kCpuVendor]
|
||||
// ============================================================================
|
||||
|
||||
//! Cpu vendor ID.
|
||||
//!
|
||||
//! Vendor IDs are specific to AsmJit library. During the library initialization
|
||||
//! AsmJit checks host CPU and tries to identify the vendor based on the CPUID
|
||||
//! calls. Some manufacturers changed their vendor strings and AsmJit is aware
|
||||
//! of that - it checks multiple combinations and decides which vendor ID should
|
||||
//! be used.
|
||||
ASMJIT_ENUM(kCpuVendor) {
|
||||
//! No/Unknown vendor.
|
||||
kCpuVendorNone = 0,
|
||||
|
||||
//! Intel vendor.
|
||||
kCpuVendorIntel = 1,
|
||||
//! AMD vendor.
|
||||
kCpuVendorAmd = 2,
|
||||
//! VIA vendor.
|
||||
kCpuVendorVia = 3
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CpuInfo]
|
||||
// ============================================================================
|
||||
|
||||
//! Base cpu information.
|
||||
struct CpuInfo {
|
||||
ASMJIT_NO_COPY(CpuInfo)
|
||||
|
||||
//! \internal
|
||||
enum {
|
||||
kFeaturesPerUInt32 = static_cast<int>(sizeof(uint32_t)) * 8
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE CpuInfo(uint32_t size = sizeof(CpuInfo)) : _size(size) {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get CPU vendor string.
|
||||
ASMJIT_INLINE const char* getVendorString() const { return _vendorString; }
|
||||
//! Get CPU brand string.
|
||||
ASMJIT_INLINE const char* getBrandString() const { return _brandString; }
|
||||
|
||||
//! Get CPU vendor ID.
|
||||
ASMJIT_INLINE uint32_t getVendorId() const { return _vendorId; }
|
||||
//! Get CPU family ID.
|
||||
ASMJIT_INLINE uint32_t getFamily() const { return _family; }
|
||||
//! Get CPU model ID.
|
||||
ASMJIT_INLINE uint32_t getModel() const { return _model; }
|
||||
//! Get CPU stepping.
|
||||
ASMJIT_INLINE uint32_t getStepping() const { return _stepping; }
|
||||
|
||||
//! Get number of hardware threads available.
|
||||
ASMJIT_INLINE uint32_t getHwThreadsCount() const { return _hwThreadsCount; }
|
||||
|
||||
//! Get whether CPU has a `feature`.
|
||||
ASMJIT_INLINE bool hasFeature(uint32_t feature) const {
|
||||
ASMJIT_ASSERT(feature < sizeof(_features) * 8);
|
||||
|
||||
return static_cast<bool>(
|
||||
(_features[feature / kFeaturesPerUInt32] >> (feature % kFeaturesPerUInt32)) & 0x1);
|
||||
}
|
||||
|
||||
//! Add a CPU `feature`.
|
||||
ASMJIT_INLINE CpuInfo& addFeature(uint32_t feature) {
|
||||
ASMJIT_ASSERT(feature < sizeof(_features) * 8);
|
||||
|
||||
_features[feature / kFeaturesPerUInt32] |= (1U << (feature % kFeaturesPerUInt32));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Statics]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Detect the number of hardware threads.
|
||||
static ASMJIT_API uint32_t detectHwThreadsCount();
|
||||
|
||||
//! Get host cpu.
|
||||
static ASMJIT_API const CpuInfo* getHost();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Size of the structure in bytes.
|
||||
uint32_t _size;
|
||||
|
||||
//! Cpu short vendor string.
|
||||
char _vendorString[16];
|
||||
//! Cpu long vendor string (brand).
|
||||
char _brandString[64];
|
||||
|
||||
//! Cpu vendor id, see `asmjit::kCpuVendor`.
|
||||
uint32_t _vendorId;
|
||||
//! Cpu family ID.
|
||||
uint32_t _family;
|
||||
//! Cpu model ID.
|
||||
uint32_t _model;
|
||||
//! Cpu stepping.
|
||||
uint32_t _stepping;
|
||||
|
||||
//! Number of hardware threads.
|
||||
uint32_t _hwThreadsCount;
|
||||
|
||||
//! Cpu features bitfield.
|
||||
uint32_t _features[4];
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_CPUINFO_H
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_CPUTICKS_H
|
||||
#define _ASMJIT_BASE_CPUTICKS_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/globals.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::CpuTicks]
|
||||
// ============================================================================
|
||||
|
||||
//! CPU ticks utilities.
|
||||
struct CpuTicks {
|
||||
//! Get the current CPU ticks for benchmarking (1ms resolution).
|
||||
static ASMJIT_API uint32_t now();
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_CPUTICKS_H
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_ERROR_H
|
||||
#define _ASMJIT_BASE_ERROR_H
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/globals.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_general
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kError]
|
||||
// ============================================================================
|
||||
|
||||
//! AsmJit error codes.
|
||||
ASMJIT_ENUM(kError) {
|
||||
//! No error (success).
|
||||
//!
|
||||
//! This is default state and state you want.
|
||||
kErrorOk = 0,
|
||||
|
||||
//! Heap memory allocation failed.
|
||||
kErrorNoHeapMemory = 1,
|
||||
|
||||
//! Virtual memory allocation failed.
|
||||
kErrorNoVirtualMemory = 2,
|
||||
|
||||
//! Invalid argument.
|
||||
kErrorInvalidArgument = 3,
|
||||
|
||||
//! Invalid state.
|
||||
kErrorInvalidState = 4,
|
||||
|
||||
//! No code generated.
|
||||
//!
|
||||
//! Returned by runtime if the code-generator contains no code.
|
||||
kErrorNoCodeGenerated = 5,
|
||||
|
||||
//! Code generated is too large to fit in memory reserved.
|
||||
//!
|
||||
//! Returned by `StaticRuntime` in case that the code generated is too large
|
||||
//! to fit in the memory already reserved for it.
|
||||
kErrorCodeTooLarge = 6,
|
||||
|
||||
//! Label is already bound.
|
||||
kErrorLabelAlreadyBound = 7,
|
||||
|
||||
//! Unknown instruction (an instruction ID is out of bounds or instruction
|
||||
//! name is invalid).
|
||||
kErrorUnknownInst = 8,
|
||||
|
||||
//! Illegal instruction.
|
||||
//!
|
||||
//! This status code can also be returned in X64 mode if AH, BH, CH or DH
|
||||
//! registers have been used together with a REX prefix. The instruction
|
||||
//! is not encodable in such case.
|
||||
//!
|
||||
//! Example of raising `kErrorIllegalInst` error.
|
||||
//!
|
||||
//! ~~~
|
||||
//! // Invalid address size.
|
||||
//! a.mov(dword_ptr(eax), al);
|
||||
//!
|
||||
//! // Undecodable instruction - AH used with R10, however R10 can only be
|
||||
//! // encoded by using REX prefix, which conflicts with AH.
|
||||
//! a.mov(byte_ptr(r10), ah);
|
||||
//! ~~~
|
||||
//!
|
||||
//! \note In debug mode assertion is raised instead of returning an error.
|
||||
kErrorIllegalInst = 9,
|
||||
|
||||
//! Illegal (unencodable) addressing used.
|
||||
kErrorIllegalAddresing = 10,
|
||||
|
||||
//! Illegal (unencodable) displacement used.
|
||||
//!
|
||||
//! X86/X64
|
||||
//! -------
|
||||
//!
|
||||
//! Short form of jump instruction has been used, but the displacement is out
|
||||
//! of bounds.
|
||||
kErrorIllegalDisplacement = 11,
|
||||
|
||||
//! A variable has been assigned more than once to a function argument (Compiler).
|
||||
kErrorOverlappedArgs = 12,
|
||||
|
||||
//! Count of AsmJit error codes.
|
||||
kErrorCount = 13
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Error]
|
||||
// ============================================================================
|
||||
|
||||
//! AsmJit error type (unsigned integer).
|
||||
typedef uint32_t Error;
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ErrorHandler]
|
||||
// ============================================================================
|
||||
|
||||
//! Error handler.
|
||||
//!
|
||||
//! Error handler can be used to override the default behavior of `CodeGen`
|
||||
//! error handling and propagation. See `handleError` on how to override it.
|
||||
//!
|
||||
//! Please note that `addRef` and `release` functions are used, but there is
|
||||
//! no reference counting implemented by default, reimplement to change the
|
||||
//! default behavior.
|
||||
struct ASMJIT_VCLASS ErrorHandler {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new `ErrorHandler` instance.
|
||||
ASMJIT_API ErrorHandler();
|
||||
//! Destroy the `ErrorHandler` instance.
|
||||
ASMJIT_API virtual ~ErrorHandler();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Reference this error handler.
|
||||
//!
|
||||
//! \note This member function is provided for convenience. The default
|
||||
//! implementation does nothing. If you are working in environment where
|
||||
//! multiple `ErrorHandler` instances are used by a different code generators
|
||||
//! you may provide your own functionality for reference counting. In that
|
||||
//! case `addRef()` and `release()` functions should be overridden.
|
||||
ASMJIT_API virtual ErrorHandler* addRef() const;
|
||||
|
||||
//! Release this error handler.
|
||||
//!
|
||||
//! \note This member function is provided for convenience. See `addRef()`
|
||||
//! for more detailed information related to reference counting.
|
||||
ASMJIT_API virtual void release();
|
||||
|
||||
//! Error handler (pure).
|
||||
//!
|
||||
//! Error handler is called when an error happened. An error can happen in
|
||||
//! many places, but error handler is mostly used by `Assembler` and
|
||||
//! `Compiler` classes to report anything that may cause incorrect code
|
||||
//! generation. There are multiple ways how the error handler can be used
|
||||
//! and each has it's pros/cons.
|
||||
//!
|
||||
//! AsmJit library doesn't use exceptions and can be compiled with or without
|
||||
//! exception handling support. Even if the AsmJit library is compiled without
|
||||
//! exceptions it is exception-safe and handleError() can report an incoming
|
||||
//! error by throwing an exception of any type. It's guaranteed that the
|
||||
//! exception won't be catched by AsmJit and will be propagated to the code
|
||||
//! calling AsmJit `Assembler` or `Compiler` methods. Alternative to
|
||||
//! throwing an exception is using `setjmp()` and `longjmp()` pair available
|
||||
//! in the standard C library.
|
||||
//!
|
||||
//! If the exception or setjmp() / longjmp() mechanism is used, the state of
|
||||
//! the `BaseAssember` or `Compiler` is unchanged and if it's possible the
|
||||
//! execution (instruction serialization) can continue. However if the error
|
||||
//! happened during any phase that translates or modifies the stored code
|
||||
//! (for example relocation done by `Assembler` or analysis/translation
|
||||
//! done by `Compiler`) the execution can't continue and the error will
|
||||
//! be also stored in `Assembler` or `Compiler`.
|
||||
//!
|
||||
//! Finally, if no exceptions nor setjmp() / longjmp() mechanisms were used,
|
||||
//! you can still implement a compatible handling by returning from your
|
||||
//! error handler. Returning `true` means that error was reported and AsmJit
|
||||
//! should continue execution, but `false` sets the rror immediately to the
|
||||
//! `Assembler` or `Compiler` and execution shouldn't continue (this
|
||||
//! is the default behavior in case no error handler is used).
|
||||
virtual bool handleError(Error code, const char* message) = 0;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::ErrorUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! Error utilities.
|
||||
struct ErrorUtil {
|
||||
#if !defined(ASMJIT_DISABLE_NAMES)
|
||||
//! Get printable version of AsmJit `kError` code.
|
||||
static ASMJIT_API const char* asString(Error code);
|
||||
#endif // ASMJIT_DISABLE_NAMES
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
// ============================================================================
|
||||
// [ASMJIT_PROPAGATE_ERROR]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Used by AsmJit to return the `_Exp_` result if it's an error.
|
||||
#define ASMJIT_PROPAGATE_ERROR(_Exp_) \
|
||||
do { \
|
||||
::asmjit::Error errval_ = (_Exp_); \
|
||||
if (errval_ != ::asmjit::kErrorOk) \
|
||||
return errval_; \
|
||||
} while (0)
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_ERROR_H
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_GLOBALS_H
|
||||
#define _ASMJIT_BASE_GLOBALS_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../build.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_general
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Ptr / SignedPtr]
|
||||
// ============================================================================
|
||||
|
||||
//! 64-bit unsigned pointer, compatible with JIT and non-JIT generators.
|
||||
//!
|
||||
//! This is the preferred pointer type to use with AsmJit library. It has a
|
||||
//! capability to hold any pointer for any architecture making it an ideal
|
||||
//! candidate for cross-platform code generation.
|
||||
typedef uint64_t Ptr;
|
||||
|
||||
//! 64-bit signed pointer, like \ref Ptr, but made signed.
|
||||
typedef int64_t SignedPtr;
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kGlobals]
|
||||
// ============================================================================
|
||||
|
||||
//! Invalid index
|
||||
//!
|
||||
//! Invalid index is the last possible index that is never used in practice. In
|
||||
//! AsmJit it is used exclusively with strings to indicate the the length of the
|
||||
//! string is not known and has to be determined.
|
||||
static const size_t kInvalidIndex = ~static_cast<size_t>(0);
|
||||
|
||||
//! Invalid base address.
|
||||
static const Ptr kNoBaseAddress = static_cast<Ptr>(static_cast<SignedPtr>(-1));
|
||||
|
||||
//! Global constants.
|
||||
ASMJIT_ENUM(kGlobals) {
|
||||
//! Invalid value or operand id.
|
||||
kInvalidValue = 0xFFFFFFFF,
|
||||
|
||||
//! Invalid register index.
|
||||
kInvalidReg = 0xFF,
|
||||
//! Invalid variable type.
|
||||
kInvalidVar = 0xFF,
|
||||
|
||||
//! Host memory allocator overhead.
|
||||
//!
|
||||
//! The overhead is decremented from all zone allocators so the operating
|
||||
//! system doesn't have allocate extra virtual page to keep tract of the
|
||||
//! requested memory block.
|
||||
//!
|
||||
//! The number is actually a guess.
|
||||
kMemAllocOverhead = sizeof(intptr_t) * 4,
|
||||
|
||||
//! Memory grow threshold.
|
||||
//!
|
||||
//! After the grow threshold is reached the capacity won't be doubled
|
||||
//! anymore.
|
||||
kMemAllocGrowMax = 8192 * 1024
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kArch]
|
||||
// ============================================================================
|
||||
|
||||
//! Architecture.
|
||||
ASMJIT_ENUM(kArch) {
|
||||
//! No/Unknown architecture.
|
||||
kArchNone = 0,
|
||||
|
||||
//! X86 architecture.
|
||||
kArchX86 = 1,
|
||||
//! X64 architecture, also called AMD64.
|
||||
kArchX64 = 2,
|
||||
|
||||
//! Arm architecture.
|
||||
kArchArm = 4,
|
||||
|
||||
#if defined(ASMJIT_HOST_X86)
|
||||
kArchHost = kArchX86,
|
||||
#endif // ASMJIT_HOST_X86
|
||||
|
||||
#if defined(ASMJIT_HOST_X64)
|
||||
kArchHost = kArchX64,
|
||||
#endif // ASMJIT_HOST_X64
|
||||
|
||||
#if defined(ASMJIT_HOST_ARM)
|
||||
kArchHost = kArchArm,
|
||||
#endif // ASMJIT_HOST_ARM
|
||||
|
||||
//! Whether the host is 64-bit.
|
||||
kArchHost64Bit = sizeof(intptr_t) >= 8
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Init / NoInit]
|
||||
// ============================================================================
|
||||
|
||||
#if !defined(ASMJIT_DOCGEN)
|
||||
struct _Init {};
|
||||
static const _Init Init = {};
|
||||
|
||||
struct _NoInit {};
|
||||
static const _NoInit NoInit = {};
|
||||
#endif // !ASMJIT_DOCGEN
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Assert]
|
||||
// ============================================================================
|
||||
|
||||
//! \addtogroup asmjit_base_general
|
||||
//! \{
|
||||
|
||||
//! Called in debug build on assertion failure.
|
||||
//!
|
||||
//! \param exp Expression that failed.
|
||||
//! \param file Source file name where it happened.
|
||||
//! \param line Line in the source file.
|
||||
//!
|
||||
//! If you have problems with assertions put a breakpoint at assertionFailed()
|
||||
//! function (asmjit/base/globals.cpp) and check the call stack to locate the
|
||||
//! failing code.
|
||||
ASMJIT_API void assertionFailed(const char* exp, const char* file, int line);
|
||||
|
||||
#if defined(ASMJIT_DEBUG)
|
||||
#define ASMJIT_ASSERT(_Exp_) \
|
||||
do { \
|
||||
if (!(_Exp_)) ::asmjit::assertionFailed(#_Exp_, __FILE__, __LINE__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ASMJIT_ASSERT(_Exp_) ASMJIT_NOP()
|
||||
#endif // DEBUG
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit_cast<>]
|
||||
// ============================================================================
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
//! Cast used to cast pointer to function. It's like reinterpret_cast<>,
|
||||
//! but uses internally C style cast to work with MinGW.
|
||||
//!
|
||||
//! If you are using single compiler and `reinterpret_cast<>` works for you,
|
||||
//! there is no reason to use `asmjit_cast<>`. If you are writing
|
||||
//! cross-platform software with various compiler support, consider using
|
||||
//! `asmjit_cast<>` instead of `reinterpret_cast<>`.
|
||||
template<typename T, typename Z>
|
||||
static ASMJIT_INLINE T asmjit_cast(Z* p) { return (T)p; }
|
||||
|
||||
//! \}
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_GLOBALS_H
|
||||
+713
@@ -0,0 +1,713 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_INTUTIL_H
|
||||
#define _ASMJIT_BASE_INTUTIL_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/globals.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::IntTraits]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
template<typename T>
|
||||
struct IntTraits {
|
||||
enum {
|
||||
kIsSigned = static_cast<T>(~static_cast<T>(0)) < static_cast<T>(0),
|
||||
kIsUnsigned = !kIsSigned,
|
||||
|
||||
kIs8Bit = sizeof(T) == 1,
|
||||
kIs16Bit = sizeof(T) == 2,
|
||||
kIs32Bit = sizeof(T) == 4,
|
||||
kIs64Bit = sizeof(T) == 8,
|
||||
|
||||
kIsIntPtr = sizeof(T) == sizeof(intptr_t)
|
||||
};
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::IntUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! Integer utilities.
|
||||
struct IntUtil {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Float <-> Int]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! \internal
|
||||
union Float {
|
||||
int32_t i;
|
||||
float f;
|
||||
};
|
||||
|
||||
//! \internal
|
||||
union Double {
|
||||
int64_t i;
|
||||
double d;
|
||||
};
|
||||
|
||||
//! Bit-cast `float` to 32-bit integer.
|
||||
static ASMJIT_INLINE int32_t floatAsInt(float f) { Float m; m.f = f; return m.i; }
|
||||
//! Bit-cast 32-bit integer to `float`.
|
||||
static ASMJIT_INLINE float intAsFloat(int32_t i) { Float m; m.i = i; return m.f; }
|
||||
|
||||
//! Bit-cast `double` to 64-bit integer.
|
||||
static ASMJIT_INLINE int64_t doubleAsInt(double d) { Double m; m.d = d; return m.i; }
|
||||
//! Bit-cast 64-bit integer to `double`.
|
||||
static ASMJIT_INLINE double intAsDouble(int64_t i) { Double m; m.i = i; return m.d; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Pack / Unpack]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Pack two 8-bit integer and one 16-bit integer into a 32-bit integer as it
|
||||
//! is an array of `{u0,u1,w2}`.
|
||||
static ASMJIT_INLINE uint32_t pack32_2x8_1x16(uint32_t u0, uint32_t u1, uint32_t w2) {
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
return u0 + (u1 << 8) + (w2 << 16);
|
||||
#else
|
||||
return (u0 << 24) + (u1 << 16) + (w2);
|
||||
#endif // ASMJIT_HOST
|
||||
}
|
||||
|
||||
//! Pack four 8-bit integer into a 32-bit integer as it is an array of `{u0,u1,u2,u3}`.
|
||||
static ASMJIT_INLINE uint32_t pack32_4x8(uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) {
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
return u0 + (u1 << 8) + (u2 << 16) + (u3 << 24);
|
||||
#else
|
||||
return (u0 << 24) + (u1 << 16) + (u2 << 8) + u3;
|
||||
#endif // ASMJIT_HOST
|
||||
}
|
||||
|
||||
//! Pack two 32-bit integer into a 64-bit integer as it is an array of `{u0,u1}`.
|
||||
static ASMJIT_INLINE uint64_t pack64_2x32(uint32_t u0, uint32_t u1) {
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
return (static_cast<uint64_t>(u1) << 32) + u0;
|
||||
#else
|
||||
return (static_cast<uint64_t>(u0) << 32) + u1;
|
||||
#endif // ASMJIT_HOST
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Min/Max]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// NOTE: Because some environments declare min() and max() as macros, it has
|
||||
// been decided to use different name so we never collide with them.
|
||||
|
||||
//! Get minimum value of `a` and `b`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T iMin(const T& a, const T& b) { return a < b ? a : b; }
|
||||
|
||||
//! Get maximum value of `a` and `b`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T iMax(const T& a, const T& b) { return a > b ? a : b; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - MaxUInt]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get maximum unsigned value of `T`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T maxUInt() { return ~T(0); }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - InInterval]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether `x` is greater or equal than `start` and less or equal than `end`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool inInterval(const T& x, const T& start, const T& end) {
|
||||
return x >= start && x <= end;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - IsInt/IsUInt]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether the given integer `x` can be casted to 8-bit signed integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isInt8(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
return sizeof(T) <= sizeof(int8_t) ? true : x >= T(-128) && x <= T(127);
|
||||
else
|
||||
return x <= T(127);
|
||||
}
|
||||
|
||||
//! Get whether the given integer `x` can be casted to 8-bit unsigned integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isUInt8(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
return x >= T(0) && (sizeof(T) <= sizeof(uint8_t) ? true : x <= T(255));
|
||||
else
|
||||
return sizeof(T) <= sizeof(uint8_t) ? true : x <= T(255);
|
||||
}
|
||||
|
||||
//! Get whether the given integer `x` can be casted to 16-bit signed integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isInt16(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
return sizeof(T) <= sizeof(int16_t) ? true : x >= T(-32768) && x <= T(32767);
|
||||
else
|
||||
return x >= T(0) && (sizeof(T) <= sizeof(int16_t) ? true : x <= T(32767));
|
||||
}
|
||||
|
||||
//! Get whether the given integer `x` can be casted to 16-bit unsigned integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isUInt16(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
return x >= T(0) && (sizeof(T) <= sizeof(uint16_t) ? true : x <= T(65535));
|
||||
else
|
||||
return sizeof(T) <= sizeof(uint16_t) ? true : x <= T(65535);
|
||||
}
|
||||
|
||||
//! Get whether the given integer `x` can be casted to 32-bit signed integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isInt32(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
return sizeof(T) <= sizeof(int32_t) ? true : x >= T(-2147483647) - 1 && x <= T(2147483647);
|
||||
else
|
||||
return x >= T(0) && (sizeof(T) <= sizeof(int32_t) ? true : x <= T(2147483647));
|
||||
}
|
||||
|
||||
//! Get whether the given integer `x` can be casted to 32-bit unsigned integer.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isUInt32(T x) {
|
||||
if (IntTraits<T>::kIsSigned)
|
||||
return x >= T(0) && (sizeof(T) <= sizeof(uint32_t) ? true : x <= T(4294967295U));
|
||||
else
|
||||
return sizeof(T) <= sizeof(uint32_t) ? true : x <= T(4294967295U);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - IsPowerOf2]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether the `n` value is a power of two (only one bit is set).
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isPowerOf2(T n) {
|
||||
return n != 0 && (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Mask]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Generate a bit-mask that has `x` bit set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x) {
|
||||
ASMJIT_ASSERT(x < 32);
|
||||
return (1U << x);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0` and `x1` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1) {
|
||||
return mask(x0) | mask(x1);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1` and `x2` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2) {
|
||||
return mask(x0) | mask(x1) | mask(x2);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2` and `x3` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3);
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3` and `x4` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4` and `x5` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5` and `x6` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6` and `x7` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) | mask(x7) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7` and `x8` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) | mask(x7) |
|
||||
mask(x8) ;
|
||||
}
|
||||
|
||||
//! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7`, `x8` and `x9` bits set.
|
||||
static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8, uint32_t x9) {
|
||||
return mask(x0) | mask(x1) | mask(x2) | mask(x3) |
|
||||
mask(x4) | mask(x5) | mask(x6) | mask(x7) |
|
||||
mask(x8) | mask(x9) ;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Bits]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Generate a bit-mask that has `x` most significant bits set.
|
||||
static ASMJIT_INLINE uint32_t bits(uint32_t x) {
|
||||
// Shifting more bits that the type has has undefined behavior. Everything
|
||||
// we need is that application shouldn't crash because of that, but the
|
||||
// content of register after shift is not defined. So in case that the
|
||||
// requested shift is too large for the type we correct this undefined
|
||||
// behavior by setting all bits to ones (this is why we generate an overflow
|
||||
// mask).
|
||||
uint32_t overflow = static_cast<uint32_t>(
|
||||
-static_cast<int32_t>(x >= sizeof(uint32_t) * 8));
|
||||
|
||||
return ((static_cast<uint32_t>(1) << x) - 1U) | overflow;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - HasBit]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get whether `x` has bit `n` set.
|
||||
static ASMJIT_INLINE bool hasBit(uint32_t x, uint32_t n) {
|
||||
return static_cast<bool>((x >> n) & 0x1);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - BitCount]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get count of bits in `x`.
|
||||
//!
|
||||
//! Taken from http://graphics.stanford.edu/~seander/bithacks.html .
|
||||
static ASMJIT_INLINE uint32_t bitCount(uint32_t x) {
|
||||
x = x - ((x >> 1) & 0x55555555U);
|
||||
x = (x & 0x33333333U) + ((x >> 2) & 0x33333333U);
|
||||
return (((x + (x >> 4)) & 0x0F0F0F0FU) * 0x01010101U) >> 24;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - FindFirstBit]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! \internal
|
||||
static ASMJIT_INLINE uint32_t findFirstBitSlow(uint32_t mask) {
|
||||
// This is a reference (slow) implementation of findFirstBit(), used when
|
||||
// we don't have compiler support for this task. The implementation speed
|
||||
// has been improved to check for 2 bits per iteration.
|
||||
uint32_t i = 1;
|
||||
|
||||
while (mask != 0) {
|
||||
uint32_t two = mask & 0x3;
|
||||
if (two != 0x0)
|
||||
return i - (two & 0x1);
|
||||
|
||||
i += 2;
|
||||
mask >>= 2;
|
||||
}
|
||||
|
||||
return 0xFFFFFFFFU;
|
||||
}
|
||||
|
||||
//! Find a first bit in `mask`.
|
||||
static ASMJIT_INLINE uint32_t findFirstBit(uint32_t mask) {
|
||||
#if defined(_MSC_VER)
|
||||
DWORD i;
|
||||
if (_BitScanForward(&i, mask)) {
|
||||
ASMJIT_ASSERT(findFirstBitSlow(mask) == i);
|
||||
return static_cast<uint32_t>(i);
|
||||
}
|
||||
return 0xFFFFFFFFU;
|
||||
#else
|
||||
return findFirstBitSlow(mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Misc]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
static ASMJIT_INLINE uint32_t keepNOnesFromRight(uint32_t mask, uint32_t nBits) {
|
||||
uint32_t m = 0x1;
|
||||
|
||||
do {
|
||||
nBits -= (mask & m) == 0;
|
||||
m <<= 1;
|
||||
if (nBits == 0) {
|
||||
m -= 1;
|
||||
mask &= m;
|
||||
break;
|
||||
}
|
||||
} while (m);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static ASMJIT_INLINE uint32_t indexNOnesFromRight(uint8_t* dst, uint32_t mask, uint32_t nBits) {
|
||||
uint32_t totalBits = nBits;
|
||||
uint8_t i = 0;
|
||||
uint32_t m = 0x1;
|
||||
|
||||
do {
|
||||
if (mask & m) {
|
||||
*dst++ = i;
|
||||
if (--nBits == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
m <<= 1;
|
||||
i++;
|
||||
} while (m);
|
||||
|
||||
return totalBits - nBits;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AsmJit - Alignment]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE bool isAligned(T base, T alignment) {
|
||||
return (base % alignment) == 0;
|
||||
}
|
||||
|
||||
//! Align `base` to `alignment`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T alignTo(T base, T alignment) {
|
||||
return (base + (alignment - 1)) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T alignToPowerOf2(T base) {
|
||||
// Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.
|
||||
base -= 1;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4293)
|
||||
#endif // _MSC_VER
|
||||
|
||||
base = base | (base >> 1);
|
||||
base = base | (base >> 2);
|
||||
base = base | (base >> 4);
|
||||
|
||||
// 8/16/32 constants are multiplied by the condition to prevent a compiler
|
||||
// complaining about the 'shift count >= type width' (GCC).
|
||||
if (sizeof(T) >= 2) base = base | (base >> ( 8 * (sizeof(T) >= 2))); // Base >> 8.
|
||||
if (sizeof(T) >= 4) base = base | (base >> (16 * (sizeof(T) >= 4))); // Base >> 16.
|
||||
if (sizeof(T) >= 8) base = base | (base >> (32 * (sizeof(T) >= 8))); // Base >> 32.
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
return base + 1;
|
||||
}
|
||||
|
||||
//! Get delta required to align `base` to `alignment`.
|
||||
template<typename T>
|
||||
static ASMJIT_INLINE T deltaTo(T base, T alignment) {
|
||||
return alignTo(base, alignment) - base;
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::UInt64]
|
||||
// ============================================================================
|
||||
|
||||
union UInt64 {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64 fromUInt64(uint64_t val) {
|
||||
UInt64 data;
|
||||
data.setUInt64(val);
|
||||
return data;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64 fromUInt64(const UInt64& val) {
|
||||
UInt64 data;
|
||||
data.setUInt64(val);
|
||||
return data;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE void reset() {
|
||||
if (kArchHost64Bit) {
|
||||
u64 = 0;
|
||||
}
|
||||
else {
|
||||
u32[0] = 0;
|
||||
u32[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE uint64_t getUInt64() const {
|
||||
return u64;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& setUInt64(uint64_t val) {
|
||||
u64 = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& setUInt64(const UInt64& val) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 = val.u64;
|
||||
}
|
||||
else {
|
||||
u32[0] = val.u32[0];
|
||||
u32[1] = val.u32[1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& setPacked_2x32(uint32_t u0, uint32_t u1) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 = IntUtil::pack64_2x32(u0, u1);
|
||||
}
|
||||
else {
|
||||
u32[0] = u0;
|
||||
u32[1] = u1;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Add]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64& add(uint64_t val) {
|
||||
u64 += val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& add(const UInt64& val) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 += val.u64;
|
||||
}
|
||||
else {
|
||||
u32[0] += val.u32[0];
|
||||
u32[1] += val.u32[1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Sub]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64& sub(uint64_t val) {
|
||||
u64 -= val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& sub(const UInt64& val) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 -= val.u64;
|
||||
}
|
||||
else {
|
||||
u32[0] -= val.u32[0];
|
||||
u32[1] -= val.u32[1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [And]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64& and_(uint64_t val) {
|
||||
u64 &= val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& and_(const UInt64& val) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 &= val.u64;
|
||||
}
|
||||
else {
|
||||
u32[0] &= val.u32[0];
|
||||
u32[1] &= val.u32[1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [AndNot]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64& andNot(uint64_t val) {
|
||||
u64 &= ~val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& andNot(const UInt64& val) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 &= ~val.u64;
|
||||
}
|
||||
else {
|
||||
u32[0] &= ~val.u32[0];
|
||||
u32[1] &= ~val.u32[1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Or]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64& or_(uint64_t val) {
|
||||
u64 |= val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& or_(const UInt64& val) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 |= val.u64;
|
||||
}
|
||||
else {
|
||||
u32[0] |= val.u32[0];
|
||||
u32[1] |= val.u32[1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Xor]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64& xor_(uint64_t val) {
|
||||
u64 ^= val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE UInt64& xor_(const UInt64& val) {
|
||||
if (kArchHost64Bit) {
|
||||
u64 ^= val.u64;
|
||||
}
|
||||
else {
|
||||
u32[0] ^= val.u32[0];
|
||||
u32[1] ^= val.u32[1];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Eq]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE bool isZero() const {
|
||||
return kArchHost64Bit ? u64 == 0 : (u32[0] | u32[1]) == 0;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE bool isNonZero() const {
|
||||
return kArchHost64Bit ? u64 != 0 : (u32[0] | u32[1]) != 0;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE bool eq(uint64_t val) const {
|
||||
return u64 == val;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE bool eq(const UInt64& val) const {
|
||||
return kArchHost64Bit ? u64 == val.u64 : (u32[0] == val.u32[0]) & (u32[1] == val.u32[1]);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Operator Overload]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE UInt64& operator+=(uint64_t val) { return add(val); }
|
||||
ASMJIT_INLINE UInt64& operator+=(const UInt64& val) { return add(val); }
|
||||
|
||||
ASMJIT_INLINE UInt64& operator-=(uint64_t val) { return sub(val); }
|
||||
ASMJIT_INLINE UInt64& operator-=(const UInt64& val) { return sub(val); }
|
||||
|
||||
ASMJIT_INLINE UInt64& operator&=(uint64_t val) { return and_(val); }
|
||||
ASMJIT_INLINE UInt64& operator&=(const UInt64& val) { return and_(val); }
|
||||
|
||||
ASMJIT_INLINE UInt64& operator|=(uint64_t val) { return or_(val); }
|
||||
ASMJIT_INLINE UInt64& operator|=(const UInt64& val) { return or_(val); }
|
||||
|
||||
ASMJIT_INLINE UInt64& operator^=(uint64_t val) { return xor_(val); }
|
||||
ASMJIT_INLINE UInt64& operator^=(const UInt64& val) { return xor_(val); }
|
||||
|
||||
ASMJIT_INLINE bool operator==(uint64_t val) const { return eq(val); }
|
||||
ASMJIT_INLINE bool operator==(const UInt64& val) const { return eq(val); }
|
||||
|
||||
ASMJIT_INLINE bool operator!=(uint64_t val) const { return !eq(val); }
|
||||
ASMJIT_INLINE bool operator!=(const UInt64& val) const { return !eq(val); }
|
||||
|
||||
ASMJIT_INLINE bool operator<(uint64_t val) const { return u64 < val; }
|
||||
ASMJIT_INLINE bool operator<(const UInt64& val) const { return u64 < val.u64; }
|
||||
|
||||
ASMJIT_INLINE bool operator<=(uint64_t val) const { return u64 <= val; }
|
||||
ASMJIT_INLINE bool operator<=(const UInt64& val) const { return u64 <= val.u64; }
|
||||
|
||||
ASMJIT_INLINE bool operator>(uint64_t val) const { return u64 > val; }
|
||||
ASMJIT_INLINE bool operator>(const UInt64& val) const { return u64 > val.u64; }
|
||||
|
||||
ASMJIT_INLINE bool operator>=(uint64_t val) const { return u64 >= val; }
|
||||
ASMJIT_INLINE bool operator>=(const UInt64& val) const { return u64 >= val.u64; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
uint64_t u64;
|
||||
|
||||
uint32_t u32[2];
|
||||
uint16_t u16[4];
|
||||
uint8_t u8[8];
|
||||
|
||||
struct {
|
||||
#if defined(ASMJIT_HOST_LE)
|
||||
uint32_t lo, hi;
|
||||
#else
|
||||
uint32_t hi, lo;
|
||||
#endif // ASMJIT_HOST_LE
|
||||
};
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_INTUTIL_H
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_LOCK_H
|
||||
#define _ASMJIT_BASE_LOCK_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../build.h"
|
||||
|
||||
// [Dependencies - Posix]
|
||||
#if defined(ASMJIT_OS_POSIX)
|
||||
# include <pthread.h>
|
||||
#endif // ASMJIT_OS_POSIX
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Lock]
|
||||
// ============================================================================
|
||||
|
||||
//! Lock - used in thread-safe code for locking.
|
||||
struct Lock {
|
||||
ASMJIT_NO_COPY(Lock)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Windows]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
typedef CRITICAL_SECTION Handle;
|
||||
|
||||
//! Create a new `Lock` instance.
|
||||
ASMJIT_INLINE Lock() { InitializeCriticalSection(&_handle); }
|
||||
//! Destroy the `Lock` instance.
|
||||
ASMJIT_INLINE ~Lock() { DeleteCriticalSection(&_handle); }
|
||||
|
||||
//! Lock.
|
||||
ASMJIT_INLINE void lock() { EnterCriticalSection(&_handle); }
|
||||
//! Unlock.
|
||||
ASMJIT_INLINE void unlock() { LeaveCriticalSection(&_handle); }
|
||||
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Posix]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_OS_POSIX)
|
||||
typedef pthread_mutex_t Handle;
|
||||
|
||||
//! Create a new `Lock` instance.
|
||||
ASMJIT_INLINE Lock() { pthread_mutex_init(&_handle, NULL); }
|
||||
//! Destroy the `Lock` instance.
|
||||
ASMJIT_INLINE ~Lock() { pthread_mutex_destroy(&_handle); }
|
||||
|
||||
//! Lock.
|
||||
ASMJIT_INLINE void lock() { pthread_mutex_lock(&_handle); }
|
||||
//! Unlock.
|
||||
ASMJIT_INLINE void unlock() { pthread_mutex_unlock(&_handle); }
|
||||
#endif // ASMJIT_OS_POSIX
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get handle.
|
||||
ASMJIT_INLINE Handle& getHandle() {
|
||||
return _handle;
|
||||
}
|
||||
//! \overload
|
||||
ASMJIT_INLINE const Handle& getHandle() const {
|
||||
return _handle;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Handle.
|
||||
Handle _handle;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::AutoLock]
|
||||
// ============================================================================
|
||||
|
||||
//! Scoped lock.
|
||||
struct AutoLock {
|
||||
ASMJIT_NO_COPY(AutoLock)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Autolock `target`, scoped.
|
||||
ASMJIT_INLINE AutoLock(Lock& target) : _target(target) {
|
||||
_target.lock();
|
||||
}
|
||||
|
||||
//! Autounlock `target`.
|
||||
ASMJIT_INLINE ~AutoLock() {
|
||||
_target.unlock();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Pointer to target (lock).
|
||||
Lock& _target;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_LOCK_H
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_LOGGER_H
|
||||
#define _ASMJIT_BASE_LOGGER_H
|
||||
|
||||
#include "../build.h"
|
||||
#if !defined(ASMJIT_DISABLE_LOGGER)
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/string.h"
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdarg.h>
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kLoggerOption]
|
||||
// ============================================================================
|
||||
|
||||
//! Logger options.
|
||||
ASMJIT_ENUM(kLoggerOption) {
|
||||
//! Whether to output instructions also in binary form.
|
||||
kLoggerOptionBinaryForm = 0,
|
||||
|
||||
//! Whether to output immediates as hexadecimal numbers.
|
||||
kLoggerOptionHexImmediate = 1,
|
||||
//! Whether to output displacements as hexadecimal numbers.
|
||||
kLoggerOptionHexDisplacement = 2,
|
||||
|
||||
//! Count of logger options.
|
||||
kLoggerOptionCount = 3
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kLoggerStyle]
|
||||
// ============================================================================
|
||||
|
||||
//! Logger style.
|
||||
ASMJIT_ENUM(kLoggerStyle) {
|
||||
kLoggerStyleDefault = 0,
|
||||
kLoggerStyleDirective = 1,
|
||||
kLoggerStyleLabel = 2,
|
||||
kLoggerStyleData = 3,
|
||||
kLoggerStyleComment = 4,
|
||||
|
||||
kLoggerStyleCount = 5
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Logger]
|
||||
// ============================================================================
|
||||
|
||||
//! Abstract logging class.
|
||||
//!
|
||||
//! This class can be inherited and reimplemented to fit into your logging
|
||||
//! subsystem. When reimplementing use `Logger::log()` method to log into
|
||||
//! a custom stream.
|
||||
//!
|
||||
//! This class also contain `_enabled` member that can be used to enable
|
||||
//! or disable logging.
|
||||
struct ASMJIT_VCLASS Logger {
|
||||
ASMJIT_NO_COPY(Logger)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a `Logger` instance.
|
||||
ASMJIT_API Logger();
|
||||
//! Destroy the `Logger` instance.
|
||||
ASMJIT_API virtual ~Logger();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Logging]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Log output.
|
||||
virtual void logString(uint32_t style, const char* buf, size_t len = kInvalidIndex) = 0;
|
||||
|
||||
//! Log formatter message (like sprintf) sending output to `logString()` method.
|
||||
ASMJIT_API void logFormat(uint32_t style, const char* fmt, ...);
|
||||
//! Log binary data.
|
||||
ASMJIT_API void logBinary(uint32_t style, const void* data, size_t size);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Options]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get all logger options as a single integer.
|
||||
ASMJIT_INLINE uint32_t getOptions() const {
|
||||
return _options;
|
||||
}
|
||||
|
||||
//! Get the given logger option.
|
||||
ASMJIT_INLINE bool getOption(uint32_t id) const {
|
||||
ASMJIT_ASSERT(id < kLoggerOptionCount);
|
||||
return static_cast<bool>((_options >> id) & 0x1);
|
||||
}
|
||||
|
||||
//! Set the given logger option.
|
||||
ASMJIT_API void setOption(uint32_t id, bool value);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Indentation]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get indentation.
|
||||
ASMJIT_INLINE const char* getIndentation() const {
|
||||
return _indentation;
|
||||
}
|
||||
|
||||
//! Set indentation.
|
||||
ASMJIT_API void setIndentation(const char* indentation);
|
||||
|
||||
//! Reset indentation.
|
||||
ASMJIT_INLINE void resetIndentation() {
|
||||
setIndentation(NULL);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Options, see `kLoggerOption`.
|
||||
uint32_t _options;
|
||||
|
||||
//! Indentation.
|
||||
char _indentation[12];
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::FileLogger]
|
||||
// ============================================================================
|
||||
|
||||
//! Logger that can log to standard C `FILE*` stream.
|
||||
struct ASMJIT_VCLASS FileLogger : public Logger {
|
||||
ASMJIT_NO_COPY(FileLogger)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new `FileLogger` that logs to a `FILE` stream.
|
||||
ASMJIT_API FileLogger(FILE* stream = NULL);
|
||||
|
||||
//! Destroy the `FileLogger`.
|
||||
ASMJIT_API virtual ~FileLogger();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get `FILE*` stream.
|
||||
//!
|
||||
//! \note Return value can be `NULL`.
|
||||
ASMJIT_INLINE FILE* getStream() const {
|
||||
return _stream;
|
||||
}
|
||||
|
||||
//! Set `FILE*` stream, can be set to `NULL` to disable logging, although
|
||||
//! the `CodeGen` will still call `logString` even if there is no stream.
|
||||
ASMJIT_INLINE void setStream(FILE* stream) {
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Logging]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API virtual void logString(uint32_t style, const char* buf, size_t len = kInvalidIndex);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! C file stream.
|
||||
FILE* _stream;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::StringLogger]
|
||||
// ============================================================================
|
||||
|
||||
//! String logger.
|
||||
struct ASMJIT_VCLASS StringLogger : public Logger {
|
||||
ASMJIT_NO_COPY(StringLogger)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create new `StringLogger`.
|
||||
ASMJIT_API StringLogger();
|
||||
|
||||
//! Destroy the `StringLogger`.
|
||||
ASMJIT_API virtual ~StringLogger();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get `char*` pointer which represents the resulting string.
|
||||
//!
|
||||
//! The pointer is owned by `StringLogger`, it can't be modified or freed.
|
||||
ASMJIT_INLINE const char* getString() const {
|
||||
return _stringBuilder.getData();
|
||||
}
|
||||
|
||||
//! Clear the resulting string.
|
||||
ASMJIT_INLINE void clearString() {
|
||||
_stringBuilder.clear();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Logging]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API virtual void logString(uint32_t style, const char* buf, size_t len = kInvalidIndex);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Output.
|
||||
StringBuilder _stringBuilder;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // !ASMJIT_DISABLE_LOGGER
|
||||
#endif // _ASMJIT_BASE_LOGGER_H
|
||||
+1090
File diff suppressed because it is too large
Load Diff
+262
@@ -0,0 +1,262 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_RUNTIME_H
|
||||
#define _ASMJIT_BASE_RUNTIME_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/error.h"
|
||||
#include "../base/vmem.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
struct Assembler;
|
||||
struct CpuInfo;
|
||||
|
||||
//! \addtogroup asmjit_base_general
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kRuntimeType]
|
||||
// ============================================================================
|
||||
|
||||
ASMJIT_ENUM(kRuntimeType) {
|
||||
kRuntimeTypeNone = 0,
|
||||
|
||||
kRuntimeTypeJit = 1,
|
||||
kRuntimeTypeRemote = 2
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Runtime]
|
||||
// ============================================================================
|
||||
|
||||
//! Base runtime.
|
||||
struct ASMJIT_VCLASS Runtime {
|
||||
ASMJIT_NO_COPY(Runtime)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a `Runtime` instance.
|
||||
ASMJIT_API Runtime();
|
||||
//! Destroy the `Runtime` instance.
|
||||
ASMJIT_API virtual ~Runtime();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get runtime type.
|
||||
ASMJIT_INLINE uint32_t getRuntimeType() const {
|
||||
return _runtimeType;
|
||||
}
|
||||
|
||||
//! Get whether the runtime has a base address.
|
||||
//!
|
||||
//! \sa \ref getBaseAddress()
|
||||
ASMJIT_INLINE bool hasBaseAddress() const {
|
||||
return _baseAddress == kNoBaseAddress;
|
||||
}
|
||||
|
||||
//! Get the base address.
|
||||
ASMJIT_INLINE Ptr getBaseAddress() const {
|
||||
return _baseAddress;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get CPU information.
|
||||
virtual const CpuInfo* getCpuInfo() = 0;
|
||||
|
||||
//! Get stack alignment of target runtime.
|
||||
virtual uint32_t getStackAlignment() = 0;
|
||||
|
||||
//! Allocate a memory needed for a code generated by `assembler` and
|
||||
//! relocate it to the target location.
|
||||
//!
|
||||
//! The beginning of the memory allocated for the function is returned in
|
||||
//! `dst`. Returns Status code as \ref kError, on failure `dst` is set to
|
||||
//! `NULL`.
|
||||
virtual Error add(void** dst, Assembler* assembler) = 0;
|
||||
|
||||
//! Release memory allocated by `add`.
|
||||
virtual Error release(void* p) = 0;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Maximum size of the code that can be added to the runtime (0=unlimited).
|
||||
size_t _sizeLimit;
|
||||
//! Base address (-1 means no base address).
|
||||
Ptr _baseAddress;
|
||||
|
||||
//! Type of the runtime.
|
||||
uint8_t _runtimeType;
|
||||
//! Type of the allocation.
|
||||
uint8_t _allocType;
|
||||
//! \internal
|
||||
uint8_t _reserved[sizeof(intptr_t) - 2];
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::HostRuntime]
|
||||
// ============================================================================
|
||||
|
||||
//! Base runtime for JIT code generation.
|
||||
struct ASMJIT_VCLASS HostRuntime : public Runtime {
|
||||
ASMJIT_NO_COPY(HostRuntime)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a `HostRuntime` instance.
|
||||
ASMJIT_API HostRuntime();
|
||||
//! Destroy the `HostRuntime` instance.
|
||||
ASMJIT_API virtual ~HostRuntime();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API virtual const CpuInfo* getCpuInfo();
|
||||
ASMJIT_API virtual uint32_t getStackAlignment();
|
||||
|
||||
//! Flush an instruction cache.
|
||||
//!
|
||||
//! This member function is called after the code has been copied to the
|
||||
//! destination buffer. It is only useful for JIT code generation as it
|
||||
//! causes a flush of the processor cache.
|
||||
//!
|
||||
//! Flushing is basically a NOP under X86/X64, but is needed by architectures
|
||||
//! that do not have a transparent instruction cache.
|
||||
//!
|
||||
//! This function can also be overridden to improve compatibility with tools
|
||||
//! such as Valgrind, however, it's not an official part of AsmJit.
|
||||
ASMJIT_API virtual void flush(void* p, size_t size);
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::StaticRuntime]
|
||||
// ============================================================================
|
||||
|
||||
//! JIT static runtime.
|
||||
//!
|
||||
//! JIT static runtime can be used to generate code to a memory location that
|
||||
//! is known.
|
||||
struct ASMJIT_VCLASS StaticRuntime : public HostRuntime {
|
||||
ASMJIT_NO_COPY(StaticRuntime)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a `StaticRuntime` instance.
|
||||
//!
|
||||
//! The `address` specifies a fixed target address, which will be used as a
|
||||
//! base address for relocation, and `sizeLimit` specified the maximum size
|
||||
//! of a code that can be copied to it. If there is no limit `sizeLimit`
|
||||
//! should be zero.
|
||||
ASMJIT_API StaticRuntime(void* baseAddress, size_t sizeLimit = 0);
|
||||
//! Destroy the `StaticRuntime` instance.
|
||||
ASMJIT_API virtual ~StaticRuntime();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get the base address.
|
||||
ASMJIT_INLINE Ptr getBaseAddress() const {
|
||||
return _baseAddress;
|
||||
}
|
||||
|
||||
//! Get the maximum size of the code that can be relocated to the target
|
||||
//! address or zero if unlimited.
|
||||
ASMJIT_INLINE size_t getSizeLimit() const {
|
||||
return _sizeLimit;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API virtual Error add(void** dst, Assembler* assembler);
|
||||
ASMJIT_API virtual Error release(void* p);
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::JitRuntime]
|
||||
// ============================================================================
|
||||
|
||||
//! JIT runtime.
|
||||
struct ASMJIT_VCLASS JitRuntime : public HostRuntime {
|
||||
ASMJIT_NO_COPY(JitRuntime)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a `JitRuntime` instance.
|
||||
ASMJIT_API JitRuntime();
|
||||
//! Destroy the `JitRuntime` instance.
|
||||
ASMJIT_API virtual ~JitRuntime();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get the type of allocation.
|
||||
ASMJIT_INLINE uint32_t getAllocType() const {
|
||||
return _allocType;
|
||||
}
|
||||
|
||||
//! Set the type of allocation.
|
||||
ASMJIT_INLINE void setAllocType(uint32_t allocType) {
|
||||
_allocType = allocType;
|
||||
}
|
||||
|
||||
//! Get the virtual memory manager.
|
||||
ASMJIT_INLINE VMemMgr* getMemMgr() const {
|
||||
return const_cast<VMemMgr*>(&_memMgr);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Interface]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API virtual Error add(void** dst, Assembler* assembler);
|
||||
ASMJIT_API virtual Error release(void* p);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Virtual memory manager.
|
||||
VMemMgr _memMgr;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_RUNTIME_H
|
||||
+372
@@ -0,0 +1,372 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_STRING_H
|
||||
#define _ASMJIT_BASE_STRING_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/globals.h"
|
||||
|
||||
// [Dependencies - C]
|
||||
#include <stdarg.h>
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kStringOp]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! String operation.
|
||||
ASMJIT_ENUM(kStringOp) {
|
||||
//! Replace the current string by a given content.
|
||||
kStringOpSet = 0,
|
||||
//! Append a given content to the current string.
|
||||
kStringOpAppend = 1
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kStringFormat]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! String format flags.
|
||||
ASMJIT_ENUM(kStringFormat) {
|
||||
kStringFormatShowSign = 0x00000001,
|
||||
kStringFormatShowSpace = 0x00000002,
|
||||
kStringFormatAlternate = 0x00000004,
|
||||
kStringFormatSigned = 0x80000000
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::StringUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! String utilities.
|
||||
struct StringUtil {
|
||||
static ASMJIT_INLINE size_t nlen(const char* s, size_t maxlen) {
|
||||
size_t i;
|
||||
for (i = 0; i < maxlen; i++)
|
||||
if (!s[i])
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::StringBuilder]
|
||||
// ============================================================================
|
||||
|
||||
//! String builder.
|
||||
//!
|
||||
//! String builder was designed to be able to build a string using append like
|
||||
//! operation to append numbers, other strings, or signle characters. It can
|
||||
//! allocate it's own buffer or use a buffer created on the stack.
|
||||
//!
|
||||
//! String builder contains method specific to AsmJit functionality, used for
|
||||
//! logging or HTML output.
|
||||
struct StringBuilder {
|
||||
ASMJIT_NO_COPY(StringBuilder)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API StringBuilder();
|
||||
ASMJIT_API ~StringBuilder();
|
||||
|
||||
ASMJIT_INLINE StringBuilder(const _NoInit&) {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get string builder capacity.
|
||||
ASMJIT_INLINE size_t getCapacity() const { return _capacity; }
|
||||
//! Get length.
|
||||
ASMJIT_INLINE size_t getLength() const { return _length; }
|
||||
|
||||
//! Get null-terminated string data.
|
||||
ASMJIT_INLINE char* getData() { return _data; }
|
||||
//! Get null-terminated string data (const).
|
||||
ASMJIT_INLINE const char* getData() const { return _data; }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Prepare / Reserve]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Prepare to set/append.
|
||||
ASMJIT_API char* prepare(uint32_t op, size_t len);
|
||||
|
||||
//! Reserve `to` bytes in string builder.
|
||||
ASMJIT_API bool reserve(size_t to);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Clear]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Clear the content in String builder.
|
||||
ASMJIT_API void clear();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Op]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_API bool _opString(uint32_t op, const char* str, size_t len = kInvalidIndex);
|
||||
ASMJIT_API bool _opVFormat(uint32_t op, const char* fmt, va_list ap);
|
||||
ASMJIT_API bool _opChar(uint32_t op, char c);
|
||||
ASMJIT_API bool _opChars(uint32_t op, char c, size_t len);
|
||||
ASMJIT_API bool _opNumber(uint32_t op, uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0);
|
||||
ASMJIT_API bool _opHex(uint32_t op, const void* data, size_t len);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Set]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Replace the current content by `str` of `len`.
|
||||
ASMJIT_INLINE bool setString(const char* str, size_t len = kInvalidIndex) {
|
||||
return _opString(kStringOpSet, str, len);
|
||||
}
|
||||
|
||||
//! Replace the current content by formatted string `fmt`.
|
||||
ASMJIT_INLINE bool setVFormat(const char* fmt, va_list ap) {
|
||||
return _opVFormat(kStringOpSet, fmt, ap);
|
||||
}
|
||||
|
||||
//! Replace the current content by formatted string `fmt`.
|
||||
ASMJIT_API bool setFormat(const char* fmt, ...);
|
||||
|
||||
//! Replace the current content by `c` character.
|
||||
ASMJIT_INLINE bool setChar(char c) {
|
||||
return _opChar(kStringOpSet, c);
|
||||
}
|
||||
|
||||
//! Replace the current content by `c` of `len`.
|
||||
ASMJIT_INLINE bool setChars(char c, size_t len) {
|
||||
return _opChars(kStringOpSet, c, len);
|
||||
}
|
||||
|
||||
//! Replace the current content by formatted integer `i`.
|
||||
ASMJIT_INLINE bool setInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpSet, i, base, width, flags | kStringFormatSigned);
|
||||
}
|
||||
|
||||
//! Replace the current content by formatted integer `i`.
|
||||
ASMJIT_INLINE bool setUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpSet, i, base, width, flags);
|
||||
}
|
||||
|
||||
//! Replace the current content by the given `data` converted to a HEX string.
|
||||
ASMJIT_INLINE bool setHex(const void* data, size_t len) {
|
||||
return _opHex(kStringOpSet, data, len);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Append]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Append `str` of `len`.
|
||||
ASMJIT_INLINE bool appendString(const char* str, size_t len = kInvalidIndex) {
|
||||
return _opString(kStringOpAppend, str, len);
|
||||
}
|
||||
|
||||
//! Append a formatted string `fmt` to the current content.
|
||||
ASMJIT_INLINE bool appendVFormat(const char* fmt, va_list ap) {
|
||||
return _opVFormat(kStringOpAppend, fmt, ap);
|
||||
}
|
||||
|
||||
//! Append a formatted string `fmt` to the current content.
|
||||
ASMJIT_API bool appendFormat(const char* fmt, ...);
|
||||
|
||||
//! Append `c` character.
|
||||
ASMJIT_INLINE bool appendChar(char c) {
|
||||
return _opChar(kStringOpAppend, c);
|
||||
}
|
||||
|
||||
//! Append `c` of `len`.
|
||||
ASMJIT_INLINE bool appendChars(char c, size_t len) {
|
||||
return _opChars(kStringOpAppend, c, len);
|
||||
}
|
||||
|
||||
//! Append `i`.
|
||||
ASMJIT_INLINE bool appendInt(int64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpAppend, static_cast<uint64_t>(i), base, width, flags | kStringFormatSigned);
|
||||
}
|
||||
|
||||
//! Append `i`.
|
||||
ASMJIT_INLINE bool appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, uint32_t flags = 0) {
|
||||
return _opNumber(kStringOpAppend, i, base, width, flags);
|
||||
}
|
||||
|
||||
//! Append the given `data` converted to a HEX string.
|
||||
ASMJIT_INLINE bool appendHex(const void* data, size_t len) {
|
||||
return _opHex(kStringOpAppend, data, len);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [_Append]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Append `str` of `len`, inlined, without buffer overflow check.
|
||||
ASMJIT_INLINE void _appendString(const char* str, size_t len = kInvalidIndex) {
|
||||
// len should be a constant if we are inlining.
|
||||
if (len == kInvalidIndex) {
|
||||
char* p = &_data[_length];
|
||||
|
||||
while (*str) {
|
||||
ASMJIT_ASSERT(p < _data + _capacity);
|
||||
*p++ = *str++;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
_length = (size_t)(p - _data);
|
||||
}
|
||||
else {
|
||||
ASMJIT_ASSERT(_capacity - _length >= len);
|
||||
|
||||
char* p = &_data[_length];
|
||||
char* pEnd = p + len;
|
||||
|
||||
while (p < pEnd)
|
||||
*p++ = *str++;
|
||||
|
||||
*p = '\0';
|
||||
_length += len;
|
||||
}
|
||||
}
|
||||
|
||||
//! Append `c` character, inlined, without buffer overflow check.
|
||||
ASMJIT_INLINE void _appendChar(char c) {
|
||||
ASMJIT_ASSERT(_capacity - _length >= 1);
|
||||
|
||||
_data[_length] = c;
|
||||
_length++;
|
||||
_data[_length] = '\0';
|
||||
}
|
||||
|
||||
//! Append `c` of `len`, inlined, without buffer overflow check.
|
||||
ASMJIT_INLINE void _appendChars(char c, size_t len) {
|
||||
ASMJIT_ASSERT(_capacity - _length >= len);
|
||||
|
||||
char* p = &_data[_length];
|
||||
char* pEnd = p + len;
|
||||
|
||||
while (p < pEnd)
|
||||
*p++ = c;
|
||||
|
||||
*p = '\0';
|
||||
_length += len;
|
||||
}
|
||||
|
||||
ASMJIT_INLINE void _appendUInt32(uint32_t i) {
|
||||
char buf_[32];
|
||||
|
||||
char* pEnd = buf_ + ASMJIT_ARRAY_SIZE(buf_);
|
||||
char* pBuf = pEnd;
|
||||
|
||||
do {
|
||||
uint32_t d = i / 10;
|
||||
uint32_t r = i % 10;
|
||||
|
||||
*--pBuf = static_cast<uint8_t>(r + '0');
|
||||
i = d;
|
||||
} while (i);
|
||||
|
||||
ASMJIT_ASSERT(_capacity - _length >= (size_t)(pEnd - pBuf));
|
||||
char* p = &_data[_length];
|
||||
|
||||
do {
|
||||
*p++ = *pBuf;
|
||||
} while (++pBuf != pEnd);
|
||||
|
||||
*p = '\0';
|
||||
_length = (size_t)(p - _data);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Eq]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Check for equality with other `str` of `len`.
|
||||
ASMJIT_API bool eq(const char* str, size_t len = kInvalidIndex) const;
|
||||
//! Check for equality with `other`.
|
||||
ASMJIT_INLINE bool eq(const StringBuilder& other) const {
|
||||
return eq(other._data);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Operator Overload]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE bool operator==(const StringBuilder& other) const { return eq(other); }
|
||||
ASMJIT_INLINE bool operator!=(const StringBuilder& other) const { return !eq(other); }
|
||||
|
||||
ASMJIT_INLINE bool operator==(const char* str) const { return eq(str); }
|
||||
ASMJIT_INLINE bool operator!=(const char* str) const { return !eq(str); }
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! String data.
|
||||
char* _data;
|
||||
//! Length.
|
||||
size_t _length;
|
||||
//! Capacity.
|
||||
size_t _capacity;
|
||||
//! Whether the string can be freed.
|
||||
size_t _canFree;
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::StringBuilderT]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
template<size_t N>
|
||||
struct StringBuilderT : public StringBuilder {
|
||||
ASMJIT_NO_COPY(StringBuilderT<N>)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE StringBuilderT() : StringBuilder(NoInit) {
|
||||
_data = _embeddedData;
|
||||
_data[0] = 0;
|
||||
|
||||
_length = 0;
|
||||
_capacity = N;
|
||||
_canFree = false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Embedded data.
|
||||
char _embeddedData[static_cast<size_t>(
|
||||
N + 1 + sizeof(intptr_t)) & ~static_cast<size_t>(sizeof(intptr_t) - 1)];
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_STRING_H
|
||||
+1251
File diff suppressed because it is too large
Load Diff
+240
@@ -0,0 +1,240 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_VMEM_H
|
||||
#define _ASMJIT_BASE_VMEM_H
|
||||
|
||||
// [Dependencies]
|
||||
#include "../base/error.h"
|
||||
#include "../base/lock.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kVMemAlloc]
|
||||
// ============================================================================
|
||||
|
||||
//! Type of virtual memory allocation, see `VMemMgr::alloc()`.
|
||||
ASMJIT_ENUM(kVMemAlloc) {
|
||||
//! Normal memory allocation, has to be freed by `VMemMgr::release()`.
|
||||
kVMemAllocFreeable = 0,
|
||||
//! Allocate permanent memory, can't be freed.
|
||||
kVMemAllocPermanent = 1
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kVMemFlags]
|
||||
// ============================================================================
|
||||
|
||||
//! Type of virtual memory allocation, see `VMemMgr::alloc()`.
|
||||
ASMJIT_ENUM(kVMemFlags) {
|
||||
//! Memory is writable.
|
||||
kVMemFlagWritable = 0x00000001,
|
||||
//! Memory is executable.
|
||||
kVMemFlagExecutable = 0x00000002
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VMemUtil]
|
||||
// ============================================================================
|
||||
|
||||
//! Virtual memory utilities.
|
||||
//!
|
||||
//! Defines functions that provide facility to allocate and free memory that is
|
||||
//! executable in a platform independent manner. If both the processor and host
|
||||
//! operating system support data-execution-prevention then the only way how to
|
||||
//! run machine code is to allocate it to a memory that has marked as executable.
|
||||
//! VMemUtil is just unified interface to platform dependent APIs.
|
||||
//!
|
||||
//! `VirtualAlloc()` function is used on Windows operating system and `mmap()`
|
||||
//! on POSIX. `VirtualAlloc()` and `mmap()` documentation provide a detailed
|
||||
//! overview on how to use a platform specific APIs.
|
||||
struct VMemUtil {
|
||||
//! Get a size/alignment of a single virtual memory page.
|
||||
static ASMJIT_API size_t getPageSize();
|
||||
|
||||
//! Get a recommended granularity for a single `alloc` call.
|
||||
static ASMJIT_API size_t getPageGranularity();
|
||||
|
||||
//! Allocate virtual memory.
|
||||
//!
|
||||
//! Pages are readable/writeable, but they are not guaranteed to be
|
||||
//! executable unless 'canExecute' is true. Returns the address of
|
||||
//! allocated memory, or NULL on failure.
|
||||
static ASMJIT_API void* alloc(size_t length, size_t* allocated, uint32_t flags);
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! Allocate virtual memory of `hProcess`.
|
||||
//!
|
||||
//! \note This function is Windows specific.
|
||||
static ASMJIT_API void* allocProcessMemory(HANDLE hProcess, size_t length, size_t* allocated, uint32_t flags);
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
//! Free memory allocated by `alloc()`.
|
||||
static ASMJIT_API Error release(void* addr, size_t length);
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! Release virtual memory of `hProcess`.
|
||||
//!
|
||||
//! \note This function is Windows specific.
|
||||
static ASMJIT_API Error releaseProcessMemory(HANDLE hProcess, void* addr, size_t length);
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::VMemMgr]
|
||||
// ============================================================================
|
||||
|
||||
//! Reference implementation of memory manager that uses `VMemUtil` to allocate
|
||||
//! chunks of virtual memory and bit arrays to manage it.
|
||||
struct VMemMgr {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if !defined(ASMJIT_OS_WINDOWS)
|
||||
//! Create a `VMemMgr` instance.
|
||||
ASMJIT_API VMemMgr();
|
||||
#else
|
||||
//! Create a `VMemMgr` instance.
|
||||
//!
|
||||
//! \note When running on Windows it's possible to specify a `hProcess` to
|
||||
//! be used for memory allocation. This allows to allocate memory of remote
|
||||
//! process.
|
||||
ASMJIT_API VMemMgr(HANDLE hProcess = static_cast<HANDLE>(0));
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
//! Destroy the `VMemMgr` instance and free all blocks.
|
||||
ASMJIT_API ~VMemMgr();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Free all allocated memory.
|
||||
ASMJIT_API void reset();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! Get the handle of the process memory manager is bound to.
|
||||
ASMJIT_INLINE HANDLE getProcessHandle() const {
|
||||
return _hProcess;
|
||||
}
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
//! Get how many bytes are currently allocated.
|
||||
ASMJIT_INLINE size_t getAllocatedBytes() const {
|
||||
return _allocatedBytes;
|
||||
}
|
||||
|
||||
//! Get how many bytes are currently used.
|
||||
ASMJIT_INLINE size_t getUsedBytes() const {
|
||||
return _usedBytes;
|
||||
}
|
||||
|
||||
//! Get whether to keep allocated memory after the `VMemMgr` is destroyed.
|
||||
//!
|
||||
//! \sa \ref setKeepVirtualMemory.
|
||||
ASMJIT_INLINE bool getKeepVirtualMemory() const {
|
||||
return _keepVirtualMemory;
|
||||
}
|
||||
|
||||
//! Set whether to keep allocated memory after memory manager is
|
||||
//! destroyed.
|
||||
//!
|
||||
//! This method is usable when patching code of remote process. You need to
|
||||
//! allocate process memory, store generated assembler into it and patch the
|
||||
//! method you want to redirect (into your code). This method affects only
|
||||
//! VMemMgr destructor. After destruction all internal
|
||||
//! structures are freed, only the process virtual memory remains.
|
||||
//!
|
||||
//! \note Memory allocated with kVMemAllocPermanent is always kept.
|
||||
//!
|
||||
//! \sa \ref getKeepVirtualMemory.
|
||||
ASMJIT_INLINE void setKeepVirtualMemory(bool keepVirtualMemory) {
|
||||
_keepVirtualMemory = keepVirtualMemory;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Alloc / Release]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Allocate a `size` bytes of virtual memory.
|
||||
//!
|
||||
//! Note that if you are implementing your own virtual memory manager then you
|
||||
//! can quitly ignore type of allocation. This is mainly for AsmJit to memory
|
||||
//! manager that allocated memory will be never freed.
|
||||
ASMJIT_API void* alloc(size_t size, uint32_t type = kVMemAllocFreeable);
|
||||
|
||||
//! Free previously allocated memory at a given `address`.
|
||||
ASMJIT_API Error release(void* p);
|
||||
|
||||
//! Free extra memory allocated with `p`.
|
||||
ASMJIT_API Error shrink(void* p, size_t used);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_OS_WINDOWS)
|
||||
//! Process passed to `VirtualAllocEx` and `VirtualFree`.
|
||||
HANDLE _hProcess;
|
||||
#endif // ASMJIT_OS_WINDOWS
|
||||
|
||||
//! Lock to enable thread-safe functionality.
|
||||
Lock _lock;
|
||||
|
||||
//! Default block size.
|
||||
size_t _blockSize;
|
||||
//! Default block density.
|
||||
size_t _blockDensity;
|
||||
|
||||
// Whether to keep virtual memory after destroy.
|
||||
bool _keepVirtualMemory;
|
||||
|
||||
//! How many bytes are currently allocated.
|
||||
size_t _allocatedBytes;
|
||||
//! How many bytes are currently used.
|
||||
size_t _usedBytes;
|
||||
|
||||
//! \internal
|
||||
//! \{
|
||||
|
||||
struct RbNode;
|
||||
struct MemNode;
|
||||
struct PermanentNode;
|
||||
|
||||
// Memory nodes root.
|
||||
MemNode* _root;
|
||||
// Memory nodes list.
|
||||
MemNode* _first;
|
||||
MemNode* _last;
|
||||
MemNode* _optimal;
|
||||
// Permanent memory.
|
||||
PermanentNode* _permanent;
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_VMEM_H
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_BASE_ZONE_H
|
||||
#define _ASMJIT_BASE_ZONE_H
|
||||
|
||||
// [Dependencies]
|
||||
#include "../base/globals.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_base_util
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::Zone]
|
||||
// ============================================================================
|
||||
|
||||
//! Zone memory allocator.
|
||||
//!
|
||||
//! Zone is an incremental memory allocator that allocates memory by simply
|
||||
//! incrementing a pointer. It allocates blocks of memory by using standard
|
||||
//! C library `malloc/free`, but divides these blocks into smaller segments
|
||||
//! requirested by calling `Zone::alloc()` and friends.
|
||||
//!
|
||||
//! Zone memory allocators are designed to allocate data of short lifetime. The
|
||||
//! data used by `Assembler` and `Compiler` has a very short lifetime, thus, is
|
||||
//! allocated by `Zone`. The advantage is that `Zone` can free all of the data
|
||||
//! allocated at once by calling `reset()` or by `Zone` destructor.
|
||||
struct Zone {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Block]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! A single block of memory.
|
||||
struct Block {
|
||||
// ------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
//! Get the size of the block.
|
||||
ASMJIT_INLINE size_t getBlockSize() const {
|
||||
return (size_t)(end - data);
|
||||
}
|
||||
|
||||
//! Get count of remaining bytes in the block.
|
||||
ASMJIT_INLINE size_t getRemainingSize() const {
|
||||
return (size_t)(end - pos);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
//! Current data pointer (pointer to the first available byte).
|
||||
uint8_t* pos;
|
||||
//! End data pointer (pointer to the first invalid byte).
|
||||
uint8_t* end;
|
||||
|
||||
//! Link to the previous block.
|
||||
Block* prev;
|
||||
//! Link to the next block.
|
||||
Block* next;
|
||||
|
||||
//! Data.
|
||||
uint8_t data[sizeof(void*)];
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new instance of `Zone` allocator.
|
||||
//!
|
||||
//! The `blockSize` parameter describes the default size of the block. If the
|
||||
//! `size` parameter passed to `alloc()` is greater than the default size
|
||||
//! `Zone` will allocate and use a larger block, but it will not change the
|
||||
//! default `blockSize`.
|
||||
//!
|
||||
//! It's not required, but it's good practice to set `blockSize` to a
|
||||
//! reasonable value that depends on the usage of `Zone`. Greater block sizes
|
||||
//! are generally safer and performs better than unreasonably low values.
|
||||
ASMJIT_API Zone(size_t blockSize);
|
||||
|
||||
//! Destroy the `Zone` instance.
|
||||
//!
|
||||
//! This will destroy the `Zone` instance and release all blocks of memory
|
||||
//! allocated by it. It performs implicit `reset(true)`.
|
||||
ASMJIT_API ~Zone();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Reset the `Zone` invalidating all blocks allocated.
|
||||
//!
|
||||
//! If `releaseMemory` is true all buffers will be released to the system.
|
||||
ASMJIT_API void reset(bool releaseMemory = false);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get the default block size.
|
||||
ASMJIT_INLINE size_t getBlockSize() const {
|
||||
return _blockSize;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Alloc]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Allocate `size` bytes of memory.
|
||||
//!
|
||||
//! Pointer returned is valid until the `Zone` instance is destroyed or reset
|
||||
//! by calling `reset()`. If you plan to make an instance of C++ from the
|
||||
//! given pointer use placement `new` and `delete` operators:
|
||||
//!
|
||||
//! ~~~
|
||||
//! using namespace asmjit;
|
||||
//!
|
||||
//! class SomeObject { ... };
|
||||
//!
|
||||
//! // Create Zone with default block size of 65536 bytes.
|
||||
//! Zone zone(65536);
|
||||
//!
|
||||
//! // Create your objects using zone object allocating, for example:
|
||||
//! Object* obj = static_cast<Object*>( zone.alloc(sizeof(SomeClass)) );
|
||||
//
|
||||
//! if (obj == NULL) {
|
||||
//! // Handle out of memory error.
|
||||
//! }
|
||||
//!
|
||||
//! // To instantiate class placement `new` and `delete` operators can be used.
|
||||
//! new(obj) Object();
|
||||
//!
|
||||
//! // ... lifetime of your objects ...
|
||||
//!
|
||||
//! // To destroy the instance (if required).
|
||||
//! obj->~Object();
|
||||
//!
|
||||
//! // Reset of destroy `Zone`.
|
||||
//! zone.reset();
|
||||
//! ~~~
|
||||
ASMJIT_INLINE void* alloc(size_t size) {
|
||||
Block* cur = _block;
|
||||
|
||||
uint8_t* ptr = cur->pos;
|
||||
size_t remainingBytes = (size_t)(cur->end - ptr);
|
||||
|
||||
if (remainingBytes < size)
|
||||
return _alloc(size);
|
||||
|
||||
cur->pos += size;
|
||||
ASMJIT_ASSERT(cur->pos <= cur->end);
|
||||
|
||||
return (void*)ptr;
|
||||
}
|
||||
|
||||
//! Allocate `size` bytes of zeroed memory.
|
||||
//!
|
||||
//! See \ref alloc() for more details.
|
||||
ASMJIT_API void* allocZeroed(size_t size);
|
||||
|
||||
//! Like `alloc()`, but the return pointer is casted to `T*`.
|
||||
template<typename T>
|
||||
ASMJIT_INLINE T* allocT(size_t size = sizeof(T)) {
|
||||
return static_cast<T*>(alloc(size));
|
||||
}
|
||||
|
||||
//! Like `allocZeroed()`, but the return pointer is casted to `T*`.
|
||||
template<typename T>
|
||||
ASMJIT_INLINE T* allocZeroedT(size_t size = sizeof(T)) {
|
||||
return static_cast<T*>(allocZeroed(size));
|
||||
}
|
||||
|
||||
//! \internal
|
||||
ASMJIT_API void* _alloc(size_t size);
|
||||
|
||||
//! Helper to duplicate data.
|
||||
ASMJIT_API void* dup(const void* data, size_t size);
|
||||
|
||||
//! Helper to duplicate string.
|
||||
ASMJIT_API char* sdup(const char* str);
|
||||
|
||||
//! Helper to duplicate formatted string, maximum length is 256 bytes.
|
||||
ASMJIT_API char* sformat(const char* str, ...);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! The current block.
|
||||
Block* _block;
|
||||
//! Default block size.
|
||||
size_t _blockSize;
|
||||
};
|
||||
|
||||
enum {
|
||||
//! Zone allocator overhead.
|
||||
kZoneOverhead = static_cast<int>(sizeof(Zone::Block) - sizeof(void*)) + kMemAllocOverhead
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_BASE_ZONE_H
|
||||
@@ -0,0 +1,59 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_HOST_H
|
||||
#define _ASMJIT_HOST_H
|
||||
|
||||
// [Dependencies - Core]
|
||||
#include "base.h"
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::host - X86 / X64]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
#include "x86.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
// Define `asmjit::host` namespace wrapping `asmjit::x86`.
|
||||
namespace host { using namespace ::asmjit::x86; }
|
||||
|
||||
// Define host assembler.
|
||||
typedef X86Assembler HostAssembler;
|
||||
|
||||
// Define host operands.
|
||||
typedef X86GpReg GpReg;
|
||||
typedef X86FpReg FpReg;
|
||||
typedef X86MmReg MmReg;
|
||||
typedef X86XmmReg XmmReg;
|
||||
typedef X86YmmReg YmmReg;
|
||||
typedef X86SegReg SegReg;
|
||||
typedef X86Mem Mem;
|
||||
|
||||
// Define host utilities.
|
||||
typedef X86CpuInfo HostCpuInfo;
|
||||
|
||||
// Define host compiler and related.
|
||||
#if !defined(ASMJIT_DISABLE_COMPILER)
|
||||
typedef X86Compiler HostCompiler;
|
||||
typedef X86CallNode HostCallNode;
|
||||
typedef X86FuncDecl HostFuncDecl;
|
||||
typedef X86FuncNode HostFuncNode;
|
||||
|
||||
typedef X86GpVar GpVar;
|
||||
typedef X86MmVar MmVar;
|
||||
typedef X86XmmVar XmmVar;
|
||||
typedef X86YmmVar YmmVar;
|
||||
#endif // !ASMJIT_DISABLE_COMPILER
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_HOST_H
|
||||
@@ -0,0 +1,21 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_X86_H
|
||||
#define _ASMJIT_X86_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "base.h"
|
||||
|
||||
#include "x86/x86assembler.h"
|
||||
#include "x86/x86compiler.h"
|
||||
#include "x86/x86cpuinfo.h"
|
||||
#include "x86/x86inst.h"
|
||||
#include "x86/x86operand.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_X86_H
|
||||
Vendored
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+314
@@ -0,0 +1,314 @@
|
||||
/* Header for BeaEngine 4.x */
|
||||
#ifndef _BEA_ENGINE_
|
||||
#define _BEA_ENGINE_
|
||||
|
||||
#include "Includes/export.h"
|
||||
#include "Includes/basic_types.h"
|
||||
|
||||
#if !defined(BEA_ENGINE_STATIC)
|
||||
#if defined(BUILD_BEA_ENGINE_DLL)
|
||||
#define BEA_API bea__api_export__
|
||||
#else
|
||||
#define BEA_API bea__api_import__
|
||||
#endif
|
||||
#else
|
||||
#define BEA_API
|
||||
#endif
|
||||
|
||||
|
||||
#define INSTRUCT_LENGTH 64
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UInt8 W_;
|
||||
UInt8 R_;
|
||||
UInt8 X_;
|
||||
UInt8 B_;
|
||||
UInt8 state;
|
||||
} REX_Struct ;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
int Number;
|
||||
int NbUndefined;
|
||||
UInt8 LockPrefix;
|
||||
UInt8 OperandSize;
|
||||
UInt8 AddressSize;
|
||||
UInt8 RepnePrefix;
|
||||
UInt8 RepPrefix;
|
||||
UInt8 FSPrefix;
|
||||
UInt8 SSPrefix;
|
||||
UInt8 GSPrefix;
|
||||
UInt8 ESPrefix;
|
||||
UInt8 CSPrefix;
|
||||
UInt8 DSPrefix;
|
||||
UInt8 BranchTaken;
|
||||
UInt8 BranchNotTaken;
|
||||
REX_Struct REX;
|
||||
char alignment[2];
|
||||
} PREFIXINFO ;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
UInt8 OF_;
|
||||
UInt8 SF_;
|
||||
UInt8 ZF_;
|
||||
UInt8 AF_;
|
||||
UInt8 PF_;
|
||||
UInt8 CF_;
|
||||
UInt8 TF_;
|
||||
UInt8 IF_;
|
||||
UInt8 DF_;
|
||||
UInt8 NT_;
|
||||
UInt8 RF_;
|
||||
UInt8 alignment;
|
||||
} EFLStruct ;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(4)
|
||||
typedef struct {
|
||||
Int32 BaseRegister;
|
||||
Int32 IndexRegister;
|
||||
Int32 Scale;
|
||||
Int64 Displacement;
|
||||
} MEMORYTYPE ;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
Int32 Category;
|
||||
Int32 Opcode;
|
||||
char Mnemonic[16];
|
||||
Int32 BranchType;
|
||||
EFLStruct Flags;
|
||||
UInt64 AddrValue;
|
||||
Int64 Immediat;
|
||||
UInt32 ImplicitModifiedRegs;
|
||||
} INSTRTYPE;
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
char ArgMnemonic[64];
|
||||
Int32 ArgType;
|
||||
Int32 ArgSize;
|
||||
Int32 ArgPosition;
|
||||
UInt32 AccessMode;
|
||||
MEMORYTYPE Memory;
|
||||
UInt32 SegmentReg;
|
||||
} ARGTYPE;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct _Disasm {
|
||||
UIntPtr EIP;
|
||||
UInt64 VirtualAddr;
|
||||
UInt32 SecurityBlock;
|
||||
char CompleteInstr[INSTRUCT_LENGTH];
|
||||
UInt32 Archi;
|
||||
UInt64 Options;
|
||||
INSTRTYPE Instruction;
|
||||
ARGTYPE Argument1;
|
||||
ARGTYPE Argument2;
|
||||
ARGTYPE Argument3;
|
||||
PREFIXINFO Prefix;
|
||||
UInt32 Reserved_[40];
|
||||
} DISASM, *PDISASM, *LPDISASM;
|
||||
#pragma pack()
|
||||
|
||||
#define ESReg 1
|
||||
#define DSReg 2
|
||||
#define FSReg 3
|
||||
#define GSReg 4
|
||||
#define CSReg 5
|
||||
#define SSReg 6
|
||||
|
||||
#define InvalidPrefix 4
|
||||
#define SuperfluousPrefix 2
|
||||
#define NotUsedPrefix 0
|
||||
#define MandatoryPrefix 8
|
||||
#define InUsePrefix 1
|
||||
|
||||
#define LowPosition 0
|
||||
#define HighPosition 1
|
||||
|
||||
enum INSTRUCTION_TYPE
|
||||
{
|
||||
GENERAL_PURPOSE_INSTRUCTION = 0x10000,
|
||||
FPU_INSTRUCTION = 0x20000,
|
||||
MMX_INSTRUCTION = 0x40000,
|
||||
SSE_INSTRUCTION = 0x80000,
|
||||
SSE2_INSTRUCTION = 0x100000,
|
||||
SSE3_INSTRUCTION = 0x200000,
|
||||
SSSE3_INSTRUCTION = 0x400000,
|
||||
SSE41_INSTRUCTION = 0x800000,
|
||||
SSE42_INSTRUCTION = 0x1000000,
|
||||
SYSTEM_INSTRUCTION = 0x2000000,
|
||||
VM_INSTRUCTION = 0x4000000,
|
||||
UNDOCUMENTED_INSTRUCTION = 0x8000000,
|
||||
AMD_INSTRUCTION = 0x10000000,
|
||||
ILLEGAL_INSTRUCTION = 0x20000000,
|
||||
AES_INSTRUCTION = 0x40000000,
|
||||
CLMUL_INSTRUCTION = (int)0x80000000,
|
||||
|
||||
|
||||
DATA_TRANSFER = 0x1,
|
||||
ARITHMETIC_INSTRUCTION,
|
||||
LOGICAL_INSTRUCTION,
|
||||
SHIFT_ROTATE,
|
||||
BIT_UInt8,
|
||||
CONTROL_TRANSFER,
|
||||
STRING_INSTRUCTION,
|
||||
InOutINSTRUCTION,
|
||||
ENTER_LEAVE_INSTRUCTION,
|
||||
FLAG_CONTROL_INSTRUCTION,
|
||||
SEGMENT_REGISTER,
|
||||
MISCELLANEOUS_INSTRUCTION,
|
||||
COMPARISON_INSTRUCTION,
|
||||
LOGARITHMIC_INSTRUCTION,
|
||||
TRIGONOMETRIC_INSTRUCTION,
|
||||
UNSUPPORTED_INSTRUCTION,
|
||||
LOAD_CONSTANTS,
|
||||
FPUCONTROL,
|
||||
STATE_MANAGEMENT,
|
||||
CONVERSION_INSTRUCTION,
|
||||
SHUFFLE_UNPACK,
|
||||
PACKED_SINGLE_PRECISION,
|
||||
SIMD128bits,
|
||||
SIMD64bits,
|
||||
CACHEABILITY_CONTROL,
|
||||
FP_INTEGER_CONVERSION,
|
||||
SPECIALIZED_128bits,
|
||||
SIMD_FP_PACKED,
|
||||
SIMD_FP_HORIZONTAL ,
|
||||
AGENT_SYNCHRONISATION,
|
||||
PACKED_ALIGN_RIGHT ,
|
||||
PACKED_SIGN,
|
||||
PACKED_BLENDING_INSTRUCTION,
|
||||
PACKED_TEST,
|
||||
PACKED_MINMAX,
|
||||
HORIZONTAL_SEARCH,
|
||||
PACKED_EQUALITY,
|
||||
STREAMING_LOAD,
|
||||
INSERTION_EXTRACTION,
|
||||
DOT_PRODUCT,
|
||||
SAD_INSTRUCTION,
|
||||
ACCELERATOR_INSTRUCTION, /* crc32, popcnt (sse4.2) */
|
||||
ROUND_INSTRUCTION
|
||||
|
||||
};
|
||||
|
||||
enum EFLAGS_STATES
|
||||
{
|
||||
TE_ = 1,
|
||||
MO_ = 2,
|
||||
RE_ = 4,
|
||||
SE_ = 8,
|
||||
UN_ = 0x10,
|
||||
PR_ = 0x20
|
||||
};
|
||||
|
||||
enum BRANCH_TYPE
|
||||
{
|
||||
JO = 1,
|
||||
JC = 2,
|
||||
JE = 3,
|
||||
JA = 4,
|
||||
JS = 5,
|
||||
JP = 6,
|
||||
JL = 7,
|
||||
JG = 8,
|
||||
JB = 2, /* JC == JB */
|
||||
JECXZ = 10,
|
||||
JmpType = 11,
|
||||
CallType = 12,
|
||||
RetType = 13,
|
||||
JNO = -1,
|
||||
JNC = -2,
|
||||
JNE = -3,
|
||||
JNA = -4,
|
||||
JNS = -5,
|
||||
JNP = -6,
|
||||
JNL = -7,
|
||||
JNG = -8,
|
||||
JNB = -2 /* JNC == JNB */
|
||||
};
|
||||
|
||||
enum ARGUMENTS_TYPE
|
||||
{
|
||||
NO_ARGUMENT = 0x10000000,
|
||||
REGISTER_TYPE = 0x20000000,
|
||||
MEMORY_TYPE = 0x40000000,
|
||||
CONSTANT_TYPE = (int)0x80000000,
|
||||
|
||||
MMX_REG = 0x10000,
|
||||
GENERAL_REG = 0x20000,
|
||||
FPU_REG = 0x40000,
|
||||
SSE_REG = 0x80000,
|
||||
CR_REG = 0x100000,
|
||||
DR_REG = 0x200000,
|
||||
SPECIAL_REG = 0x400000,
|
||||
MEMORY_MANAGEMENT_REG = 0x800000,
|
||||
SEGMENT_REG = 0x1000000,
|
||||
|
||||
RELATIVE_ = 0x4000000,
|
||||
ABSOLUTE_ = 0x8000000,
|
||||
|
||||
READ = 0x1,
|
||||
WRITE = 0x2,
|
||||
|
||||
REG0 = 0x1,
|
||||
REG1 = 0x2,
|
||||
REG2 = 0x4,
|
||||
REG3 = 0x8,
|
||||
REG4 = 0x10,
|
||||
REG5 = 0x20,
|
||||
REG6 = 0x40,
|
||||
REG7 = 0x80,
|
||||
REG8 = 0x100,
|
||||
REG9 = 0x200,
|
||||
REG10 = 0x400,
|
||||
REG11 = 0x800,
|
||||
REG12 = 0x1000,
|
||||
REG13 = 0x2000,
|
||||
REG14 = 0x4000,
|
||||
REG15 = 0x8000
|
||||
};
|
||||
|
||||
enum SPECIAL_INFO
|
||||
{
|
||||
UNKNOWN_OPCODE = -1,
|
||||
OUT_OF_BLOCK = 0,
|
||||
|
||||
/* === mask = 0xff */
|
||||
NoTabulation = 0x00000000,
|
||||
Tabulation = 0x00000001,
|
||||
|
||||
/* === mask = 0xff00 */
|
||||
MasmSyntax = 0x00000000,
|
||||
GoAsmSyntax = 0x00000100,
|
||||
NasmSyntax = 0x00000200,
|
||||
ATSyntax = 0x00000400,
|
||||
|
||||
/* === mask = 0xff0000 */
|
||||
PrefixedNumeral = 0x00010000,
|
||||
SuffixedNumeral = 0x00000000,
|
||||
|
||||
/* === mask = 0xff000000 */
|
||||
ShowSegmentRegs = 0x01000000
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
||||
BEA_API int __bea_callspec__ Disasm (LPDISASM pDisAsm);
|
||||
BEA_API const__ char* __bea_callspec__ BeaEngineVersion (void);
|
||||
BEA_API const__ char* __bea_callspec__ BeaEngineRevision (void);
|
||||
#endif
|
||||
+250
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* @file basic_types.h
|
||||
* @author <igor.gutnik@gmail.com>
|
||||
* @date Thu Dec 24 19:31:22 2009
|
||||
*
|
||||
* @brief Definitions of fixed-size integer types for various platforms
|
||||
*
|
||||
* This file is part of BeaEngine.
|
||||
*
|
||||
* BeaEngine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BeaEngine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with BeaEngine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef __BEA_BASIC_TYPES_HPP__
|
||||
#define __BEA_BASIC_TYPES_HPP__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__GNUC__) || defined (__INTEL_COMPILER) || defined(__LCC__)
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/*
|
||||
* Windows/Visual C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef signed __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#if defined(_WIN64)
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
typedef signed __int64 IntPtr;
|
||||
typedef unsigned __int64 UIntPtr;
|
||||
#else
|
||||
typedef signed long IntPtr;
|
||||
typedef size_t UIntPtr;
|
||||
#endif
|
||||
#define BEA_HAVE_INT64 1
|
||||
#elif defined(__GNUC__) || defined(__LCC__)
|
||||
/*
|
||||
* Unix/GCC
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef intptr_t IntPtr;
|
||||
typedef uintptr_t UIntPtr;
|
||||
#if defined(__LP64__)
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
#define BEA_LONG_IS_64_BIT 1
|
||||
typedef signed long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
#else
|
||||
#if defined (__INTEL_COMPILER) || defined (__ICC) || defined (_ICC)
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#else
|
||||
typedef signed long long Int64;
|
||||
typedef unsigned long long UInt64;
|
||||
#endif
|
||||
#endif
|
||||
#define BEA_HAVE_INT64 1
|
||||
#elif defined(__DECCXX)
|
||||
/*
|
||||
* Compaq C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef signed __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#if defined(__VMS)
|
||||
#if defined(__32BITS)
|
||||
typedef signed long IntPtr;
|
||||
typedef unsigned long UIntPtr;
|
||||
#else
|
||||
typedef Int64 IntPtr;
|
||||
typedef UInt64 UIntPtr;
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
#endif
|
||||
#else
|
||||
typedef signed long IntPtr;
|
||||
typedef unsigned long UIntPtr;
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
#define BEA_LONG_IS_64_BIT 1
|
||||
#endif
|
||||
#define BEA_HAVE_INT64 1
|
||||
#elif defined(__HP_aCC)
|
||||
/*
|
||||
* HP Ansi C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef signed long IntPtr;
|
||||
typedef unsigned long UIntPtr;
|
||||
#if defined(__LP64__)
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
#define BEA_LONG_IS_64_BIT 1
|
||||
typedef signed long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
#else
|
||||
typedef signed long long Int64;
|
||||
typedef unsigned long long UInt64;
|
||||
#endif
|
||||
#define BEA_HAVE_INT64 1
|
||||
#elif defined(__SUNPRO_CC) || defined(__SUNPRO_C)
|
||||
/*
|
||||
* SUN Forte C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef signed long IntPtr;
|
||||
typedef unsigned long UIntPtr;
|
||||
#if defined(__sparcv9)
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
#define BEA_LONG_IS_64_BIT 1
|
||||
typedef signed long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
#else
|
||||
typedef signed long long Int64;
|
||||
typedef unsigned long long UInt64;
|
||||
#endif
|
||||
#define BEA_HAVE_INT64 1
|
||||
#elif defined(__IBMCPP__)
|
||||
/*
|
||||
* IBM XL C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef signed long IntPtr;
|
||||
typedef unsigned long UIntPtr;
|
||||
#if defined(__64BIT__)
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
#define BEA_LONG_IS_64_BIT 1
|
||||
typedef signed long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
#else
|
||||
typedef signed long long Int64;
|
||||
typedef unsigned long long UInt64;
|
||||
#endif
|
||||
#define BEA_HAVE_INT64 1
|
||||
#elif defined(__BORLANDC__)
|
||||
/*
|
||||
* Borland C/C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef unsigned __int64 Int64;
|
||||
typedef signed __int64 UInt64;
|
||||
typedef unsigned long UIntPtr;
|
||||
#define BEA_HAVE_INT64 1
|
||||
#elif defined(__WATCOMC__)
|
||||
/*
|
||||
* Watcom C/C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef unsigned __int64 Int64;
|
||||
typedef signed __int64 UInt64;
|
||||
#define BEA_HAVE_INT64 1
|
||||
typedef size_t UIntPtr;
|
||||
#elif defined(__sgi)
|
||||
/*
|
||||
* MIPSpro C++
|
||||
*/
|
||||
typedef signed char Int8;
|
||||
typedef unsigned char UInt8;
|
||||
typedef signed short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
typedef signed int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
typedef signed long IntPtr;
|
||||
typedef unsigned long UIntPtr;
|
||||
#if _MIPS_SZLONG == 64
|
||||
#define BEA_PTR_IS_64_BIT 1
|
||||
#define BEA_LONG_IS_64_BIT 1
|
||||
typedef signed long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
#else
|
||||
typedef signed long long Int64;
|
||||
typedef unsigned long long UInt64;
|
||||
#endif
|
||||
#define BEA_HAVE_INT64 1
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
#define W64LIT(x) x##ui64
|
||||
#else
|
||||
#define W64LIT(x) x##ULL
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef C_STATIC_ASSERT
|
||||
#define C_STATIC_ASSERT(tag_name, x) \
|
||||
typedef int cache_static_assert_ ## tag_name[(x) * 2-1]
|
||||
#endif
|
||||
|
||||
C_STATIC_ASSERT(sizeof_Int8 , (sizeof(Int8) == 1));
|
||||
C_STATIC_ASSERT(sizeof_UInt8, (sizeof(UInt8) == 1));
|
||||
|
||||
C_STATIC_ASSERT(sizeof_Int16 , (sizeof(Int16) == 2));
|
||||
C_STATIC_ASSERT(sizeof_UInt16, (sizeof(UInt16) == 2));
|
||||
|
||||
C_STATIC_ASSERT(sizeof_Int32 , (sizeof(Int32) == 4));
|
||||
C_STATIC_ASSERT(sizeof_UInt32, (sizeof(UInt32) == 4));
|
||||
|
||||
C_STATIC_ASSERT(sizeof_Int64 , (sizeof(Int64) == 8));
|
||||
C_STATIC_ASSERT(sizeof_UInt64, (sizeof(UInt64) == 8));
|
||||
|
||||
#endif
|
||||
Vendored
+173
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @file export.h
|
||||
* @author igor.gutnik@gmail.com
|
||||
* @date Mon Sep 22 09:28:54 2008
|
||||
*
|
||||
* @brief This file sets things up for C dynamic library function definitions and
|
||||
* static inlined functions
|
||||
*
|
||||
* This file is part of BeaEngine.
|
||||
*
|
||||
* BeaEngine is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BeaEngine is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with BeaEngine. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef __BEA_EXPORT_H__
|
||||
#define __BEA_EXPORT_H__
|
||||
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define CPP_VISIBLE_BEGIN extern "C" {
|
||||
#define CPP_VISIBLE_END }
|
||||
#else
|
||||
#define CPP_VISIBLE_BEGIN
|
||||
#define CPP_VISIBLE_END
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning( disable: 4251 )
|
||||
#endif
|
||||
|
||||
/* Some compilers use a special export keyword */
|
||||
#ifndef bea__api_export__
|
||||
# if defined(__BEOS__)
|
||||
# if defined(__GNUC__)
|
||||
# define bea__api_export__ __declspec(dllexport)
|
||||
# else
|
||||
# define bea__api_export__ __declspec(export)
|
||||
# endif
|
||||
# elif defined(_WIN32) || defined(_WIN64)
|
||||
# ifdef __BORLANDC__
|
||||
# define bea__api_export__ __declspec(dllexport)
|
||||
# define bea__api_import__ __declspec(dllimport)
|
||||
# elif defined(__WATCOMC__)
|
||||
# define bea__api_export__ __declspec(dllexport)
|
||||
# define bea__api_import__
|
||||
# else
|
||||
# define bea__api_export__ __declspec(dllexport)
|
||||
# define bea__api_import__ __declspec(dllimport)
|
||||
# endif
|
||||
# elif defined(__OS2__)
|
||||
# ifdef __WATCOMC__
|
||||
# define bea__api_export__ __declspec(dllexport)
|
||||
# define bea__api_import__
|
||||
# else
|
||||
# define bea__api_export__
|
||||
# define bea__api_import__
|
||||
# endif
|
||||
# else
|
||||
# if defined(_WIN32) && defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define bea__api_export__ __attribubea__ ((visibility("default")))
|
||||
# define bea__api_import__ __attribubea__ ((visibility("default")))
|
||||
# else
|
||||
# define bea__api_export__
|
||||
# define bea__api_import__
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Use C calling convention by default*/
|
||||
|
||||
#ifndef __bea_callspec__
|
||||
#if defined(BEA_USE_STDCALL)
|
||||
#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__POCC__)
|
||||
#define __bea_callspec__ __stdcall
|
||||
#else
|
||||
#define __bea_callspec__
|
||||
#endif
|
||||
#else
|
||||
#ifdef __OS2__
|
||||
#define __bea_callspec__ _System
|
||||
#else
|
||||
#define __bea_callspec__
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define __bea_callspec__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __SYMBIAN32__
|
||||
# ifndef EKA2
|
||||
# undef bea__api_export__
|
||||
# undef bea__api_import__
|
||||
# define bea__api_export__
|
||||
# define bea__api_import__
|
||||
# elif !defined(__WINS__)
|
||||
# undef bea__api_export__
|
||||
# undef bea__api_import__
|
||||
# define bea__api_export__ __declspec(dllexport)
|
||||
# define bea__api_import__ __declspec(dllexport)
|
||||
# endif /* !EKA2 */
|
||||
#endif /* __SYMBIAN32__ */
|
||||
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
#define BEA_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
|
||||
#define BEA_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
|
||||
#else
|
||||
#define BEA_EXPECT_CONDITIONAL(c) (c)
|
||||
#define BEA_UNEXPECT_CONDITIONAL(c) (c)
|
||||
#endif
|
||||
|
||||
|
||||
/* Set up compiler-specific options for inlining functions */
|
||||
#ifndef BEA_HAS_INLINE
|
||||
#if defined(__GNUC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
|
||||
#define BEA_HAS_INLINE
|
||||
#else
|
||||
/* Add any special compiler-specific cases here */
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || \
|
||||
defined(__DMC__) || defined(__SC__) || \
|
||||
defined(__WATCOMC__) || defined(__LCC__) || \
|
||||
defined(__DECC) || defined(__EABI__)
|
||||
#ifndef __inline__
|
||||
#define __inline__ __inline
|
||||
#endif
|
||||
#define BEA_HAS_INLINE
|
||||
#else
|
||||
#if !defined(__MRC__) && !defined(_SGI_SOURCE)
|
||||
#ifndef __inline__
|
||||
#define __inline__ inline
|
||||
#endif
|
||||
#define BEA_HAS_INLINE
|
||||
#endif /* Not a funky compiler */
|
||||
#endif /* Visual C++ */
|
||||
#endif /* GNU C */
|
||||
#endif /* CACHE_HAS_INLINE */
|
||||
|
||||
/* If inlining isn't supported, remove "__inline__", turning static
|
||||
inlined functions into static functions (resulting in code bloat
|
||||
in all files which include the offending header files)
|
||||
*/
|
||||
#ifndef BEA_HAS_INLINE
|
||||
#define __inline__
|
||||
#endif
|
||||
|
||||
/* fix a bug with gcc under windows */
|
||||
|
||||
#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(__MINGW32__)
|
||||
#define const__
|
||||
#else
|
||||
#define const__ const
|
||||
#endif
|
||||
#else
|
||||
#define const__ const
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
+4093
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+42
@@ -0,0 +1,42 @@
|
||||
// diacreate.h - creation helper functions for DIA initialization
|
||||
//-----------------------------------------------------------------
|
||||
//
|
||||
// Copyright Microsoft Corporation. All Rights Reserved.
|
||||
//
|
||||
//---------------------------------------------------------------
|
||||
#ifndef _DIACREATE_H_
|
||||
#define _DIACREATE_H_
|
||||
|
||||
//
|
||||
// Create a dia data source object from the dia dll (by dll name - does not access the registry).
|
||||
//
|
||||
|
||||
HRESULT STDMETHODCALLTYPE NoRegCoCreate( const __wchar_t *dllName,
|
||||
REFCLSID rclsid,
|
||||
REFIID riid,
|
||||
void **ppv);
|
||||
|
||||
#ifndef _NATIVE_WCHAR_T_DEFINED
|
||||
#ifdef __cplusplus
|
||||
|
||||
HRESULT STDMETHODCALLTYPE NoRegCoCreate( const wchar_t *dllName,
|
||||
REFCLSID rclsid,
|
||||
REFIID riid,
|
||||
void **ppv)
|
||||
{
|
||||
return NoRegCoCreate( (const __wchar_t *)dllName, rclsid, riid, ppv );
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Create a dia data source object from the dia dll (looks up the class id in the registry).
|
||||
//
|
||||
HRESULT STDMETHODCALLTYPE NoOleCoCreate( REFCLSID rclsid,
|
||||
REFIID riid,
|
||||
void **ppv);
|
||||
|
||||
#endif
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,334 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
#define VERSIONHELPERAPI inline bool
|
||||
|
||||
#define _WIN32_WINNT_NT4 0x0400
|
||||
#define _WIN32_WINNT_WIN2K 0x0500
|
||||
#define _WIN32_WINNT_WINXP 0x0501
|
||||
#define _WIN32_WINNT_WS03 0x0502
|
||||
#define _WIN32_WINNT_WIN6 0x0600
|
||||
#define _WIN32_WINNT_VISTA 0x0600
|
||||
#define _WIN32_WINNT_WS08 0x0600
|
||||
#define _WIN32_WINNT_LONGHORN 0x0600
|
||||
#define _WIN32_WINNT_WIN7 0x0601
|
||||
#define _WIN32_WINNT_WIN8 0x0602
|
||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
||||
#define _WIN32_WINNT_WIN10 0x0A00
|
||||
|
||||
using fnRtlGetVersion = NTSTATUS( NTAPI* )(PRTL_OSVERSIONINFOEXW lpVersionInformation);
|
||||
|
||||
enum eBuildThreshold
|
||||
{
|
||||
Build_RS0 = 10586,
|
||||
Build_RS1 = 14393,
|
||||
Build_RS2 = 15063,
|
||||
Build_RS3 = 16299,
|
||||
Build_RS4 = 17134,
|
||||
Build_RS5 = 17763,
|
||||
Build_19H1 = 18362,
|
||||
Build_19H2 = 18363,
|
||||
Build_20H1 = 19041,
|
||||
Build_21H2 = 22000,
|
||||
Build_22H2 = 22621,
|
||||
Build_RS_MAX = 99999,
|
||||
};
|
||||
|
||||
enum eVerShort
|
||||
{
|
||||
WinUnsupported, // Unsupported OS
|
||||
WinXP, // Windows XP
|
||||
Win7, // Windows 7
|
||||
Win8, // Windows 8
|
||||
Win8Point1, // Windows 8.1
|
||||
Win10, // Windows 10
|
||||
Win10_RS1, // Windows 10 Anniversary update
|
||||
Win10_RS2, // Windows 10 Creators update
|
||||
Win10_RS3, // Windows 10 Fall Creators update
|
||||
Win10_RS4, // Windows 10 Spring Creators update
|
||||
Win10_RS5, // Windows 10 October 2018 update
|
||||
Win10_19H1, // Windows 10 May 2019 update
|
||||
Win10_19H2, // Windows 10 November 2019 update
|
||||
Win10_20H1, // Windows 10 April 2020 update
|
||||
Win11_21H2, // Windows 11
|
||||
Win11_22H2 // Windows 11 September 2022 update
|
||||
};
|
||||
|
||||
struct WinVersion
|
||||
{
|
||||
eVerShort ver = WinUnsupported;
|
||||
uint32_t revision = 0;
|
||||
RTL_OSVERSIONINFOEXW native = { };
|
||||
};
|
||||
|
||||
BLACKBONE_API inline WinVersion& WinVer()
|
||||
{
|
||||
static WinVersion g_WinVer;
|
||||
return g_WinVer;
|
||||
}
|
||||
|
||||
BLACKBONE_API inline uint32_t GetRevision()
|
||||
{
|
||||
HKEY hKey = NULL;
|
||||
|
||||
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey ) == 0)
|
||||
{
|
||||
wchar_t data[MAX_PATH] = {};
|
||||
DWORD dataSize = sizeof( data );
|
||||
DWORD type = REG_SZ;
|
||||
|
||||
if (RegQueryValueExW( hKey, L"BuildLabEx", nullptr, &type, reinterpret_cast<LPBYTE>(data), &dataSize ) == 0)
|
||||
{
|
||||
std::wstring buildStr = data;
|
||||
size_t first = buildStr.find( L'.' );
|
||||
size_t second = buildStr.find( L'.', first + 1 );
|
||||
|
||||
if (second > first && first != buildStr.npos)
|
||||
{
|
||||
RegCloseKey( hKey );
|
||||
return std::wcstol( buildStr.substr( first + 1, second - first - 1 ).c_str(), nullptr, 10 );
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey( hKey );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLACKBONE_API inline void InitVersion()
|
||||
{
|
||||
auto& g_WinVer = WinVer();
|
||||
g_WinVer.native.dwOSVersionInfoSize = sizeof( g_WinVer.native );
|
||||
|
||||
auto RtlGetVersion = (fnRtlGetVersion)GetProcAddress( GetModuleHandleW( L"ntdll.dll" ), "RtlGetVersion" );
|
||||
if (RtlGetVersion)
|
||||
{
|
||||
RtlGetVersion( &g_WinVer.native );
|
||||
}
|
||||
|
||||
if (g_WinVer.native.dwMajorVersion != 0)
|
||||
{
|
||||
auto fullver = (g_WinVer.native.dwMajorVersion << 8) | g_WinVer.native.dwMinorVersion;
|
||||
switch (fullver)
|
||||
{
|
||||
case _WIN32_WINNT_WIN10:
|
||||
if (g_WinVer.native.dwBuildNumber >= Build_22H2)
|
||||
g_WinVer.ver = Win11_22H2;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_21H2)
|
||||
g_WinVer.ver = Win11_21H2;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_20H1)
|
||||
g_WinVer.ver = Win10_20H1;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_19H2)
|
||||
g_WinVer.ver = Win10_19H2;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_19H1)
|
||||
g_WinVer.ver = Win10_19H1;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_RS5)
|
||||
g_WinVer.ver = Win10_RS5;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_RS4)
|
||||
g_WinVer.ver = Win10_RS4;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_RS3)
|
||||
g_WinVer.ver = Win10_RS3;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_RS2)
|
||||
g_WinVer.ver = Win10_RS2;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_RS1)
|
||||
g_WinVer.ver = Win10_RS1;
|
||||
else if (g_WinVer.native.dwBuildNumber >= Build_RS0)
|
||||
g_WinVer.ver = Win10;
|
||||
break;
|
||||
|
||||
case _WIN32_WINNT_WINBLUE:
|
||||
g_WinVer.ver = Win8Point1;
|
||||
break;
|
||||
|
||||
case _WIN32_WINNT_WIN8:
|
||||
g_WinVer.ver = Win8;
|
||||
break;
|
||||
|
||||
case _WIN32_WINNT_WIN7:
|
||||
g_WinVer.ver = Win7;
|
||||
break;
|
||||
|
||||
case _WIN32_WINNT_WINXP:
|
||||
g_WinVer.ver = WinXP;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_WinVer.ver = WinUnsupported;
|
||||
}
|
||||
}
|
||||
|
||||
g_WinVer.revision = GetRevision();
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVersionOrGreater( WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor, DWORD dwBuild )
|
||||
{
|
||||
auto& g_WinVer = WinVer();
|
||||
if (g_WinVer.native.dwMajorVersion != 0)
|
||||
{
|
||||
if (g_WinVer.native.dwMajorVersion > wMajorVersion)
|
||||
return true;
|
||||
else if (g_WinVer.native.dwMajorVersion < wMajorVersion)
|
||||
return false;
|
||||
|
||||
if (g_WinVer.native.dwMinorVersion > wMinorVersion)
|
||||
return true;
|
||||
else if (g_WinVer.native.dwMinorVersion < wMinorVersion)
|
||||
return false;
|
||||
|
||||
if (g_WinVer.native.wServicePackMajor > wServicePackMajor)
|
||||
return true;
|
||||
else if (g_WinVer.native.wServicePackMajor < wServicePackMajor)
|
||||
return false;
|
||||
|
||||
if (g_WinVer.native.dwBuildNumber >= dwBuild)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BLACKBONE_API
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPOrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WINXP ), LOBYTE( _WIN32_WINNT_WINXP ), 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WINXP ), LOBYTE( _WIN32_WINNT_WINXP ), 1, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WINXP ), LOBYTE( _WIN32_WINNT_WINXP ), 2, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP3OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WINXP ), LOBYTE( _WIN32_WINNT_WINXP ), 3, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaOrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_VISTA ), LOBYTE( _WIN32_WINNT_VISTA ), 0, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaSP1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_VISTA ), LOBYTE( _WIN32_WINNT_VISTA ), 1, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaSP2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_VISTA ), LOBYTE( _WIN32_WINNT_VISTA ), 2, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows7OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN7 ), LOBYTE( _WIN32_WINNT_WIN7 ), 0, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows7SP1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN7 ), LOBYTE( _WIN32_WINNT_WIN7 ), 1, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows8OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN8 ), LOBYTE( _WIN32_WINNT_WIN8 ), 0, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows8Point1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WINBLUE ), LOBYTE( _WIN32_WINNT_WINBLUE ), 0, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows10OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, 0 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows10RS1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_RS1 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows10RS2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_RS2 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows10RS3OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_RS3 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows10RS4OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_RS4 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows10RS5OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_RS5 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows1019H1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_19H1 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows1019H2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_19H2 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows1020H1OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_20H1 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows1121H2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_21H2);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindows1122H2OrGreater()
|
||||
{
|
||||
return IsWindowsVersionOrGreater( HIBYTE( _WIN32_WINNT_WIN10 ), LOBYTE( _WIN32_WINNT_WIN10 ), 0, Build_22H2 );
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsServer()
|
||||
{
|
||||
OSVERSIONINFOEXW osvi = { sizeof( osvi ), 0, 0, 0, 0, { 0 }, 0, 0, 0, VER_NT_WORKSTATION };
|
||||
DWORDLONG const dwlConditionMask = VerSetConditionMask( 0, VER_PRODUCT_TYPE, VER_EQUAL );
|
||||
|
||||
return !VerifyVersionInfoW( &osvi, VER_PRODUCT_TYPE, dwlConditionMask );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,291 @@
|
||||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 6.00.0366 */
|
||||
//@@MIDL_FILE_HEADING( )
|
||||
|
||||
#pragma warning( disable: 4049 ) /* more than 64k source lines */
|
||||
|
||||
|
||||
/* verify that the <rpcndr.h> version is high enough to compile this file*/
|
||||
#ifndef __REQUIRED_RPCNDR_H_VERSION__
|
||||
#define __REQUIRED_RPCNDR_H_VERSION__ 475
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rpcndr.h"
|
||||
|
||||
#ifndef __RPCNDR_H_VERSION__
|
||||
#error this stub requires an updated version of <rpcndr.h>
|
||||
#endif // __RPCNDR_H_VERSION__
|
||||
|
||||
#ifndef COM_NO_WINDOWS_H
|
||||
#include "windows.h"
|
||||
#include "ole2.h"
|
||||
#endif /*COM_NO_WINDOWS_H*/
|
||||
|
||||
#ifndef __gchost_h__
|
||||
#define __gchost_h__
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* Forward Declarations */
|
||||
|
||||
#ifndef __IGCHost_FWD_DEFINED__
|
||||
#define __IGCHost_FWD_DEFINED__
|
||||
typedef interface IGCHost IGCHost;
|
||||
#endif /* __IGCHost_FWD_DEFINED__ */
|
||||
|
||||
|
||||
/* header files for imported files */
|
||||
#include "unknwn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
void * __RPC_USER MIDL_user_allocate(size_t);
|
||||
void __RPC_USER MIDL_user_free( void * );
|
||||
|
||||
/* interface __MIDL_itf_gchost_0000 */
|
||||
/* [local] */
|
||||
|
||||
typedef /* [public] */
|
||||
enum __MIDL___MIDL_itf_gchost_0000_0001
|
||||
{ COR_GC_COUNTS = 0x1,
|
||||
COR_GC_MEMORYUSAGE = 0x2
|
||||
} COR_GC_STAT_TYPES;
|
||||
|
||||
typedef /* [public] */
|
||||
enum __MIDL___MIDL_itf_gchost_0000_0002
|
||||
{ COR_GC_THREAD_HAS_PROMOTED_BYTES = 0x1
|
||||
} COR_GC_THREAD_STATS_TYPES;
|
||||
|
||||
typedef struct _COR_GC_STATS
|
||||
{
|
||||
ULONG Flags;
|
||||
SIZE_T ExplicitGCCount;
|
||||
SIZE_T GenCollectionsTaken[ 3 ];
|
||||
SIZE_T CommittedKBytes;
|
||||
SIZE_T ReservedKBytes;
|
||||
SIZE_T Gen0HeapSizeKBytes;
|
||||
SIZE_T Gen1HeapSizeKBytes;
|
||||
SIZE_T Gen2HeapSizeKBytes;
|
||||
SIZE_T LargeObjectHeapSizeKBytes;
|
||||
SIZE_T KBytesPromotedFromGen0;
|
||||
SIZE_T KBytesPromotedFromGen1;
|
||||
} COR_GC_STATS;
|
||||
|
||||
typedef struct _COR_GC_THREAD_STATS
|
||||
{
|
||||
ULONGLONG PerThreadAllocation;
|
||||
ULONG Flags;
|
||||
} COR_GC_THREAD_STATS;
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_gchost_0000_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_gchost_0000_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __IGCHost_INTERFACE_DEFINED__
|
||||
#define __IGCHost_INTERFACE_DEFINED__
|
||||
|
||||
/* interface IGCHost */
|
||||
/* [local][unique][uuid][object] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_IGCHost;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("FAC34F6E-0DCD-47b5-8021-531BC5ECCA63")
|
||||
IGCHost : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE SetGCStartupLimits(
|
||||
/* [in] */ DWORD SegmentSize,
|
||||
/* [in] */ DWORD MaxGen0Size) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Collect(
|
||||
/* [in] */ LONG Generation) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetStats(
|
||||
/* [out][in] */ COR_GC_STATS *pStats) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetThreadStats(
|
||||
/* [in] */ DWORD *pFiberCookie,
|
||||
/* [out][in] */ COR_GC_THREAD_STATS *pStats) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE SetVirtualMemLimit(
|
||||
/* [in] */ SIZE_T sztMaxVirtualMemMB) = 0;
|
||||
|
||||
};
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct IGCHostVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
IGCHost * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [iid_is][out] */ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
IGCHost * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
IGCHost * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetGCStartupLimits )(
|
||||
IGCHost * This,
|
||||
/* [in] */ DWORD SegmentSize,
|
||||
/* [in] */ DWORD MaxGen0Size);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *Collect )(
|
||||
IGCHost * This,
|
||||
/* [in] */ LONG Generation);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetStats )(
|
||||
IGCHost * This,
|
||||
/* [out][in] */ COR_GC_STATS *pStats);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *GetThreadStats )(
|
||||
IGCHost * This,
|
||||
/* [in] */ DWORD *pFiberCookie,
|
||||
/* [out][in] */ COR_GC_THREAD_STATS *pStats);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetVirtualMemLimit )(
|
||||
IGCHost * This,
|
||||
/* [in] */ SIZE_T sztMaxVirtualMemMB);
|
||||
|
||||
END_INTERFACE
|
||||
} IGCHostVtbl;
|
||||
|
||||
interface IGCHost
|
||||
{
|
||||
CONST_VTBL struct IGCHostVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define IGCHost_QueryInterface(This,riid,ppvObject) \
|
||||
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
|
||||
|
||||
#define IGCHost_AddRef(This) \
|
||||
(This)->lpVtbl -> AddRef(This)
|
||||
|
||||
#define IGCHost_Release(This) \
|
||||
(This)->lpVtbl -> Release(This)
|
||||
|
||||
|
||||
#define IGCHost_SetGCStartupLimits(This,SegmentSize,MaxGen0Size) \
|
||||
(This)->lpVtbl -> SetGCStartupLimits(This,SegmentSize,MaxGen0Size)
|
||||
|
||||
#define IGCHost_Collect(This,Generation) \
|
||||
(This)->lpVtbl -> Collect(This,Generation)
|
||||
|
||||
#define IGCHost_GetStats(This,pStats) \
|
||||
(This)->lpVtbl -> GetStats(This,pStats)
|
||||
|
||||
#define IGCHost_GetThreadStats(This,pFiberCookie,pStats) \
|
||||
(This)->lpVtbl -> GetThreadStats(This,pFiberCookie,pStats)
|
||||
|
||||
#define IGCHost_SetVirtualMemLimit(This,sztMaxVirtualMemMB) \
|
||||
(This)->lpVtbl -> SetVirtualMemLimit(This,sztMaxVirtualMemMB)
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IGCHost_SetGCStartupLimits_Proxy(
|
||||
IGCHost * This,
|
||||
/* [in] */ DWORD SegmentSize,
|
||||
/* [in] */ DWORD MaxGen0Size);
|
||||
|
||||
|
||||
void __RPC_STUB IGCHost_SetGCStartupLimits_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IGCHost_Collect_Proxy(
|
||||
IGCHost * This,
|
||||
/* [in] */ LONG Generation);
|
||||
|
||||
|
||||
void __RPC_STUB IGCHost_Collect_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IGCHost_GetStats_Proxy(
|
||||
IGCHost * This,
|
||||
/* [out][in] */ COR_GC_STATS *pStats);
|
||||
|
||||
|
||||
void __RPC_STUB IGCHost_GetStats_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IGCHost_GetThreadStats_Proxy(
|
||||
IGCHost * This,
|
||||
/* [in] */ DWORD *pFiberCookie,
|
||||
/* [out][in] */ COR_GC_THREAD_STATS *pStats);
|
||||
|
||||
|
||||
void __RPC_STUB IGCHost_GetThreadStats_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IGCHost_SetVirtualMemLimit_Proxy(
|
||||
IGCHost * This,
|
||||
/* [in] */ SIZE_T sztMaxVirtualMemMB);
|
||||
|
||||
|
||||
void __RPC_STUB IGCHost_SetVirtualMemLimit_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
|
||||
#endif /* __IGCHost_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
/* end of Additional Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 6.00.0366 */
|
||||
//@@MIDL_FILE_HEADING( )
|
||||
|
||||
#pragma warning( disable: 4049 ) /* more than 64k source lines */
|
||||
|
||||
|
||||
/* verify that the <rpcndr.h> version is high enough to compile this file*/
|
||||
#ifndef __REQUIRED_RPCNDR_H_VERSION__
|
||||
#define __REQUIRED_RPCNDR_H_VERSION__ 475
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rpcndr.h"
|
||||
|
||||
#ifndef __RPCNDR_H_VERSION__
|
||||
#error this stub requires an updated version of <rpcndr.h>
|
||||
#endif // __RPCNDR_H_VERSION__
|
||||
|
||||
#ifndef COM_NO_WINDOWS_H
|
||||
#include "windows.h"
|
||||
#include "ole2.h"
|
||||
#endif /*COM_NO_WINDOWS_H*/
|
||||
|
||||
#ifndef __ivalidator_h__
|
||||
#define __ivalidator_h__
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* Forward Declarations */
|
||||
|
||||
#ifndef __IValidator_FWD_DEFINED__
|
||||
#define __IValidator_FWD_DEFINED__
|
||||
typedef interface IValidator IValidator;
|
||||
#endif /* __IValidator_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ICLRValidator_FWD_DEFINED__
|
||||
#define __ICLRValidator_FWD_DEFINED__
|
||||
typedef interface ICLRValidator ICLRValidator;
|
||||
#endif /* __ICLRValidator_FWD_DEFINED__ */
|
||||
|
||||
|
||||
/* header files for imported files */
|
||||
#include "ivehandler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
void * __RPC_USER MIDL_user_allocate(size_t);
|
||||
void __RPC_USER MIDL_user_free( void * );
|
||||
|
||||
/* interface __MIDL_itf_ivalidator_0000 */
|
||||
/* [local] */
|
||||
|
||||
|
||||
|
||||
|
||||
enum ValidatorFlags
|
||||
{ VALIDATOR_EXTRA_VERBOSE = 0x1,
|
||||
VALIDATOR_SHOW_SOURCE_LINES = 0x2,
|
||||
VALIDATOR_CHECK_ILONLY = 0x4,
|
||||
VALIDATOR_CHECK_PEFORMAT_ONLY = 0x8,
|
||||
VALIDATOR_NOCHECK_PEFORMAT = 0x10
|
||||
} ;
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_ivalidator_0000_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_ivalidator_0000_v0_0_s_ifspec;
|
||||
|
||||
#ifndef __IValidator_INTERFACE_DEFINED__
|
||||
#define __IValidator_INTERFACE_DEFINED__
|
||||
|
||||
/* interface IValidator */
|
||||
/* [unique][uuid][object] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_IValidator;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("63DF8730-DC81-4062-84A2-1FF943F59FAC")
|
||||
IValidator : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE Validate(
|
||||
/* [in] */ IVEHandler *veh,
|
||||
/* [in] */ IUnknown *pAppDomain,
|
||||
/* [in] */ unsigned long ulFlags,
|
||||
/* [in] */ unsigned long ulMaxError,
|
||||
/* [in] */ unsigned long token,
|
||||
/* [in] */ LPWSTR fileName,
|
||||
/* [size_is][in] */ BYTE *pe,
|
||||
/* [in] */ unsigned long ulSize) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE FormatEventInfo(
|
||||
/* [in] */ HRESULT hVECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [out][in] */ LPWSTR msg,
|
||||
/* [in] */ unsigned long ulMaxLength,
|
||||
/* [in] */ SAFEARRAY * psa) = 0;
|
||||
|
||||
};
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct IValidatorVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
IValidator * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [iid_is][out] */ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
IValidator * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
IValidator * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *Validate )(
|
||||
IValidator * This,
|
||||
/* [in] */ IVEHandler *veh,
|
||||
/* [in] */ IUnknown *pAppDomain,
|
||||
/* [in] */ unsigned long ulFlags,
|
||||
/* [in] */ unsigned long ulMaxError,
|
||||
/* [in] */ unsigned long token,
|
||||
/* [in] */ LPWSTR fileName,
|
||||
/* [size_is][in] */ BYTE *pe,
|
||||
/* [in] */ unsigned long ulSize);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *FormatEventInfo )(
|
||||
IValidator * This,
|
||||
/* [in] */ HRESULT hVECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [out][in] */ LPWSTR msg,
|
||||
/* [in] */ unsigned long ulMaxLength,
|
||||
/* [in] */ SAFEARRAY * psa);
|
||||
|
||||
END_INTERFACE
|
||||
} IValidatorVtbl;
|
||||
|
||||
interface IValidator
|
||||
{
|
||||
CONST_VTBL struct IValidatorVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define IValidator_QueryInterface(This,riid,ppvObject) \
|
||||
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
|
||||
|
||||
#define IValidator_AddRef(This) \
|
||||
(This)->lpVtbl -> AddRef(This)
|
||||
|
||||
#define IValidator_Release(This) \
|
||||
(This)->lpVtbl -> Release(This)
|
||||
|
||||
|
||||
#define IValidator_Validate(This,veh,pAppDomain,ulFlags,ulMaxError,token,fileName,pe,ulSize) \
|
||||
(This)->lpVtbl -> Validate(This,veh,pAppDomain,ulFlags,ulMaxError,token,fileName,pe,ulSize)
|
||||
|
||||
#define IValidator_FormatEventInfo(This,hVECode,Context,msg,ulMaxLength,psa) \
|
||||
(This)->lpVtbl -> FormatEventInfo(This,hVECode,Context,msg,ulMaxLength,psa)
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IValidator_Validate_Proxy(
|
||||
IValidator * This,
|
||||
/* [in] */ IVEHandler *veh,
|
||||
/* [in] */ IUnknown *pAppDomain,
|
||||
/* [in] */ unsigned long ulFlags,
|
||||
/* [in] */ unsigned long ulMaxError,
|
||||
/* [in] */ unsigned long token,
|
||||
/* [in] */ LPWSTR fileName,
|
||||
/* [size_is][in] */ BYTE *pe,
|
||||
/* [in] */ unsigned long ulSize);
|
||||
|
||||
|
||||
void __RPC_STUB IValidator_Validate_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IValidator_FormatEventInfo_Proxy(
|
||||
IValidator * This,
|
||||
/* [in] */ HRESULT hVECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [out][in] */ LPWSTR msg,
|
||||
/* [in] */ unsigned long ulMaxLength,
|
||||
/* [in] */ SAFEARRAY * psa);
|
||||
|
||||
|
||||
void __RPC_STUB IValidator_FormatEventInfo_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
|
||||
#endif /* __IValidator_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __ICLRValidator_INTERFACE_DEFINED__
|
||||
#define __ICLRValidator_INTERFACE_DEFINED__
|
||||
|
||||
/* interface ICLRValidator */
|
||||
/* [unique][uuid][object] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_ICLRValidator;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("63DF8730-DC81-4062-84A2-1FF943F59FDD")
|
||||
ICLRValidator : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE Validate(
|
||||
/* [in] */ IVEHandler *veh,
|
||||
/* [in] */ unsigned long ulAppDomainId,
|
||||
/* [in] */ unsigned long ulFlags,
|
||||
/* [in] */ unsigned long ulMaxError,
|
||||
/* [in] */ unsigned long token,
|
||||
/* [in] */ LPWSTR fileName,
|
||||
/* [size_is][in] */ BYTE *pe,
|
||||
/* [in] */ unsigned long ulSize) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE FormatEventInfo(
|
||||
/* [in] */ HRESULT hVECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [out][in] */ LPWSTR msg,
|
||||
/* [in] */ unsigned long ulMaxLength,
|
||||
/* [in] */ SAFEARRAY * psa) = 0;
|
||||
|
||||
};
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct ICLRValidatorVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
ICLRValidator * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [iid_is][out] */ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
ICLRValidator * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
ICLRValidator * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *Validate )(
|
||||
ICLRValidator * This,
|
||||
/* [in] */ IVEHandler *veh,
|
||||
/* [in] */ unsigned long ulAppDomainId,
|
||||
/* [in] */ unsigned long ulFlags,
|
||||
/* [in] */ unsigned long ulMaxError,
|
||||
/* [in] */ unsigned long token,
|
||||
/* [in] */ LPWSTR fileName,
|
||||
/* [size_is][in] */ BYTE *pe,
|
||||
/* [in] */ unsigned long ulSize);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *FormatEventInfo )(
|
||||
ICLRValidator * This,
|
||||
/* [in] */ HRESULT hVECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [out][in] */ LPWSTR msg,
|
||||
/* [in] */ unsigned long ulMaxLength,
|
||||
/* [in] */ SAFEARRAY * psa);
|
||||
|
||||
END_INTERFACE
|
||||
} ICLRValidatorVtbl;
|
||||
|
||||
interface ICLRValidator
|
||||
{
|
||||
CONST_VTBL struct ICLRValidatorVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define ICLRValidator_QueryInterface(This,riid,ppvObject) \
|
||||
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
|
||||
|
||||
#define ICLRValidator_AddRef(This) \
|
||||
(This)->lpVtbl -> AddRef(This)
|
||||
|
||||
#define ICLRValidator_Release(This) \
|
||||
(This)->lpVtbl -> Release(This)
|
||||
|
||||
|
||||
#define ICLRValidator_Validate(This,veh,ulAppDomainId,ulFlags,ulMaxError,token,fileName,pe,ulSize) \
|
||||
(This)->lpVtbl -> Validate(This,veh,ulAppDomainId,ulFlags,ulMaxError,token,fileName,pe,ulSize)
|
||||
|
||||
#define ICLRValidator_FormatEventInfo(This,hVECode,Context,msg,ulMaxLength,psa) \
|
||||
(This)->lpVtbl -> FormatEventInfo(This,hVECode,Context,msg,ulMaxLength,psa)
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ICLRValidator_Validate_Proxy(
|
||||
ICLRValidator * This,
|
||||
/* [in] */ IVEHandler *veh,
|
||||
/* [in] */ unsigned long ulAppDomainId,
|
||||
/* [in] */ unsigned long ulFlags,
|
||||
/* [in] */ unsigned long ulMaxError,
|
||||
/* [in] */ unsigned long token,
|
||||
/* [in] */ LPWSTR fileName,
|
||||
/* [size_is][in] */ BYTE *pe,
|
||||
/* [in] */ unsigned long ulSize);
|
||||
|
||||
|
||||
void __RPC_STUB ICLRValidator_Validate_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE ICLRValidator_FormatEventInfo_Proxy(
|
||||
ICLRValidator * This,
|
||||
/* [in] */ HRESULT hVECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [out][in] */ LPWSTR msg,
|
||||
/* [in] */ unsigned long ulMaxLength,
|
||||
/* [in] */ SAFEARRAY * psa);
|
||||
|
||||
|
||||
void __RPC_STUB ICLRValidator_FormatEventInfo_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
|
||||
#endif /* __ICLRValidator_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
unsigned long __RPC_USER LPSAFEARRAY_UserSize( unsigned long *, unsigned long , LPSAFEARRAY * );
|
||||
unsigned char * __RPC_USER LPSAFEARRAY_UserMarshal( unsigned long *, unsigned char *, LPSAFEARRAY * );
|
||||
unsigned char * __RPC_USER LPSAFEARRAY_UserUnmarshal(unsigned long *, unsigned char *, LPSAFEARRAY * );
|
||||
void __RPC_USER LPSAFEARRAY_UserFree( unsigned long *, LPSAFEARRAY * );
|
||||
|
||||
/* end of Additional Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
|
||||
|
||||
|
||||
/* File created by MIDL compiler version 6.00.0366 */
|
||||
//@@MIDL_FILE_HEADING( )
|
||||
|
||||
#pragma warning( disable: 4049 ) /* more than 64k source lines */
|
||||
|
||||
|
||||
/* verify that the <rpcndr.h> version is high enough to compile this file*/
|
||||
#ifndef __REQUIRED_RPCNDR_H_VERSION__
|
||||
#define __REQUIRED_RPCNDR_H_VERSION__ 475
|
||||
#endif
|
||||
|
||||
#include "rpc.h"
|
||||
#include "rpcndr.h"
|
||||
|
||||
#ifndef __RPCNDR_H_VERSION__
|
||||
#error this stub requires an updated version of <rpcndr.h>
|
||||
#endif // __RPCNDR_H_VERSION__
|
||||
|
||||
#ifndef COM_NO_WINDOWS_H
|
||||
#include "windows.h"
|
||||
#include "ole2.h"
|
||||
#endif /*COM_NO_WINDOWS_H*/
|
||||
|
||||
#ifndef __ivehandler_h__
|
||||
#define __ivehandler_h__
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/* Forward Declarations */
|
||||
|
||||
#ifndef __VEHandlerClass_FWD_DEFINED__
|
||||
#define __VEHandlerClass_FWD_DEFINED__
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef class VEHandlerClass VEHandlerClass;
|
||||
#else
|
||||
typedef struct VEHandlerClass VEHandlerClass;
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __VEHandlerClass_FWD_DEFINED__ */
|
||||
|
||||
|
||||
#ifndef __IVEHandler_FWD_DEFINED__
|
||||
#define __IVEHandler_FWD_DEFINED__
|
||||
typedef interface IVEHandler IVEHandler;
|
||||
#endif /* __IVEHandler_FWD_DEFINED__ */
|
||||
|
||||
|
||||
/* header files for imported files */
|
||||
#include "unknwn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
void * __RPC_USER MIDL_user_allocate(size_t);
|
||||
void __RPC_USER MIDL_user_free( void * );
|
||||
|
||||
/* interface __MIDL_itf_ivehandler_0000 */
|
||||
/* [local] */
|
||||
|
||||
typedef struct tag_VerError
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long opcode;
|
||||
unsigned long uOffset;
|
||||
unsigned long Token;
|
||||
unsigned long item1_flags;
|
||||
int *item1_data;
|
||||
unsigned long item2_flags;
|
||||
int *item2_data;
|
||||
} _VerError;
|
||||
|
||||
typedef _VerError VEContext;
|
||||
|
||||
|
||||
|
||||
|
||||
extern RPC_IF_HANDLE __MIDL_itf_ivehandler_0000_v0_0_c_ifspec;
|
||||
extern RPC_IF_HANDLE __MIDL_itf_ivehandler_0000_v0_0_s_ifspec;
|
||||
|
||||
|
||||
#ifndef __VEHandlerLib_LIBRARY_DEFINED__
|
||||
#define __VEHandlerLib_LIBRARY_DEFINED__
|
||||
|
||||
/* library VEHandlerLib */
|
||||
/* [helpstring][version][uuid] */
|
||||
|
||||
|
||||
EXTERN_C const IID LIBID_VEHandlerLib;
|
||||
|
||||
EXTERN_C const CLSID CLSID_VEHandlerClass;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
class DECLSPEC_UUID("856CA1B1-7DAB-11d3-ACEC-00C04F86C309")
|
||||
VEHandlerClass;
|
||||
#endif
|
||||
#endif /* __VEHandlerLib_LIBRARY_DEFINED__ */
|
||||
|
||||
#ifndef __IVEHandler_INTERFACE_DEFINED__
|
||||
#define __IVEHandler_INTERFACE_DEFINED__
|
||||
|
||||
/* interface IVEHandler */
|
||||
/* [unique][uuid][object] */
|
||||
|
||||
|
||||
EXTERN_C const IID IID_IVEHandler;
|
||||
|
||||
#if defined(__cplusplus) && !defined(CINTERFACE)
|
||||
|
||||
MIDL_INTERFACE("856CA1B2-7DAB-11d3-ACEC-00C04F86C309")
|
||||
IVEHandler : public IUnknown
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE VEHandler(
|
||||
/* [in] */ HRESULT VECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [in] */ SAFEARRAY * psa) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE SetReporterFtn(
|
||||
/* [in] */ __int64 lFnPtr) = 0;
|
||||
|
||||
};
|
||||
|
||||
#else /* C style interface */
|
||||
|
||||
typedef struct IVEHandlerVtbl
|
||||
{
|
||||
BEGIN_INTERFACE
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
|
||||
IVEHandler * This,
|
||||
/* [in] */ REFIID riid,
|
||||
/* [iid_is][out] */ void **ppvObject);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *AddRef )(
|
||||
IVEHandler * This);
|
||||
|
||||
ULONG ( STDMETHODCALLTYPE *Release )(
|
||||
IVEHandler * This);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *VEHandler )(
|
||||
IVEHandler * This,
|
||||
/* [in] */ HRESULT VECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [in] */ SAFEARRAY * psa);
|
||||
|
||||
HRESULT ( STDMETHODCALLTYPE *SetReporterFtn )(
|
||||
IVEHandler * This,
|
||||
/* [in] */ __int64 lFnPtr);
|
||||
|
||||
END_INTERFACE
|
||||
} IVEHandlerVtbl;
|
||||
|
||||
interface IVEHandler
|
||||
{
|
||||
CONST_VTBL struct IVEHandlerVtbl *lpVtbl;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef COBJMACROS
|
||||
|
||||
|
||||
#define IVEHandler_QueryInterface(This,riid,ppvObject) \
|
||||
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
|
||||
|
||||
#define IVEHandler_AddRef(This) \
|
||||
(This)->lpVtbl -> AddRef(This)
|
||||
|
||||
#define IVEHandler_Release(This) \
|
||||
(This)->lpVtbl -> Release(This)
|
||||
|
||||
|
||||
#define IVEHandler_VEHandler(This,VECode,Context,psa) \
|
||||
(This)->lpVtbl -> VEHandler(This,VECode,Context,psa)
|
||||
|
||||
#define IVEHandler_SetReporterFtn(This,lFnPtr) \
|
||||
(This)->lpVtbl -> SetReporterFtn(This,lFnPtr)
|
||||
|
||||
#endif /* COBJMACROS */
|
||||
|
||||
|
||||
#endif /* C style interface */
|
||||
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IVEHandler_VEHandler_Proxy(
|
||||
IVEHandler * This,
|
||||
/* [in] */ HRESULT VECode,
|
||||
/* [in] */ VEContext Context,
|
||||
/* [in] */ SAFEARRAY * psa);
|
||||
|
||||
|
||||
void __RPC_STUB IVEHandler_VEHandler_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE IVEHandler_SetReporterFtn_Proxy(
|
||||
IVEHandler * This,
|
||||
/* [in] */ __int64 lFnPtr);
|
||||
|
||||
|
||||
void __RPC_STUB IVEHandler_SetReporterFtn_Stub(
|
||||
IRpcStubBuffer *This,
|
||||
IRpcChannelBuffer *_pRpcChannelBuffer,
|
||||
PRPC_MESSAGE _pRpcMessage,
|
||||
DWORD *_pdwStubPhase);
|
||||
|
||||
|
||||
|
||||
#endif /* __IVEHandler_INTERFACE_DEFINED__ */
|
||||
|
||||
|
||||
/* Additional Prototypes for ALL interfaces */
|
||||
|
||||
unsigned long __RPC_USER LPSAFEARRAY_UserSize( unsigned long *, unsigned long , LPSAFEARRAY * );
|
||||
unsigned char * __RPC_USER LPSAFEARRAY_UserMarshal( unsigned long *, unsigned char *, LPSAFEARRAY * );
|
||||
unsigned char * __RPC_USER LPSAFEARRAY_UserUnmarshal(unsigned long *, unsigned char *, LPSAFEARRAY * );
|
||||
void __RPC_USER LPSAFEARRAY_UserFree( unsigned long *, LPSAFEARRAY * );
|
||||
|
||||
/* end of Additional Prototypes */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Vendored
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
*
|
||||
* WOW64Ext Library
|
||||
*
|
||||
* Copyright (c) 2014 ReWolf
|
||||
* http://blog.rewolf.pl/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
class CMemPtr
|
||||
{
|
||||
private:
|
||||
void** m_ptr;
|
||||
bool watchActive;
|
||||
|
||||
public:
|
||||
CMemPtr(void** ptr) : m_ptr(ptr), watchActive(true) {}
|
||||
|
||||
~CMemPtr()
|
||||
{
|
||||
if (*m_ptr && watchActive)
|
||||
{
|
||||
free(*m_ptr);
|
||||
*m_ptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void disableWatch() { watchActive = false; }
|
||||
};
|
||||
|
||||
#define WATCH(ptr) \
|
||||
CMemPtr watch_##ptr((void**)&ptr)
|
||||
|
||||
#define DISABLE_WATCH(ptr) \
|
||||
watch_##ptr.disableWatch()
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
*
|
||||
* WOW64Ext Library
|
||||
*
|
||||
* Copyright (c) 2014 ReWolf
|
||||
* http://blog.rewolf.pl/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define EMIT(a) __asm __emit (a)
|
||||
|
||||
#define X64_Start_with_CS(_cs) \
|
||||
{ \
|
||||
EMIT(0x6A) EMIT(_cs) /* push _cs */ \
|
||||
EMIT(0xE8) EMIT(0) EMIT(0) EMIT(0) EMIT(0) /* call $+5 */ \
|
||||
EMIT(0x83) EMIT(4) EMIT(0x24) EMIT(5) /* add dword [esp], 5 */ \
|
||||
EMIT(0xCB) /* retf */ \
|
||||
}
|
||||
|
||||
#define X64_End_with_CS(_cs) \
|
||||
{ \
|
||||
EMIT(0xE8) EMIT(0) EMIT(0) EMIT(0) EMIT(0) /* call $+5 */ \
|
||||
EMIT(0xC7) EMIT(0x44) EMIT(0x24) EMIT(4) EMIT(_cs) EMIT(0) EMIT(0) EMIT(0) /* mov dword [rsp + 4], _cs */ \
|
||||
EMIT(0x83) EMIT(4) EMIT(0x24) EMIT(0xD) /* add dword [rsp], 0xD */ \
|
||||
EMIT(0xCB) /* retf */ \
|
||||
}
|
||||
|
||||
#define X64_Start() X64_Start_with_CS(0x33)
|
||||
#define X64_End() X64_End_with_CS(0x23)
|
||||
|
||||
#define _RAX 0
|
||||
#define _RCX 1
|
||||
#define _RDX 2
|
||||
#define _RBX 3
|
||||
#define _RSP 4
|
||||
#define _RBP 5
|
||||
#define _RSI 6
|
||||
#define _RDI 7
|
||||
#define _R8 8
|
||||
#define _R9 9
|
||||
#define _R10 10
|
||||
#define _R11 11
|
||||
#define _R12 12
|
||||
#define _R13 13
|
||||
#define _R14 14
|
||||
#define _R15 15
|
||||
|
||||
#define X64_Push(r) EMIT(0x48 | ((r) >> 3)) EMIT(0x50 | ((r) & 7))
|
||||
#define X64_Pop(r) EMIT(0x48 | ((r) >> 3)) EMIT(0x58 | ((r) & 7))
|
||||
|
||||
#define REX_W EMIT(0x48) __asm
|
||||
|
||||
//to fool M$ inline asm compiler I'm using 2 DWORDs instead of DWORD64
|
||||
//use of DWORD64 will generate wrong 'pop word ptr[]' and it will break stack
|
||||
union reg64
|
||||
{
|
||||
DWORD64 v;
|
||||
DWORD dw[2];
|
||||
};
|
||||
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by wow64ext.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
Vendored
+377
@@ -0,0 +1,377 @@
|
||||
/**
|
||||
*
|
||||
* WOW64Ext Library
|
||||
*
|
||||
* Copyright (c) 2014 ReWolf
|
||||
* http://blog.rewolf.pl/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef STATUS_SUCCESS
|
||||
# define STATUS_SUCCESS 0
|
||||
#endif
|
||||
|
||||
#pragma warning(disable : 4201)
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
template <class T>
|
||||
struct _LIST_ENTRY_T
|
||||
{
|
||||
T Flink;
|
||||
T Blink;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct _UNICODE_STRING_T
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
WORD Length;
|
||||
WORD MaximumLength;
|
||||
};
|
||||
T dummy;
|
||||
};
|
||||
T Buffer;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct _NT_TIB_T
|
||||
{
|
||||
T ExceptionList;
|
||||
T StackBase;
|
||||
T StackLimit;
|
||||
T SubSystemTib;
|
||||
T FiberData;
|
||||
T ArbitraryUserPointer;
|
||||
T Self;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct _CLIENT_ID_T
|
||||
{
|
||||
T UniqueProcess;
|
||||
T UniqueThread;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct _TEB_T_
|
||||
{
|
||||
_NT_TIB_T<T> NtTib;
|
||||
T EnvironmentPointer;
|
||||
_CLIENT_ID_T<T> ClientId;
|
||||
T ActiveRpcHandle;
|
||||
T ThreadLocalStoragePointer;
|
||||
T ProcessEnvironmentBlock;
|
||||
DWORD LastErrorValue;
|
||||
DWORD CountOfOwnedCriticalSections;
|
||||
T CsrClientThread;
|
||||
T Win32ThreadInfo;
|
||||
DWORD User32Reserved[26];
|
||||
//rest of the structure is not defined for now, as it is not needed
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct _LDR_DATA_TABLE_ENTRY_T
|
||||
{
|
||||
_LIST_ENTRY_T<T> InLoadOrderLinks;
|
||||
_LIST_ENTRY_T<T> InMemoryOrderLinks;
|
||||
_LIST_ENTRY_T<T> InInitializationOrderLinks;
|
||||
T DllBase;
|
||||
T EntryPoint;
|
||||
union
|
||||
{
|
||||
DWORD SizeOfImage;
|
||||
T dummy01;
|
||||
};
|
||||
_UNICODE_STRING_T<T> FullDllName;
|
||||
_UNICODE_STRING_T<T> BaseDllName;
|
||||
DWORD Flags;
|
||||
WORD LoadCount;
|
||||
WORD TlsIndex;
|
||||
union
|
||||
{
|
||||
_LIST_ENTRY_T<T> HashLinks;
|
||||
struct
|
||||
{
|
||||
T SectionPointer;
|
||||
T CheckSum;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
T LoadedImports;
|
||||
DWORD TimeDateStamp;
|
||||
};
|
||||
T EntryPointActivationContext;
|
||||
T PatchInformation;
|
||||
_LIST_ENTRY_T<T> ForwarderLinks;
|
||||
_LIST_ENTRY_T<T> ServiceTagLinks;
|
||||
_LIST_ENTRY_T<T> StaticLinks;
|
||||
T ContextInformation;
|
||||
T OriginalBase;
|
||||
_LARGE_INTEGER LoadTime;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct _PEB_LDR_DATA_T
|
||||
{
|
||||
DWORD Length;
|
||||
DWORD Initialized;
|
||||
T SsHandle;
|
||||
_LIST_ENTRY_T<T> InLoadOrderModuleList;
|
||||
_LIST_ENTRY_T<T> InMemoryOrderModuleList;
|
||||
_LIST_ENTRY_T<T> InInitializationOrderModuleList;
|
||||
T EntryInProgress;
|
||||
DWORD ShutdownInProgress;
|
||||
T ShutdownThreadId;
|
||||
|
||||
};
|
||||
|
||||
template <class T, class NGF, int A>
|
||||
struct _PEB_T
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE InheritedAddressSpace;
|
||||
BYTE ReadImageFileExecOptions;
|
||||
BYTE BeingDebugged;
|
||||
BYTE BitField;
|
||||
};
|
||||
T dummy01;
|
||||
};
|
||||
T Mutant;
|
||||
T ImageBaseAddress;
|
||||
T Ldr;
|
||||
T ProcessParameters;
|
||||
T SubSystemData;
|
||||
T ProcessHeap;
|
||||
T FastPebLock;
|
||||
T AtlThunkSListPtr;
|
||||
T IFEOKey;
|
||||
T CrossProcessFlags;
|
||||
T UserSharedInfoPtr;
|
||||
DWORD SystemReserved;
|
||||
DWORD AtlThunkSListPtr32;
|
||||
T ApiSetMap;
|
||||
T TlsExpansionCounter;
|
||||
T TlsBitmap;
|
||||
DWORD TlsBitmapBits[2];
|
||||
T ReadOnlySharedMemoryBase;
|
||||
T HotpatchInformation;
|
||||
T ReadOnlyStaticServerData;
|
||||
T AnsiCodePageData;
|
||||
T OemCodePageData;
|
||||
T UnicodeCaseTableData;
|
||||
DWORD NumberOfProcessors;
|
||||
union
|
||||
{
|
||||
DWORD NtGlobalFlag;
|
||||
NGF dummy02;
|
||||
};
|
||||
LARGE_INTEGER CriticalSectionTimeout;
|
||||
T HeapSegmentReserve;
|
||||
T HeapSegmentCommit;
|
||||
T HeapDeCommitTotalFreeThreshold;
|
||||
T HeapDeCommitFreeBlockThreshold;
|
||||
DWORD NumberOfHeaps;
|
||||
DWORD MaximumNumberOfHeaps;
|
||||
T ProcessHeaps;
|
||||
T GdiSharedHandleTable;
|
||||
T ProcessStarterHelper;
|
||||
T GdiDCAttributeList;
|
||||
T LoaderLock;
|
||||
DWORD OSMajorVersion;
|
||||
DWORD OSMinorVersion;
|
||||
WORD OSBuildNumber;
|
||||
WORD OSCSDVersion;
|
||||
DWORD OSPlatformId;
|
||||
DWORD ImageSubsystem;
|
||||
DWORD ImageSubsystemMajorVersion;
|
||||
T ImageSubsystemMinorVersion;
|
||||
T ActiveProcessAffinityMask;
|
||||
T GdiHandleBuffer[A];
|
||||
T PostProcessInitRoutine;
|
||||
T TlsExpansionBitmap;
|
||||
DWORD TlsExpansionBitmapBits[32];
|
||||
T SessionId;
|
||||
ULARGE_INTEGER AppCompatFlags;
|
||||
ULARGE_INTEGER AppCompatFlagsUser;
|
||||
T pShimData;
|
||||
T AppCompatInfo;
|
||||
_UNICODE_STRING_T<T> CSDVersion;
|
||||
T ActivationContextData;
|
||||
T ProcessAssemblyStorageMap;
|
||||
T SystemDefaultActivationContextData;
|
||||
T SystemAssemblyStorageMap;
|
||||
T MinimumStackCommit;
|
||||
T FlsCallback;
|
||||
_LIST_ENTRY_T<T> FlsListHead;
|
||||
T FlsBitmap;
|
||||
DWORD FlsBitmapBits[4];
|
||||
T FlsHighIndex;
|
||||
T WerRegistrationData;
|
||||
T WerShipAssertPtr;
|
||||
T pContextData;
|
||||
T pImageHeaderHash;
|
||||
T TracingFlags;
|
||||
};
|
||||
|
||||
typedef _LDR_DATA_TABLE_ENTRY_T<DWORD> LDR_DATA_TABLE_ENTRY32;
|
||||
typedef _LDR_DATA_TABLE_ENTRY_T<DWORD64> LDR_DATA_TABLE_ENTRY64;
|
||||
|
||||
typedef _TEB_T_<DWORD> TEB32;
|
||||
typedef _TEB_T_<DWORD64> TEB64;
|
||||
|
||||
typedef _PEB_LDR_DATA_T<DWORD> PEB_LDR_DATA32;
|
||||
typedef _PEB_LDR_DATA_T<DWORD64> PEB_LDR_DATA64;
|
||||
|
||||
typedef _PEB_T<DWORD, DWORD64, 34> PEB32;
|
||||
typedef _PEB_T<DWORD64, DWORD, 30> PEB64;
|
||||
|
||||
struct _XSAVE_FORMAT64
|
||||
{
|
||||
WORD ControlWord;
|
||||
WORD StatusWord;
|
||||
BYTE TagWord;
|
||||
BYTE Reserved1;
|
||||
WORD ErrorOpcode;
|
||||
DWORD ErrorOffset;
|
||||
WORD ErrorSelector;
|
||||
WORD Reserved2;
|
||||
DWORD DataOffset;
|
||||
WORD DataSelector;
|
||||
WORD Reserved3;
|
||||
DWORD MxCsr;
|
||||
DWORD MxCsr_Mask;
|
||||
_M128A FloatRegisters[8];
|
||||
_M128A XmmRegisters[16];
|
||||
BYTE Reserved4[96];
|
||||
};
|
||||
|
||||
struct _CONTEXT64_2
|
||||
{
|
||||
DWORD64 P1Home;
|
||||
DWORD64 P2Home;
|
||||
DWORD64 P3Home;
|
||||
DWORD64 P4Home;
|
||||
DWORD64 P5Home;
|
||||
DWORD64 P6Home;
|
||||
DWORD ContextFlags;
|
||||
DWORD MxCsr;
|
||||
WORD SegCs;
|
||||
WORD SegDs;
|
||||
WORD SegEs;
|
||||
WORD SegFs;
|
||||
WORD SegGs;
|
||||
WORD SegSs;
|
||||
DWORD EFlags;
|
||||
DWORD64 Dr0;
|
||||
DWORD64 Dr1;
|
||||
DWORD64 Dr2;
|
||||
DWORD64 Dr3;
|
||||
DWORD64 Dr6;
|
||||
DWORD64 Dr7;
|
||||
DWORD64 Rax;
|
||||
DWORD64 Rcx;
|
||||
DWORD64 Rdx;
|
||||
DWORD64 Rbx;
|
||||
DWORD64 Rsp;
|
||||
DWORD64 Rbp;
|
||||
DWORD64 Rsi;
|
||||
DWORD64 Rdi;
|
||||
DWORD64 R8;
|
||||
DWORD64 R9;
|
||||
DWORD64 R10;
|
||||
DWORD64 R11;
|
||||
DWORD64 R12;
|
||||
DWORD64 R13;
|
||||
DWORD64 R14;
|
||||
DWORD64 R15;
|
||||
DWORD64 Rip;
|
||||
_XSAVE_FORMAT64 FltSave;
|
||||
_M128A Header[2];
|
||||
_M128A Legacy[8];
|
||||
_M128A Xmm0;
|
||||
_M128A Xmm1;
|
||||
_M128A Xmm2;
|
||||
_M128A Xmm3;
|
||||
_M128A Xmm4;
|
||||
_M128A Xmm5;
|
||||
_M128A Xmm6;
|
||||
_M128A Xmm7;
|
||||
_M128A Xmm8;
|
||||
_M128A Xmm9;
|
||||
_M128A Xmm10;
|
||||
_M128A Xmm11;
|
||||
_M128A Xmm12;
|
||||
_M128A Xmm13;
|
||||
_M128A Xmm14;
|
||||
_M128A Xmm15;
|
||||
_M128A VectorRegister[26];
|
||||
DWORD64 VectorControl;
|
||||
DWORD64 DebugControl;
|
||||
DWORD64 LastBranchToRip;
|
||||
DWORD64 LastBranchFromRip;
|
||||
DWORD64 LastExceptionToRip;
|
||||
DWORD64 LastExceptionFromRip;
|
||||
};
|
||||
#pragma warning(default : 4201)
|
||||
|
||||
// Below defines for .ContextFlags field are taken from WinNT.h
|
||||
#ifndef CONTEXT_AMD64
|
||||
#define CONTEXT_AMD64 0x100000
|
||||
#endif
|
||||
|
||||
#define CONTEXT64_CONTROL (CONTEXT_AMD64 | 0x1L)
|
||||
#define CONTEXT64_INTEGER (CONTEXT_AMD64 | 0x2L)
|
||||
#define CONTEXT64_SEGMENTS (CONTEXT_AMD64 | 0x4L)
|
||||
#define CONTEXT64_FLOATING_POINT (CONTEXT_AMD64 | 0x8L)
|
||||
#define CONTEXT64_DEBUG_REGISTERS (CONTEXT_AMD64 | 0x10L)
|
||||
#define CONTEXT64_FULL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_FLOATING_POINT)
|
||||
#define CONTEXT64_ALL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_SEGMENTS | CONTEXT64_FLOATING_POINT | CONTEXT64_DEBUG_REGISTERS)
|
||||
#define CONTEXT64_XSTATE (CONTEXT_AMD64 | 0x20L)
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef WOW64EXT_EXPORTS
|
||||
# define SPEC dllexport
|
||||
#else
|
||||
# define SPEC dllimport
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...);
|
||||
DWORD64 __cdecl GetModuleHandle64(const wchar_t* lpModuleName);
|
||||
DWORD64 __cdecl getNTDLL64();
|
||||
DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, const char* funcName);
|
||||
SIZE_T __cdecl VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength);
|
||||
DWORD64 __cdecl VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
|
||||
BOOL __cdecl VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType);
|
||||
BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect);
|
||||
BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
|
||||
BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
|
||||
BOOL __cdecl GetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext);
|
||||
BOOL __cdecl SetThreadContext64(HANDLE hThread, _CONTEXT64_2* lpContext);
|
||||
VOID __cdecl SetLastErrorFromX64Call(DWORD64 status);
|
||||
}
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
winapifamily.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Master include file for API family partitioning.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_WINAPIFAMILY
|
||||
#define _INC_WINAPIFAMILY
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4001) /* nonstandard extension 'single line comment' was used */
|
||||
#endif
|
||||
#pragma once
|
||||
#endif // defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
|
||||
#include <winpackagefamily.h>
|
||||
|
||||
/*
|
||||
* When compiling C and C++ code using SDK header files, the development
|
||||
* environment can specify a target platform by #define-ing the
|
||||
* pre-processor symbol WINAPI_FAMILY to one of the following values.
|
||||
* Each FAMILY value denotes an application family for which a different
|
||||
* subset of the total set of header-file-defined APIs are available.
|
||||
* Setting the WINAPI_FAMILY value will effectively hide from the
|
||||
* editing and compilation environments the existence of APIs that
|
||||
* are not applicable to the family of applications targeting a
|
||||
* specific platform.
|
||||
*/
|
||||
|
||||
/* In Windows 10, WINAPI_PARTITIONs will be used to add additional
|
||||
* device specific APIs to a particular WINAPI_FAMILY.
|
||||
* For example, when writing Windows Universal apps, specifying
|
||||
* WINAPI_FAMILY_APP will hide phone APIs from compilation.
|
||||
* However, specifying WINAPI_PARTITION_PHONE_APP=1 additionally, will
|
||||
* unhide any API hidden behind the partition, to the compiler.
|
||||
|
||||
* The following partitions are currently defined:
|
||||
* WINAPI_PARTITION_DESKTOP // usable for Desktop Win32 apps (but not store apps)
|
||||
* WINAPI_PARTITION_APP // usable for Windows Universal store apps
|
||||
* WINAPI_PARTITION_PC_APP // specific to Desktop-only store apps
|
||||
* WINAPI_PARTITION_PHONE_APP // specific to Phone-only store apps
|
||||
* WINAPI_PARTITION_SYSTEM // specific to System applications
|
||||
|
||||
* The following partitions are indirect partitions and defined in
|
||||
* winpackagefamily.h. These partitions are related to package based
|
||||
* partitions. For example, specifying WINAPI_PARTITION_SERVER=1 will light up
|
||||
* any API hidden behind the package based partitions that are bound to
|
||||
* WINAPI_PARTITION_SERVER, to the compiler.
|
||||
* WINAPI_PARTITION_SERVER // specific to Server applications
|
||||
*/
|
||||
|
||||
/*
|
||||
* The WINAPI_FAMILY values of 0 and 1 are reserved to ensure that
|
||||
* an error will occur if WINAPI_FAMILY is set to any
|
||||
* WINAPI_PARTITION value (which must be 0 or 1, see below).
|
||||
*/
|
||||
#define WINAPI_FAMILY_PC_APP 2 /* Windows Store Applications */
|
||||
#define WINAPI_FAMILY_PHONE_APP 3 /* Windows Phone Applications */
|
||||
#define WINAPI_FAMILY_SYSTEM 4 /* Windows Drivers and Tools */
|
||||
#define WINAPI_FAMILY_SERVER 5 /* Windows Server Applications */
|
||||
#define WINAPI_FAMILY_DESKTOP_APP 100 /* Windows Desktop Applications */
|
||||
/* The value of WINAPI_FAMILY_DESKTOP_APP may change in future SDKs. */
|
||||
/* Additional WINAPI_FAMILY values may be defined in future SDKs. */
|
||||
|
||||
/*
|
||||
* For compatibility with Windows 8 header files, the following
|
||||
* synonym for WINAPI_FAMILY_PC_APP is temporarily #define'd.
|
||||
* Use of this symbol should be considered deprecated.
|
||||
*/
|
||||
#define WINAPI_FAMILY_APP WINAPI_FAMILY_PC_APP
|
||||
|
||||
/*
|
||||
* If no WINAPI_FAMILY value is specified, then all APIs available to
|
||||
* Windows desktop applications are exposed.
|
||||
*/
|
||||
#ifndef WINAPI_FAMILY
|
||||
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
|
||||
#endif
|
||||
|
||||
/*
|
||||
* API PARTITONs are part of an indirection mechanism for mapping between
|
||||
* individual APIs and the FAMILYs to which they apply.
|
||||
* Each PARTITION is a category or subset of named APIs. PARTITIONs
|
||||
* are permitted to have overlapping membership -- some single API
|
||||
* might be part of more than one PARTITION. PARTITIONS are each #define-ed
|
||||
* to be either 1 or 0 or depending on the platform at which the app is targeted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The mapping between families and partitions is summarized here.
|
||||
* An X indicates that the given partition is active for the given
|
||||
* platform/family.
|
||||
*
|
||||
* +-------------------+---+
|
||||
* | *Partition* | |
|
||||
* +---+---+---+---+---+---+
|
||||
* | | | | | | |
|
||||
* | | | | | | |
|
||||
* | | | | P | | |
|
||||
* | | | | H | | |
|
||||
* | D | | | O | | |
|
||||
* | E | | P | N | S | S |
|
||||
* | S | | C | E | Y | E |
|
||||
* | K | | _ | _ | S | R |
|
||||
* | T | A | A | A | T | V |
|
||||
* +-------------------------+----+ O | P | P | P | E | E |
|
||||
* | *Platform/Family* \| P | P | P | P | M | R |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_DESKTOP_APP | X | X | X | | | |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_PC_APP | | X | X | | | |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_PHONE_APP | | X | | X | | |
|
||||
* +----------------------------- +---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_SYSTEM | | | | | X | |
|
||||
* +----------------------------- +---+---+---+---+---+---+
|
||||
* | WINAPI_FAMILY_SERVER | | | | | X | X |
|
||||
* +------------------------------+---+---+---+---+---+---+
|
||||
*
|
||||
* The table above is encoded in the following expressions,
|
||||
* each of which evaluates to 1 or 0.
|
||||
*
|
||||
* Whenever a new family is added, all of these expressions
|
||||
* need to be reconsidered.
|
||||
*/
|
||||
#if WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_PC_APP && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_SYSTEM && \
|
||||
WINAPI_FAMILY != WINAPI_FAMILY_SERVER
|
||||
#error Unknown WINAPI_FAMILY value. Was it defined in terms of a WINAPI_PARTITION_* value?
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_DESKTOP
|
||||
#define WINAPI_PARTITION_DESKTOP (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_APP
|
||||
#define WINAPI_PARTITION_APP \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_PC_APP
|
||||
#define WINAPI_PARTITION_PC_APP \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_PC_APP)
|
||||
#endif
|
||||
|
||||
#ifndef WINAPI_PARTITION_PHONE_APP
|
||||
#define WINAPI_PARTITION_PHONE_APP (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SYSTEM is the only partition defined here.
|
||||
* All other System based editions are defined as packages
|
||||
* on top of the System partition.
|
||||
* See winpackagefamily.h for packages level partitions
|
||||
*/
|
||||
#ifndef WINAPI_PARTITION_SYSTEM
|
||||
#define WINAPI_PARTITION_SYSTEM \
|
||||
(WINAPI_FAMILY == WINAPI_FAMILY_SYSTEM || \
|
||||
WINAPI_FAMILY == WINAPI_FAMILY_SERVER)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For compatibility with Windows Phone 8 header files, the following
|
||||
* synonym for WINAPI_PARTITION_PHONE_APP is temporarily #define'd.
|
||||
* Use of this symbol should be regarded as deprecated.
|
||||
*/
|
||||
#define WINAPI_PARTITION_PHONE WINAPI_PARTITION_PHONE_APP
|
||||
|
||||
/*
|
||||
* Header files use the WINAPI_FAMILY_PARTITION macro to assign one or
|
||||
* more declarations to some group of partitions. The macro chooses
|
||||
* whether the preprocessor will emit or omit a sequence of declarations
|
||||
* bracketed by an #if/#endif pair. All header file references to the
|
||||
* WINAPI_PARTITION_* values should be in the form of occurrences of
|
||||
* WINAPI_FAMILY_PARTITION(...).
|
||||
*
|
||||
* For example, the following usage of WINAPI_FAMILY_PARTITION identifies
|
||||
* a sequence of declarations that are part of both the Windows Desktop
|
||||
* Partition and the Windows-Phone-Specific Store Partition:
|
||||
*
|
||||
* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
|
||||
* ...
|
||||
* #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
|
||||
*
|
||||
* The comment on the closing #endif allow tools as well as people to find the
|
||||
* matching #ifdef properly.
|
||||
*
|
||||
* Usages of WINAPI_FAMILY_PARTITION may be combined, when the partitition definitions are
|
||||
* related. In particular one might use declarations like
|
||||
*
|
||||
* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
*
|
||||
* or
|
||||
*
|
||||
* #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
|
||||
*
|
||||
* Direct references to WINAPI_PARTITION_ values (eg #if !WINAPI_FAMILY_PARTITION_...)
|
||||
* should not be used.
|
||||
*/
|
||||
#define WINAPI_FAMILY_PARTITION(Partitions) (Partitions)
|
||||
|
||||
/*
|
||||
* Macro used to #define or typedef a symbol used for selective deprecation
|
||||
* of individual methods of a COM interfaces that are otherwise available
|
||||
* for a given set of partitions.
|
||||
*/
|
||||
#define _WINAPI_DEPRECATED_DECLARATION __declspec(deprecated("This API cannot be used in the context of the caller's application type."))
|
||||
|
||||
/*
|
||||
* For compatibility with Windows 8 header files, the following
|
||||
* symbol is temporarily conditionally #define'd. Additional symbols
|
||||
* like this should be not defined in winapifamily.h, but rather should be
|
||||
* introduced locally to the header files of the component that needs them.
|
||||
*/
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
# define APP_DEPRECATED_HRESULT HRESULT _WINAPI_DEPRECATED_DECLARATION
|
||||
#endif // WINAPIFAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !_INC_WINAPIFAMILY */
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
winpackagefamily.h
|
||||
|
||||
Abstract:
|
||||
|
||||
API family partitioning based on packages.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _INC_WINPACKAGEFAMILY
|
||||
#define _INC_WINPACKAGEFAMILY
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4001) /* nonstandard extension 'single line comment' was used */
|
||||
#endif
|
||||
#pragma once
|
||||
#endif // defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
|
||||
#ifndef WINAPI_PARTITION_SERVER
|
||||
#define WINAPI_PARTITION_SERVER (WINAPI_FAMILY == WINAPI_FAMILY_SERVER)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PARTITIONS based on packages are each #undef'ed below, and then will be #define-ed
|
||||
* to be either 1 or 0 or depending on the active WINAPI_FAMILY.
|
||||
*/
|
||||
#undef WINAPI_PARTITION_PKG_WINTRUST
|
||||
#undef WINAPI_PARTITION_PKG_WEBSERVICES
|
||||
#undef WINAPI_PARTITION_PKG_EVENTLOGSERVICE
|
||||
#undef WINAPI_PARTITION_PKG_VHD
|
||||
#undef WINAPI_PARTITION_PKG_PERFCOUNTER
|
||||
#undef WINAPI_PARTITION_PKG_SECURESTARTUP
|
||||
#undef WINAPI_PARTITION_PKG_REMOTEFS
|
||||
#undef WINAPI_PARTITION_PKG_BOOTABLESKU
|
||||
#undef WINAPI_PARTITION_PKG_CMDTOOLS
|
||||
#undef WINAPI_PARTITION_PKG_DISM
|
||||
#undef WINAPI_PARTITION_PKG_CORESETUP
|
||||
#undef WINAPI_PARTITION_PKG_APPRUNTIME
|
||||
#undef WINAPI_PARTITION_PKG_ESENT
|
||||
#undef WINAPI_PARTITION_PKG_WINMGMT
|
||||
#undef WINAPI_PARTITION_PKG_WNV
|
||||
#undef WINAPI_PARTITION_PKG_CLUSTER
|
||||
#undef WINAPI_PARTITION_PKG_VSS
|
||||
#undef WINAPI_PARTITION_PKG_TRAFFIC
|
||||
#undef WINAPI_PARTITION_PKG_ISCSI
|
||||
#undef WINAPI_PARTITION_PKG_STORAGE
|
||||
#undef WINAPI_PARTITION_PKG_MPSSVC
|
||||
#undef WINAPI_PARTITION_PKG_APPXDEPLOYMENT
|
||||
#undef WINAPI_PARTITION_PKG_WER
|
||||
|
||||
/*
|
||||
* PARTITIONS for feature packages. Each package might be active for one or more editions
|
||||
*/
|
||||
#define WINAPI_PARTITION_PKG_WINTRUST (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WEBSERVICES (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_EVENTLOGSERVICE (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_VHD (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_PERFCOUNTER (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_SECURESTARTUP (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_REMOTEFS (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_BOOTABLESKU (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_CMDTOOLS (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_DISM (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_CORESETUP (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_APPRUNTIME (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_ESENT (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WINMGMT (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WNV (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_CLUSTER (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_VSS (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_TRAFFIC (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_ISCSI (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_STORAGE (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_MPSSVC (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_APPXDEPLOYMENT (WINAPI_PARTITION_SERVER == 1)
|
||||
#define WINAPI_PARTITION_PKG_WER (WINAPI_PARTITION_SERVER == 1)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(MOFCOMP_PASS)
|
||||
#if _MSC_VER >= 1200
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* !_INC_WINPACKAGEFAMILY */
|
||||
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
#include "../Config.h"
|
||||
#include "../Include/Types.h"
|
||||
|
||||
#include "AsmHelper64.h"
|
||||
#include "AsmHelper32.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
using AsmHelperPtr = std::unique_ptr<IAsmHelper>;
|
||||
|
||||
/// <summary>
|
||||
/// Get suitable asm generator
|
||||
/// </summary>
|
||||
class AsmFactory
|
||||
{
|
||||
public:
|
||||
enum eAsmArch
|
||||
{
|
||||
asm32, // x86
|
||||
asm64 // x86_64
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Get suitable asm generator
|
||||
/// </summary>
|
||||
/// <param name="arch">Desired CPU architecture</param>
|
||||
/// <returns>AsmHelperBase interface</returns>
|
||||
static AsmHelperPtr GetAssembler( eAsmArch arch )
|
||||
{
|
||||
switch (arch)
|
||||
{
|
||||
case asm32:
|
||||
return std::make_unique<AsmHelper32>();
|
||||
case asm64:
|
||||
return std::make_unique<AsmHelper64>();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get suitable asm generator
|
||||
/// </summary>
|
||||
/// <param name="mt">Desired PE module architecture</param>
|
||||
/// <returns>AsmHelperBase interface</returns>
|
||||
static AsmHelperPtr GetAssembler( eModType mt )
|
||||
{
|
||||
if (mt == mt_default)
|
||||
mt = sizeof( intptr_t ) > sizeof( int32_t ) ? mt_mod64 : mt_mod32;
|
||||
|
||||
switch (mt)
|
||||
{
|
||||
case mt_mod32:
|
||||
return GetAssembler( asm32 );
|
||||
case mt_mod64:
|
||||
return GetAssembler( asm64 );
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get suitable asm generator
|
||||
/// </summary>
|
||||
/// <param name="wow64process">Target process CPU architecture</param>
|
||||
/// <returns>AsmHelperBase interface</returns>
|
||||
static AsmHelperPtr GetAssembler( bool wow64process )
|
||||
{
|
||||
return GetAssembler( wow64process ? asm32 : asm64 );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get default asm generator
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
static AsmHelperPtr GetAssembler()
|
||||
{
|
||||
#ifdef USE64
|
||||
return std::make_unique<AsmHelper64>();
|
||||
#else
|
||||
return std::make_unique<AsmHelper32>();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "IAsmHelper.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 32 bit assembler helper
|
||||
/// </summary>
|
||||
class AsmHelper32 : public IAsmHelper
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API AsmHelper32( );
|
||||
BLACKBONE_API ~AsmHelper32( void );
|
||||
|
||||
/// <summary>
|
||||
/// Generate function prologue code
|
||||
/// </summary>
|
||||
/// <param name="switchMode">Unused</param>
|
||||
virtual void GenPrologue( bool switchMode = false );
|
||||
|
||||
/// <summary>
|
||||
/// Generate function epilogue code
|
||||
/// </summary>
|
||||
/// <param name="switchMode">Unused</param>
|
||||
/// <param name="retSize">Stack change value</param>
|
||||
virtual void GenEpilogue( bool switchMode = false, int retSize = -1 );
|
||||
|
||||
/// <summary>
|
||||
/// Generate function call
|
||||
/// </summary>
|
||||
/// <param name="pFN">Function pointer</param>
|
||||
/// <param name="args">Function arguments</param>
|
||||
/// <param name="cc">Calling convention</param>
|
||||
virtual void GenCall( const AsmFunctionPtr& pFN, const std::vector<AsmVariant>& args, eCalligConvention cc = cc_stdcall );
|
||||
|
||||
/// <summary>
|
||||
/// Save eax value and terminate current thread
|
||||
/// </summary>
|
||||
/// <param name="pExitThread">NtTerminateThread address</param>
|
||||
/// <param name="resultPtr">Memory where eax value will be saved</param>
|
||||
virtual void ExitThreadWithStatus( uint64_t pExitThread, uint64_t resultPtr );
|
||||
|
||||
/// <summary>
|
||||
/// Save return value and signal thread return event
|
||||
/// </summary>
|
||||
/// <param name="pSetEvent">NtSetEvent address</param>
|
||||
/// <param name="ResultPtr">Result value memory location</param>
|
||||
/// <param name="EventPtr">Event memory location</param>
|
||||
/// <param name="errPtr">Error code memory location</param>
|
||||
/// <param name="rtype">Return type</param>
|
||||
virtual void SaveRetValAndSignalEvent(
|
||||
uint64_t pSetEvent,
|
||||
uint64_t ResultPtr,
|
||||
uint64_t EventPtr,
|
||||
uint64_t errPtr,
|
||||
eReturnType rtype = rt_int32
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Does nothing under x86
|
||||
/// </summary>
|
||||
/// <param name="">Unused</param>
|
||||
virtual void EnableX64CallStack( bool ) { }
|
||||
|
||||
private:
|
||||
AsmHelper32( const AsmHelper32& ) = delete;
|
||||
AsmHelper32& operator = (const AsmHelper32&) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Push function argument
|
||||
/// </summary>
|
||||
/// <param name="arg">Argument.</param>
|
||||
/// <param name="regidx">Push type(register or stack)</param>
|
||||
void PushArg( const AsmVariant& arg, eArgType regidx = at_stack );
|
||||
|
||||
/// <summary>
|
||||
/// Push argument into function
|
||||
/// </summary>
|
||||
/// <param name="arg">Argument</param>
|
||||
/// <param name="index">Argument location</param>
|
||||
template<typename _Type>
|
||||
void PushArgp( _Type arg, eArgType index );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include "IAsmHelper.h"
|
||||
#include "../Include/Macro.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
class AsmHelper64 : public IAsmHelper
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API AsmHelper64();
|
||||
BLACKBONE_API ~AsmHelper64( void );
|
||||
|
||||
/// <summary>
|
||||
/// Generate function prologue code
|
||||
/// </summary>
|
||||
/// <param name="switchMode">true if execution must be swithed to x64 mode</param>
|
||||
virtual void GenPrologue( bool switchMode = false );
|
||||
|
||||
/// <summary>
|
||||
/// Generate function epilogue code
|
||||
/// </summary>
|
||||
/// <param name="switchMode">true if execution must be swithed to x86 mode</param>
|
||||
/// <param name="retSize">Stack change value</param>
|
||||
virtual void GenEpilogue( bool switchMode = false, int retSize = -1 );
|
||||
|
||||
/// <summary>
|
||||
/// Generate function call
|
||||
/// </summary>
|
||||
/// <param name="pFN">Function pointer</param>
|
||||
/// <param name="args">Function arguments</param>
|
||||
/// <param name="cc">Ignored</param>
|
||||
virtual void GenCall( const AsmFunctionPtr& pFN, const std::vector<AsmVariant>& args, eCalligConvention cc = cc_stdcall );
|
||||
|
||||
/// <summary>
|
||||
/// Save rax value and terminate current thread
|
||||
/// </summary>
|
||||
/// <param name="pExitThread">NtTerminateThread address</param>
|
||||
/// <param name="resultPtr">Memory where rax value will be saved</param>
|
||||
virtual void ExitThreadWithStatus( uint64_t pExitThread, uint64_t resultPtr );
|
||||
|
||||
/// <summary>
|
||||
/// Save return value and signal thread return event
|
||||
/// </summary>
|
||||
/// <param name="pSetEvent">NtSetEvent address</param>
|
||||
/// <param name="ResultPtr">Result value memory location</param>
|
||||
/// <param name="EventPtr">Event memory location</param>
|
||||
/// <param name="errPtr">Error code memory location</param>
|
||||
/// <param name="rtype">Return type</param>
|
||||
virtual void SaveRetValAndSignalEvent(
|
||||
uint64_t pSetEvent,
|
||||
uint64_t ResultPtr,
|
||||
uint64_t EventPtr,
|
||||
uint64_t lastStatusPtr,
|
||||
eReturnType rtype = rt_int32
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Set stack reservation policy on call generation
|
||||
/// </summary>
|
||||
/// <param name="state">
|
||||
/// If true - stack space will be reserved during each call generation
|
||||
/// If false - no automatic stack reservation, user must allocate stack by hand
|
||||
/// </param>
|
||||
virtual void EnableX64CallStack( bool state );
|
||||
|
||||
private:
|
||||
AsmHelper64( const AsmHelper64& ) = delete;
|
||||
AsmHelper64& operator = (const AsmHelper64&) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Push function argument
|
||||
/// </summary>
|
||||
/// <param name="arg">Argument.</param>
|
||||
/// <param name="regidx">Push type(register or stack)</param>
|
||||
void PushArg( const AsmVariant& arg, int32_t index );
|
||||
|
||||
/// <summary>
|
||||
/// Push function argument
|
||||
/// </summary>
|
||||
/// <param name="arg">Argument</param>
|
||||
/// <param name="index">Argument index</param>
|
||||
/// <param name="fpu">true if argument is a floating point value</param>
|
||||
template<typename _Type>
|
||||
void PushArgp( const _Type& arg, int32_t index, bool fpu = false );
|
||||
|
||||
private:
|
||||
bool _stackEnabled; // if true - GenCall will allocate shadow stack space
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4100)
|
||||
#include "../../3rd_party/AsmJit/AsmJit.h"
|
||||
#pragma warning(pop)
|
||||
|
||||
#include "../Include/Macro.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
class AsmStackAllocator
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API AsmStackAllocator( asmjit::X86Assembler* pAsm, int32_t baseval = 0x28 )
|
||||
: _pAsm( pAsm )
|
||||
, disp_ofst( pAsm->getArch() == asmjit::kArch::kArchX64 ? baseval : sizeof( uint64_t ) )
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocate stack variable
|
||||
/// </summary>
|
||||
/// <param name="size">Variable size</param>
|
||||
/// <returns>Variable memory object</returns>
|
||||
BLACKBONE_API asmjit::Mem AllocVar( int32_t size )
|
||||
{
|
||||
bool x64 = _pAsm->getArch() == asmjit::kArch::kArchX64;
|
||||
|
||||
// Align on word length
|
||||
size = static_cast<int32_t>(Align( size, x64 ? sizeof( uint64_t ) : sizeof( uint32_t ) ));
|
||||
|
||||
asmjit::Mem val;
|
||||
if (x64)
|
||||
val = asmjit::Mem( _pAsm->zsp, disp_ofst, size );
|
||||
else
|
||||
val = asmjit::Mem( _pAsm->zbp, -disp_ofst - size, size );
|
||||
|
||||
disp_ofst += size;
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allocate array of stack variables
|
||||
/// </summary>
|
||||
/// <param name="arr">Output array</param>
|
||||
/// <param name="count">Array elements count.</param>
|
||||
/// <param name="size">Element size.</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool AllocArray( asmjit::Mem arr[], int count, int32_t size )
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (_pAsm->getArch() == asmjit::kArch::kArchX64)
|
||||
arr[i] = asmjit::Mem( _pAsm->zsp, disp_ofst, size );
|
||||
else
|
||||
arr[i] = asmjit::Mem( _pAsm->zbp, -disp_ofst - size, size );
|
||||
|
||||
disp_ofst += size;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get total size of all stack variables
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
BLACKBONE_API inline intptr_t getTotalSize() const { return disp_ofst; };
|
||||
|
||||
private:
|
||||
asmjit::X86Assembler* _pAsm; // Underlying assembler
|
||||
int32_t disp_ofst; // Next variable stack offset
|
||||
};
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
#define ALLOC_STACK_VAR(worker, name, type) asmjit::Mem name( worker.AllocVar( sizeof(type) ) );
|
||||
#define ALLOC_STACK_VAR_S(worker, name, size) asmjit::Mem name( worker.AllocVar( size ) );
|
||||
|
||||
#define ALLOC_STACK_ARRAY(worker, name, type, count) \
|
||||
asmjit::Mem name[count]; \
|
||||
worker.AllocArray( name, count, sizeof(type) );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../Config.h"
|
||||
#pragma warning(disable : 4100)
|
||||
#include "../../3rd_party/AsmJit/AsmJit.h"
|
||||
#pragma warning(default : 4100)
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
/// <summary>
|
||||
/// General purpose assembly variable
|
||||
/// </summary>
|
||||
struct AsmVariant
|
||||
{
|
||||
template<typename T>
|
||||
using cleanup_t = std::remove_cv_t<std::remove_pointer_t<T>>;
|
||||
|
||||
template<typename T, typename S>
|
||||
static constexpr bool is_string_ptr = (std::is_pointer_v<T> && std::is_same_v<cleanup_t<T>, S>);
|
||||
|
||||
template<typename T>
|
||||
static constexpr bool is_number = (std::is_integral_v<T> || std::is_enum_v<T>);
|
||||
|
||||
template<typename T>
|
||||
static constexpr bool is_void_ptr = (std::is_pointer_v<T> && std::is_void_v<cleanup_t<T>>);
|
||||
|
||||
enum eType
|
||||
{
|
||||
noarg, // void
|
||||
reg, // register
|
||||
imm, // immediate value (e.g. address)
|
||||
imm_double, // double or long double
|
||||
imm_float, // float
|
||||
dataPtr, // pointer to local data (e.g. string or pointer to structure)
|
||||
dataStruct, // structure passed by value
|
||||
structRet, // pointer to space into which return value is copied (used when returning structures by value)
|
||||
mem, // stack variable
|
||||
mem_ptr // pointer to stack variable
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
AsmVariant( T&& arg )
|
||||
{
|
||||
using RAW_T = std::decay_t<T>;
|
||||
constexpr size_t argSize = sizeof( RAW_T );
|
||||
|
||||
// bool, short, int, unsigned long long, etc.
|
||||
if constexpr (is_number<RAW_T>)
|
||||
{
|
||||
set( imm, argSize, static_cast<uint64_t>(arg) );
|
||||
}
|
||||
// Array of elements
|
||||
else if constexpr(std::is_array_v<std::remove_reference_t<T>>)
|
||||
{
|
||||
set( dataPtr, sizeof( arg ), reinterpret_cast<uint64_t>(arg) );
|
||||
}
|
||||
// char*, const char*, etc.
|
||||
else if constexpr(is_string_ptr<RAW_T, char>)
|
||||
{
|
||||
set( dataPtr, strlen( arg ) + 1, reinterpret_cast<uint64_t>(arg) );
|
||||
}
|
||||
// wchar_t*, const wchar_t*, etc.
|
||||
else if constexpr(is_string_ptr<RAW_T, wchar_t>)
|
||||
{
|
||||
set( dataPtr, (wcslen( arg ) + 1) * sizeof( wchar_t ), reinterpret_cast<uint64_t>(arg) );
|
||||
}
|
||||
// void*, const void*, etc.
|
||||
else if constexpr(is_void_ptr<RAW_T>)
|
||||
{
|
||||
set( imm, argSize, reinterpret_cast<uint64_t>(arg) );
|
||||
}
|
||||
// dirty hack to threat HWND as a simple pointer
|
||||
else if constexpr(std::is_same_v<RAW_T, HWND>)
|
||||
{
|
||||
set( imm, argSize, reinterpret_cast<uint64_t>(arg) );
|
||||
}
|
||||
// Function pointer
|
||||
else if constexpr(std::is_function_v<cleanup_t<RAW_T>>)
|
||||
{
|
||||
set( imm, argSize, reinterpret_cast<uint64_t>(arg) );
|
||||
}
|
||||
// Arbitrary pointer
|
||||
else if constexpr(std::is_pointer_v<RAW_T>)
|
||||
{
|
||||
set( dataPtr, sizeof( cleanup_t<RAW_T> ), reinterpret_cast<uint64_t>(arg) );
|
||||
}
|
||||
// Arbitrary variable passed by value
|
||||
// Can fit into register
|
||||
else if constexpr (argSize <= sizeof( uintptr_t ))
|
||||
{
|
||||
type = imm;
|
||||
size = argSize;
|
||||
memcpy( &imm_val64, &arg, argSize );
|
||||
}
|
||||
else
|
||||
{
|
||||
buf.resize( argSize );
|
||||
set( dataStruct, argSize, reinterpret_cast<uint64_t>(buf.data()) );
|
||||
memcpy( buf.data(), &arg, argSize );
|
||||
}
|
||||
}
|
||||
|
||||
// Custom size pointer
|
||||
template <typename T>
|
||||
explicit AsmVariant( T* ptr, size_t size_ )
|
||||
: type( dataPtr )
|
||||
, size( size_ )
|
||||
, imm_val64( reinterpret_cast<uint64_t>(ptr) ) { }
|
||||
|
||||
BLACKBONE_API AsmVariant( float _imm_fpu )
|
||||
: type( imm_float )
|
||||
, size( sizeof( float ) )
|
||||
, imm_float_val( _imm_fpu ) { }
|
||||
|
||||
BLACKBONE_API AsmVariant( double _imm_fpu )
|
||||
: type( imm_double )
|
||||
, size( sizeof( double ) )
|
||||
, imm_double_val( _imm_fpu ) { }
|
||||
|
||||
BLACKBONE_API AsmVariant( asmjit::GpReg _reg )
|
||||
: type( reg )
|
||||
, size( sizeof( uintptr_t ) )
|
||||
, reg_val( _reg ) { }
|
||||
|
||||
// Stack variable
|
||||
BLACKBONE_API AsmVariant( asmjit::Mem _mem )
|
||||
: type( mem )
|
||||
, size( sizeof( uintptr_t ) )
|
||||
, mem_val( _mem ) { }
|
||||
|
||||
// Pointer to stack address
|
||||
BLACKBONE_API AsmVariant( asmjit::Mem* _mem )
|
||||
: type( mem_ptr )
|
||||
, size( sizeof( uintptr_t ) )
|
||||
, mem_val( *_mem ) { }
|
||||
|
||||
BLACKBONE_API AsmVariant( const asmjit::Mem* _mem )
|
||||
: AsmVariant( const_cast<asmjit::Mem*>(_mem) ) { }
|
||||
|
||||
BLACKBONE_API AsmVariant( const AsmVariant& ) = default;
|
||||
BLACKBONE_API AsmVariant( AsmVariant&& ) = default;
|
||||
BLACKBONE_API AsmVariant& operator =( const AsmVariant& ) = default;
|
||||
|
||||
//
|
||||
// Get floating point value as raw data
|
||||
//
|
||||
BLACKBONE_API inline uint32_t getImm_float() const { return *(reinterpret_cast<const uint32_t*>(&imm_float_val)); }
|
||||
BLACKBONE_API inline uint64_t getImm_double() const { return *(reinterpret_cast<const uint64_t*>(&imm_double_val)); }
|
||||
|
||||
/// <summary>
|
||||
/// Check if argument can be passed in x86 register
|
||||
/// </summary>
|
||||
/// <returns>true if can</returns>
|
||||
BLACKBONE_API inline bool reg86Compatible() const
|
||||
{
|
||||
if (type == dataStruct || type == imm_float || type == imm_double || type == structRet)
|
||||
return false;
|
||||
/*if (type == imm && size > sizeof( uint32_t ))
|
||||
return false;*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void set( eType type_, size_t size_, uint64_t val )
|
||||
{
|
||||
type = type_;
|
||||
size = size_;
|
||||
imm_val64 = val;
|
||||
}
|
||||
|
||||
eType type = noarg; // Variable type
|
||||
size_t size = 0; // Variable size
|
||||
asmjit::GpReg reg_val; // General purpose register
|
||||
asmjit::Mem mem_val; // Memory pointer
|
||||
|
||||
// Immediate values
|
||||
union
|
||||
{
|
||||
uint64_t imm_val64 = 0;
|
||||
uintptr_t imm_val;
|
||||
uint32_t imm_val32;
|
||||
double imm_double_val;
|
||||
float imm_float_val;
|
||||
};
|
||||
|
||||
uint64_t new_imm_val = 0; // Replaced immediate value for dataPtr type
|
||||
std::vector<uint8_t> buf; // Value buffer
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Remote function pointer
|
||||
/// </summary>
|
||||
struct AsmFunctionPtr: public AsmVariant
|
||||
{
|
||||
AsmFunctionPtr( int ptr )
|
||||
: AsmVariant( ptr ) { }
|
||||
|
||||
AsmFunctionPtr( unsigned int ptr )
|
||||
: AsmVariant( ptr ) { }
|
||||
|
||||
AsmFunctionPtr( long ptr )
|
||||
: AsmVariant( ptr ) { }
|
||||
|
||||
AsmFunctionPtr( unsigned long ptr )
|
||||
: AsmVariant( ptr ) { }
|
||||
|
||||
AsmFunctionPtr( long long ptr )
|
||||
: AsmVariant( ptr ) { }
|
||||
|
||||
AsmFunctionPtr( unsigned long long ptr )
|
||||
: AsmVariant( ptr ) { }
|
||||
|
||||
AsmFunctionPtr( void* ptr )
|
||||
: AsmVariant( reinterpret_cast<uintptr_t>(ptr) ) { }
|
||||
|
||||
AsmFunctionPtr( const void* ptr )
|
||||
: AsmVariant( reinterpret_cast<uintptr_t>(ptr) ) { }
|
||||
|
||||
AsmFunctionPtr( asmjit::GpReg reg_ )
|
||||
: AsmVariant( reg_ ) { }
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
#pragma once
|
||||
|
||||
#include "AsmVariant.hpp"
|
||||
#include "AsmStack.hpp"
|
||||
#include "../Include/Macro.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <vector>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
//
|
||||
// Function calling convention
|
||||
//
|
||||
enum eCalligConvention
|
||||
{
|
||||
cc_cdecl, // cdecl
|
||||
cc_stdcall, // stdcall
|
||||
cc_thiscall, // thiscall
|
||||
cc_fastcall // fastcall
|
||||
};
|
||||
|
||||
//
|
||||
// Function return type
|
||||
// Do not change numeric values!
|
||||
//
|
||||
enum eReturnType
|
||||
{
|
||||
rt_int32 = 4, // 32bit value
|
||||
rt_int64 = 8, // 64bit value
|
||||
rt_float = 1, // float value
|
||||
rt_double = 2, // double value
|
||||
rt_struct = 3, // structure returned by value
|
||||
};
|
||||
|
||||
// Argument pass method
|
||||
enum eArgType
|
||||
{
|
||||
at_ecx = 0, // In ecx
|
||||
at_edx = 1, // In edx
|
||||
at_stack = 2, // On stack
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Assembly generation helper
|
||||
/// </summary>
|
||||
class IAsmHelper
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API IAsmHelper( uint32_t arch = asmjit::kArchHost )
|
||||
: _assembler( &_runtime, arch ) { }
|
||||
|
||||
virtual ~IAsmHelper() { }
|
||||
|
||||
virtual void GenPrologue( bool switchMode = false ) = 0;
|
||||
virtual void GenEpilogue( bool switchMode = false, int retSize = -1) = 0;
|
||||
virtual void GenCall( const AsmFunctionPtr&, const std::vector<AsmVariant>& args, eCalligConvention cc = cc_stdcall ) = 0;
|
||||
virtual void ExitThreadWithStatus( uint64_t pExitThread, uint64_t resultPtr ) = 0;
|
||||
virtual void SaveRetValAndSignalEvent( uint64_t pSetEvent, uint64_t ResultPtr, uint64_t EventPtr, uint64_t errPtr, eReturnType rtype = rt_int32 ) = 0;
|
||||
virtual void EnableX64CallStack( bool state ) = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Switch processor into WOW64 emulation mode
|
||||
/// </summary>
|
||||
BLACKBONE_API void SwitchTo86()
|
||||
{
|
||||
asmjit::Label l = _assembler.newLabel();
|
||||
|
||||
_assembler.call( l ); _assembler.bind( l );
|
||||
_assembler.mov( asmjit::host::dword_ptr( asmjit::host::esp, 4 ), 0x23 );
|
||||
_assembler.add( asmjit::host::dword_ptr( asmjit::host::esp ), 0xD );
|
||||
_assembler.db( 0xCB ); // retf
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switch processor into x64 mode (long mode)
|
||||
/// </summary>
|
||||
BLACKBONE_API void SwitchTo64()
|
||||
{
|
||||
asmjit::Label l = _assembler.newLabel();
|
||||
|
||||
_assembler.push( 0x33 );
|
||||
_assembler.call( l ); _assembler.bind( l );
|
||||
//_assembler.add( asmjit::host::dword_ptr( asmjit::host::esp ), 5 );
|
||||
_assembler.dd( '\x83\x04\x24\x05' );
|
||||
_assembler.db( 0xCB ); // retf
|
||||
}
|
||||
|
||||
BLACKBONE_API inline asmjit::X86Assembler* assembler() { return &_assembler; }
|
||||
BLACKBONE_API inline asmjit::X86Assembler* operator ->() { return &_assembler; }
|
||||
|
||||
private:
|
||||
IAsmHelper( const IAsmHelper& ) = delete;
|
||||
IAsmHelper& operator =(const IAsmHelper&) = delete;
|
||||
|
||||
protected:
|
||||
asmjit::JitRuntime _runtime;
|
||||
asmjit::X86Assembler _assembler;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef _LDASM_
|
||||
#define _LDASM_
|
||||
|
||||
#include "../Config.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USE64
|
||||
#define is_x64 1
|
||||
#else
|
||||
#define is_x64 0
|
||||
#endif//USE64
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define F_INVALID 0x01
|
||||
#define F_PREFIX 0x02
|
||||
#define F_REX 0x04
|
||||
#define F_MODRM 0x08
|
||||
#define F_SIB 0x10
|
||||
#define F_DISP 0x20
|
||||
#define F_IMM 0x40
|
||||
#define F_RELATIVE 0x80
|
||||
|
||||
typedef struct _ldasm_data
|
||||
{
|
||||
uint8_t flags;
|
||||
uint8_t rex;
|
||||
uint8_t modrm;
|
||||
uint8_t sib;
|
||||
uint8_t opcd_offset;
|
||||
uint8_t opcd_size;
|
||||
uint8_t disp_offset;
|
||||
uint8_t disp_size;
|
||||
uint8_t imm_offset;
|
||||
uint8_t imm_size;
|
||||
} ldasm_data;
|
||||
|
||||
BLACKBONE_API unsigned int __fastcall ldasm( void *code, ldasm_data *ld, uint32_t is64 );
|
||||
BLACKBONE_API unsigned long __fastcall SizeOfProc( void *Proc );
|
||||
BLACKBONE_API void* __fastcall ResolveJmp( void *Proc );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//_LDASM_
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
// Lib/Dll switch
|
||||
#if !defined(BLACKBONE_EXPORTS) && !defined(BLACKBONE_IMPORTS) && !defined(BLACKBONE_STATIC)
|
||||
#define BLACKBONE_STATIC
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#ifndef COMPILER_MSVC
|
||||
#define COMPILER_MSVC 1
|
||||
#endif
|
||||
|
||||
#if defined(BLACKBONE_IMPORTS)
|
||||
#define BLACKBONE_API __declspec(dllimport)
|
||||
#elif defined(BLACKBONE_EXPORTS)
|
||||
#define BLACKBONE_API __declspec(dllexport)
|
||||
#else
|
||||
#define BLACKBONE_API
|
||||
#endif
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
#define COMPILER_GCC
|
||||
#define BLACKBONE_API
|
||||
#else
|
||||
#error "Unknown or unsupported compiler"
|
||||
#endif
|
||||
|
||||
// No IA64 support
|
||||
#if defined (_M_AMD64) || defined (__x86_64__)
|
||||
#define USE64
|
||||
#elif defined (_M_IX86) || defined (__i386__)
|
||||
#define USE32
|
||||
#else
|
||||
#error "Unknown or unsupported platform"
|
||||
#endif
|
||||
|
||||
|
||||
+322
@@ -0,0 +1,322 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Include/Winheaders.h"
|
||||
#include "../Include/Types.h"
|
||||
#include "../Include/Macro.h"
|
||||
#include "../Include/HandleGuard.h"
|
||||
#include "../../BlackBoneDrv/BlackBoneDef.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
ENUM_OPS( KMmapFlags );
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
// [Original ptr, size] <--> [Mapped ptr]
|
||||
using mapMemoryMap = std::map<std::pair<ptr_t, uint32_t>, ptr_t>;
|
||||
|
||||
struct MapMemoryResult
|
||||
{
|
||||
ptr_t hostSharedPage; // Shared page address in current process
|
||||
ptr_t targetSharedPage; // Shared page address in target process
|
||||
HANDLE targetPipe; // Hook pipe handle in the target process
|
||||
|
||||
mapMemoryMap regions; // Mapped regions info
|
||||
};
|
||||
|
||||
struct MapMemoryRegionResult
|
||||
{
|
||||
ptr_t originalPtr; // Address of region in the target process
|
||||
ptr_t newPtr; // Address of mapped region in the current process
|
||||
ptr_t removedPtr; // Address of region unmapped because of address conflict
|
||||
uint32_t size; // Size of mapped region
|
||||
uint32_t removedSize; // Size of unmapped region
|
||||
};
|
||||
|
||||
|
||||
class DriverControl
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API DriverControl();
|
||||
BLACKBONE_API ~DriverControl();
|
||||
|
||||
BLACKBONE_API static DriverControl& Instance();
|
||||
|
||||
/// <summary>
|
||||
/// Try to load driver if it isn't loaded
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the driver file</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS EnsureLoaded( const std::wstring& path = L"" );
|
||||
|
||||
/// <summary>
|
||||
/// Reload driver
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the driver file</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS Reload( std::wstring path = L"" );
|
||||
|
||||
/// <summary>
|
||||
/// Unload driver
|
||||
/// </summary>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS Unload();
|
||||
|
||||
/// <summary>
|
||||
/// Disable DEP for process
|
||||
/// Has no effect on native x64 processes
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS DisableDEP( DWORD pid );
|
||||
|
||||
/// <summary>
|
||||
/// Change process protection flag
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="protection">Process protection policy</param>
|
||||
/// <param name="dynamicCode">Prohibit dynamic code</param>
|
||||
/// <param name="binarySignature">Prohibit loading non-microsoft dlls</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS ProtectProcess(
|
||||
DWORD pid,
|
||||
PolicyOpt protection,
|
||||
PolicyOpt dynamicCode = Policy_Keep,
|
||||
PolicyOpt binarySignature = Policy_Keep
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Change handle access rights
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID.</param>
|
||||
/// <param name="handle">Handle</param>
|
||||
/// <param name="access">New access</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS PromoteHandle( DWORD pid, HANDLE handle, DWORD access );
|
||||
|
||||
/// <summary>
|
||||
/// Allocate virtual memory
|
||||
/// </summary>
|
||||
/// <param name="pid">Tarhet PID</param>
|
||||
/// <param name="base">Desired base. If 0 address is chosed by the system</param>
|
||||
/// <param name="size">Region size</param>
|
||||
/// <param name="type">Allocation type - MEM_RESERVE/MEM_COMMIT</param>
|
||||
/// <param name="protection">Memory protection</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS AllocateMem( DWORD pid, ptr_t& base, ptr_t& size, DWORD type, DWORD protection, bool physical = false );
|
||||
|
||||
/// <summary>
|
||||
/// Free virtual memory
|
||||
/// </summary>
|
||||
/// <param name="pid">Tarhet PID</param>
|
||||
/// <param name="base">Desired base. If 0 address is chosed by the system</param>
|
||||
/// <param name="size">Region size</param>
|
||||
/// <param name="type">Free type - MEM_RELEASE/MEM_DECOMMIT</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS FreeMem( DWORD pid, ptr_t base, ptr_t size, DWORD type );
|
||||
|
||||
/// <summary>
|
||||
/// Read process memory
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="base">Target base</param>
|
||||
/// <param name="size">Data size</param>
|
||||
/// <param name="buffer">Buffer address</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS ReadMem( DWORD pid, ptr_t base, ptr_t size, PVOID buffer );
|
||||
|
||||
/// <summary>
|
||||
/// Write process memory
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="base">Target base</param>
|
||||
/// <param name="size">Data size</param>
|
||||
/// <param name="buffer">Buffer address</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS WriteMem( DWORD pid, ptr_t base, ptr_t size, PVOID buffer );
|
||||
|
||||
/// <summary>
|
||||
/// Change memory protection
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID.</param>
|
||||
/// <param name="base">Regiod base address</param>
|
||||
/// <param name="size">Region size</param>
|
||||
/// <param name="protection">New protection</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS ProtectMem( DWORD pid, ptr_t base, ptr_t size, DWORD protection );
|
||||
|
||||
/// <summary>
|
||||
/// Maps target process memory into current process
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="pipeName">Pipe name to use for hook data transfer</param>
|
||||
/// <param name="mapSections">The map sections.</param>
|
||||
/// <param name="result">Results</param>
|
||||
/// <returns>Status code </returns>
|
||||
BLACKBONE_API NTSTATUS MapMemory( DWORD pid, const std::wstring& pipeName, bool mapSections, MapMemoryResult& result );
|
||||
|
||||
/// <summary>
|
||||
/// Maps single memory region into current process
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="base">Region base address</param>
|
||||
/// <param name="size">Region size</param>
|
||||
/// <param name="result">Mapped region info</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS MapMemoryRegion( DWORD pid, ptr_t base, uint32_t size, MapMemoryRegionResult& result );
|
||||
|
||||
/// <summary>
|
||||
/// Unmap memory of the target process from current
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS UnmapMemory( DWORD pid );
|
||||
|
||||
/// <summary>
|
||||
/// Unmap single memory region
|
||||
/// If unmapped region size is smaller than the size specified during map, function will return info about
|
||||
/// 2 regions that emerged after unmap
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="base">Region base</param>
|
||||
/// <param name="size">Region size</param>
|
||||
/// <param name="result">Unampped region info</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS UnmapMemoryRegion( DWORD pid, ptr_t base, uint32_t size );
|
||||
|
||||
/// <summary>
|
||||
/// Inject DLL into arbitrary process
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID.</param>
|
||||
/// <param name="path">Full qualified dll path.</param>
|
||||
/// <param name="itype">Injection type</param>
|
||||
/// <param name="initRVA">Init routine RVA</param>
|
||||
/// <param name="initArg">Init routine argument</param>
|
||||
/// <param name="unlink">Unlink module after injection</param>
|
||||
/// <param name="erasePE">Erase PE headers after injection</param>
|
||||
/// <param name="wait">Wait for injection</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS InjectDll(
|
||||
DWORD pid,
|
||||
const std::wstring& path,
|
||||
InjectType itype,
|
||||
uint32_t initRVA = 0,
|
||||
const std::wstring& initArg = L"",
|
||||
bool unlink = false,
|
||||
bool erasePE = false,
|
||||
bool wait = true
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Manually map PE image
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="path">Full qualified image path</param>
|
||||
/// <param name="flags">Mapping flags</param>
|
||||
/// <param name="initRVA">Init routine RVA</param>
|
||||
/// <param name="initArg">Init routine argument</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS MmapDll(
|
||||
DWORD pid,
|
||||
const std::wstring& path,
|
||||
KMmapFlags flags,
|
||||
uint32_t initRVA = 0,
|
||||
const std::wstring& initArg = L""
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Manually map PE image
|
||||
/// </summary>
|
||||
/// <param name="pid">Target PID</param>
|
||||
/// <param name="address">Memory location of the image to map</param>
|
||||
/// <param name="size">Image size</param>
|
||||
/// <param name="asImage">Memory chunk has image layout</param>
|
||||
/// <param name="flags">Mapping flags</param>
|
||||
/// <param name="initRVA">Init routine RVA</param>
|
||||
/// <param name="initArg">Init routine argument</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS MmapDll(
|
||||
DWORD pid,
|
||||
void* address,
|
||||
uint32_t size,
|
||||
bool asImage,
|
||||
KMmapFlags flags,
|
||||
uint32_t initRVA = 0,
|
||||
const std::wstring& initArg = L""
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Manually map another system driver into system space
|
||||
/// </summary>
|
||||
/// <param name="path">Fully quialified path to the drver</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS MMapDriver( const std::wstring& path );
|
||||
|
||||
/// <summary>
|
||||
/// Make VAD region appear as PAGE_NO_ACESS to NtQueryVirtualMemory
|
||||
/// </summary>
|
||||
/// <param name="pid">Target process ID</param>
|
||||
/// <param name="base">Region base</param>
|
||||
/// <param name="size">Region size</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS ConcealVAD( DWORD pid, ptr_t base, uint32_t size );
|
||||
|
||||
/// <summary>
|
||||
/// Unlink process handle table from HandleListHead
|
||||
/// </summary>
|
||||
/// <param name="pid">Target process ID</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS UnlinkHandleTable( DWORD pid );
|
||||
|
||||
/// <summary>
|
||||
/// Enumerate committed, accessible, non-guarded memory regions
|
||||
/// </summary>
|
||||
/// <param name="pid">Target process ID</param>
|
||||
/// <param name="regions">Found regions</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS EnumMemoryRegions( DWORD pid, std::vector<MEMORY_BASIC_INFORMATION64>& regions );
|
||||
|
||||
/// <summary>
|
||||
/// Check if driver is loaded
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
BLACKBONE_API inline bool loaded() const { return _hDriver.valid(); }
|
||||
BLACKBONE_API inline NTSTATUS status() const { return _loadStatus; }
|
||||
|
||||
private:
|
||||
DriverControl( const DriverControl& ) = delete;
|
||||
DriverControl& operator = (const DriverControl&) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Load arbitrary driver
|
||||
/// </summary>
|
||||
/// <param name="svcName">Driver service name</param>
|
||||
/// <param name="path">Driver file path</param>
|
||||
/// <returns>Status</returns>
|
||||
NTSTATUS LoadDriver( const std::wstring& svcName, const std::wstring& path );
|
||||
|
||||
/// <summary>
|
||||
/// Unload arbitrary driver
|
||||
/// </summary>
|
||||
/// <param name="svcName">Driver service name</param>
|
||||
/// <returns>Status</returns>
|
||||
NTSTATUS UnloadDriver( const std::wstring& svcName );
|
||||
|
||||
/// <summary>
|
||||
/// Fill minimum driver registry entry
|
||||
/// </summary>
|
||||
/// <param name="svcName">Driver service name</param>
|
||||
/// <param name="path">Driver path</param>
|
||||
/// <returns>Status code</returns>
|
||||
LSTATUS PrepareDriverRegEntry( const std::wstring& svcName, const std::wstring& path );
|
||||
private:
|
||||
Handle _hDriver;
|
||||
NTSTATUS _loadStatus = STATUS_NOT_FOUND;
|
||||
};
|
||||
|
||||
// Syntax sugar
|
||||
inline DriverControl& Driver() { return DriverControl::Instance(); }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
#pragma once
|
||||
|
||||
#include "Winheaders.h"
|
||||
|
||||
//
|
||||
// Api schema structures
|
||||
//
|
||||
|
||||
//
|
||||
// Win 10
|
||||
//
|
||||
typedef struct _API_SET_VALUE_ENTRY_10
|
||||
{
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG ValueOffset;
|
||||
ULONG ValueLength;
|
||||
} API_SET_VALUE_ENTRY_10, *PAPI_SET_VALUE_ENTRY_10;
|
||||
|
||||
typedef struct _API_SET_VALUE_ARRAY_10
|
||||
{
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG Unk;
|
||||
ULONG NameLength;
|
||||
ULONG DataOffset;
|
||||
ULONG Count;
|
||||
|
||||
inline PAPI_SET_VALUE_ENTRY_10 entry( void* pApiSet, DWORD i )
|
||||
{
|
||||
return (PAPI_SET_VALUE_ENTRY_10)((BYTE*)pApiSet + DataOffset + i * sizeof( API_SET_VALUE_ENTRY_10 ));
|
||||
}
|
||||
} API_SET_VALUE_ARRAY_10, *PAPI_SET_VALUE_ARRAY_10;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ENTRY_10
|
||||
{
|
||||
ULONG Limit;
|
||||
ULONG Size;
|
||||
} API_SET_NAMESPACE_ENTRY_10, *PAPI_SET_NAMESPACE_ENTRY_10;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ARRAY_10
|
||||
{
|
||||
ULONG Version;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
ULONG Count;
|
||||
ULONG Start;
|
||||
ULONG End;
|
||||
ULONG Unk[2];
|
||||
|
||||
inline PAPI_SET_NAMESPACE_ENTRY_10 entry( DWORD i )
|
||||
{
|
||||
return (PAPI_SET_NAMESPACE_ENTRY_10)((BYTE*)this + End + i * sizeof( API_SET_NAMESPACE_ENTRY_10 ));
|
||||
}
|
||||
|
||||
inline PAPI_SET_VALUE_ARRAY_10 valArray( PAPI_SET_NAMESPACE_ENTRY_10 pEntry )
|
||||
{
|
||||
return (PAPI_SET_VALUE_ARRAY_10)((BYTE*)this + Start + sizeof( API_SET_VALUE_ARRAY_10 ) * pEntry->Size);
|
||||
}
|
||||
|
||||
inline ULONG apiName( PAPI_SET_NAMESPACE_ENTRY_10 pEntry, wchar_t* output )
|
||||
{
|
||||
auto pArray = valArray( pEntry );
|
||||
memcpy( output, (char*)this + pArray->NameOffset, pArray->NameLength );
|
||||
return pArray->NameLength;
|
||||
}
|
||||
} API_SET_NAMESPACE_ARRAY_10, *PAPI_SET_NAMESPACE_ARRAY_10;
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Win 8.1
|
||||
//
|
||||
typedef struct _API_SET_VALUE_ENTRY
|
||||
{
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG ValueOffset;
|
||||
ULONG ValueLength;
|
||||
} API_SET_VALUE_ENTRY, *PAPI_SET_VALUE_ENTRY;
|
||||
|
||||
typedef struct _API_SET_VALUE_ARRAY
|
||||
{
|
||||
ULONG Flags;
|
||||
ULONG Count;
|
||||
API_SET_VALUE_ENTRY Array[ANYSIZE_ARRAY];
|
||||
|
||||
inline PAPI_SET_VALUE_ENTRY entry( void* /*pApiSet*/, DWORD i )
|
||||
{
|
||||
return Array + i;
|
||||
}
|
||||
} API_SET_VALUE_ARRAY, *PAPI_SET_VALUE_ARRAY;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ENTRY
|
||||
{
|
||||
ULONG Flags;
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG AliasOffset;
|
||||
ULONG AliasLength;
|
||||
ULONG DataOffset;
|
||||
} API_SET_NAMESPACE_ENTRY, *PAPI_SET_NAMESPACE_ENTRY;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ARRAY
|
||||
{
|
||||
ULONG Version;
|
||||
ULONG Size;
|
||||
ULONG Flags;
|
||||
ULONG Count;
|
||||
API_SET_NAMESPACE_ENTRY Array[ANYSIZE_ARRAY];
|
||||
|
||||
inline PAPI_SET_NAMESPACE_ENTRY entry( DWORD i )
|
||||
{
|
||||
return Array + i;
|
||||
}
|
||||
|
||||
inline PAPI_SET_VALUE_ARRAY valArray( PAPI_SET_NAMESPACE_ENTRY pEntry )
|
||||
{
|
||||
return (PAPI_SET_VALUE_ARRAY)((BYTE*)this + pEntry->DataOffset);
|
||||
}
|
||||
|
||||
inline ULONG apiName( PAPI_SET_NAMESPACE_ENTRY pEntry, wchar_t* output )
|
||||
{
|
||||
memcpy( output, (char*)this + pEntry->NameOffset, pEntry->NameLength );
|
||||
return pEntry->NameLength;
|
||||
}
|
||||
} API_SET_NAMESPACE_ARRAY, *PAPI_SET_NAMESPACE_ARRAY;
|
||||
|
||||
|
||||
//
|
||||
// Win 8 and 7
|
||||
//
|
||||
typedef struct _API_SET_VALUE_ENTRY_V2
|
||||
{
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG ValueOffset;
|
||||
ULONG ValueLength;
|
||||
} API_SET_VALUE_ENTRY_V2, *PAPI_SET_VALUE_ENTRY_V2;
|
||||
|
||||
typedef struct _API_SET_VALUE_ARRAY_V2
|
||||
{
|
||||
ULONG Count;
|
||||
API_SET_VALUE_ENTRY_V2 Array[ANYSIZE_ARRAY];
|
||||
|
||||
inline PAPI_SET_VALUE_ENTRY_V2 entry( void* /*pApiSet*/, DWORD i )
|
||||
{
|
||||
return Array + i;
|
||||
}
|
||||
} API_SET_VALUE_ARRAY_V2, *PAPI_SET_VALUE_ARRAY_V2;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ENTRY_V2
|
||||
{
|
||||
ULONG NameOffset;
|
||||
ULONG NameLength;
|
||||
ULONG DataOffset; // API_SET_VALUE_ARRAY
|
||||
} API_SET_NAMESPACE_ENTRY_V2, *PAPI_SET_NAMESPACE_ENTRY_V2;
|
||||
|
||||
typedef struct _API_SET_NAMESPACE_ARRAY_V2
|
||||
{
|
||||
ULONG Version;
|
||||
ULONG Count;
|
||||
API_SET_NAMESPACE_ENTRY_V2 Array[ANYSIZE_ARRAY];
|
||||
|
||||
inline PAPI_SET_NAMESPACE_ENTRY_V2 entry( DWORD i )
|
||||
{
|
||||
return Array + i;
|
||||
}
|
||||
|
||||
inline PAPI_SET_VALUE_ARRAY_V2 valArray( PAPI_SET_NAMESPACE_ENTRY_V2 pEntry )
|
||||
{
|
||||
return (PAPI_SET_VALUE_ARRAY_V2)((BYTE*)this + pEntry->DataOffset);
|
||||
}
|
||||
|
||||
inline ULONG apiName( PAPI_SET_NAMESPACE_ENTRY_V2 pEntry, wchar_t* output )
|
||||
{
|
||||
memcpy( output, (char*)this + pEntry->NameOffset, pEntry->NameLength );
|
||||
return pEntry->NameLength;
|
||||
}
|
||||
} API_SET_NAMESPACE_ARRAY_V2, *PAPI_SET_NAMESPACE_ARRAY_V2;
|
||||
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
#if _MSC_VER >= 1910
|
||||
|
||||
#include <optional>
|
||||
#include <cassert>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
/// <summary>
|
||||
/// Function result or failure status
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
struct call_result_t
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL; // Execution status
|
||||
std::optional<T> result_data = std::nullopt; // Returned value
|
||||
|
||||
call_result_t() = default;
|
||||
|
||||
call_result_t( T result_, NTSTATUS status_ = STATUS_SUCCESS )
|
||||
: status ( status_ )
|
||||
, result_data ( std::move( result_ ) )
|
||||
{
|
||||
assert( result_data.has_value() );
|
||||
}
|
||||
|
||||
call_result_t( NTSTATUS status_ )
|
||||
: status ( status_ )
|
||||
{
|
||||
assert( status_ != STATUS_SUCCESS );
|
||||
}
|
||||
|
||||
inline bool success() const { return NT_SUCCESS( status ); }
|
||||
inline T& result() { return result_data.value(); }
|
||||
inline const T& result() const { return result_data.value(); }
|
||||
inline T result( const T& def_val ) const { return result_data.value_or( def_val ); }
|
||||
|
||||
inline explicit operator bool() const { return NT_SUCCESS( status ); }
|
||||
inline explicit operator T() const { return result_data.value(); }
|
||||
|
||||
inline T* operator ->() { return &result_data.value(); }
|
||||
inline T& operator *() { return result_data.value(); }
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
/// <summary>
|
||||
/// Function result or failure status
|
||||
/// </summary>
|
||||
template <typename T>
|
||||
struct call_result_t
|
||||
{
|
||||
NTSTATUS status = STATUS_UNSUCCESSFUL; // Execution status
|
||||
std::unique_ptr<T> result_data; // Returned value
|
||||
|
||||
call_result_t() = default;
|
||||
|
||||
call_result_t(T result_, NTSTATUS status_ = STATUS_SUCCESS)
|
||||
: status(status_)
|
||||
, result_data(std::make_unique<T>(std::move(result_)))
|
||||
{
|
||||
assert(result_data.get());
|
||||
}
|
||||
|
||||
call_result_t(NTSTATUS status_)
|
||||
: status(status_)
|
||||
{
|
||||
assert(status_ != STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
inline T* value() {
|
||||
if (!result_data) {
|
||||
throw std::logic_error("bad optional access.");
|
||||
}
|
||||
return result_data.get();
|
||||
}
|
||||
public:
|
||||
|
||||
inline bool success() const { return NT_SUCCESS( status ); }
|
||||
inline T& result() { return *value(); }
|
||||
inline const T& result() const { return *value(); }
|
||||
inline T result(const T& def_val) const { return result_data ? *result_data.get() : def_val; }
|
||||
|
||||
inline explicit operator bool() const { return NT_SUCCESS( status ); }
|
||||
inline explicit operator T() const { return *value(); }
|
||||
|
||||
inline T* operator ->() { return value(); }
|
||||
inline T& operator *() { return *value(); }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Config.h"
|
||||
#include "NativeStructures.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
// NtCreateEvent
|
||||
typedef NTSTATUS( NTAPI* fnNtCreateEvent )(
|
||||
OUT PHANDLE EventHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
||||
IN ULONG EventType,
|
||||
IN BOOLEAN InitialState
|
||||
);
|
||||
|
||||
// NtOpenEvent
|
||||
typedef NTSTATUS( NTAPI* fnNtOpenEvent )(
|
||||
OUT PHANDLE EventHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_ATTRIBUTES ObjectAttributes
|
||||
);
|
||||
|
||||
// NtQueryVirtualMemory
|
||||
typedef NTSTATUS( NTAPI* fnNtQueryVirtualMemory )(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PVOID BaseAddress,
|
||||
IN MEMORY_INFORMATION_CLASS MemoryInformationClass,
|
||||
OUT PVOID MemoryInformation,
|
||||
IN SIZE_T MemoryInformationLength,
|
||||
OUT PSIZE_T ReturnLength
|
||||
);
|
||||
|
||||
// NtWow64QueryInformationProcess64
|
||||
typedef NTSTATUS( NTAPI *fnNtWow64QueryInformationProcess64 )(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN ULONG ProcessInformationClass,
|
||||
OUT PVOID ProcessInformation64,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ReturnLength OPTIONAL
|
||||
);
|
||||
|
||||
// NtWow64ReadVirtualMemory64
|
||||
typedef NTSTATUS( NTAPI *fnNtWow64ReadVirtualMemory64 )(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN ULONG64 BaseAddress,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG64 BufferLength,
|
||||
OUT PULONG64 ReturnLength OPTIONAL
|
||||
);
|
||||
|
||||
// NtWow64WriteVirtualMemory64
|
||||
using fnNtWow64WriteVirtualMemory64 = fnNtWow64ReadVirtualMemory64;
|
||||
|
||||
// NtWow64AllocateVirtualMemory64
|
||||
typedef NTSTATUS( NTAPI *fnNtWow64AllocateVirtualMemory64 )(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PULONG64 BaseAddress,
|
||||
IN ULONG64 ZeroBits,
|
||||
IN PULONG64 Size,
|
||||
IN ULONG AllocationType,
|
||||
IN ULONG Protection
|
||||
);
|
||||
|
||||
// NtWow64QueryVirtualMemory64
|
||||
typedef NTSTATUS( NTAPI *fnNtWow64QueryVirtualMemory64 )(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN ULONG64 BaseAddress,
|
||||
IN DWORD MemoryInformationClass,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG64 Length,
|
||||
OUT PULONG ResultLength OPTIONAL
|
||||
);
|
||||
|
||||
// RtlDosApplyFileIsolationRedirection_Ustr
|
||||
typedef NTSTATUS( NTAPI *fnRtlDosApplyFileIsolationRedirection_Ustr )(
|
||||
IN ULONG Flags,
|
||||
IN PUNICODE_STRING OriginalName,
|
||||
IN PUNICODE_STRING Extension,
|
||||
IN OUT PUNICODE_STRING StaticString,
|
||||
IN OUT PUNICODE_STRING DynamicString,
|
||||
IN OUT PUNICODE_STRING *NewName,
|
||||
IN PULONG NewFlags,
|
||||
IN PSIZE_T FileNameSize,
|
||||
IN PSIZE_T RequiredLength
|
||||
);
|
||||
|
||||
// RtlDosPathNameToNtPathName_U
|
||||
typedef BOOLEAN( NTAPI *fnRtlDosPathNameToNtPathName_U )(
|
||||
IN PCWSTR DosFileName,
|
||||
OUT PUNICODE_STRING NtFileName,
|
||||
OUT OPTIONAL PWSTR *FilePart,
|
||||
OUT OPTIONAL PVOID RelativeName
|
||||
);
|
||||
|
||||
// RtlHashUnicodeString
|
||||
typedef NTSTATUS( NTAPI *fnRtlHashUnicodeString )(
|
||||
IN PCUNICODE_STRING String,
|
||||
IN BOOLEAN CaseInSensitive,
|
||||
IN ULONG HashAlgorithm,
|
||||
OUT PULONG HashValue
|
||||
);
|
||||
|
||||
// RtlRemoteCall
|
||||
typedef NTSTATUS( NTAPI *fnRtlRemoteCall )(
|
||||
IN HANDLE Process,
|
||||
IN HANDLE Thread,
|
||||
IN PVOID CallSite,
|
||||
IN ULONG ArgumentCount,
|
||||
IN PULONG Arguments,
|
||||
IN BOOLEAN PassContext,
|
||||
IN BOOLEAN AlreadySuspended
|
||||
);
|
||||
|
||||
// NtCreateThreadEx
|
||||
typedef NTSTATUS( NTAPI* fnNtCreateThreadEx )(
|
||||
OUT PHANDLE hThread,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN LPVOID ObjectAttributes,
|
||||
IN HANDLE ProcessHandle,
|
||||
IN LPTHREAD_START_ROUTINE lpStartAddress,
|
||||
IN LPVOID lpParameter,
|
||||
IN DWORD Flags,
|
||||
IN SIZE_T StackZeroBits,
|
||||
IN SIZE_T SizeOfStackCommit,
|
||||
IN SIZE_T SizeOfStackReserve,
|
||||
OUT LPVOID lpBytesBuffer
|
||||
);
|
||||
|
||||
// NtLockVirtualMemory
|
||||
typedef NTSTATUS( NTAPI* fnNtLockVirtualMemory )(
|
||||
IN HANDLE process,
|
||||
IN OUT PVOID* baseAddress,
|
||||
IN OUT ULONG* size,
|
||||
IN ULONG flags
|
||||
);
|
||||
|
||||
// RtlRbInsertNodeEx
|
||||
typedef int (NTAPI* fnRtlRbInsertNodeEx)(
|
||||
_RTL_RB_TREE<DWORD_PTR>* Tree,
|
||||
_RTL_BALANCED_NODE<DWORD_PTR>* Parent,
|
||||
BOOLEAN Right,
|
||||
_RTL_BALANCED_NODE<DWORD_PTR> * Node
|
||||
);
|
||||
|
||||
// NtSetInformationProcess
|
||||
typedef NTSTATUS( NTAPI* fnNtSetInformationProcess )(
|
||||
IN HANDLE ProcessHandle,
|
||||
IN PROCESSINFOCLASS ProcessInformationClass,
|
||||
IN PVOID ProcessInformation,
|
||||
IN ULONG ProcessInformationLength
|
||||
);
|
||||
|
||||
// NtDuplicateObject
|
||||
typedef NTSTATUS( NTAPI* fnNtDuplicateObject )(
|
||||
IN HANDLE SourceProcessHandle,
|
||||
IN HANDLE SourceHandle,
|
||||
IN HANDLE TargetProcessHandle,
|
||||
IN PHANDLE TargetHandle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN ULONG Attributes,
|
||||
IN ULONG Options
|
||||
);
|
||||
|
||||
// RtlRbRemoveNode
|
||||
typedef int (NTAPI* fnRtlRbRemoveNode)(
|
||||
_RTL_RB_TREE<DWORD_PTR>* Tree,
|
||||
_RTL_BALANCED_NODE<DWORD_PTR>* Node
|
||||
);
|
||||
|
||||
// RtlUpcaseUnicodeChar
|
||||
typedef WCHAR( NTAPI *fnRtlUpcaseUnicodeChar )(
|
||||
WCHAR chr
|
||||
);
|
||||
|
||||
// RtlEncodeSystemPointer
|
||||
typedef PVOID( NTAPI *fnRtlEncodeSystemPointer )(
|
||||
IN PVOID Pointer
|
||||
);
|
||||
|
||||
// NtLoadDriver
|
||||
typedef NTSTATUS( NTAPI* fnNtLoadDriver )(
|
||||
IN PUNICODE_STRING path
|
||||
);
|
||||
|
||||
// NtUnloadDriver
|
||||
typedef NTSTATUS( NTAPI* fnNtUnloadDriver )(
|
||||
IN PUNICODE_STRING path
|
||||
);
|
||||
|
||||
// NtQuerySection
|
||||
typedef DWORD( NTAPI* fnNtQuerySection )(
|
||||
HANDLE hSection,
|
||||
SECTION_INFORMATION_CLASS InfoClass,
|
||||
PVOID Buffer,
|
||||
ULONG BufferSize,
|
||||
PULONG ReturnLength
|
||||
);
|
||||
|
||||
// NtSuspendProcess
|
||||
typedef NTSTATUS( NTAPI* fnNtSuspendProcess )(
|
||||
HANDLE ProcessHandle
|
||||
);
|
||||
|
||||
// NtResumeProcess
|
||||
typedef NTSTATUS( NTAPI* fnNtResumeProcess )(
|
||||
HANDLE ProcessHandle
|
||||
);
|
||||
|
||||
// RtlCreateActivationContext
|
||||
typedef NTSTATUS( NTAPI *fnRtlCreateActivationContext )(
|
||||
IN ULONG Flags,
|
||||
IN PACTCTXW ActivationContextData,
|
||||
IN ULONG ExtraBytes,
|
||||
IN PVOID NotificationRoutine,
|
||||
IN PVOID NotificationContext,
|
||||
OUT PVOID* ActCtx
|
||||
);
|
||||
|
||||
// NtQueueApcThread
|
||||
typedef NTSTATUS( NTAPI* fnNtQueueApcThread )(
|
||||
IN HANDLE ThreadHandle,
|
||||
IN PVOID ApcRoutine, /*PKNORMAL_ROUTINE*/
|
||||
IN PVOID NormalContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2
|
||||
);
|
||||
|
||||
// RtlQueueApcWow64Thread
|
||||
using fnRtlQueueApcWow64Thread = fnNtQueueApcThread;
|
||||
|
||||
// RtlImageNtHeader
|
||||
typedef PIMAGE_NT_HEADERS( NTAPI* fnRtlImageNtHeader )(
|
||||
IN PVOID ModuleAddress
|
||||
);
|
||||
|
||||
// RtlInitUnicodeString
|
||||
using fnRtlInitUnicodeString = decltype(&RtlInitUnicodeString);
|
||||
|
||||
// RtlFreeUnicodeString
|
||||
using fnRtlFreeUnicodeString = decltype(&RtlFreeUnicodeString);
|
||||
|
||||
// NtQuerySystemInformation
|
||||
using fnNtQuerySystemInformation = decltype(&NtQuerySystemInformation);
|
||||
|
||||
// NtQueryInformationProcess
|
||||
using fnNtQueryInformationProcess = decltype(&NtQueryInformationProcess);
|
||||
|
||||
// NtQueryInformationThread
|
||||
using fnNtQueryInformationThread = decltype(&NtQueryInformationThread);
|
||||
|
||||
// NtQueryObject
|
||||
using fnNtQueryObject = decltype(&NtQueryObject);
|
||||
|
||||
//
|
||||
// GCC compatibility
|
||||
//
|
||||
|
||||
// Wow64GetThreadContext
|
||||
typedef BOOL( __stdcall* fnWow64GetThreadContext )
|
||||
(
|
||||
HANDLE hThread,
|
||||
PWOW64_CONTEXT lpContext
|
||||
);
|
||||
|
||||
// Wow64SetThreadContext
|
||||
typedef BOOL( __stdcall* fnWow64SetThreadContext )
|
||||
(
|
||||
HANDLE hThread,
|
||||
const WOW64_CONTEXT *lpContext
|
||||
);
|
||||
|
||||
// Wow64SuspendThread
|
||||
typedef DWORD( __stdcall* fnWow64SuspendThread )
|
||||
(
|
||||
HANDLE hThread
|
||||
);
|
||||
|
||||
// GetProcessDEPPolicy
|
||||
typedef BOOL( __stdcall* fnGetProcessDEPPolicy )
|
||||
(
|
||||
HANDLE hProcess,
|
||||
LPDWORD lpFlags,
|
||||
PBOOL lpPermanent
|
||||
);
|
||||
|
||||
// QueryFullProcessImageNameW
|
||||
typedef BOOL( __stdcall* fnQueryFullProcessImageNameW)
|
||||
(
|
||||
HANDLE hProcess,
|
||||
DWORD dwFlags,
|
||||
PWSTR lpExeName,
|
||||
PDWORD lpdwSize
|
||||
);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
#pragma once
|
||||
#include "Winheaders.h"
|
||||
#include <memory>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct non_zero
|
||||
{
|
||||
static bool call( T handle ) noexcept
|
||||
{
|
||||
return intptr_t( handle ) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct non_negative
|
||||
{
|
||||
static bool call( T handle ) noexcept
|
||||
{
|
||||
return intptr_t( handle ) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename> typename wrapped_t, typename T>
|
||||
struct with_pseudo_t
|
||||
{
|
||||
static bool call( T handle ) noexcept
|
||||
{
|
||||
if (wrapped_t<T>::call( handle ))
|
||||
return true;
|
||||
|
||||
// Check if it's a pseudo handle
|
||||
auto h = (HANDLE)(uintptr_t)handle;
|
||||
return h == GetCurrentProcess() || h == GetCurrentThread();
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename> typename wrapped_t>
|
||||
struct with_pseudo
|
||||
{
|
||||
template<typename T>
|
||||
using type = with_pseudo_t<wrapped_t, T>;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Strong exception guarantee
|
||||
/// </summary>
|
||||
template<typename handle_t, auto close, template<typename> typename is_valid = non_negative>
|
||||
class HandleGuard
|
||||
{
|
||||
public:
|
||||
static constexpr handle_t zero_handle = handle_t( 0 );
|
||||
|
||||
public:
|
||||
explicit HandleGuard( handle_t handle = zero_handle ) noexcept
|
||||
: _handle( handle )
|
||||
{
|
||||
}
|
||||
|
||||
HandleGuard( HandleGuard&& rhs ) noexcept
|
||||
: _handle( rhs._handle )
|
||||
{
|
||||
rhs._handle = zero_handle;
|
||||
}
|
||||
|
||||
~HandleGuard()
|
||||
{
|
||||
if (non_negative<handle_t>::call( _handle ))
|
||||
close( _handle );
|
||||
}
|
||||
|
||||
HandleGuard( const HandleGuard& ) = delete;
|
||||
HandleGuard& operator =( const HandleGuard& ) = delete;
|
||||
|
||||
HandleGuard& operator =( HandleGuard&& rhs ) noexcept
|
||||
{
|
||||
if (std::addressof( rhs ) == this)
|
||||
return *this;
|
||||
|
||||
reset( rhs._handle );
|
||||
rhs._handle = zero_handle;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
HandleGuard& operator =( handle_t handle ) noexcept
|
||||
{
|
||||
reset( handle );
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset( handle_t handle = zero_handle ) noexcept
|
||||
{
|
||||
if (handle == _handle)
|
||||
return;
|
||||
|
||||
if (non_negative<handle_t>::call( _handle ))
|
||||
close( _handle );
|
||||
|
||||
_handle = handle;
|
||||
}
|
||||
|
||||
handle_t release() noexcept
|
||||
{
|
||||
auto tmp = _handle;
|
||||
_handle = zero_handle;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
handle_t get() const noexcept { return _handle; }
|
||||
bool valid() const noexcept { return is_valid<handle_t>::call( _handle ); }
|
||||
|
||||
operator handle_t() const noexcept { return _handle; }
|
||||
explicit operator bool() const noexcept { return valid(); }
|
||||
|
||||
handle_t* operator &() noexcept { return &_handle; }
|
||||
|
||||
bool operator ==( const HandleGuard& rhs ) const noexcept { return _handle == rhs._handle; }
|
||||
bool operator <( const HandleGuard& rhs ) const noexcept { return _handle < rhs._handle; }
|
||||
|
||||
private:
|
||||
handle_t _handle;
|
||||
};
|
||||
|
||||
|
||||
using Handle = HandleGuard<HANDLE, &CloseHandle>;
|
||||
using ProcessHandle = HandleGuard<HANDLE, &CloseHandle, with_pseudo<non_negative>::type>;
|
||||
using ACtxHandle = HandleGuard<HANDLE, &ReleaseActCtx>;
|
||||
using RegHandle = HandleGuard<HKEY, &RegCloseKey>;
|
||||
using Mapping = HandleGuard<void*, & UnmapViewOfFile, non_zero>;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
#include "../Config.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// Architecture-dependent pointer size
|
||||
#define BlackBoneWordSize sizeof(void*)
|
||||
|
||||
// Rebase address
|
||||
#define MAKE_PTR(T, pRVA, base) (T)((ptr_t)pRVA + (ptr_t)base)
|
||||
#define REBASE(pRVA, baseOld, baseNew) ((ptr_t)pRVA - (ptr_t)baseOld + (ptr_t)baseNew)
|
||||
|
||||
// Field offset info
|
||||
#define FIELD_OFFSET2(type, field) ((LONG)(LONG_PTR)&(((type)0)->field))
|
||||
#define GET_FIELD_PTR(entry, field) (uintptr_t)((uint8_t*)entry + FIELD_OFFSET2(decltype(entry), field))
|
||||
|
||||
#define CALL_64_86(b, f, ...) (b ? f<uint64_t>(__VA_ARGS__) : f<uint32_t>(__VA_ARGS__))
|
||||
#define FIELD_PTR_64_86(b, e, t, f) (b ? fieldPtr( e, &t<uint64_t>::f ) : fieldPtr( e, &t<uint32_t>::f ))
|
||||
|
||||
#define LODWORD(l) ((uint32_t)(((uint64_t)(l)) & 0xffffffff))
|
||||
#define HIDWORD(l) ((uint32_t)((((uint64_t)(l)) >> 32) & 0xffffffff))
|
||||
|
||||
// Set or reset particular bit
|
||||
#define SET_BIT(v, b) v |= (1ull << b)
|
||||
#define RESET_BIT(v, b) v &= ~(1ull << b)
|
||||
|
||||
// Register aliases
|
||||
#ifdef USE64
|
||||
#define NAX Rax
|
||||
#define NSP Rsp
|
||||
#define NIP Rip
|
||||
#define NDI Rdi
|
||||
|
||||
#define BitScanForwardT _BitScanForward64
|
||||
#define BitScanReverseT _BitScanReverse64
|
||||
#define BitTestAndSetT _bittestandset64
|
||||
#define BitTestAndResetT _bittestandreset64
|
||||
|
||||
#define SET_JUMP(_src,_dst) *(uintptr_t*)(_src) = 0x25FF; *(uintptr_t*)((_src) + 6) = (uintptr_t)_dst;
|
||||
#else
|
||||
#define NAX Eax
|
||||
#define NSP Esp
|
||||
#define NIP Eip
|
||||
#define NDI Edi
|
||||
|
||||
#define BitScanForwardT _BitScanForward
|
||||
#define BitScanReverseT _BitScanReverse
|
||||
#define BitTestAndSetT _bittestandset
|
||||
#define BitTestAndResetT _bittestandreset
|
||||
|
||||
#define SET_JUMP(_src,_dst) *(uint8_t*)(_src) = 0xE9; *(uintptr_t*)((_src) + 1) = (uintptr_t)(_dst) - (uintptr_t)(_src) - 5
|
||||
#endif
|
||||
|
||||
#define ENUM_OPS(e) \
|
||||
inline e operator |(e a1, e a2) { \
|
||||
return static_cast<e>(static_cast<int>(a1) | static_cast<int>(a2)); \
|
||||
} \
|
||||
\
|
||||
inline e operator |= (e& a1, e a2) { \
|
||||
return a1 = a1 | a2; \
|
||||
} \
|
||||
\
|
||||
inline e operator &(e a1, e a2) { \
|
||||
return static_cast<e>(static_cast<int>(a1)& static_cast<int>(a2)); \
|
||||
} \
|
||||
\
|
||||
inline e operator &= (e& a1, e a2) { \
|
||||
return a1 = a1 & a2; \
|
||||
} \
|
||||
\
|
||||
inline e operator ~(e a1) { \
|
||||
return static_cast<e>(~static_cast<int>(a1)); \
|
||||
}
|
||||
|
||||
|
||||
template<int s>
|
||||
struct CompileTimeSizeOf;
|
||||
|
||||
// offsetof alternative
|
||||
template<typename T, typename U>
|
||||
constexpr size_t offsetOf( U T::*member )
|
||||
{
|
||||
return reinterpret_cast<size_t>(&(reinterpret_cast<T*>(nullptr)->*member));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
constexpr uint64_t fieldPtr( uint64_t base, U T::*member )
|
||||
{
|
||||
return base + offsetOf( member );
|
||||
}
|
||||
|
||||
// CONTAINING_RECORD alternative
|
||||
template<typename T, typename U>
|
||||
constexpr uint64_t structBase( uint64_t ptr, U T::*member )
|
||||
{
|
||||
return ptr - offsetOf( member );
|
||||
}
|
||||
|
||||
// Type-unsafe cast.
|
||||
template<typename _Tgt, typename _Src>
|
||||
inline _Tgt brutal_cast( const _Src& src )
|
||||
{
|
||||
static_assert(sizeof( _Tgt ) == sizeof( _Src ), "Operand size mismatch");
|
||||
union _u { _Src s; _Tgt t; } u;
|
||||
u.s = src;
|
||||
return u.t;
|
||||
}
|
||||
|
||||
// Align value
|
||||
inline size_t Align( size_t val, size_t alignment )
|
||||
{
|
||||
return (val % alignment == 0) ? val : (val / alignment + 1) * alignment;
|
||||
}
|
||||
|
||||
// Offset of 'LastStatus' field in TEB
|
||||
#define LAST_STATUS_OFS (0x598 + 0x197 * BlackBoneWordSize)
|
||||
|
||||
using NTSTATUS = long;
|
||||
|
||||
/// <summary>
|
||||
/// Get last NT status
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
inline NTSTATUS LastNtStatus()
|
||||
{
|
||||
return *(NTSTATUS*)((unsigned char*)NtCurrentTeb() + LAST_STATUS_OFS);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set last NT status
|
||||
/// </summary>
|
||||
/// <param name="status">The status.</param>
|
||||
/// <returns></returns>
|
||||
inline NTSTATUS SetLastNtStatus( NTSTATUS status )
|
||||
{
|
||||
return *(NTSTATUS*)((unsigned char*)NtCurrentTeb() + LAST_STATUS_OFS) = status;
|
||||
}
|
||||
|
||||
#define SharedUserData32 ((KUSER_SHARED_DATA* const)0x7FFE0000)
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
enum MEMORY_INFORMATION_CLASS
|
||||
{
|
||||
MemoryBasicInformation = 0,
|
||||
MemoryWorkingSetList,
|
||||
MemorySectionName,
|
||||
MemoryBasicVlmInformation,
|
||||
MemoryWorkingSetExList
|
||||
};
|
||||
|
||||
enum SECTION_INFORMATION_CLASS
|
||||
{
|
||||
SectionBasicInformation,
|
||||
SectionImageInformation
|
||||
};
|
||||
|
||||
enum POOL_TYPE
|
||||
{
|
||||
NonPagedPool,
|
||||
PagedPool,
|
||||
NonPagedPoolMustSucceed,
|
||||
DontUseThisType,
|
||||
NonPagedPoolCacheAligned,
|
||||
PagedPoolCacheAligned,
|
||||
NonPagedPoolCacheAlignedMustS
|
||||
};
|
||||
|
||||
//
|
||||
// Loader related
|
||||
//
|
||||
enum _LDR_DDAG_STATE
|
||||
{
|
||||
LdrModulesMerged = -5,
|
||||
LdrModulesInitError = -4,
|
||||
LdrModulesSnapError = -3,
|
||||
LdrModulesUnloaded = -2,
|
||||
LdrModulesUnloading = -1,
|
||||
LdrModulesPlaceHolder = 0,
|
||||
LdrModulesMapping = 1,
|
||||
LdrModulesMapped = 2,
|
||||
LdrModulesWaitingForDependencies = 3,
|
||||
LdrModulesSnapping = 4,
|
||||
LdrModulesSnapped = 5,
|
||||
LdrModulesCondensed = 6,
|
||||
LdrModulesReadyToInit = 7,
|
||||
LdrModulesInitializing = 8,
|
||||
LdrModulesReadyToRun = 9
|
||||
};
|
||||
|
||||
enum _LDR_DLL_LOAD_REASON
|
||||
{
|
||||
LoadReasonStaticDependency = 0,
|
||||
LoadReasonStaticForwarderDependency = 1,
|
||||
LoadReasonDynamicForwarderDependency = 2,
|
||||
LoadReasonDelayloadDependency = 3,
|
||||
LoadReasonDynamicLoad = 4,
|
||||
LoadReasonAsImageLoad = 5,
|
||||
LoadReasonAsDataLoad = 6,
|
||||
LoadReasonUnknown = -1
|
||||
};
|
||||
|
||||
}
|
||||
+818
@@ -0,0 +1,818 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Config.h"
|
||||
#include "NativeEnums.h"
|
||||
|
||||
#include "Winheaders.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
|
||||
template <int n>
|
||||
using const_int = std::integral_constant<int, n>;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is32bit = std::is_same_v<T, uint32_t>;
|
||||
|
||||
template<typename T, typename T32, typename T64>
|
||||
using type_32_64 = std::conditional_t<is32bit<T>, T32, T64>;
|
||||
|
||||
template<typename T, int v32, int v64>
|
||||
constexpr int int_32_64 = std::conditional_t<is32bit<T>, const_int<v32>, const_int<v64>>::value;
|
||||
|
||||
// nonstandard extension used : nameless struct/union
|
||||
#pragma warning(disable : 4201)
|
||||
|
||||
template <typename T>
|
||||
struct _LIST_ENTRY_T
|
||||
{
|
||||
T Flink;
|
||||
T Blink;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _UNICODE_STRING_T
|
||||
{
|
||||
using type = T;
|
||||
|
||||
uint16_t Length;
|
||||
uint16_t MaximumLength;
|
||||
T Buffer;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _NT_TIB_T
|
||||
{
|
||||
T ExceptionList;
|
||||
T StackBase;
|
||||
T StackLimit;
|
||||
T SubSystemTib;
|
||||
T FiberData;
|
||||
T ArbitraryUserPointer;
|
||||
T Self;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _CLIENT_ID_T
|
||||
{
|
||||
T UniqueProcess;
|
||||
T UniqueThread;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _GDI_TEB_BATCH_T
|
||||
{
|
||||
uint32_t Offset;
|
||||
T HDC;
|
||||
uint32_t Buffer[310];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _ACTIVATION_CONTEXT_STACK_T
|
||||
{
|
||||
T ActiveFrame;
|
||||
_LIST_ENTRY_T<T> FrameListCache;
|
||||
uint32_t Flags;
|
||||
uint32_t NextCookieSequenceNumber;
|
||||
uint32_t StackId;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct _TEB_T
|
||||
{
|
||||
struct Specific32_1
|
||||
{
|
||||
uint8_t InstrumentationCallbackDisabled;
|
||||
uint8_t SpareBytes[23];
|
||||
uint32_t TxFsContext;
|
||||
};
|
||||
|
||||
struct Specific64_1
|
||||
{
|
||||
uint32_t TxFsContext;
|
||||
uint32_t InstrumentationCallbackDisabled;
|
||||
};
|
||||
|
||||
struct Specific64_2
|
||||
{
|
||||
T TlsExpansionSlots;
|
||||
T DeallocationBStore;
|
||||
T BStoreLimit;
|
||||
};
|
||||
|
||||
struct Specific32_2
|
||||
{
|
||||
T TlsExpansionSlots;
|
||||
};
|
||||
|
||||
_NT_TIB_T<T> NtTib;
|
||||
T EnvironmentPointer;
|
||||
_CLIENT_ID_T<T> ClientId;
|
||||
T ActiveRpcHandle;
|
||||
T ThreadLocalStoragePointer;
|
||||
T ProcessEnvironmentBlock;
|
||||
uint32_t LastErrorValue;
|
||||
uint32_t CountOfOwnedCriticalSections;
|
||||
T CsrClientThread;
|
||||
T Win32ThreadInfo;
|
||||
uint32_t User32Reserved[26];
|
||||
uint32_t UserReserved[5];
|
||||
T WOW32Reserved;
|
||||
uint32_t CurrentLocale;
|
||||
uint32_t FpSoftwareStatusRegister;
|
||||
T ReservedForDebuggerInstrumentation[16];
|
||||
T SystemReserved1[int_32_64<T, 26, 30>];
|
||||
uint8_t PlaceholderCompatibilityMode;
|
||||
uint8_t PlaceholderReserved[11];
|
||||
uint32_t ProxiedProcessId;
|
||||
_ACTIVATION_CONTEXT_STACK_T<T> ActivationStack;
|
||||
uint8_t WorkingOnBehalfTicket[8];
|
||||
uint32_t ExceptionCode;
|
||||
T ActivationContextStackPointer;
|
||||
T InstrumentationCallbackSp;
|
||||
T InstrumentationCallbackPreviousPc;
|
||||
T InstrumentationCallbackPreviousSp;
|
||||
type_32_64<T, Specific32_1, Specific64_1> spec1;
|
||||
_GDI_TEB_BATCH_T<T> GdiTebBatch;
|
||||
_CLIENT_ID_T<T> RealClientId;
|
||||
T GdiCachedProcessHandle;
|
||||
uint32_t GdiClientPID;
|
||||
uint32_t GdiClientTID;
|
||||
T GdiThreadLocalInfo;
|
||||
T Win32ClientInfo[62];
|
||||
T glDispatchTable[233];
|
||||
T glReserved1[29];
|
||||
T glReserved2;
|
||||
T glSectionInfo;
|
||||
T glSection;
|
||||
T glTable;
|
||||
T glCurrentRC;
|
||||
T glContext;
|
||||
uint32_t LastStatusValue;
|
||||
_UNICODE_STRING_T<T> StaticUnicodeString;
|
||||
wchar_t StaticUnicodeBuffer[261];
|
||||
T DeallocationStack;
|
||||
T TlsSlots[64];
|
||||
_LIST_ENTRY_T<T> TlsLinks;
|
||||
T Vdm;
|
||||
T ReservedForNtRpc;
|
||||
T DbgSsReserved[2];
|
||||
uint32_t HardErrorMode;
|
||||
T Instrumentation[int_32_64<T, 9, 11>];
|
||||
GUID ActivityId;
|
||||
T SubProcessTag;
|
||||
T PerflibData;
|
||||
T EtwTraceData;
|
||||
T WinSockData;
|
||||
uint32_t GdiBatchCount; // TEB64 pointer
|
||||
uint32_t IdealProcessorValue;
|
||||
uint32_t GuaranteedStackBytes;
|
||||
T ReservedForPerf;
|
||||
T ReservedForOle;
|
||||
uint32_t WaitingOnLoaderLock;
|
||||
T SavedPriorityState;
|
||||
T ReservedForCodeCoverage;
|
||||
T ThreadPoolData;
|
||||
type_32_64<T, Specific32_2, Specific64_2> spec2;
|
||||
uint32_t MuiGeneration;
|
||||
uint32_t IsImpersonating;
|
||||
T NlsCache;
|
||||
T pShimData;
|
||||
uint16_t HeapVirtualAffinity;
|
||||
uint16_t LowFragHeapDataSlot;
|
||||
T CurrentTransactionHandle;
|
||||
T ActiveFrame;
|
||||
T FlsData;
|
||||
T PreferredLanguages;
|
||||
T UserPrefLanguages;
|
||||
T MergedPrefLanguages;
|
||||
uint32_t MuiImpersonation;
|
||||
uint16_t CrossTebFlags;
|
||||
union
|
||||
{
|
||||
uint16_t SameTebFlags;
|
||||
struct
|
||||
{
|
||||
uint16_t SafeThunkCall : 1;
|
||||
uint16_t InDebugPrint : 1;
|
||||
uint16_t HasFiberData : 1;
|
||||
uint16_t SkipThreadAttach : 1;
|
||||
uint16_t WerInShipAssertCode : 1;
|
||||
uint16_t RanProcessInit : 1;
|
||||
uint16_t ClonedThread : 1;
|
||||
uint16_t SuppressDebugMsg : 1;
|
||||
uint16_t DisableUserStackWalk : 1;
|
||||
uint16_t RtlExceptionAttached : 1;
|
||||
uint16_t InitialThread : 1;
|
||||
uint16_t SessionAware : 1;
|
||||
uint16_t LoadOwner : 1;
|
||||
uint16_t LoaderWorker : 1;
|
||||
uint16_t SkipLoaderInit : 1;
|
||||
uint16_t SpareSameTebBits : 1;
|
||||
};
|
||||
};
|
||||
T TxnScopeEnterCallback;
|
||||
T TxnScopeExitCallback;
|
||||
T TxnScopeContext;
|
||||
uint32_t LockCount;
|
||||
uint32_t WowTebOffset;
|
||||
T ResourceRetValue;
|
||||
T ReservedForWdf;
|
||||
uint64_t ReservedForCrt;
|
||||
GUID EffectiveContainerId;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _PEB_T
|
||||
{
|
||||
static_assert( std::is_same_v<T, uint32_t> || std::is_same_v<T, uint64_t>, "T must be uint32_t or uint64_t" );
|
||||
|
||||
uint8_t InheritedAddressSpace;
|
||||
uint8_t ReadImageFileExecOptions;
|
||||
uint8_t BeingDebugged;
|
||||
union
|
||||
{
|
||||
uint8_t BitField;
|
||||
struct
|
||||
{
|
||||
uint8_t ImageUsesLargePages : 1;
|
||||
uint8_t IsProtectedProcess : 1;
|
||||
uint8_t IsImageDynamicallyRelocated : 1;
|
||||
uint8_t SkipPatchingUser32Forwarders : 1;
|
||||
uint8_t IsPackagedProcess : 1;
|
||||
uint8_t IsAppContainer : 1;
|
||||
uint8_t IsProtectedProcessLight : 1;
|
||||
uint8_t SpareBits : 1;
|
||||
};
|
||||
};
|
||||
T Mutant;
|
||||
T ImageBaseAddress;
|
||||
T Ldr;
|
||||
T ProcessParameters;
|
||||
T SubSystemData;
|
||||
T ProcessHeap;
|
||||
T FastPebLock;
|
||||
T AtlThunkSListPtr;
|
||||
T IFEOKey;
|
||||
union
|
||||
{
|
||||
T CrossProcessFlags;
|
||||
struct
|
||||
{
|
||||
uint32_t ProcessInJob : 1;
|
||||
uint32_t ProcessInitializing : 1;
|
||||
uint32_t ProcessUsingVEH : 1;
|
||||
uint32_t ProcessUsingVCH : 1;
|
||||
uint32_t ProcessUsingFTH : 1;
|
||||
uint32_t ReservedBits0 : 27;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
T KernelCallbackTable;
|
||||
T UserSharedInfoPtr;
|
||||
};
|
||||
uint32_t SystemReserved;
|
||||
uint32_t AtlThunkSListPtr32;
|
||||
T ApiSetMap;
|
||||
union
|
||||
{
|
||||
uint32_t TlsExpansionCounter;
|
||||
T Padding2;
|
||||
};
|
||||
T TlsBitmap;
|
||||
uint32_t TlsBitmapBits[2];
|
||||
T ReadOnlySharedMemoryBase;
|
||||
T SparePvoid0;
|
||||
T ReadOnlyStaticServerData;
|
||||
T AnsiCodePageData;
|
||||
T OemCodePageData;
|
||||
T UnicodeCaseTableData;
|
||||
uint32_t NumberOfProcessors;
|
||||
uint32_t NtGlobalFlag;
|
||||
LARGE_INTEGER CriticalSectionTimeout;
|
||||
T HeapSegmentReserve;
|
||||
T HeapSegmentCommit;
|
||||
T HeapDeCommitTotalFreeThreshold;
|
||||
T HeapDeCommitFreeBlockThreshold;
|
||||
uint32_t NumberOfHeaps;
|
||||
uint32_t MaximumNumberOfHeaps;
|
||||
T ProcessHeaps;
|
||||
T GdiSharedHandleTable;
|
||||
T ProcessStarterHelper;
|
||||
union
|
||||
{
|
||||
uint32_t GdiDCAttributeList;
|
||||
T Padding3;
|
||||
};
|
||||
T LoaderLock;
|
||||
uint32_t OSMajorVersion;
|
||||
uint32_t OSMinorVersion;
|
||||
uint16_t OSBuildNumber;
|
||||
uint16_t OSCSDVersion;
|
||||
uint32_t OSPlatformId;
|
||||
uint32_t ImageSubsystem;
|
||||
uint32_t ImageSubsystemMajorVersion;
|
||||
union
|
||||
{
|
||||
uint32_t ImageSubsystemMinorVersion;
|
||||
T Padding4;
|
||||
};
|
||||
T ActiveProcessAffinityMask;
|
||||
uint32_t GdiHandleBuffer[int_32_64<T, 34, 60>];
|
||||
T PostProcessInitRoutine;
|
||||
T TlsExpansionBitmap;
|
||||
uint32_t TlsExpansionBitmapBits[32];
|
||||
union
|
||||
{
|
||||
uint32_t SessionId;
|
||||
T Padding5;
|
||||
};
|
||||
ULARGE_INTEGER AppCompatFlags;
|
||||
ULARGE_INTEGER AppCompatFlagsUser;
|
||||
T pShimData;
|
||||
T AppCompatInfo;
|
||||
_UNICODE_STRING_T<T> CSDVersion;
|
||||
T ActivationContextData;
|
||||
T ProcessAssemblyStorageMap;
|
||||
T SystemDefaultActivationContextData;
|
||||
T SystemAssemblyStorageMap;
|
||||
T MinimumStackCommit;
|
||||
T FlsCallback;
|
||||
_LIST_ENTRY_T<T> FlsListHead;
|
||||
T FlsBitmap;
|
||||
uint32_t FlsBitmapBits[4];
|
||||
uint32_t FlsHighIndex;
|
||||
T WerRegistrationData;
|
||||
T WerShipAssertPtr;
|
||||
T pUnused;
|
||||
T pImageHeaderHash;
|
||||
union
|
||||
{
|
||||
uint64_t TracingFlags;
|
||||
struct
|
||||
{
|
||||
uint32_t HeapTracingEnabled : 1;
|
||||
uint32_t CritSecTracingEnabled : 1;
|
||||
uint32_t LibLoaderTracingEnabled : 1;
|
||||
uint32_t SpareTracingBits : 29;
|
||||
};
|
||||
};
|
||||
T CsrServerReadOnlySharedMemoryBase;
|
||||
};
|
||||
|
||||
#pragma warning(default : 4201)
|
||||
|
||||
template<typename T>
|
||||
struct _ACTCTXW_T
|
||||
{
|
||||
uint32_t cbSize;
|
||||
uint32_t dwFlags;
|
||||
T lpSource;
|
||||
uint16_t wProcessorArchitecture;
|
||||
LANGID wLangId;
|
||||
T lpAssemblyDirectory;
|
||||
T lpResourceName;
|
||||
T lpApplicationName;
|
||||
T hModule;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _PROCESS_BASIC_INFORMATION_T
|
||||
{
|
||||
NTSTATUS ExitStatus;
|
||||
uint32_t Reserved0;
|
||||
T PebBaseAddress;
|
||||
T AffinityMask;
|
||||
LONG BasePriority;
|
||||
ULONG Reserved1;
|
||||
T uUniqueProcessId;
|
||||
T uInheritedFromUniqueProcessId;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _SECTION_BASIC_INFORMATION_T
|
||||
{
|
||||
T Base;
|
||||
uint32_t Attributes;
|
||||
LARGE_INTEGER Size;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _PROCESS_EXTENDED_BASIC_INFORMATION_T
|
||||
{
|
||||
T Size; // Must be set to structure size on input
|
||||
_PROCESS_BASIC_INFORMATION_T<T> BasicInfo;
|
||||
struct
|
||||
{
|
||||
uint32_t IsProtectedProcess : 1;
|
||||
uint32_t IsWow64Process : 1;
|
||||
uint32_t IsProcessDeleting : 1;
|
||||
uint32_t IsCrossSessionCreate : 1;
|
||||
uint32_t IsFrozen : 1;
|
||||
uint32_t IsBackground : 1;
|
||||
uint32_t IsStronglyNamed : 1;
|
||||
uint32_t SpareBits : 25;
|
||||
}Flags;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _THREAD_BASIC_INFORMATION_T
|
||||
{
|
||||
NTSTATUS ExitStatus;
|
||||
T TebBaseAddress;
|
||||
_CLIENT_ID_T<T> ClientID;
|
||||
T AffinityMask;
|
||||
LONG Priority;
|
||||
LONG BasePriority;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _VM_COUNTERS_T
|
||||
{
|
||||
T PeakVirtualSize;
|
||||
T VirtualSize;
|
||||
uint32_t PageFaultCount;
|
||||
T PeakWorkingSetSize;
|
||||
T WorkingSetSize;
|
||||
T QuotaPeakPagedPoolUsage;
|
||||
T QuotaPagedPoolUsage;
|
||||
T QuotaPeakNonPagedPoolUsage;
|
||||
T QuotaNonPagedPoolUsage;
|
||||
T PagefileUsage;
|
||||
T PeakPagefileUsage;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _SYSTEM_THREAD_INFORMATION_T
|
||||
{
|
||||
LARGE_INTEGER KernelTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
LARGE_INTEGER CreateTime;
|
||||
uint32_t WaitTime;
|
||||
T StartAddress;
|
||||
_CLIENT_ID_T<T> ClientId;
|
||||
LONG Priority;
|
||||
LONG BasePriority;
|
||||
uint32_t ContextSwitches;
|
||||
uint32_t ThreadState;
|
||||
uint32_t WaitReason;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _SYSTEM_EXTENDED_THREAD_INFORMATION_T
|
||||
{
|
||||
_SYSTEM_THREAD_INFORMATION_T<T> ThreadInfo;
|
||||
T StackBase;
|
||||
T StackLimit;
|
||||
T Win32StartAddress;
|
||||
T TebBase;
|
||||
T Reserved[3];
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _SYSTEM_PROCESS_INFORMATION_T
|
||||
{
|
||||
uint32_t NextEntryOffset;
|
||||
uint32_t NumberOfThreads;
|
||||
LARGE_INTEGER WorkingSetPrivateSize;
|
||||
uint32_t HardFaultCount;
|
||||
uint32_t NumberOfThreadsHighWatermark;
|
||||
ULONGLONG CycleTime;
|
||||
LARGE_INTEGER CreateTime;
|
||||
LARGE_INTEGER UserTime;
|
||||
LARGE_INTEGER KernelTime;
|
||||
_UNICODE_STRING_T<T> ImageName;
|
||||
LONG BasePriority;
|
||||
T UniqueProcessId;
|
||||
T InheritedFromUniqueProcessId;
|
||||
uint32_t HandleCount;
|
||||
uint32_t SessionId;
|
||||
T UniqueProcessKey;
|
||||
_VM_COUNTERS_T<T> VmCounters;
|
||||
T PrivatePageCount;
|
||||
IO_COUNTERS IoCounters;
|
||||
_SYSTEM_EXTENDED_THREAD_INFORMATION_T<T> Threads[1];
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _SYSTEM_HANDLE_T
|
||||
{
|
||||
uint32_t ProcessId;
|
||||
uint8_t ObjectTypeNumber;
|
||||
uint8_t Flags;
|
||||
uint16_t Handle;
|
||||
T Object;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _SYSTEM_HANDLE_INFORMATION_T
|
||||
{
|
||||
uint32_t HandleCount;
|
||||
_SYSTEM_HANDLE_T<T> Handles[1];
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _OBJECT_TYPE_INFORMATION_T
|
||||
{
|
||||
_UNICODE_STRING_T<T> Name;
|
||||
uint32_t TotalNumberOfObjects;
|
||||
uint32_t TotalNumberOfHandles;
|
||||
uint32_t TotalPagedPoolUsage;
|
||||
uint32_t TotalNonPagedPoolUsage;
|
||||
uint32_t TotalNamePoolUsage;
|
||||
uint32_t TotalHandleTableUsage;
|
||||
uint32_t HighWaterNumberOfObjects;
|
||||
uint32_t HighWaterNumberOfHandles;
|
||||
uint32_t HighWaterPagedPoolUsage;
|
||||
uint32_t HighWaterNonPagedPoolUsage;
|
||||
uint32_t HighWaterNamePoolUsage;
|
||||
uint32_t HighWaterHandleTableUsage;
|
||||
uint32_t InvalidAttributes;
|
||||
GENERIC_MAPPING GenericMapping;
|
||||
uint32_t ValidAccess;
|
||||
BOOLEAN SecurityRequired;
|
||||
BOOLEAN MaintainHandleCount;
|
||||
uint16_t MaintainTypeList;
|
||||
POOL_TYPE PoolType;
|
||||
uint32_t PagedPoolUsage;
|
||||
uint32_t NonPagedPoolUsage;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _OBJECT_ATTRIBUTES_T
|
||||
{
|
||||
uint32_t Length;
|
||||
T RootDirectory;
|
||||
T ObjectName;
|
||||
uint32_t Attributes;
|
||||
T SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
|
||||
T SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
|
||||
};
|
||||
|
||||
struct _XSAVE_FORMAT64
|
||||
{
|
||||
uint16_t ControlWord;
|
||||
uint16_t StatusWord;
|
||||
uint8_t TagWord;
|
||||
uint8_t Reserved1;
|
||||
uint16_t ErrorOpcode;
|
||||
uint32_t ErrorOffset;
|
||||
uint16_t ErrorSelector;
|
||||
uint16_t Reserved2;
|
||||
uint32_t DataOffset;
|
||||
uint16_t DataSelector;
|
||||
uint16_t Reserved3;
|
||||
uint32_t MxCsr;
|
||||
uint32_t MxCsr_Mask;
|
||||
_M128A FloatRegisters[8];
|
||||
_M128A XmmRegisters[16];
|
||||
uint8_t Reserved4[96];
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _CONTEXT_T;
|
||||
|
||||
template<>
|
||||
struct _CONTEXT_T<uint32_t>
|
||||
{
|
||||
uint32_t ContextFlags;
|
||||
uint32_t Dr0;
|
||||
uint32_t Dr1;
|
||||
uint32_t Dr2;
|
||||
uint32_t Dr3;
|
||||
uint32_t Dr6;
|
||||
uint32_t Dr7;
|
||||
WOW64_FLOATING_SAVE_AREA FloatSave;
|
||||
uint32_t SegGs;
|
||||
uint32_t SegFs;
|
||||
uint32_t SegEs;
|
||||
uint32_t SegDs;
|
||||
uint32_t Edi;
|
||||
uint32_t Esi;
|
||||
uint32_t Ebx;
|
||||
uint32_t Edx;
|
||||
uint32_t Ecx;
|
||||
uint32_t Eax;
|
||||
uint32_t Ebp;
|
||||
uint32_t Eip;
|
||||
uint32_t SegCs; // MUST BE SANITIZED
|
||||
uint32_t EFlags; // MUST BE SANITIZED
|
||||
uint32_t Esp;
|
||||
uint32_t SegSs;
|
||||
uint8_t ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION];
|
||||
};
|
||||
|
||||
template<>
|
||||
struct _CONTEXT_T<uint64_t>
|
||||
{
|
||||
uint64_t P1Home;
|
||||
uint64_t P2Home;
|
||||
uint64_t P3Home;
|
||||
uint64_t P4Home;
|
||||
uint64_t P5Home;
|
||||
uint64_t P6Home;
|
||||
uint32_t ContextFlags;
|
||||
uint32_t MxCsr;
|
||||
uint16_t SegCs;
|
||||
uint16_t SegDs;
|
||||
uint16_t SegEs;
|
||||
uint16_t SegFs;
|
||||
uint16_t SegGs;
|
||||
uint16_t SegSs;
|
||||
uint32_t EFlags;
|
||||
uint64_t Dr0;
|
||||
uint64_t Dr1;
|
||||
uint64_t Dr2;
|
||||
uint64_t Dr3;
|
||||
uint64_t Dr6;
|
||||
uint64_t Dr7;
|
||||
uint64_t Rax;
|
||||
uint64_t Rcx;
|
||||
uint64_t Rdx;
|
||||
uint64_t Rbx;
|
||||
uint64_t Rsp;
|
||||
uint64_t Rbp;
|
||||
uint64_t Rsi;
|
||||
uint64_t Rdi;
|
||||
uint64_t R8;
|
||||
uint64_t R9;
|
||||
uint64_t R10;
|
||||
uint64_t R11;
|
||||
uint64_t R12;
|
||||
uint64_t R13;
|
||||
uint64_t R14;
|
||||
uint64_t R15;
|
||||
uint64_t Rip;
|
||||
_XSAVE_FORMAT64 FltSave;
|
||||
_M128A Header[2];
|
||||
_M128A Legacy[8];
|
||||
_M128A Xmm0;
|
||||
_M128A Xmm1;
|
||||
_M128A Xmm2;
|
||||
_M128A Xmm3;
|
||||
_M128A Xmm4;
|
||||
_M128A Xmm5;
|
||||
_M128A Xmm6;
|
||||
_M128A Xmm7;
|
||||
_M128A Xmm8;
|
||||
_M128A Xmm9;
|
||||
_M128A Xmm10;
|
||||
_M128A Xmm11;
|
||||
_M128A Xmm12;
|
||||
_M128A Xmm13;
|
||||
_M128A Xmm14;
|
||||
_M128A Xmm15;
|
||||
_M128A VectorRegister[26];
|
||||
uint64_t VectorControl;
|
||||
uint64_t DebugControl;
|
||||
uint64_t LastBranchToRip;
|
||||
uint64_t LastBranchFromRip;
|
||||
uint64_t LastExceptionToRip;
|
||||
uint64_t LastExceptionFromRip;
|
||||
|
||||
_CONTEXT_T<uint64_t>& FromCtx32( const _CONTEXT_T<uint32_t>& ctx32 )
|
||||
{
|
||||
ContextFlags = ctx32.ContextFlags;
|
||||
Dr0 = ctx32.Dr0;
|
||||
Dr1 = ctx32.Dr1;
|
||||
Dr2 = ctx32.Dr2;
|
||||
Dr3 = ctx32.Dr3;
|
||||
Dr6 = ctx32.Dr6;
|
||||
Dr7 = ctx32.Dr7;
|
||||
SegGs = static_cast<uint16_t>(ctx32.SegGs);
|
||||
SegFs = static_cast<uint16_t>(ctx32.SegFs);
|
||||
SegEs = static_cast<uint16_t>(ctx32.SegEs);
|
||||
SegDs = static_cast<uint16_t>(ctx32.SegDs);
|
||||
SegCs = static_cast<uint16_t>(ctx32.SegCs);
|
||||
SegSs = static_cast<uint16_t>(ctx32.SegSs);
|
||||
Rdi = ctx32.Edi;
|
||||
Rsi = ctx32.Esi;
|
||||
Rbx = ctx32.Ebx;
|
||||
Rdx = ctx32.Edx;
|
||||
Rcx = ctx32.Ecx;
|
||||
Rax = ctx32.Eax;
|
||||
Rbp = ctx32.Ebp;
|
||||
Rip = ctx32.Eip;
|
||||
Rsp = ctx32.Esp;
|
||||
EFlags = ctx32.EFlags;
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
#ifndef CONTEXT_AMD64
|
||||
#define CONTEXT_AMD64 0x100000
|
||||
#endif
|
||||
|
||||
#define CONTEXT64_CONTROL (CONTEXT_AMD64 | 0x1L)
|
||||
#define CONTEXT64_INTEGER (CONTEXT_AMD64 | 0x2L)
|
||||
#define CONTEXT64_SEGMENTS (CONTEXT_AMD64 | 0x4L)
|
||||
#define CONTEXT64_FLOATING_POINT (CONTEXT_AMD64 | 0x8L)
|
||||
#define CONTEXT64_DEBUG_REGISTERS (CONTEXT_AMD64 | 0x10L)
|
||||
#define CONTEXT64_FULL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_FLOATING_POINT)
|
||||
#define CONTEXT64_ALL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_SEGMENTS | CONTEXT64_FLOATING_POINT | CONTEXT64_DEBUG_REGISTERS)
|
||||
#define CONTEXT64_XSTATE (CONTEXT_AMD64 | 0x20L)
|
||||
|
||||
template<typename T>
|
||||
struct _PEB_LDR_DATA2_T
|
||||
{
|
||||
uint32_t Length;
|
||||
uint8_t Initialized;
|
||||
T SsHandle;
|
||||
_LIST_ENTRY_T<T> InLoadOrderModuleList;
|
||||
_LIST_ENTRY_T<T> InMemoryOrderModuleList;
|
||||
_LIST_ENTRY_T<T> InInitializationOrderModuleList;
|
||||
T EntryInProgress;
|
||||
uint8_t ShutdownInProgress;
|
||||
T ShutdownThreadId;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _LDR_DATA_TABLE_ENTRY_BASE_T
|
||||
{
|
||||
_LIST_ENTRY_T<T> InLoadOrderLinks;
|
||||
_LIST_ENTRY_T<T> InMemoryOrderLinks;
|
||||
_LIST_ENTRY_T<T> InInitializationOrderLinks;
|
||||
T DllBase;
|
||||
T EntryPoint;
|
||||
uint32_t SizeOfImage;
|
||||
_UNICODE_STRING_T<T> FullDllName;
|
||||
_UNICODE_STRING_T<T> BaseDllName;
|
||||
uint32_t Flags;
|
||||
uint16_t LoadCount;
|
||||
uint16_t TlsIndex;
|
||||
_LIST_ENTRY_T<T> HashLinks;
|
||||
uint32_t TimeDateStamp;
|
||||
T EntryPointActivationContext;
|
||||
T PatchInformation;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _RTL_INVERTED_FUNCTION_TABLE_ENTRY
|
||||
{
|
||||
T ExceptionDirectory; // PIMAGE_RUNTIME_FUNCTION_ENTRY
|
||||
T ImageBase;
|
||||
uint32_t ImageSize;
|
||||
uint32_t SizeOfTable;
|
||||
};
|
||||
|
||||
using _UNICODE_STRING32 = _UNICODE_STRING_T<uint32_t>;
|
||||
using _UNICODE_STRING64 = _UNICODE_STRING_T<uint64_t>;
|
||||
using UNICODE_STRING_T = _UNICODE_STRING_T<uintptr_t>;
|
||||
|
||||
using _PEB32 = _PEB_T<uint32_t>;
|
||||
using _PEB64 = _PEB_T<uint64_t>;
|
||||
using PEB_T = _PEB_T<uintptr_t>;
|
||||
|
||||
using _TEB32 = _TEB_T<uint32_t>;
|
||||
using _TEB64 = _TEB_T<uint64_t>;
|
||||
using TEB_T = _TEB_T<uintptr_t>;
|
||||
|
||||
using _PEB_LDR_DATA232 = _PEB_LDR_DATA2_T<uint32_t>;
|
||||
using _PEB_LDR_DATA264 = _PEB_LDR_DATA2_T<uint64_t>;
|
||||
using PEB_LDR_DATA_T = _PEB_LDR_DATA2_T<uintptr_t>;
|
||||
|
||||
using _LDR_DATA_TABLE_ENTRY_BASE32 = _LDR_DATA_TABLE_ENTRY_BASE_T<uint32_t>;
|
||||
using _LDR_DATA_TABLE_ENTRY_BASE64 = _LDR_DATA_TABLE_ENTRY_BASE_T<uint64_t>;
|
||||
using LDR_DATA_TABLE_ENTRY_BASE_T = _LDR_DATA_TABLE_ENTRY_BASE_T<uintptr_t>;
|
||||
|
||||
using _CONTEXT32 = _CONTEXT_T<uint32_t>;
|
||||
using _CONTEXT64 = _CONTEXT_T<uint64_t>;
|
||||
using CONTEXT_T = _CONTEXT_T<uintptr_t>;
|
||||
|
||||
using _SECTION_BASIC_INFORMATION32 = _SECTION_BASIC_INFORMATION_T<uint32_t>;
|
||||
using _SECTION_BASIC_INFORMATION64 = _SECTION_BASIC_INFORMATION_T<uint64_t>;
|
||||
using SECTION_BASIC_INFORMATION_T = _SECTION_BASIC_INFORMATION_T<uintptr_t>;
|
||||
|
||||
using _SYSTEM_HANDLE_INFORMATION32 = _SYSTEM_HANDLE_INFORMATION_T<uint32_t>;
|
||||
using _SYSTEM_HANDLE_INFORMATION64 = _SYSTEM_HANDLE_INFORMATION_T<uint64_t>;
|
||||
using SYSTEM_HANDLE_INFORMATION_T = _SYSTEM_HANDLE_INFORMATION_T<uintptr_t>;
|
||||
|
||||
using _OBJECT_TYPE_INFORMATION32 = _OBJECT_TYPE_INFORMATION_T<uint32_t>;
|
||||
using _OBJECT_TYPE_INFORMATION64 = _OBJECT_TYPE_INFORMATION_T<uint64_t>;
|
||||
using OBJECT_TYPE_INFORMATION_T = _OBJECT_TYPE_INFORMATION_T<uintptr_t>;
|
||||
|
||||
using _OBJECT_ATTRIBUTES32 = _OBJECT_ATTRIBUTES_T<uint32_t>;
|
||||
using _OBJECT_ATTRIBUTES64 = _OBJECT_ATTRIBUTES_T<uint64_t>;
|
||||
using OBJECT_ATTRIBUTES_T = _OBJECT_ATTRIBUTES_T<uintptr_t>;
|
||||
|
||||
using _ACTCTXW32 = _ACTCTXW_T<uint32_t>;
|
||||
using _ACTCTXW64 = _ACTCTXW_T<uint64_t>;
|
||||
using ACTCTXW_T = _ACTCTXW_T<uintptr_t>;
|
||||
}
|
||||
|
||||
#include "ApiSet.h"
|
||||
|
||||
// OS specific structures
|
||||
#include "Win7Specific.h"
|
||||
#include "Win8Specific.h"
|
||||
|
||||
#ifdef XP_BUILD
|
||||
#include "WinXPSpecific.h"
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include "NativeStructures.h"
|
||||
#include "FunctionTypes.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
using ptr_t = uint64_t; // Generic pointer in remote process
|
||||
using module_t = ptr_t; // Module base pointer
|
||||
|
||||
// Type of barrier
|
||||
enum eBarrier
|
||||
{
|
||||
wow_32_32 = 0, // Both processes are WoW64
|
||||
wow_64_64, // Both processes are x64
|
||||
wow_32_64, // Managing x64 process from WoW64 process
|
||||
wow_64_32, // Managing WOW64 process from x64 process
|
||||
};
|
||||
|
||||
struct Wow64Barrier
|
||||
{
|
||||
eBarrier type = wow_32_32;
|
||||
bool sourceWow64 = false;
|
||||
bool targetWow64 = false;
|
||||
bool x86OS = false;
|
||||
bool mismatch = false;
|
||||
};
|
||||
|
||||
// Module type
|
||||
enum eModType
|
||||
{
|
||||
mt_mod32, // 32 bit module
|
||||
mt_mod64, // 64 bit module
|
||||
mt_default, // type is deduced from target process
|
||||
mt_unknown // Failed to detect type
|
||||
};
|
||||
|
||||
// Module search method
|
||||
enum eModSeachType
|
||||
{
|
||||
LdrList, // InLoadOrder list
|
||||
Sections, // Scan for section objects
|
||||
PEHeaders, // Scan for PE headers in memory
|
||||
};
|
||||
|
||||
// Switch created wow64 thread to long mode
|
||||
enum eThreadModeSwitch
|
||||
{
|
||||
NoSwitch, // Never switch
|
||||
ForceSwitch, // Always switch
|
||||
AutoSwitch // Switch depending on wow64 barrier
|
||||
};
|
||||
|
||||
// Module info
|
||||
struct ModuleData
|
||||
{
|
||||
module_t baseAddress; // Base image address
|
||||
std::wstring name; // File name
|
||||
std::wstring fullPath; // Full file path
|
||||
uint32_t size; // Size of image
|
||||
eModType type; // Module type
|
||||
ptr_t ldrPtr; // LDR_DATA_TABLE_ENTRY_BASE_T address
|
||||
bool manual; // Image is manually mapped
|
||||
|
||||
|
||||
bool operator ==(const ModuleData& other) const
|
||||
{
|
||||
return (baseAddress == other.baseAddress);
|
||||
}
|
||||
|
||||
bool operator <(const ModuleData& other)
|
||||
{
|
||||
return baseAddress < other.baseAddress;
|
||||
}
|
||||
};
|
||||
|
||||
using ModuleDataPtr = std::shared_ptr<const ModuleData>;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "Winheaders.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
template<typename T>
|
||||
struct _LDR_DATA_TABLE_ENTRY_W7 : _LDR_DATA_TABLE_ENTRY_BASE_T<T>
|
||||
{
|
||||
_LIST_ENTRY_T<T> ForwarderLinks;
|
||||
_LIST_ENTRY_T<T> ServiceTagLinks;
|
||||
_LIST_ENTRY_T<T> StaticLinks;
|
||||
T ContextInformation;
|
||||
uint32_t OriginalBase;
|
||||
LARGE_INTEGER LoadTime;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _RTL_INVERTED_FUNCTION_TABLE7
|
||||
{
|
||||
uint32_t Count;
|
||||
uint32_t MaxCount;
|
||||
uint32_t Epoch;
|
||||
_RTL_INVERTED_FUNCTION_TABLE_ENTRY<T> Entries[0x200];
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include "Winheaders.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
struct _RTL_RB_TREE
|
||||
{
|
||||
T Root;
|
||||
T Min;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _RTL_BALANCED_NODE
|
||||
{
|
||||
T Left;
|
||||
T Right;
|
||||
T ParentValue;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _LDR_DDAG_NODE
|
||||
{
|
||||
_LIST_ENTRY_T<T> Modules;
|
||||
T ServiceTagList;
|
||||
uint32_t LoadCount;
|
||||
uint32_t ReferenceCount;
|
||||
uint32_t DependencyCount;
|
||||
T RemovalLink;
|
||||
T IncomingDependencies;
|
||||
_LDR_DDAG_STATE State;
|
||||
T CondenseLink;
|
||||
uint32_t PreorderNumber;
|
||||
uint32_t LowestLink;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _LDR_DATA_TABLE_ENTRY_W8 : _LDR_DATA_TABLE_ENTRY_BASE_T<T>
|
||||
{
|
||||
T DdagNode; // _LDR_DDAG_NODE*
|
||||
_LIST_ENTRY_T<T> NodeModuleLink;
|
||||
T SnapContext;
|
||||
T ParentDllBase;
|
||||
T SwitchBackContext;
|
||||
_RTL_BALANCED_NODE<T> BaseAddressIndexNode;
|
||||
_RTL_BALANCED_NODE<T> MappingInfoIndexNode;
|
||||
T OriginalBase;
|
||||
LARGE_INTEGER LoadTime;
|
||||
uint32_t BaseNameHashValue;
|
||||
_LDR_DLL_LOAD_REASON LoadReason;
|
||||
uint32_t ImplicitPathOptions;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _RTL_INVERTED_FUNCTION_TABLE8
|
||||
{
|
||||
ULONG Count;
|
||||
ULONG MaxCount;
|
||||
ULONG Epoch;
|
||||
UCHAR Overflow;
|
||||
_RTL_INVERTED_FUNCTION_TABLE_ENTRY<T> Entries[0x200];
|
||||
};
|
||||
|
||||
using _LDR_DATA_TABLE_ENTRY_W832 = _LDR_DATA_TABLE_ENTRY_W8<uint32_t>;
|
||||
using _LDR_DATA_TABLE_ENTRY_W864 = _LDR_DATA_TABLE_ENTRY_W8<uint64_t>;
|
||||
using LDR_DATA_TABLE_ENTRY_W8T = _LDR_DATA_TABLE_ENTRY_W8<uintptr_t>;
|
||||
|
||||
using _LDR_DDAG_NODE_32 = _LDR_DDAG_NODE<uint32_t>;
|
||||
using _LDR_DDAG_NODE_64 = _LDR_DDAG_NODE<uint64_t>;
|
||||
using LDR_DDAG_NODE_T = _LDR_DDAG_NODE<uintptr_t>;
|
||||
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "Winheaders.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201)
|
||||
typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR
|
||||
{
|
||||
union
|
||||
{
|
||||
DWORD AllAttributes;
|
||||
struct {
|
||||
DWORD RvaBased : 1; // Delay load version 2
|
||||
DWORD ReservedAttributes : 31;
|
||||
};
|
||||
} Attributes;
|
||||
|
||||
DWORD DllNameRVA; // RVA to the name of the target library (NULL-terminate ASCII string)
|
||||
DWORD ModuleHandleRVA; // RVA to the HMODULE caching location (PHMODULE)
|
||||
DWORD ImportAddressTableRVA; // RVA to the start of the IAT (PIMAGE_THUNK_DATA)
|
||||
DWORD ImportNameTableRVA; // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData)
|
||||
DWORD BoundImportAddressTableRVA; // RVA to an optional bound IAT
|
||||
DWORD UnloadInformationTableRVA; // RVA to an optional unload info table
|
||||
DWORD TimeDateStamp; // 0 if not bound, Otherwise, date/time of the target DLL
|
||||
} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;
|
||||
#pragma warning(pop)
|
||||
|
||||
typedef struct _EXCEPTION_REGISTRATION_RECORD
|
||||
{
|
||||
_EXCEPTION_REGISTRATION_RECORD *Next;
|
||||
PEXCEPTION_ROUTINE Handler;
|
||||
} EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <winternl.h>
|
||||
#include <winioctl.h>
|
||||
#include <TlHelp32.h>
|
||||
#include <Shlwapi.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#include <ntstatus.h>
|
||||
#pragma warning(pop)
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename R, typename... Args, class C>
|
||||
struct HookHandler<R( __cdecl* )(Args...), C> : public DetourBase
|
||||
{
|
||||
using ReturnType = std::conditional_t<std::is_same_v<R, void>, int, R>;
|
||||
|
||||
using type = R( __cdecl* )(Args...);
|
||||
using hktype = R( __cdecl* )(Args&...);
|
||||
using hktypeC = R( C::* )(Args&...);
|
||||
|
||||
//
|
||||
// Workaround for void return type
|
||||
//
|
||||
using typeR = ReturnType( __cdecl* )(Args...);
|
||||
using hktypeR = ReturnType( __cdecl* )(Args&...);
|
||||
using hktypeCR = ReturnType( C::* )(Args&...);
|
||||
|
||||
static __declspec(noinline) ReturnType __cdecl Handler( Args... args )
|
||||
{
|
||||
HookHandler* pInst = (HookHandler*)((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer;
|
||||
return pInst->HandlerP( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
ReturnType HandlerP( Args&&... args )
|
||||
{
|
||||
ReturnType val_new, val_original;
|
||||
|
||||
DisableHook();
|
||||
|
||||
if (_order == CallOrder::HookFirst)
|
||||
{
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
}
|
||||
else if (_order == CallOrder::HookLast)
|
||||
{
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
else
|
||||
{
|
||||
val_original = val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
if (this->_hooked)
|
||||
EnableHook();
|
||||
|
||||
return (_retType == ReturnMethod::UseOriginal ? val_original : val_new);
|
||||
}
|
||||
|
||||
inline ReturnType CallOriginal( Args&&... args )
|
||||
{
|
||||
return (reinterpret_cast<typeR>(_callOriginal))(args...);
|
||||
}
|
||||
|
||||
inline ReturnType CallCallback( Args&&... args )
|
||||
{
|
||||
if (_callbackClass != nullptr)
|
||||
return (reinterpret_cast<C*>(_callbackClass)->*brutal_cast<hktypeCR>(_callback))(args...);
|
||||
else
|
||||
return (reinterpret_cast<hktypeR>(_callback))(args...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename R, typename... Args, class C>
|
||||
struct HookHandler<R( __fastcall* )(Args...), C> : public DetourBase
|
||||
{
|
||||
using ReturnType = std::conditional_t<std::is_same_v<R, void>, int, R>;
|
||||
|
||||
using type = R( __fastcall* )(Args...);
|
||||
using hktype = R( __fastcall* )(Args&...);
|
||||
using hktypeC = R( C::* )(Args&...);
|
||||
|
||||
//
|
||||
// Workaround for void return type
|
||||
//
|
||||
using typeR = ReturnType( __fastcall* )(Args...);
|
||||
using hktypeR = ReturnType( __fastcall* )(Args&...);
|
||||
using hktypeCR = ReturnType( C::* )(Args&...);
|
||||
|
||||
static __declspec(noinline) ReturnType __fastcall Handler( Args... args )
|
||||
{
|
||||
HookHandler* pInst = (HookHandler*)((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer;
|
||||
return pInst->HandlerP( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
ReturnType HandlerP( Args&&... args )
|
||||
{
|
||||
ReturnType val_new, val_original;
|
||||
|
||||
DisableHook();
|
||||
|
||||
if (_order == CallOrder::HookFirst)
|
||||
{
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
}
|
||||
else if (_order == CallOrder::HookLast)
|
||||
{
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
else
|
||||
{
|
||||
val_original = val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
if (this->_hooked)
|
||||
EnableHook();
|
||||
|
||||
return (_retType == ReturnMethod::UseOriginal ? val_original : val_new);
|
||||
}
|
||||
|
||||
inline ReturnType CallOriginal( Args&&... args )
|
||||
{
|
||||
return (reinterpret_cast<typeR>(_callOriginal))(args...);
|
||||
}
|
||||
|
||||
inline ReturnType CallCallback( Args&&... args )
|
||||
{
|
||||
if (_callbackClass != nullptr)
|
||||
return ((C*)_callbackClass->*brutal_cast<hktypeCR>(_callback))(args...);
|
||||
else
|
||||
return (reinterpret_cast<hktypeR>(_callback))(args...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename R, typename... Args, class C>
|
||||
struct HookHandler<R( __stdcall* )(Args...), C> : public DetourBase
|
||||
{
|
||||
using ReturnType = std::conditional_t<std::is_same_v<R, void>, int, R>;
|
||||
|
||||
using type = R( __stdcall* )(Args...);
|
||||
using hktype = R( __stdcall* )(Args&...);
|
||||
using hktypeC = R( C::* )(Args&...);
|
||||
|
||||
//
|
||||
// Workaround for void return type
|
||||
//
|
||||
using typeR = ReturnType( __stdcall* )(Args...);
|
||||
using hktypeR = ReturnType( __stdcall* )(Args&...);
|
||||
using hktypeCR = ReturnType( C::* )(Args&...);
|
||||
|
||||
static __declspec(noinline) ReturnType __stdcall Handler( Args... args )
|
||||
{
|
||||
HookHandler* pInst = (HookHandler*)((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer;
|
||||
return pInst->HandlerP( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
ReturnType HandlerP( Args&&... args )
|
||||
{
|
||||
ReturnType val_new, val_original;
|
||||
|
||||
DisableHook();
|
||||
|
||||
if (_order == CallOrder::HookFirst)
|
||||
{
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
}
|
||||
else if (_order == CallOrder::HookLast)
|
||||
{
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
else
|
||||
{
|
||||
val_original = val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
if (this->_hooked)
|
||||
EnableHook();
|
||||
|
||||
return (_retType == ReturnMethod::UseOriginal ? val_original : val_new);
|
||||
}
|
||||
|
||||
inline ReturnType CallOriginal( Args&&... args )
|
||||
{
|
||||
return (reinterpret_cast<typeR>(_callOriginal))(args...);
|
||||
}
|
||||
|
||||
inline ReturnType CallCallback( Args&&... args )
|
||||
{
|
||||
if (_callbackClass != nullptr)
|
||||
return ((C*)_callbackClass->*brutal_cast<hktypeCR>(_callback))(args...);
|
||||
else
|
||||
return (reinterpret_cast<hktypeR>(_callback))(args...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename R, typename... Args, class C>
|
||||
struct HookHandler<R( __thiscall* )(Args...), C> : public DetourBase
|
||||
{
|
||||
using ReturnType = std::conditional_t<std::is_same_v<R, void>, int, R>;
|
||||
|
||||
using type = R( __thiscall* )(Args...);
|
||||
using hktype = R( __stdcall* )(Args&...);
|
||||
using hktypeC = R( C::* )(Args&...);
|
||||
|
||||
//
|
||||
// Workaround for void return type
|
||||
//
|
||||
using typeR = ReturnType( __thiscall* )(Args...);
|
||||
using hktypeR = ReturnType( __stdcall* )(Args&...);
|
||||
using hktypeCR = ReturnType( C::* )(Args&...);
|
||||
|
||||
static __declspec(noinline) ReturnType __thiscall Handler( Args... args )
|
||||
{
|
||||
HookHandler* pInst = (HookHandler*)((_NT_TIB*)NtCurrentTeb())->ArbitraryUserPointer;
|
||||
return pInst->HandlerP( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
ReturnType HandlerP( Args&&... args )
|
||||
{
|
||||
ReturnType val_new, val_original;
|
||||
|
||||
DisableHook();
|
||||
|
||||
if (_order == CallOrder::HookFirst)
|
||||
{
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
}
|
||||
else if (_order == CallOrder::HookLast)
|
||||
{
|
||||
val_original = CallOriginal( std::forward<Args>( args )... );
|
||||
val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
else
|
||||
{
|
||||
val_original = val_new = CallCallback( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
if (this->_hooked)
|
||||
EnableHook();
|
||||
|
||||
return (_retType == ReturnMethod::UseOriginal ? val_original : val_new);
|
||||
}
|
||||
|
||||
inline ReturnType CallOriginal( Args&&... args )
|
||||
{
|
||||
return (reinterpret_cast<typeR>(_callOriginal))( args...);
|
||||
}
|
||||
|
||||
inline ReturnType CallCallback( Args&&... args )
|
||||
{
|
||||
if (_callbackClass != nullptr)
|
||||
return ((C*)_callbackClass->*brutal_cast<hktypeCR>(_callback))( args...);
|
||||
else
|
||||
return (reinterpret_cast<hktypeR>(_callback))( args...);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "LocalHookBase.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
class BLACKBONE_API NoClass { };
|
||||
|
||||
template<typename Fn, class C>
|
||||
struct HookHandler;
|
||||
}
|
||||
|
||||
#include "HookHandlerCdecl.h"
|
||||
|
||||
#ifndef USE64
|
||||
#include "HookHandlerStdcall.h"
|
||||
#include "HookHandlerThiscall.h"
|
||||
#include "HookHandlerFastcall.h"
|
||||
#endif
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
#pragma once
|
||||
|
||||
#include "HookHandlers.h"
|
||||
#include "../Process/Process.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename Fn, class C = NoClass>
|
||||
class Detour: public HookHandler<Fn, C>
|
||||
{
|
||||
public:
|
||||
using type = typename HookHandler<Fn, C>::type;
|
||||
using hktype = typename HookHandler<Fn, C>::hktype;
|
||||
using hktypeC = typename HookHandler<Fn, C>::hktypeC;
|
||||
|
||||
public:
|
||||
Detour()
|
||||
{
|
||||
this->_internalHandler = &HookHandler<Fn, C>::Handler;
|
||||
}
|
||||
|
||||
~Detour()
|
||||
{
|
||||
Restore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hook function
|
||||
/// </summary>
|
||||
/// <param name="ptr">Target function address</param>
|
||||
/// <param name="hkPtr">Hook function address</param>
|
||||
/// <param name="type">Hooking method</param>
|
||||
/// <param name="order">Call order. Hook before original or vice versa</param>
|
||||
/// <param name="retType">Return value. Use origianl or value from hook</param>
|
||||
/// <returns>true on success</returns>
|
||||
bool Hook(
|
||||
type ptr,
|
||||
hktype hkPtr,
|
||||
HookType::e type,
|
||||
CallOrder::e order = CallOrder::HookFirst,
|
||||
ReturnMethod::e retType = ReturnMethod::UseOriginal
|
||||
)
|
||||
{
|
||||
if (this->_hooked)
|
||||
return false;
|
||||
|
||||
this->_type = type;
|
||||
this->_order = order;
|
||||
this->_retType = retType;
|
||||
this->_callOriginal = this->_original = ptr;
|
||||
this->_callback = hkPtr;
|
||||
|
||||
if (!DetourBase::AllocateBuffer( reinterpret_cast<uint8_t*>(ptr) ))
|
||||
return false;
|
||||
|
||||
switch (this->_type)
|
||||
{
|
||||
case HookType::Inline:
|
||||
return HookInline();
|
||||
|
||||
case HookType::Int3:
|
||||
return HookInt3();
|
||||
|
||||
case HookType::HWBP:
|
||||
return HookHWBP();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hook function
|
||||
/// </summary>
|
||||
/// <param name="Ptr">Target function address</param>
|
||||
/// <param name="hkPtr">Hook class member address</param>
|
||||
/// <param name="pClass">Hook class address</param>
|
||||
/// <param name="type">Hooking method</param>
|
||||
/// <param name="order">Call order. Hook before original or vice versa</param>
|
||||
/// <param name="retType">Return value. Use origianl or value from hook</param>
|
||||
/// <returns>true on success</returns>
|
||||
bool Hook(
|
||||
type Ptr,
|
||||
hktypeC hkPtr,
|
||||
C* pClass,
|
||||
HookType::e type,
|
||||
CallOrder::e order = CallOrder::HookFirst,
|
||||
ReturnMethod::e retType = ReturnMethod::UseOriginal
|
||||
)
|
||||
{
|
||||
this->_callbackClass = pClass;
|
||||
return Hook( Ptr, brutal_cast<hktype>(hkPtr), type, order, retType );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Restore hooked function
|
||||
/// </summary>
|
||||
/// <returns>true on success, false if not hooked</returns>
|
||||
bool Restore()
|
||||
{
|
||||
if (!this->_hooked)
|
||||
return false;
|
||||
|
||||
switch (this->_type)
|
||||
{
|
||||
case HookType::Inline:
|
||||
case HookType::InternalInline:
|
||||
case HookType::Int3:
|
||||
{
|
||||
DWORD flOld = 0;
|
||||
if (!VirtualProtect(this->_original, this->_origSize, PAGE_EXECUTE_READWRITE, &flOld))
|
||||
return false;
|
||||
memcpy(this->_original, this->_origCode, this->_origSize);
|
||||
VirtualProtect(this->_original, this->_origSize, flOld, &flOld);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case HookType::HWBP:
|
||||
{
|
||||
Process thisProc;
|
||||
thisProc.Attach( GetCurrentProcessId() );
|
||||
|
||||
for (auto& thd : thisProc.threads().getAll())
|
||||
thd->RemoveHWBP( reinterpret_cast<ptr_t>(this->_original) );
|
||||
|
||||
this->_hwbpIdx.clear();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this->_hooked = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// <summary>
|
||||
/// Perform inline hook
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
bool HookInline()
|
||||
{
|
||||
auto jmpToHook = AsmFactory::GetAssembler();
|
||||
auto jmpToThunk = AsmFactory::GetAssembler();
|
||||
|
||||
//
|
||||
// Construct jump to thunk
|
||||
//
|
||||
#ifdef USE64
|
||||
(*jmpToThunk)->mov( asmjit::host::rax, (uint64_t)this->_buf );
|
||||
(*jmpToThunk)->jmp( asmjit::host::rax );
|
||||
|
||||
this->_origSize = (*jmpToThunk)->getCodeSize();
|
||||
#else
|
||||
(*jmpToThunk)->jmp( (asmjit::Ptr)this->_buf );
|
||||
this->_origSize = (*jmpToThunk)->getCodeSize();
|
||||
#endif
|
||||
|
||||
DetourBase::CopyOldCode( (uint8_t*)this->_original );
|
||||
|
||||
// Construct jump to hook handler
|
||||
#ifdef USE64
|
||||
// mov gs:[0x28], this
|
||||
(*jmpToHook)->mov( asmjit::host::rax, (uint64_t)this );
|
||||
(*jmpToHook)->mov( asmjit::host::qword_ptr_abs( 0x28 ).setSegment( asmjit::host::gs ), asmjit::host::rax );
|
||||
#else
|
||||
// mov fs:[0x14], this
|
||||
(*jmpToHook)->mov( asmjit::host::dword_ptr_abs( 0x14 ).setSegment( asmjit::host::fs ) , (uint32_t)this );
|
||||
#endif // USE64
|
||||
|
||||
(*jmpToHook)->jmp( (asmjit::Ptr)&HookHandler<Fn, C>::Handler );
|
||||
(*jmpToHook)->relocCode( this->_buf );
|
||||
|
||||
(*jmpToThunk)->setBaseAddress( (uintptr_t)this->_original );
|
||||
auto codeSize = (*jmpToThunk)->relocCode( this->_newCode );
|
||||
|
||||
DWORD flOld = 0;
|
||||
if (!VirtualProtect( this->_original, codeSize, PAGE_EXECUTE_READWRITE, &flOld ))
|
||||
return false;
|
||||
|
||||
memcpy( this->_original, this->_newCode, codeSize );
|
||||
|
||||
VirtualProtect( this->_original, codeSize, flOld, &flOld );
|
||||
|
||||
this->_hooked = (codeSize != 0);
|
||||
return this->_hooked;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform int3 hook
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
bool HookInt3()
|
||||
{
|
||||
this->_newCode[0] = 0xCC;
|
||||
this->_origSize = sizeof( this->_newCode[0] );
|
||||
|
||||
// Setup handler
|
||||
if (this->_vecHandler == nullptr)
|
||||
this->_vecHandler = AddVectoredExceptionHandler( 1, &DetourBase::VectoredHandler );
|
||||
|
||||
if (!this->_vecHandler)
|
||||
return false;
|
||||
|
||||
this->_breakpoints.insert( std::make_pair( this->_original, (DetourBase*)this ) );
|
||||
|
||||
// Save original code
|
||||
memcpy( this->_origCode, this->_original, this->_origSize );
|
||||
|
||||
// Write break instruction
|
||||
DWORD flOld = 0;
|
||||
if (!VirtualProtect(this->_original, this->_origSize, PAGE_EXECUTE_READWRITE, &flOld))
|
||||
return false;
|
||||
memcpy( this->_original, this->_newCode, this->_origSize );
|
||||
VirtualProtect( this->_original, this->_origSize, flOld, &flOld );
|
||||
|
||||
return this->_hooked = TRUE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform hardware breakpoint hook
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
bool HookHWBP()
|
||||
{
|
||||
Process thisProc;
|
||||
thisProc.Attach( GetCurrentProcessId() );
|
||||
|
||||
// Setup handler
|
||||
if (this->_vecHandler == nullptr)
|
||||
this->_vecHandler = AddVectoredExceptionHandler( 1, &DetourBase::VectoredHandler );
|
||||
|
||||
if (!this->_vecHandler)
|
||||
return false;
|
||||
|
||||
this->_breakpoints.insert( std::make_pair( this->_original, (DetourBase*)this ) );
|
||||
|
||||
// Add breakpoint to every thread
|
||||
for (auto& thd : thisProc.threads().getAll())
|
||||
this->_hwbpIdx[thd->id()] = thd->AddHWBP( reinterpret_cast<ptr_t>(this->_original), hwbp_execute, hwbp_1 ).result();
|
||||
|
||||
return this->_hooked = true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Config.h"
|
||||
#include "../Include/Winheaders.h"
|
||||
#include "../Asm/AsmFactory.h"
|
||||
#include "../Asm/LDasm.h"
|
||||
#include "../Include/Macro.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
namespace CallOrder
|
||||
{
|
||||
enum e
|
||||
{
|
||||
HookFirst, // Hook called before original function
|
||||
HookLast, // Hook called after original function
|
||||
NoOriginal, // Original function doesn't get called
|
||||
};
|
||||
}
|
||||
|
||||
namespace HookType
|
||||
{
|
||||
enum e
|
||||
{
|
||||
Inline, // Patch first few bytes
|
||||
Int3, // Place Int3 breakpoint
|
||||
HWBP, // Set hardware breakpoint
|
||||
|
||||
// Reserved for internal use
|
||||
VTable,
|
||||
InternalInline
|
||||
};
|
||||
}
|
||||
|
||||
namespace ReturnMethod
|
||||
{
|
||||
enum e
|
||||
{
|
||||
UseNew, // Return value returned by hook
|
||||
UseOriginal // Return original function value
|
||||
};
|
||||
}
|
||||
|
||||
class DetourBase
|
||||
{
|
||||
using mapIdx = std::unordered_map<DWORD, int>;
|
||||
|
||||
public:
|
||||
BLACKBONE_API DetourBase();
|
||||
BLACKBONE_API ~DetourBase();
|
||||
|
||||
protected:
|
||||
|
||||
/// <summary>
|
||||
/// Allocate detour buffer as close to target as possible
|
||||
/// </summary>
|
||||
/// <param name="nearest">Target address</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool AllocateBuffer( uint8_t* nearest );
|
||||
|
||||
/// <summary>
|
||||
/// Temporarily disable hook
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool DisableHook();
|
||||
|
||||
/// <summary>
|
||||
/// Enable disabled hook
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool EnableHook();
|
||||
|
||||
/// <summary>
|
||||
/// Toggle hardware breakpoint for current thread
|
||||
/// </summary>
|
||||
/// <param name="index">Breakpoint index ( 0-4 )</param>
|
||||
/// <param name="enable">true to enable, false to disable</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool ToggleHBP( int index, bool enable );
|
||||
|
||||
/// <summary>
|
||||
/// Copy original function bytes
|
||||
/// </summary>
|
||||
/// <param name="Ptr">Origianl function address</param>
|
||||
BLACKBONE_API void CopyOldCode( uint8_t* Ptr );
|
||||
|
||||
/// <summary>
|
||||
/// Exception handlers
|
||||
/// </summary>
|
||||
/// <param name="excpt">Exception information</param>
|
||||
/// <returns>Exception disposition</returns>
|
||||
BLACKBONE_API static LONG NTAPI VectoredHandler ( PEXCEPTION_POINTERS excpt );
|
||||
BLACKBONE_API static LONG NTAPI Int3Handler ( PEXCEPTION_POINTERS excpt );
|
||||
BLACKBONE_API static LONG NTAPI AVHandler ( PEXCEPTION_POINTERS excpt );
|
||||
BLACKBONE_API static LONG NTAPI StepHandler ( PEXCEPTION_POINTERS excpt );
|
||||
|
||||
protected:
|
||||
bool _hooked = false; // Hook is installed
|
||||
|
||||
void* _callback = nullptr; // User supplied hook function
|
||||
void* _callbackClass = nullptr; // Class pointer for user hook
|
||||
void* _original = nullptr; // Original function address
|
||||
void* _internalHandler = nullptr; // Pointer to hook handler
|
||||
void* _callOriginal = nullptr; // Pointer to original function
|
||||
|
||||
mapIdx _hwbpIdx; // Thread HWBP index
|
||||
size_t _origSize = 0; // Original code size
|
||||
uint8_t* _buf = nullptr; // Trampoline buffer
|
||||
uint8_t* _origCode = nullptr; // Original function bytes
|
||||
uint8_t* _origThunk = nullptr; // Original bytes adjusted for relocation
|
||||
uint8_t* _newCode = nullptr; // Trampoline bytes
|
||||
|
||||
HookType::e _type = HookType::Inline;
|
||||
CallOrder::e _order = CallOrder::HookFirst;
|
||||
ReturnMethod::e _retType = ReturnMethod::UseOriginal;
|
||||
|
||||
// Global hook instances relationship
|
||||
BLACKBONE_API static std::unordered_map<void*, DetourBase*> _breakpoints;
|
||||
|
||||
// Exception handler
|
||||
BLACKBONE_API static void* _vecHandler;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Include/WinHeaders.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
enum TraceState
|
||||
{
|
||||
TS_Start, // Initial state. Internal use only
|
||||
TS_Step, // Do single-step
|
||||
TS_StepOut, // Break on function return
|
||||
TS_StepInto, // Step into specific function
|
||||
TS_WaitReturn, // Wait for break-on-return
|
||||
};
|
||||
|
||||
struct PathNode
|
||||
{
|
||||
TraceState action;
|
||||
uintptr_t arg;
|
||||
|
||||
PathNode( TraceState _action, uintptr_t _arg = 0 )
|
||||
: action( _action )
|
||||
, arg( _arg ) { }
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Hook-related data
|
||||
/// </summary>
|
||||
struct HookContext
|
||||
{
|
||||
using mapHooks = std::unordered_map<uintptr_t, std::pair<uintptr_t, bool>>;
|
||||
using vecState = std::vector<PathNode>;
|
||||
|
||||
uintptr_t lastIP = 0; // Previous EIP/RIP value
|
||||
uintptr_t lastSP = 0; // Previous ESP/RSP value
|
||||
uintptr_t targetPtr = 0; // Address causing exception
|
||||
uintptr_t origPtrVal = 0; // Original pointer value
|
||||
uintptr_t checkIP = 0; // Address of instruction that checks target pointer
|
||||
uintptr_t breakValue = 0; // Value used to generate exception
|
||||
uintptr_t stateIdx = 0; // Current state index in state vector
|
||||
|
||||
TraceState state = TS_Start; // Current tracing state
|
||||
vecState tracePath; // Function trace path
|
||||
mapHooks hooks; // List of hooks associated with current pointer
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reset tracing state
|
||||
/// </summary>
|
||||
void reset()
|
||||
{
|
||||
state = TS_Start;
|
||||
lastIP = lastSP = 0;
|
||||
stateIdx = 0;
|
||||
|
||||
// Mark hooks as non-called
|
||||
for (auto& item : hooks)
|
||||
item.second.second = false;
|
||||
}
|
||||
};
|
||||
|
||||
class TraceHook
|
||||
{
|
||||
public:
|
||||
using mapContext = std::map<uintptr_t, HookContext>;
|
||||
using vecStackFrames = std::vector <std::pair<uintptr_t, uintptr_t>>;
|
||||
|
||||
public:
|
||||
~TraceHook();
|
||||
BLACKBONE_API static TraceHook& Instance();
|
||||
|
||||
/// <summary>
|
||||
/// Setup hook
|
||||
/// </summary>
|
||||
/// <param name="targetFunc">Target function to be hooked</param>
|
||||
/// <param name="hookFunc">New function</param>
|
||||
/// <param name="ptrAddress">Address of pointer to destroy</param>
|
||||
/// <param name="tracePath">Function tracing path</param>
|
||||
/// <param name="checkIP">Optional. Address of instruction that checks target pointer</param>
|
||||
/// <returns>true on success, false if already hooked</returns>
|
||||
BLACKBONE_API bool ApplyHook( void* targetFunc,
|
||||
void* hookFunc,
|
||||
void* ptrAddress,
|
||||
const HookContext::vecState& tracePath = HookContext::vecState(),
|
||||
void* checkIP = 0 );
|
||||
|
||||
/// <summary>
|
||||
/// Remove existing hook
|
||||
/// </summary>
|
||||
/// <param name="targetFunc">Target function ptr</param>
|
||||
/// <returns>true on success, false if not found</returns>
|
||||
BLACKBONE_API bool RemoveHook( void* targetFunc );
|
||||
|
||||
private:
|
||||
//
|
||||
// Singleton
|
||||
//
|
||||
TraceHook();
|
||||
TraceHook( const TraceHook& ) = delete;
|
||||
TraceHook& operator =( const TraceHook& ) = delete;
|
||||
|
||||
//
|
||||
// Exception handlers
|
||||
//
|
||||
static LONG __stdcall VecHandler( PEXCEPTION_POINTERS ExceptionInfo );
|
||||
LONG VecHandlerP( PEXCEPTION_POINTERS ExceptionInfo );
|
||||
|
||||
/// <summary>
|
||||
/// Capture stack frames
|
||||
/// </summary>
|
||||
/// <param name="ip">Current instruction pointer</param>
|
||||
/// <param name="sp">Current stack pointer</param>
|
||||
/// <param name="results">Found frames.</param>
|
||||
/// <param name="depth">Frame depth limit</param>
|
||||
/// <returns>Number of found frames</returns>
|
||||
size_t StackBacktrace( uintptr_t ip, uintptr_t sp, vecStackFrames& results, uintptr_t depth = 10 );
|
||||
|
||||
/// <summary>
|
||||
/// Setup exception upon function return
|
||||
/// </summary>
|
||||
/// <param name="ExceptionInfo">The exception information</param>
|
||||
inline void BreakOnReturn( uintptr_t sp );
|
||||
|
||||
/// <summary>
|
||||
/// Check if last instruction caused branching
|
||||
/// </summary>
|
||||
/// <param name="ctx">Current hook info</param>
|
||||
/// <param name="ip">Instruction pointer</param>
|
||||
/// <param name="sp">Stack pointer</param>
|
||||
/// <returns>True if branching has occurred</returns>
|
||||
bool CheckBranching( const HookContext& ctx, uintptr_t ip, uintptr_t sp );
|
||||
|
||||
/// <summary>
|
||||
/// Handle branching
|
||||
/// </summary>
|
||||
/// <param name="ctx">Current hook context</param>
|
||||
/// <param name="exptContex">Thread context</param>
|
||||
void HandleBranch( HookContext& ctx, PCONTEXT exptContex );
|
||||
|
||||
/// <summary>
|
||||
/// Restore original pointer value
|
||||
/// </summary>
|
||||
/// <param name="ctx">The CTX.</param>
|
||||
/// <param name="ExceptionInfo">The exception information</param>
|
||||
/// <returns>true on success, false if no invalid register was found</returns>
|
||||
bool RestorePtr( const HookContext& ctx, PEXCEPTION_POINTERS ExceptionInfo );
|
||||
|
||||
private:
|
||||
PVOID _pExptHandler = nullptr; // Exception handler
|
||||
mapContext _contexts; // Hook contexts
|
||||
uintptr_t _breakPtr = 0x2000; // Exception pointer generator
|
||||
};
|
||||
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
#pragma once
|
||||
|
||||
#include "LocalHook.hpp"
|
||||
#include "../Misc/DynImport.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
template<typename Fn, class C = NoClass>
|
||||
class VTableDetour : public Detour<Fn, C>
|
||||
{
|
||||
public:
|
||||
using type = typename HookHandler<Fn, C>::type;
|
||||
using hktype = typename HookHandler<Fn, C>::hktype;
|
||||
using hktypeC = typename HookHandler<Fn, C>::hktypeC;
|
||||
|
||||
public:
|
||||
VTableDetour()
|
||||
{
|
||||
DetourBase::AllocateBuffer( nullptr );
|
||||
}
|
||||
|
||||
~VTableDetour()
|
||||
{
|
||||
Restore();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hook function in vtable
|
||||
/// </summary>
|
||||
/// <param name="ppVtable">Pointer to vtable pointer</param>
|
||||
/// <param name="index">Function index</param>
|
||||
/// <param name="hkPtr">Hook function address</param>
|
||||
/// <param name="order">Call order. Hook before original or vice versa</param>
|
||||
/// <param name="retType">Return value. Use origianl or value from hook</param>
|
||||
/// <param name="copyVtable">if true, vtable will be copied and edited, otherwise existing vtable will be edited</param>
|
||||
/// <param name="vtableLen">Optional. Valid only when copyVtable is true. Number of function in vtable.
|
||||
/// Used to determine number of function to copy</param>
|
||||
/// <returns>true on success</returns>
|
||||
bool Hook(
|
||||
void** ppVtable,
|
||||
int index,
|
||||
hktype hkPtr,
|
||||
CallOrder::e order = CallOrder::HookFirst,
|
||||
ReturnMethod::e retType = ReturnMethod::UseOriginal,
|
||||
bool copyVtable = false,
|
||||
int vtableLen = 0
|
||||
)
|
||||
{
|
||||
auto jmpToHook = AsmFactory::GetAssembler();
|
||||
|
||||
this->_type = HookType::VTable;
|
||||
this->_order = order;
|
||||
this->_retType = retType;
|
||||
this->_callOriginal = this->_original = (*(void***)ppVtable)[index];
|
||||
this->_callback = hkPtr;
|
||||
this->_internalHandler = &HookHandler<Fn, C>::Handler;
|
||||
this->_ppVtable = ppVtable;
|
||||
this->_pVtable = *ppVtable;
|
||||
this->_vtIndex = index;
|
||||
this->_vtCopied = copyVtable;
|
||||
|
||||
// Construct jump to hook handler
|
||||
#ifdef USE64
|
||||
// mov gs:[0x28], this
|
||||
(*jmpToHook)->mov( asmjit::host::rax, (uint64_t)this );
|
||||
(*jmpToHook)->mov( asmjit::host::qword_ptr_abs( 0x28 ).setSegment( asmjit::host::gs ), asmjit::host::rax );
|
||||
#else
|
||||
// mov fs:[0x14], this
|
||||
(*jmpToHook)->mov( asmjit::host::dword_ptr_abs( 0x14 ).setSegment( asmjit::host::fs ), (uint32_t)this );
|
||||
#endif // USE64
|
||||
|
||||
(*jmpToHook)->jmp( (asmjit::Ptr)this->_internalHandler );
|
||||
(*jmpToHook)->relocCode( this->_buf );
|
||||
|
||||
// Modify VTable copy
|
||||
if (copyVtable)
|
||||
{
|
||||
// Copy VTable
|
||||
if (vtableLen != 0)
|
||||
{
|
||||
memcpy( this->_buf + 0x300 - sizeof( void* ), (*(void***)ppVtable) - 1, vtableLen * sizeof( void* ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Process proc;
|
||||
proc.Attach( GetCurrentProcessId() );
|
||||
auto vptr = (*(uintptr_t**)ppVtable)[index];
|
||||
auto mod = proc.modules().GetModule( vptr, false );
|
||||
uintptr_t imageBase = static_cast<uintptr_t>(mod->baseAddress);
|
||||
uintptr_t imageSzie = mod->size;
|
||||
|
||||
for (;; vtableLen++)
|
||||
{
|
||||
vptr = (*(uintptr_t**)ppVtable)[vtableLen];
|
||||
if (vptr < imageBase || vptr >= imageBase + imageSzie)
|
||||
{
|
||||
memcpy( this->_buf + 0x300 - sizeof( void* ), (*(void***)ppVtable) - 1, vtableLen * sizeof( void* ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace pointer to VTable
|
||||
((void**)this->_buf + 0x300 / sizeof( uintptr_t ))[index] = this->_buf;
|
||||
*ppVtable = this->_buf + 0x300;
|
||||
}
|
||||
// Modify pointer in-place
|
||||
else
|
||||
{
|
||||
DWORD flOld = 0;
|
||||
|
||||
VirtualProtect( *(uintptr_t**)ppVtable + index, sizeof(void*), PAGE_EXECUTE_READWRITE, &flOld );
|
||||
(*(void***)ppVtable)[index] = this->_buf;
|
||||
VirtualProtect( *(uintptr_t**)ppVtable + index, sizeof(void*), flOld, &flOld );
|
||||
}
|
||||
|
||||
return (this->_hooked = true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hooks function in vtable
|
||||
/// </summary>
|
||||
/// <param name="ppVtable">Pointer to vtable pointer</param>
|
||||
/// <param name="index">Function index</param>
|
||||
/// <param name="hkPtr">Hook class member address</param>
|
||||
/// <param name="pClass">Hook class address</param>
|
||||
/// <param name="order">Call order. Hook before original or vice versa</param>
|
||||
/// <param name="retType">Return value. Use origianl or value from hook</param>
|
||||
/// <param name="copyVtable">if true, vtable will be copied and edited, otherwise existing vtable will be edited</param>
|
||||
/// <param name="vtableLen">Optional. Valid only when copyVtable is true. Number of function in vtable.
|
||||
/// Used to determine number of function to copy</param>
|
||||
/// <returns>true on success</returns>
|
||||
bool Hook(
|
||||
void** ppVtable,
|
||||
int index,
|
||||
hktypeC hkPtr,
|
||||
C* pClass,
|
||||
CallOrder::e order = CallOrder::HookFirst,
|
||||
ReturnMethod::e retType = ReturnMethod::UseOriginal,
|
||||
bool copyVtable = false,
|
||||
int vtableLen = 0
|
||||
)
|
||||
{
|
||||
this->_callbackClass = pClass;
|
||||
return Hook( ppVtable, index, brutal_cast<hktype>(hkPtr), order, retType, copyVtable, vtableLen );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore hooked function
|
||||
/// </summary>
|
||||
/// <returns>true on success, false if not hooked</returns>
|
||||
bool Restore()
|
||||
{
|
||||
if (!this->_hooked)
|
||||
return false;
|
||||
|
||||
if (this->_vtCopied)
|
||||
{
|
||||
*this->_ppVtable = this->_pVtable;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD flOld = 0;
|
||||
|
||||
VirtualProtect( *(uintptr_t**)this->_ppVtable + this->_vtIndex, sizeof( void* ), PAGE_EXECUTE_READWRITE, &flOld );
|
||||
(*(void***)this->_ppVtable)[this->_vtIndex] = this->_original;
|
||||
VirtualProtect( *(uintptr_t**)this->_ppVtable + this->_vtIndex, sizeof( void* ), flOld, &flOld );
|
||||
}
|
||||
|
||||
this->_hooked = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _vtCopied = false; // VTable was copied
|
||||
void** _ppVtable = nullptr; // Pointer to VTable pointer
|
||||
void* _pVtable = nullptr; // Pointer to VTable
|
||||
int _vtIndex = 0; // VTable function index
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Include/Winheaders.h"
|
||||
#include "../Process/MemBlock.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// x64 exception module info
|
||||
/// </summary>
|
||||
struct ExceptionModule
|
||||
{
|
||||
ptr_t base;
|
||||
ptr_t size;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// x64 module table
|
||||
/// </summary>
|
||||
struct ModuleTable
|
||||
{
|
||||
ptr_t count; // Number of used entries
|
||||
ExceptionModule entry[250]; // Module data
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Exception handling support for arbitrary code
|
||||
/// </summary>
|
||||
class MExcept
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API MExcept() = default;
|
||||
BLACKBONE_API ~MExcept() = default;
|
||||
|
||||
MExcept( const MExcept& ) = delete;
|
||||
MExcept& operator =( const MExcept& ) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Inject VEH wrapper into process
|
||||
/// Used to enable execution of SEH handlers out of image
|
||||
/// </summary>
|
||||
/// <param name="proc">Target process</param>
|
||||
/// <param name="mod">Target module</param>
|
||||
/// <param name="partial">Partial exception support</param>
|
||||
/// <returns>Error code</returns>
|
||||
BLACKBONE_API NTSTATUS CreateVEH( class Process& proc, ModuleData& mod, bool partial );
|
||||
|
||||
/// <summary>
|
||||
/// Removes VEH from target process
|
||||
/// </summary>
|
||||
/// <param name="proc">Target process</param>
|
||||
/// <param name="partial">Partial exception support</param>
|
||||
/// <param name="mt">Module type</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS RemoveVEH( class Process& proc, bool partial, eModType mt );
|
||||
|
||||
/// <summary>
|
||||
/// Reset data
|
||||
/// </summary>
|
||||
BLACKBONE_API void reset() { _pModTable.Free(); }
|
||||
|
||||
private:
|
||||
MemBlock _pVEHCode; // VEH function codecave
|
||||
MemBlock _pModTable; // x64 module address range table
|
||||
uint64_t _hVEH = 0; // VEH handle
|
||||
|
||||
static uint8_t _handler32[];
|
||||
static uint8_t _handler64[];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Config.h"
|
||||
#include "../Include/Winheaders.h"
|
||||
#include "../Include/Macro.h"
|
||||
#include "../PE/PEImage.h"
|
||||
|
||||
#include "../Process/MemBlock.h"
|
||||
#include "../ManualMap/Native/NtLoader.h"
|
||||
#include "MExcept.h"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
class CustomArgs_t
|
||||
{
|
||||
public:
|
||||
void push_back( const void* ptr, size_t size )
|
||||
{
|
||||
append( ptr, size );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void push_back( const T* ptr )
|
||||
{
|
||||
append( ptr, sizeof( T ) );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void push_back( const std::basic_string<T>& str )
|
||||
{
|
||||
append( str.data(), str.size() * sizeof( T ) );
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void push_back( const std::vector<T>& cVec )
|
||||
{
|
||||
append( cVec.data(), cVec.size() * sizeof( T ) );
|
||||
}
|
||||
|
||||
template<class T, size_t N>
|
||||
void push_back( const std::array<T, N>& arr )
|
||||
{
|
||||
append( arr.data(), arr.size() * sizeof( T ) );
|
||||
}
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
template<typename... Args>
|
||||
void push_back( const std::tuple<Args...>& tpl )
|
||||
{
|
||||
tuple_detail::copyTuple( tpl, _buffer );
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Get raw data size
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
inline size_t size() const { return _buffer.size(); }
|
||||
|
||||
/// <summary>
|
||||
/// Get raw data
|
||||
/// </summary>
|
||||
/// <returns>Data ptr</returns>
|
||||
inline uint8_t* data() { return _buffer.data(); }
|
||||
inline const uint8_t* data() const { return _buffer.data(); }
|
||||
|
||||
private:
|
||||
/// <summary>
|
||||
/// Append buffer from raw memory
|
||||
/// </summary>
|
||||
/// <param name="ptr">Raw pointer</param>
|
||||
/// <param name="size">Data size</param>
|
||||
void append( const void* ptr, size_t size )
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
const auto offset = _buffer.size();
|
||||
_buffer.resize( offset + size );
|
||||
memcpy( _buffer.data() + offset, ptr, size );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint8_t> _buffer;
|
||||
};
|
||||
|
||||
// Loader flags
|
||||
enum eLoadFlags
|
||||
{
|
||||
NoFlags = 0x00, // No flags
|
||||
ManualImports = 0x01, // Manually map import libraries
|
||||
CreateLdrRef = 0x02, // Create module references for native loader
|
||||
WipeHeader = 0x04, // Wipe image PE headers
|
||||
HideVAD = 0x10, // Make image appear as PAGE_NOACESS region
|
||||
MapInHighMem = 0x20, // Try to map image in address space beyond 4GB limit
|
||||
RebaseProcess = 0x40, // If target image is an .exe file, process base address will be replaced with mapped module value
|
||||
NoThreads = 0x80, // Don't create new threads, use hijacking
|
||||
ForceRemap = 0x100, // Force remapping module even if it's already loaded
|
||||
|
||||
NoExceptions = 0x01000, // Do not create custom exception handler
|
||||
PartialExcept = 0x02000, // Only create Inverted function table, without VEH
|
||||
NoDelayLoad = 0x04000, // Do not resolve delay import
|
||||
NoSxS = 0x08000, // Do not apply SxS activation context
|
||||
NoTLS = 0x10000, // Skip TLS initialization and don't execute TLS callbacks
|
||||
IsDependency = 0x20000, // Module is a dependency
|
||||
};
|
||||
|
||||
ENUM_OPS( eLoadFlags )
|
||||
|
||||
// Image mapping type
|
||||
enum MappingType
|
||||
{
|
||||
MT_Default, // Use eLoadFlags value
|
||||
MT_Native, // Use native loader
|
||||
MT_Manual, // Manually map
|
||||
MT_None, // Don't load
|
||||
};
|
||||
|
||||
struct LoadData
|
||||
{
|
||||
MappingType mtype = MT_Default;
|
||||
enum LdrRefFlags ldrFlags = static_cast<enum LdrRefFlags>(0);
|
||||
|
||||
LoadData() = default;
|
||||
|
||||
LoadData( MappingType mtype_, enum LdrRefFlags ldrFlags_ )
|
||||
: mtype( mtype_ )
|
||||
, ldrFlags( ldrFlags_ ) { }
|
||||
};
|
||||
|
||||
// Image mapping callback
|
||||
enum CallbackType
|
||||
{
|
||||
PreCallback, // Called before loading. Loading type is decided here
|
||||
PostCallback // Called after manual mapping, but before entry point invocation. Loader flags are decided here
|
||||
};
|
||||
|
||||
using MapCallback = LoadData( *)(CallbackType type, void* context, Process& process, const ModuleData& modInfo);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Image data
|
||||
/// </summary>
|
||||
struct ImageContext
|
||||
{
|
||||
using vecPtr = std::vector<ptr_t>;
|
||||
|
||||
pe::PEImage peImage; // PE image data
|
||||
MemBlock imgMem; // Target image memory region
|
||||
NtLdrEntry ldrEntry; // Native loader module information
|
||||
vecPtr tlsCallbacks; // TLS callback routines
|
||||
ptr_t pExpTableAddr = 0; // Exception table address (amd64 only)
|
||||
eLoadFlags flags = NoFlags; // Image loader flags
|
||||
bool initialized = false; // Image entry point was called
|
||||
};
|
||||
|
||||
using ImageContextPtr = std::shared_ptr<ImageContext>;
|
||||
using vecImageCtx = std::vector<ImageContextPtr>;
|
||||
|
||||
/// <summary>
|
||||
/// Manual image mapper
|
||||
/// </summary>
|
||||
class MMap
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API MMap( class Process& proc );
|
||||
BLACKBONE_API ~MMap( void );
|
||||
|
||||
/// <summary>
|
||||
/// Manually map PE image into underlying target process
|
||||
/// </summary>
|
||||
/// <param name="path">Image path</param>
|
||||
/// <param name="flags">Image mapping flags</param>
|
||||
/// <param name="mapCallback">Mapping callback. Triggers for each mapped module</param>
|
||||
/// <param name="context">User-supplied callback context</param>
|
||||
/// <returns>Mapped image info </returns>
|
||||
BLACKBONE_API call_result_t<ModuleDataPtr> MapImage(
|
||||
const std::wstring& path,
|
||||
eLoadFlags flags = NoFlags,
|
||||
MapCallback mapCallback = nullptr,
|
||||
void* context = nullptr,
|
||||
CustomArgs_t* pCustomArgs_t = nullptr
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
///Manually map PE image into underlying target process
|
||||
/// </summary>
|
||||
/// <param name="buffer">Image data buffer</param>
|
||||
/// <param name="size">Buffer size.</param>
|
||||
/// <param name="asImage">If set to true - buffer has image memory layout</param>
|
||||
/// <param name="flags">Image mapping flags</param>
|
||||
/// <param name="mapCallback">Mapping callback. Triggers for each mapped module</param>
|
||||
/// <param name="context">User-supplied callback context</param>
|
||||
/// <returns>Mapped image info</returns>
|
||||
BLACKBONE_API call_result_t<ModuleDataPtr> MapImage(
|
||||
size_t size, void* buffer,
|
||||
bool asImage = false,
|
||||
eLoadFlags flags = NoFlags,
|
||||
MapCallback mapCallback = nullptr,
|
||||
void* context = nullptr,
|
||||
CustomArgs_t* pCustomArgs_t = nullptr
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Unmap all manually mapped modules
|
||||
/// </summary>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS UnmapAllModules();
|
||||
|
||||
/// <summary>
|
||||
/// Remove any traces from remote process
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
BLACKBONE_API void Cleanup();
|
||||
|
||||
/// <summary>
|
||||
/// Reset local data
|
||||
/// </summary>
|
||||
BLACKBONE_API inline void reset() { _images.clear(); _pAContext.Reset(); _usedBlocks.clear(); }
|
||||
private:
|
||||
/// <summary>
|
||||
/// Manually map PE image into underlying target process
|
||||
/// </summary>
|
||||
/// <param name="path">Image path</param>
|
||||
/// <param name="buffer">Image data buffer</param>
|
||||
/// <param name="size">Buffer size.</param>
|
||||
/// <param name="asImage">If set to true - buffer has image memory layout</param>
|
||||
/// <param name="flags">Image mapping flags</param>
|
||||
/// <param name="mapCallback">Mapping callback. Triggers for each mapped module</param>
|
||||
/// <param name="context">User-supplied callback context</param>
|
||||
/// <returns>Mapped image info</returns>
|
||||
call_result_t<ModuleDataPtr> MapImageInternal(
|
||||
const std::wstring& path,
|
||||
void* buffer, size_t size,
|
||||
bool asImage = false,
|
||||
eLoadFlags flags = NoFlags,
|
||||
MapCallback ldrCallback = nullptr,
|
||||
void* ldrContext = nullptr,
|
||||
CustomArgs_t* pCustomArgs_t = nullptr
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Fix image path for pure managed mapping
|
||||
/// </summary>
|
||||
/// <param name="base">Image base</param>
|
||||
/// <param name="path">New image path</param>
|
||||
template<typename T>
|
||||
void FixManagedPath( ptr_t base, const std::wstring &path );
|
||||
|
||||
/// <summary>
|
||||
/// Get existing module or map it if absent
|
||||
/// </summary>
|
||||
/// <param name="path">Image path</param>
|
||||
/// <param name="flags">Mapping flags</param>
|
||||
/// <returns>Module info</returns>
|
||||
call_result_t<ModuleDataPtr> FindOrMapModule(
|
||||
const std::wstring& path,
|
||||
void* buffer, size_t size, bool asImage,
|
||||
eLoadFlags flags = NoFlags
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Run module initializers(TLS and entry point).
|
||||
/// </summary>
|
||||
/// <param name="pImage">Image data</param>
|
||||
/// <param name="dwReason">one of the following:
|
||||
/// DLL_PROCESS_ATTACH
|
||||
/// DLL_THREAD_ATTACH
|
||||
/// DLL_PROCESS_DETACH
|
||||
/// DLL_THREAD_DETTACH
|
||||
/// </param>
|
||||
/// <returns>DllMain result</returns>
|
||||
call_result_t<uint64_t> RunModuleInitializers( ImageContextPtr pImage, DWORD dwReason, CustomArgs_t* pCustomArgs_t = nullptr );
|
||||
|
||||
/// <summary>
|
||||
/// Copies image into target process
|
||||
/// </summary>
|
||||
/// <param name="pImage">Image data</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS CopyImage( ImageContextPtr pImage );
|
||||
|
||||
/// <summary>
|
||||
/// Adjust image memory protection
|
||||
/// </summary>
|
||||
/// <param name="pImage">image data</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS ProtectImageMemory( ImageContextPtr pImage );
|
||||
|
||||
/// <summary>
|
||||
/// Fix relocations if image wasn't loaded at base address
|
||||
/// </summary>
|
||||
/// <param name="pImage">image data</param>
|
||||
/// <returns>true on success</returns>
|
||||
NTSTATUS RelocateImage( ImageContextPtr pImage );
|
||||
|
||||
/// <summary>
|
||||
/// Resolves image import or delayed image import
|
||||
/// </summary>
|
||||
/// <param name="pImage">Image data</param>
|
||||
/// <param name="useDelayed">Resolve delayed import instead</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS ResolveImport( ImageContextPtr pImage, bool useDelayed = false );
|
||||
|
||||
/// <summary>
|
||||
/// Resolve static TLS storage
|
||||
/// </summary>
|
||||
/// <param name="pImage">image data</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS InitStaticTLS( ImageContextPtr pImage );
|
||||
|
||||
/// <summary>
|
||||
/// Set custom exception handler to bypass SafeSEH under DEP
|
||||
/// </summary>
|
||||
/// <param name="pImage">image data</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS EnableExceptions( ImageContextPtr pImage );
|
||||
|
||||
/// <summary>
|
||||
/// Remove custom exception handler
|
||||
/// </summary>
|
||||
/// <param name="pImage">image data</param>
|
||||
/// <returns>true on success</returns>
|
||||
NTSTATUS DisableExceptions( ImageContextPtr pImage );
|
||||
|
||||
/// <summary>
|
||||
/// Calculate and set security cookie
|
||||
/// </summary>
|
||||
/// <param name="pImage">image data</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS InitializeCookie( ImageContextPtr pImage );
|
||||
|
||||
/// <summary>
|
||||
/// Return existing or load missing dependency
|
||||
/// </summary>
|
||||
/// <param name="pImage">Currently mapped image data</param>
|
||||
/// <param name="path">Dependency path</param>
|
||||
/// <returns></returns>
|
||||
call_result_t<ModuleDataPtr> FindOrMapDependency( ImageContextPtr pImage, std::wstring& path );
|
||||
|
||||
/// <summary>
|
||||
/// Create activation context
|
||||
/// Target memory layout:
|
||||
/// -----------------------------
|
||||
/// | hCtx | ACTCTX | file_path |
|
||||
/// -----------------------------
|
||||
/// </summary>
|
||||
/// <param name="path">Manifest container path</param>
|
||||
/// <param name="id">Manifest resource id</param>
|
||||
/// <param name="asImage">if true - 'path' points to a valid PE file, otherwise - 'path' points to separate manifest file</param>
|
||||
/// <returns>true on success</returns>
|
||||
NTSTATUS CreateActx( const pe::PEImage& image );
|
||||
|
||||
/// <summary>
|
||||
/// Do SxS path probing in the target process
|
||||
/// </summary>
|
||||
/// <param name="path">Path to probe</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS ProbeRemoteSxS( std::wstring& path );
|
||||
|
||||
/// <summary>
|
||||
/// Hide memory VAD node
|
||||
/// </summary>
|
||||
/// <param name="imageMem">Image to purge</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS ConcealVad( const MemBlock& imageMem );
|
||||
|
||||
/// <summary>
|
||||
/// Allocates memory region beyond 4GB limit
|
||||
/// </summary>
|
||||
/// <param name="imageMem">Image data</param>
|
||||
/// <param name="size">Block size</param>
|
||||
/// <returns>Status code</returns>
|
||||
NTSTATUS AllocateInHighMem( MemBlock& imageMem, size_t size );
|
||||
|
||||
/// <summary>
|
||||
/// Transform section characteristics into memory protection flags
|
||||
/// </summary>
|
||||
/// <param name="characteristics">Section characteristics</param>
|
||||
/// <returns>Memory protection value</returns>
|
||||
DWORD GetSectionProt( DWORD characteristics );
|
||||
|
||||
private:
|
||||
class Process& _process; // Target process manager
|
||||
MExcept _expMgr; // Exception handler manager
|
||||
vecImageCtx _images; // Mapped images
|
||||
MemBlock _pAContext; // SxS activation context memory address
|
||||
MapCallback _mapCallback = nullptr; // Loader callback for adding image into loader lists
|
||||
void* _userContext = nullptr; // user context for _ldrCallback
|
||||
|
||||
std::vector<std::pair<ptr_t, size_t>> _usedBlocks; // Used memory blocks
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../Include/Winheaders.h"
|
||||
#include "../../PE/PEImage.h"
|
||||
#include "../../Include/Types.h"
|
||||
#include "../../Include/NativeStructures.h"
|
||||
#include "../../Include/Macro.h"
|
||||
#include "../../Include/CallResult.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
enum LdrRefFlags
|
||||
{
|
||||
Ldr_None = 0x00, // Do not create any reference
|
||||
Ldr_ModList = 0x01, // Add to module list - LdrpModuleIndex( win8 only ), InMemoryOrderModuleList( win7 only )
|
||||
Ldr_HashTable = 0x02, // Add to LdrpHashTable
|
||||
Ldr_ThdCall = 0x04, // Add to thread callback list (dllmain will be called with THREAD_ATTACH/DETACH reasons)
|
||||
Ldr_All = 0xFF, // Add to everything
|
||||
Ldr_Ignore = 0xDE // Only valid in mod callback, mod callback value will be ignored
|
||||
};
|
||||
|
||||
ENUM_OPS( LdrRefFlags )
|
||||
|
||||
struct NtLdrEntry : ModuleData
|
||||
{
|
||||
LdrRefFlags flags = Ldr_None;
|
||||
ptr_t entryPoint = 0;
|
||||
ULONG hash = 0;
|
||||
bool safeSEH = false;
|
||||
};
|
||||
|
||||
class NtLdr
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API NtLdr( class Process& proc );
|
||||
|
||||
/// <summary>
|
||||
/// Initialize some loader stuff
|
||||
/// </summary>
|
||||
/// <param name="initFor">Target module type</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool Init( eModType initFor = mt_default );
|
||||
|
||||
/// <summary>
|
||||
/// Add module to some loader structures
|
||||
/// (LdrpHashTable, LdrpModuleIndex( win8 only ), InMemoryOrderModuleList( win7 only ))
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool CreateNTReference( NtLdrEntry& mod );
|
||||
|
||||
/// <summary>
|
||||
/// Create thread static TLS array
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <param name="tlsPtr">TLS directory of target image</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS AddStaticTLSEntry( NtLdrEntry& mod, ptr_t tlsPtr );
|
||||
|
||||
/// <summary>
|
||||
/// Create module record in LdrpInvertedFunctionTable
|
||||
/// Used to create fake SAFESEH entries
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool InsertInvertedFunctionTable( NtLdrEntry& mod );
|
||||
|
||||
/// <summary>
|
||||
/// Free static TLS
|
||||
/// </summary>
|
||||
/// <param name="mod">Target module</param>
|
||||
/// <param name="noThread">Don't create new threads during remote call</param>
|
||||
/// <returns>Status code</returns>
|
||||
BLACKBONE_API NTSTATUS UnloadTLS( const NtLdrEntry& mod, bool noThread = false );
|
||||
|
||||
/// <summary>
|
||||
/// Unlink module from Ntdll loader
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <param name="noThread">Don't create new threads during unlink</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool Unlink( const ModuleData& mod, bool noThread = false );
|
||||
private:
|
||||
|
||||
/// <summary>
|
||||
/// Find LdrpHashTable[] variable
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
template<typename T>
|
||||
bool FindLdrpHashTable();
|
||||
|
||||
/// <summary>
|
||||
/// Find LdrpModuleIndex variable under win8
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
template<typename T>
|
||||
bool FindLdrpModuleIndexBase();
|
||||
|
||||
/// <summary>
|
||||
/// Find Loader heap base
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
template<typename T>
|
||||
bool FindLdrHeap();
|
||||
|
||||
/// <summary>
|
||||
/// Initialize OS-specific module entry
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <returns>Pointer to created entry</returns>
|
||||
template<typename T>
|
||||
ptr_t InitBaseNode( NtLdrEntry& mod );
|
||||
|
||||
/// <summary>
|
||||
/// Initialize OS-specific module entry
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <returns>Pointer to created entry</returns>
|
||||
template<typename T>
|
||||
ptr_t InitW8Node( NtLdrEntry& mod );
|
||||
|
||||
/// <summary>
|
||||
/// Initialize OS-specific module entry
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <returns>Pointer to created entry</returns>
|
||||
template<typename T>
|
||||
ptr_t InitW7Node( NtLdrEntry& mod );
|
||||
|
||||
/// <summary>
|
||||
/// Insert entry into win8 module graph
|
||||
/// </summary>
|
||||
/// <param name="nodePtr">Node to insert</param>
|
||||
/// <param name="mod">Module data</param>
|
||||
template<typename T>
|
||||
void InsertTreeNode( ptr_t nodePtr, const NtLdrEntry& mod );
|
||||
|
||||
/// <summary>
|
||||
/// Insert entry into LdrpHashTable[]
|
||||
/// </summary>
|
||||
/// <param name="pNodeLink">Link of entry to be inserted</param>
|
||||
/// <param name="hash">Module hash</param>
|
||||
template<typename T>
|
||||
void InsertHashNode( ptr_t pNodeLink, ULONG hash );
|
||||
|
||||
/// <summary>
|
||||
/// Insert entry into InLoadOrderModuleList and InMemoryOrderModuleList
|
||||
/// </summary>
|
||||
/// <param name="pNodeMemoryOrderLink">InMemoryOrderModuleList link of entry to be inserted</param>
|
||||
/// <param name="pNodeLoadOrderLink">InLoadOrderModuleList link of entry to be inserted</param>
|
||||
template<typename T>
|
||||
void InsertMemModuleNode( ptr_t pNodeMemoryOrderLink, ptr_t pNodeLoadOrderLink, ptr_t pNodeInitOrderLink );
|
||||
|
||||
/// <summary>
|
||||
/// Insert entry into standard double linked list
|
||||
/// </summary>
|
||||
/// <param name="ListHead">List head pointer</param>
|
||||
/// <param name="Entry">Entry list link to be inserted</param>
|
||||
template<typename T>
|
||||
void InsertTailList( ptr_t ListHead, ptr_t Entry );
|
||||
|
||||
/// <summary>
|
||||
/// Hash image name
|
||||
/// </summary>
|
||||
/// <param name="str">Image name</param>
|
||||
/// <returns>Hash</returns>
|
||||
ULONG HashString( const std::wstring& str );
|
||||
|
||||
/// <summary>
|
||||
/// Allocate memory from heap if possible
|
||||
/// </summary>
|
||||
/// <param name="size">Module type</param>
|
||||
/// <param name="size">Size to allocate</param>
|
||||
/// <returns>Allocated address</returns>
|
||||
call_result_t<ptr_t> AllocateInHeap( eModType mt, size_t size );
|
||||
|
||||
/// <summary>
|
||||
/// Get module native node ptr or create new
|
||||
/// </summary>
|
||||
/// <param name="ptr">node pointer (if nullptr - new dummy node is allocated)</param>
|
||||
/// <param name="pModule">Module base address</param>
|
||||
/// <returns>Node address</returns>
|
||||
template<typename T, typename Module>
|
||||
ptr_t SetNode( ptr_t ptr, Module pModule );
|
||||
|
||||
/// <summary>
|
||||
/// Unlink module from PEB_LDR_DATA
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <returns>Address of removed record</returns>
|
||||
template<typename T>
|
||||
ptr_t UnlinkFromLdr( const ModuleData& mod );
|
||||
|
||||
/// <summary>
|
||||
/// Finds LDR entry for module
|
||||
/// </summary>
|
||||
/// <param name="moduleBase">Target module base</param>
|
||||
/// <param name="found">Found entry</param>
|
||||
/// <returns>Found LDR entry address</returns>
|
||||
template<typename T>
|
||||
ptr_t FindLdrEntry( module_t moduleBase, _LDR_DATA_TABLE_ENTRY_BASE_T<T>* found = nullptr );
|
||||
|
||||
/// <summary>
|
||||
/// Remove record from LIST_ENTRY structure
|
||||
/// </summary>
|
||||
/// <param name="pListLink">Entry link</param>
|
||||
template<typename T>
|
||||
void UnlinkListEntry( ptr_t pListLink );
|
||||
|
||||
/// <summary>
|
||||
/// Unlink from module graph
|
||||
/// </summary>
|
||||
/// <param name="mod">Module data</param>
|
||||
/// <param name="ldrEntry">Module LDR entry</param>
|
||||
/// <param name="noThread">Don't create new threads during unlink</param>
|
||||
/// <returns>Address of removed record</returns>
|
||||
template<typename T>
|
||||
ptr_t UnlinkTreeNode( const ModuleData& mod, ptr_t ldrEntry, bool noThread = false );
|
||||
|
||||
NtLdr( const NtLdr& ) = delete;
|
||||
NtLdr& operator =( const NtLdr& ) = delete;
|
||||
|
||||
private:
|
||||
class Process& _process; // Process memory routines
|
||||
|
||||
ptr_t _LdrpHashTable = 0; // LdrpHashTable address
|
||||
ptr_t _LdrpModuleIndexBase = 0; // LdrpModuleIndex address
|
||||
ptr_t _LdrHeapBase = 0; // Loader heap base address
|
||||
|
||||
eModType _initializedFor = mt_unknown; // Loader initialization target
|
||||
std::map<ptr_t, ptr_t> _nodeMap; // Allocated native structures
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Include/Types.h"
|
||||
#include "../Include/Winheaders.h"
|
||||
#include "Utils.h"
|
||||
#include "InitOnce.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Dynamic import
|
||||
/// </summary>
|
||||
class DynImport
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API static DynImport& Instance()
|
||||
{
|
||||
static DynImport instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
DynImport() = default;
|
||||
DynImport( const DynImport& ) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Get dll function
|
||||
/// </summary>
|
||||
/// <param name="name">Function name</param>
|
||||
/// <returns>Function pointer</returns>
|
||||
template<typename T>
|
||||
T get( const std::string& name )
|
||||
{
|
||||
InitializeOnce();
|
||||
|
||||
CSLock lck( _mapGuard );
|
||||
|
||||
auto iter = _funcs.find( name );
|
||||
if (iter != _funcs.end())
|
||||
return reinterpret_cast<T>(iter->second);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely call import
|
||||
/// If import not found - return STATUS_ORDINAL_NOT_FOUND
|
||||
/// </summary>
|
||||
/// <param name="name">Import name.</param>
|
||||
/// <param name="...args">Function args</param>
|
||||
/// <returns>Function result or STATUS_ORDINAL_NOT_FOUND if import not found</returns>
|
||||
template<typename T, typename... Args>
|
||||
NTSTATUS safeNativeCall( const std::string& name, Args&&... args )
|
||||
{
|
||||
auto pfn = DynImport::get<T>( name );
|
||||
return pfn ? pfn( std::forward<Args>( args )... ) : STATUS_ORDINAL_NOT_FOUND;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Safely call import
|
||||
/// If import not found - return 0
|
||||
/// </summary>
|
||||
/// <param name="name">Import name.</param>
|
||||
/// <param name="...args">Function args</param>
|
||||
/// <returns>Function result or 0 if import not found</returns>
|
||||
template<typename T, typename... Args>
|
||||
auto safeCall( const std::string& name, Args&&... args )
|
||||
{
|
||||
auto pfn = DynImport::get<T>( name );
|
||||
return pfn ? pfn( std::forward<Args>( args )... ) : std::invoke_result_t<T, Args...>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load function into database
|
||||
/// </summary>
|
||||
/// <param name="name">Function name</param>
|
||||
/// <param name="module">Module name</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API FARPROC load( const std::string& name, const std::wstring& modName )
|
||||
{
|
||||
auto mod = GetModuleHandleW( modName.c_str() );
|
||||
return load( name, mod );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load function into database
|
||||
/// </summary>
|
||||
/// <param name="name">Function name</param>
|
||||
/// <param name="hMod">Module base</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API FARPROC load( const std::string& name, HMODULE hMod )
|
||||
{
|
||||
CSLock lck( _mapGuard );
|
||||
|
||||
auto proc = GetProcAddress( hMod, name.c_str() );
|
||||
if (proc)
|
||||
{
|
||||
_funcs.insert( std::make_pair( name, proc ) );
|
||||
return proc;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, FARPROC> _funcs; // function database
|
||||
CriticalSection _mapGuard; // function database guard
|
||||
};
|
||||
|
||||
// Syntax sugar
|
||||
#define LOAD_IMPORT(name, mod) (DynImport::Instance().load( name, mod ))
|
||||
#define GET_IMPORT(name) (DynImport::Instance().get<fn ## name>( #name ))
|
||||
#define SAFE_NATIVE_CALL(name, ...) (DynImport::Instance().safeNativeCall<fn ## name>( #name, __VA_ARGS__ ))
|
||||
#define SAFE_CALL(name, ...) (DynImport::Instance().safeCall<fn ## name>( #name, __VA_ARGS__ ))
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "../Config.h"
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
BLACKBONE_API bool InitializeOnce();
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Include/Winheaders.h"
|
||||
#include "../Include/Types.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
class NameResolve
|
||||
{
|
||||
using mapApiSchema = std::unordered_map<std::wstring, std::vector<std::wstring>>;
|
||||
|
||||
public:
|
||||
enum eResolveFlag
|
||||
{
|
||||
Default = 0, // Full resolve
|
||||
ApiSchemaOnly = 1, // Resolve only Api schema dlls
|
||||
EnsureFullPath = 2, // Make sure resulting path is full-qualified
|
||||
NoSearch = 4, // Don't perform file search, only resolve name
|
||||
Wow64 = 8, // Redirect System32 files to SysWow64
|
||||
};
|
||||
|
||||
public:
|
||||
BLACKBONE_API ~NameResolve() = default;
|
||||
|
||||
BLACKBONE_API static NameResolve& Instance();
|
||||
|
||||
/// <summary>
|
||||
/// Initialize api set map
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
BLACKBONE_API bool Initialize();
|
||||
|
||||
/// <summary>
|
||||
/// Resolve image path.
|
||||
/// </summary>
|
||||
/// <param name="path">Image to resolve</param>
|
||||
/// <param name="baseName">Name of parent image. Used only when resolving import images</param>
|
||||
/// <param name="searchDir">Directory where source image is located</param>
|
||||
/// <param name="flags">Resolve flags</param>
|
||||
/// <param name="proc">Process. Used to search process executable directory</param>
|
||||
/// <param name="actx">Activation context</param>
|
||||
/// <returns>Status</returns>
|
||||
BLACKBONE_API NTSTATUS ResolvePath(
|
||||
std::wstring& path,
|
||||
const std::wstring& baseName,
|
||||
const std::wstring& searchDir,
|
||||
eResolveFlag flags,
|
||||
class Process& proc,
|
||||
HANDLE actx = INVALID_HANDLE_VALUE
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Try SxS redirection
|
||||
/// </summary>
|
||||
/// <param name="path">Image path.</param>
|
||||
/// <param name="proc">Process. Used to search process executable directory</param>
|
||||
/// <param name="actx">Activation context</param>
|
||||
/// <returns></returns>
|
||||
BLACKBONE_API NTSTATUS ProbeSxSRedirect( std::wstring& path, class Process& proc, HANDLE actx = INVALID_HANDLE_VALUE );
|
||||
|
||||
private:
|
||||
// Ensure singleton
|
||||
NameResolve() = default;
|
||||
NameResolve( const NameResolve& ) = delete;
|
||||
NameResolve& operator =( const NameResolve& ) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the process executable directory
|
||||
/// </summary>
|
||||
/// <param name="pid">Process ID</param>
|
||||
/// <returns>Process executable directory</returns>
|
||||
std::wstring GetProcessDirectory( DWORD pid );
|
||||
|
||||
/// <summary>
|
||||
/// OS dependent api set initialization
|
||||
/// </summary>
|
||||
/// <returns>true on success</returns>
|
||||
template<typename PApiSetMap, typename PApiSetEntry, typename PHostArray, typename PHostEntry>
|
||||
bool InitializeP();
|
||||
|
||||
private:
|
||||
mapApiSchema _apiSchema; // Api schema table
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "../Config.h"
|
||||
#include <stdint.h>
|
||||
#include <winnt.h>
|
||||
|
||||
// Thunk code
|
||||
#pragma pack(push, 1)
|
||||
struct ThunkData
|
||||
{
|
||||
#ifndef USE64
|
||||
/*
|
||||
mov eax, pInstance
|
||||
mov fs:[0x14], eax
|
||||
mov eax, pMethod
|
||||
jmp eax
|
||||
*/
|
||||
uint8_t mov1 = 0xB8;
|
||||
void* pInst = nullptr;
|
||||
uint16_t fs1 = '\x64\xA3';
|
||||
uint8_t fs2 = FIELD_OFFSET( NT_TIB, ArbitraryUserPointer );
|
||||
uint8_t fs3 = 0;
|
||||
uint16_t fs4 = 0;
|
||||
uint8_t mov2 = 0xB8;
|
||||
void* pFn = nullptr;
|
||||
uint16_t jmp1 = '\xFF\xE0';
|
||||
#else
|
||||
/*
|
||||
mov rax, pInstance
|
||||
mov gs:[0x28], rax
|
||||
mov rax, pMethod
|
||||
jmp rax
|
||||
*/
|
||||
uint16_t mov1 = '\x48\xB8';
|
||||
void* pInst = nullptr;
|
||||
uint32_t fs1 = '\x65\x48\x89\x04';
|
||||
uint8_t fs2 = 0x25;
|
||||
uint8_t fs3 = FIELD_OFFSET( NT_TIB, ArbitraryUserPointer );
|
||||
uint8_t fs4 = 0;
|
||||
uint16_t fs5 = 0;
|
||||
uint16_t mov2 = '\x48\xB8';
|
||||
void* pFn = nullptr;
|
||||
uint16_t jmp1 = '\xFF\xE0';
|
||||
#endif
|
||||
|
||||
void setup( void* pInstance, void* pMethod )
|
||||
{
|
||||
pInst = pInstance;
|
||||
pFn = pMethod;
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
|
||||
template<typename fn, typename C>
|
||||
class Win32Thunk;
|
||||
|
||||
template<typename R, typename... Args, typename C>
|
||||
class Win32Thunk < R( __stdcall* )(Args...), C >
|
||||
{
|
||||
public:
|
||||
using TypeMember = R( C::* )(Args...);
|
||||
using TypeFree = R( __stdcall* )(Args...);
|
||||
|
||||
public:
|
||||
Win32Thunk( TypeMember pfn, C* pInstance )
|
||||
: _pMethod( pfn )
|
||||
, _pInstance( pInstance )
|
||||
{
|
||||
DWORD dwOld = 0;
|
||||
VirtualProtect( &_thunk, sizeof( _thunk ), PAGE_EXECUTE_READWRITE, &dwOld );
|
||||
_thunk.setup( this, &Win32Thunk::WrapHandler );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redirect call
|
||||
/// </summary>
|
||||
/// <param name="...args">Arguments</param>
|
||||
/// <returns>Call result</returns>
|
||||
static R __stdcall WrapHandler( Args... args )
|
||||
{
|
||||
auto _this = reinterpret_cast<Win32Thunk*>(((PNT_TIB)NtCurrentTeb())->ArbitraryUserPointer);
|
||||
return (_this->_pInstance->*_this->_pMethod)(args...);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get thunk
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
TypeFree GetThunk()
|
||||
{
|
||||
return reinterpret_cast<TypeFree>(&_thunk);
|
||||
}
|
||||
|
||||
private:
|
||||
TypeMember _pMethod = nullptr; // Member function to call
|
||||
C* _pInstance = nullptr; // Bound instance
|
||||
ThunkData _thunk; // Thunk code
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4091)
|
||||
#include <DbgHelp.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
#ifndef BLACKBONE_NO_TRACE
|
||||
|
||||
inline void DoTraceV( const char* fmt, va_list va_args )
|
||||
{
|
||||
char buf[2048], userbuf[1024];
|
||||
vsprintf_s( userbuf, fmt, va_args );
|
||||
sprintf_s( buf, "BlackBone: %s\r\n", userbuf );
|
||||
OutputDebugStringA( buf );
|
||||
|
||||
#ifdef CONSOLE_TRACE
|
||||
printf_s( buf );
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void DoTraceV( const wchar_t* fmt, va_list va_args )
|
||||
{
|
||||
wchar_t buf[2048], userbuf[1024];
|
||||
vswprintf_s( userbuf, fmt, va_args );
|
||||
swprintf_s( buf, L"BlackBone: %ls\r\n", userbuf );
|
||||
OutputDebugStringW( buf );
|
||||
|
||||
#ifdef CONSOLE_TRACE
|
||||
wprintf_s( buf );
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Ch>
|
||||
inline void DoTrace( const Ch* fmt, ... )
|
||||
{
|
||||
va_list va_args;
|
||||
va_start( va_args, fmt );
|
||||
DoTraceV( fmt, va_args );
|
||||
va_end( va_args );
|
||||
}
|
||||
|
||||
#define BLACKBONE_TRACE(fmt, ...) DoTrace(fmt, ##__VA_ARGS__)
|
||||
|
||||
#else
|
||||
#define BLACKBONE_TRACE(...)
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Include/Winheaders.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Convert UTF-8 string to wide char one
|
||||
/// </summary>
|
||||
/// <param name="str">UTF-8 string</param>
|
||||
/// <returns>wide char string</returns>
|
||||
BLACKBONE_API static std::wstring UTF8ToWstring( const std::string& str );
|
||||
|
||||
/// <summary>
|
||||
/// Convert wide string to UTF-8
|
||||
/// </summary>
|
||||
/// <param name="str">UTF-8 string</param>
|
||||
/// <returns>wide char string</returns>
|
||||
BLACKBONE_API static std::string WstringToUTF8( const std::wstring& str );
|
||||
|
||||
/// <summary>
|
||||
/// Convert ANSI string to wide char one
|
||||
/// </summary>
|
||||
/// <param name="input">ANSI string.</param>
|
||||
/// <param name="locale">String locale</param>
|
||||
/// <returns>wide char string</returns>
|
||||
BLACKBONE_API static std::wstring AnsiToWstring( const std::string& input, DWORD locale = CP_ACP );
|
||||
|
||||
/// <summary>
|
||||
/// Convert wide char string to ANSI one
|
||||
/// </summary>
|
||||
/// <param name="input">wide char string.</param>
|
||||
/// <param name="locale">String locale</param>
|
||||
/// <returns>ANSI string</returns>
|
||||
BLACKBONE_API static std::string WstringToAnsi( const std::wstring& input, DWORD locale = CP_ACP );
|
||||
|
||||
/// <summary>
|
||||
/// Format string
|
||||
/// </summary>
|
||||
/// <param name="fmt">Format specifier</param>
|
||||
/// <param name="">Arguments</param>
|
||||
/// <returns>Formatted string</returns>
|
||||
BLACKBONE_API static std::wstring FormatString( const wchar_t* fmt, ... );
|
||||
|
||||
/// <summary>
|
||||
/// Get filename from full-qualified path
|
||||
/// </summary>
|
||||
/// <param name="path">File path</param>
|
||||
/// <returns>Filename</returns>
|
||||
BLACKBONE_API static std::wstring StripPath( const std::wstring& path );
|
||||
|
||||
/// <summary>
|
||||
/// Get parent directory
|
||||
/// </summary>
|
||||
/// <param name="path">File path</param>
|
||||
/// <returns>Parent directory</returns>
|
||||
BLACKBONE_API static std::wstring GetParent( const std::wstring& path );
|
||||
|
||||
/// <summary>
|
||||
/// Get current process exe file directory
|
||||
/// </summary>
|
||||
/// <returns>Exe directory</returns>
|
||||
BLACKBONE_API static std::wstring GetExeDirectory();
|
||||
|
||||
/// <summary>
|
||||
/// Cast string characters to lower case
|
||||
/// </summary>
|
||||
/// <param name="str">Source string.</param>
|
||||
/// <returns>Result string</returns>
|
||||
BLACKBONE_API static std::wstring ToLower( std::wstring str );
|
||||
|
||||
/// <summary>
|
||||
/// Generate random alpha-numeric string
|
||||
/// </summary>
|
||||
/// <param name="length">Desired length. 0 - random length from 5 to 15</param>
|
||||
/// <returns>Generated string</returns>
|
||||
BLACKBONE_API static std::wstring RandomANString( int length = 0 );
|
||||
|
||||
/// <summary>
|
||||
/// Get system error description
|
||||
/// </summary>
|
||||
/// <param name="code">The code.</param>
|
||||
/// <returns>Error message</returns>
|
||||
BLACKBONE_API static std::wstring GetErrorDescription( NTSTATUS code );
|
||||
|
||||
/// <summary>
|
||||
/// Check if file exists
|
||||
/// </summary>
|
||||
/// <param name="path">Full-qualified file path</param>
|
||||
/// <returns>true if exists</returns>
|
||||
BLACKBONE_API static bool FileExists( const std::wstring& path );
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// std::mutex alternative
|
||||
/// </summary>
|
||||
class CriticalSection
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API CriticalSection()
|
||||
{
|
||||
InitializeCriticalSection( &_native );
|
||||
}
|
||||
|
||||
BLACKBONE_API ~CriticalSection()
|
||||
{
|
||||
DeleteCriticalSection( &_native );
|
||||
}
|
||||
|
||||
BLACKBONE_API void lock()
|
||||
{
|
||||
EnterCriticalSection( &_native );
|
||||
}
|
||||
|
||||
BLACKBONE_API void unlock()
|
||||
{
|
||||
LeaveCriticalSection( &_native );
|
||||
}
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION _native;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// std::lock_guard alternative
|
||||
/// </summary>
|
||||
class CSLock
|
||||
{
|
||||
public:
|
||||
BLACKBONE_API CSLock( CriticalSection& cs )
|
||||
: _cs( cs )
|
||||
{
|
||||
cs.lock();
|
||||
}
|
||||
|
||||
BLACKBONE_API ~CSLock()
|
||||
{
|
||||
_cs.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
CSLock( const CSLock& ) = delete;
|
||||
CSLock& operator = ( const CSLock& ) = delete;
|
||||
|
||||
private:
|
||||
CriticalSection& _cs;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// System32 helper
|
||||
/// </summary>
|
||||
class FsRedirector
|
||||
{
|
||||
public:
|
||||
FsRedirector( bool wow64 )
|
||||
: _wow64( wow64 )
|
||||
{
|
||||
#ifndef XP_BUILD
|
||||
if (wow64)
|
||||
Wow64DisableWow64FsRedirection( &_fsRedirection );
|
||||
#endif
|
||||
}
|
||||
|
||||
~FsRedirector()
|
||||
{
|
||||
#ifndef XP_BUILD
|
||||
if (_wow64)
|
||||
Wow64RevertWow64FsRedirection( _fsRedirection );
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
PVOID _fsRedirection = nullptr;
|
||||
bool _wow64;
|
||||
};
|
||||
|
||||
#if _MSC_VER >= 1900
|
||||
namespace tuple_detail
|
||||
{
|
||||
template<typename T, typename F, size_t... Is>
|
||||
void visit_each( T&& t, F f, std::index_sequence<Is...> ) { auto l = { (f( std::get<Is>( t ) ), 0)... }; }
|
||||
|
||||
template<typename... Ts>
|
||||
void copyTuple( std::tuple<Ts...> const& from, std::vector<char>& to )
|
||||
{
|
||||
auto func = [&to]( auto& v )
|
||||
{
|
||||
auto ptr = to.size();
|
||||
to.resize( ptr + sizeof( v ) );
|
||||
memcpy( to.data() + ptr, &v, sizeof( v ) );
|
||||
return 0;
|
||||
};
|
||||
|
||||
visit_each( from, func, std::index_sequence_for<Ts...>() );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include "../Config.h"
|
||||
#ifdef COMPILER_MSVC
|
||||
|
||||
#include "../Include/Winheaders.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#if _MSC_VER >= 1920
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4091)
|
||||
#include "cor.h"
|
||||
#include <atlbase.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
namespace blackbone
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// .NET metadata parser
|
||||
/// </summary>
|
||||
class ImageNET
|
||||
{
|
||||
public:
|
||||
using mapMethodRVA = std::map<std::pair<std::wstring, std::wstring>, uintptr_t>;
|
||||
|
||||
public:
|
||||
BLACKBONE_API ImageNET(void);
|
||||
BLACKBONE_API ~ImageNET(void);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize COM classes
|
||||
/// </summary>
|
||||
/// <param name="path">Image file path</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool Init( const std::wstring& path );
|
||||
|
||||
/// <summary>
|
||||
/// Extract methods from image
|
||||
/// </summary>
|
||||
/// <param name="methods">Found Methods</param>
|
||||
/// <returns>true on success</returns>
|
||||
BLACKBONE_API bool Parse( mapMethodRVA* methods = nullptr );
|
||||
|
||||
/// <summary>
|
||||
/// Get image .NET runtime version
|
||||
/// </summary>
|
||||
/// <returns>runtime version, "n/a" if nothing found</returns>
|
||||
BLACKBONE_API static std::wstring GetImageRuntimeVer( const wchar_t* ImagePath );
|
||||
|
||||
private:
|
||||
std::wstring _path; // Image path
|
||||
mapMethodRVA _methods; // Image methods
|
||||
|
||||
// COM helpers
|
||||
CComPtr<IMetaDataDispenserEx> _pMetaDisp;
|
||||
CComPtr<IMetaDataImport> _pMetaImport;
|
||||
CComPtr<IMetaDataAssemblyImport> _pAssemblyImport;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user